test_getUserMedia_audioCapture.html (4837B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Test AudioCapture </title> 5 <script type="application/javascript" src="mediaStreamPlayback.js"></script> 6 </head> 7 <body> 8 <pre id="test"> 9 <script> 10 11 (async () => { 12 await createHTML({ 13 bug: "1156472", 14 title: "Test AudioCapture with regular HTMLMediaElement, AudioContext, " + 15 "and HTMLMediaElement playing a MediaStream", 16 visible: true 17 }); 18 19 await runTestWhenReady(async () => { 20 // Reduce noise for when --use-test-media-devices is not in use. 21 await SpecialPowers.pushPrefEnv({ set: [[ "media.volume_scale", "0.0" ]] }); 22 /** 23 * Get two HTMLMediaElements: 24 * - One playing a sine tone from a blob (of an opus file created on the fly) 25 * - One being the output for an AudioContext's OscillatorNode, connected to 26 * a MediaSourceDestinationNode. 27 * 28 * Also, use the AudioContext playing through its AudioDestinationNode another 29 * tone, using another OscillatorNode. 30 * 31 * Capture the output of the document, feed that back into the AudioContext, 32 * with an AnalyserNode, and check the frequency content to make sure we 33 * have recorded the three sources. 34 * 35 * The three sine tones have frequencies far apart from each other, so that we 36 * can check that the spectrum of the capture stream contains three 37 * components with a high magnitude. 38 */ 39 const decodedTone = createMediaElement("audio", "decodedTone"); 40 decodedTone.muted = false; 41 const decodedToneMuted = createMediaElement("audio", "decodedToneMuted"); 42 const acTone = createMediaElement("audio", "audioContextTone"); 43 acTone.muted = false; 44 const acToneMuted = createMediaElement("audio", "audioContextToneMuted"); 45 const micTone = createMediaElement("audio", "audioContextTone"); 46 micTone.muted = false; 47 const ac = new AudioContext(); 48 const constraints = {audio: {mediaSource: "audioCapture"}}; 49 const stream = await getUserMedia(constraints); 50 const analyser = new AudioStreamAnalyser(ac, stream); 51 52 const osc200 = ac.createOscillator(); 53 osc200.frequency.value = analyser.frequencyForBinIndex(200); 54 const osc250 = ac.createOscillator(); 55 osc250.frequency.value = analyser.frequencyForBinIndex(250); 56 const oscThroughAudioDestinationNode = ac.createOscillator(); 57 oscThroughAudioDestinationNode.frequency.value = 58 analyser.frequencyForBinIndex(100); 59 const msDest200 = ac.createMediaStreamDestination(); 60 const msDest250 = ac.createMediaStreamDestination(); 61 62 osc200.connect(msDest200); 63 osc250.connect(msDest250); 64 oscThroughAudioDestinationNode.connect(ac.destination); 65 66 acTone.srcObject = msDest200.stream; 67 acToneMuted.srcObject = msDest250.stream; 68 69 // The fake microphone uses signed 16-bit audio data: 70 await SpecialPowers.pushPrefEnv({ set: [ 71 [ 72 "media.navigator.audio.fake_frequency", 73 analyser.frequencyForBinIndex(300) 74 ] 75 ]}); 76 const micStream = await navigator.mediaDevices.getUserMedia({ 77 'audio': true, 'fake': true 78 }); 79 micTone.srcObject = micStream; 80 81 decodedTone.src = "/tests/dom/media/test/sin-441-1s-44100.flac"; 82 decodedToneMuted.src = "/tests/dom/media/test/sin-441-1s-44100.flac"; 83 decodedTone.preservesPitch = false; 84 decodedToneMuted.preservesPitch = false; 85 decodedTone.playbackRate = analyser.frequencyForBinIndex(20) / 441; 86 ok(decodedTone.playbackRate >= 1/16, "within firefox min playback rate"); 87 decodedToneMuted.playbackRate = analyser.frequencyForBinIndex(40) / 441; 88 ok(decodedToneMuted.playbackRate <= 16, "within firefox max playback rate"); 89 osc200.start(); 90 osc250.start(); 91 oscThroughAudioDestinationNode.start(); 92 decodedTone.loop = true; 93 decodedToneMuted.loop = true; 94 decodedTone.play(); 95 decodedToneMuted.play(); 96 acTone.play(); 97 acToneMuted.play(); 98 99 let frequencyBytes; 100 try { 101 analyser.enableDebugCanvas(); 102 await analyser.waitForAnalysisSuccess(array => { 103 // We want to find three frequency components here. 104 // Frequencies are logarithmic. Also make sure we have low 105 // energy in between, not just a flat white noise. 106 if (array[10] == 0 && 107 array[20] == 255 && 108 array[40] == 0 && 109 array[70] == 0 && 110 array[100] == 255 && 111 array[150] == 0 && 112 array[200] == 255 && 113 array[300] > 240) { 114 frequencyBytes = new Uint8Array(array); 115 return true; 116 } 117 return false; 118 }); 119 } finally { 120 await ac.close(); 121 for (let t of [...stream.getTracks(), ...micStream.getTracks()]) { 122 t.stop(); 123 } 124 } 125 todo(frequencyBytes[250] < 50, "muted MediaStream srcObject - bug 1864067"); 126 }); 127 })(); 128 </script> 129 </pre> 130 </body> 131 </html>