OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Audio test utilities. | 5 // Audio test utilities. |
6 | 6 |
7 // GetStats reports audio output energy in the [0, 32768] range. | 7 // GetStats reports audio output energy in the [0, 32768] range. |
8 var MAX_AUDIO_OUTPUT_ENERGY = 32768; | 8 var MAX_AUDIO_OUTPUT_ENERGY = 32768; |
9 | 9 |
| 10 // Queries WebRTC stats on |peerConnection| to find out whether audio is playing |
| 11 // on the connection. Note this does not necessarily mean the audio is actually |
| 12 // playing out (for instance if there's a bug in the WebRTC web media player). |
| 13 // If |beLenient| is true, we assume we're on a slow and unreliable bot and that |
| 14 // we should do a minimum of checking. |
| 15 function ensureAudioPlaying(peerConnection, beLenient) { |
| 16 addExpectedEvent(); |
| 17 |
| 18 // Gather 50 samples per second for 2 seconds. |
| 19 gatherAudioLevelSamples(peerConnection, 100, 50, function(samples) { |
| 20 identifyFakeDeviceSignal_(samples, beLenient); |
| 21 eventOccured(); |
| 22 }); |
| 23 } |
| 24 |
| 25 // Queries WebRTC stats on |peerConnection| to find out whether audio is muted |
| 26 // on the connection. |
| 27 function ensureSilence(peerConnection) { |
| 28 addExpectedEvent(); |
| 29 setTimeout(function() { |
| 30 gatherAudioLevelSamples(peerConnection, 100, 50, function(samples) { |
| 31 identifySilence_(samples); |
| 32 eventOccured(); |
| 33 }); |
| 34 }, 500); |
| 35 } |
| 36 |
10 // Gathers |numSamples| samples at |frequency| number of times per second and | 37 // Gathers |numSamples| samples at |frequency| number of times per second and |
11 // calls back |callback| with an array with numbers in the [0, 32768] range. | 38 // calls back |callback| with an array with numbers in the [0, 32768] range. |
12 function gatherAudioLevelSamples(peerConnection, numSamples, frequency, | 39 function gatherAudioLevelSamples(peerConnection, numSamples, frequency, |
13 callback) { | 40 callback) { |
14 console.log('Gathering ' + numSamples + ' audio samples...'); | 41 console.log('Gathering ' + numSamples + ' audio samples...'); |
15 var audioLevelSamples = [] | 42 var audioLevelSamples = [] |
16 var gatherSamples = setInterval(function() { | 43 var gatherSamples = setInterval(function() { |
17 peerConnection.getStats(function(response) { | 44 peerConnection.getStats(function(response) { |
18 audioOutputLevels = getAudioLevelFromStats_(response); | 45 audioOutputLevels = getAudioLevelFromStats_(response); |
19 if (audioOutputLevels.length == 0) { | 46 if (audioOutputLevels.length == 0) { |
20 // The call probably isn't up yet. | 47 // The call probably isn't up yet. |
21 return; | 48 return; |
22 } | 49 } |
23 | 50 |
24 // If more than one audio level is reported we get confused. | 51 // If more than one audio level is reported we get confused. |
25 assertEquals(1, audioOutputLevels.length); | 52 assertEquals(1, audioOutputLevels.length); |
26 audioLevelSamples.push(audioOutputLevels[0]); | 53 audioLevelSamples.push(audioOutputLevels[0]); |
27 | 54 |
28 if (audioLevelSamples.length == numSamples) { | 55 if (audioLevelSamples.length == numSamples) { |
29 console.log('Gathered all samples.'); | 56 console.log('Gathered all samples.'); |
30 clearInterval(gatherSamples); | 57 clearInterval(gatherSamples); |
31 callback(audioLevelSamples); | 58 callback(audioLevelSamples); |
32 } | 59 } |
33 }); | 60 }); |
34 }, 1000 / frequency); | 61 }, 1000 / frequency); |
35 } | 62 } |
36 | 63 |
37 // Tries to identify the beep-every-half-second signal generated by the fake | 64 /** |
38 // audio device in media/video/capture/fake_video_capture_device.cc. Fails the | 65 * Tries to identify the beep-every-half-second signal generated by the fake |
39 // test if we can't see a signal. The samples should have been gathered over at | 66 * audio device in media/video/capture/fake_video_capture_device.cc. Fails the |
40 // least two seconds since we expect to see at least three "peaks" in there | 67 * test if we can't see a signal. The samples should have been gathered over at |
41 // (we should see either 3 or 4 depending on how things line up). | 68 * least two seconds since we expect to see at least three "peaks" in there |
42 // | 69 * (we should see either 3 or 4 depending on how things line up). |
43 // If |beLenient| is specified, we assume we're running on a slow device or | 70 * |
44 // or under TSAN, and relax the checks quite a bit. | 71 * If |beLenient| is specified, we assume we're running on a slow device or |
45 function verifyAudioIsPlaying(samples, beLenient) { | 72 * or under TSAN, and relax the checks quite a bit. |
| 73 * |
| 74 * @private |
| 75 */ |
| 76 function identifyFakeDeviceSignal_(samples, beLenient) { |
46 var numPeaks = 0; | 77 var numPeaks = 0; |
47 var threshold = MAX_AUDIO_OUTPUT_ENERGY * 0.7; | 78 var threshold = MAX_AUDIO_OUTPUT_ENERGY * 0.7; |
48 if (beLenient) | 79 if (beLenient) |
49 threshold = MAX_AUDIO_OUTPUT_ENERGY * 0.6; | 80 threshold = MAX_AUDIO_OUTPUT_ENERGY * 0.6; |
50 var currentlyOverThreshold = false; | 81 var currentlyOverThreshold = false; |
51 | 82 |
52 // Detect when we have been been over the threshold and is going back again | 83 // Detect when we have been been over the threshold and is going back again |
53 // (i.e. count peaks). We should see about one peak per second. | 84 // (i.e. count peaks). We should see about one peak per second. |
54 for (var i = 0; i < samples.length; ++i) { | 85 for (var i = 0; i < samples.length; ++i) { |
55 if (currentlyOverThreshold && samples[i] < threshold) | 86 if (currentlyOverThreshold && samples[i] < threshold) |
56 numPeaks++; | 87 numPeaks++; |
57 currentlyOverThreshold = samples[i] >= threshold; | 88 currentlyOverThreshold = samples[i] >= threshold; |
58 } | 89 } |
59 | 90 |
60 console.log('Number of peaks identified: ' + numPeaks); | 91 console.log('Number of peaks identified: ' + numPeaks); |
61 | 92 |
62 var expectedPeaks = 2; | 93 var expectedPeaks = 2; |
63 if (beLenient) | 94 if (beLenient) |
64 expectedPeaks = 1; | 95 expectedPeaks = 1; |
65 | 96 |
66 if (numPeaks < expectedPeaks) | 97 if (numPeaks < expectedPeaks) |
67 failTest('Expected to see at least ' + expectedPeaks + ' peak(s) in ' + | 98 failTest('Expected to see at least ' + expectedPeaks + ' peak(s) in ' + |
68 'audio signal, got ' + numPeaks + '. Dumping samples for analysis: "' + | 99 'audio signal, got ' + numPeaks + '. Dumping samples for analysis: "' + |
69 samples + '"'); | 100 samples + '"'); |
70 } | 101 } |
71 | 102 |
72 // If silent (like when muted), we should get very near zero audio level. | 103 /** |
73 function verifyIsSilent(samples) { | 104 * @private |
| 105 */ |
| 106 function identifySilence_(samples) { |
74 var average = 0; | 107 var average = 0; |
75 for (var i = 0; i < samples.length; ++i) | 108 for (var i = 0; i < samples.length; ++i) |
76 average += samples[i] / samples.length; | 109 average += samples[i] / samples.length; |
77 | 110 |
| 111 // If silent (like when muted), we should get very near zero audio level. |
78 console.log('Average audio level: ' + average); | 112 console.log('Average audio level: ' + average); |
79 if (average > 500) | 113 if (average > 500) |
80 failTest('Expected silence, but avg audio level was ' + average); | 114 failTest('Expected silence, but avg audio level was ' + average); |
81 } | 115 } |
82 | 116 |
83 /** | 117 /** |
84 * @private | 118 * @private |
85 */ | 119 */ |
86 function getAudioLevelFromStats_(response) { | 120 function getAudioLevelFromStats_(response) { |
87 var reports = response.result(); | 121 var reports = response.result(); |
88 var audioOutputLevels = []; | 122 var audioOutputLevels = []; |
89 for (var i = 0; i < reports.length; ++i) { | 123 for (var i = 0; i < reports.length; ++i) { |
90 var report = reports[i]; | 124 var report = reports[i]; |
91 if (report.names().indexOf('audioOutputLevel') != -1) { | 125 if (report.names().indexOf('audioOutputLevel') != -1) { |
92 audioOutputLevels.push(report.stat('audioOutputLevel')); | 126 audioOutputLevels.push(report.stat('audioOutputLevel')); |
93 } | 127 } |
94 } | 128 } |
95 return audioOutputLevels; | 129 return audioOutputLevels; |
96 } | 130 } |
OLD | NEW |