Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Notes about generated waveforms: | 1 // Notes about generated waveforms: |
| 2 // | 2 // |
| 3 // QUESTION: Why does the wave shape not look like the exact shape (sharp edges) ? | 3 // QUESTION: Why does the wave shape not look like the exact shape (sharp edges) ? |
| 4 // ANSWER: Because a shape with sharp edges has infinitely high frequency conten t. | 4 // ANSWER: Because a shape with sharp edges has infinitely high frequency conten t. |
| 5 // Since a digital audio signal must be band-limited based on the nyquist freque ncy (half the sample-rate) | 5 // Since a digital audio signal must be band-limited based on the nyquist freque ncy (half the sample-rate) |
| 6 // in order to avoid aliasing, this creates more rounded edges and "ringing" in the | 6 // in order to avoid aliasing, this creates more rounded edges and "ringing" in the |
| 7 // appearance of the waveform. See Nyquist-Shannon sampling theorem: | 7 // appearance of the waveform. See Nyquist-Shannon sampling theorem: |
| 8 // http://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem | 8 // http://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem |
| 9 // | 9 // |
| 10 // QUESTION: Why does the very end of the generated signal appear to get slightl y weaker? | 10 // QUESTION: Why does the very end of the generated signal appear to get slightl y weaker? |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 // </head> | 28 // </head> |
| 29 // <body> | 29 // <body> |
| 30 // <script> | 30 // <script> |
| 31 // OscillatorTestingUtils.createNewReference("sine"); | 31 // OscillatorTestingUtils.createNewReference("sine"); |
| 32 // </script> | 32 // </script> |
| 33 // </body> | 33 // </body> |
| 34 // </html> | 34 // </html> |
| 35 | 35 |
| 36 OscillatorTestingUtils = (function () { | 36 OscillatorTestingUtils = (function () { |
| 37 | 37 |
| 38 var audit = Audit.createTaskRunner(); | |
|
hongchan
2017/02/07 18:18:53
Not sure what's fixed here.
Raymond Toy
2017/02/07 18:57:58
Forgot to remove it.
Raymond Toy
2017/02/07 18:57:58
Oops. Forgot to remove this.
| |
| 38 var sampleRate = 44100.0; | 39 var sampleRate = 44100.0; |
| 39 var nyquist = 0.5 * sampleRate; | 40 var nyquist = 0.5 * sampleRate; |
| 40 var lengthInSeconds = 4; | 41 var lengthInSeconds = 4; |
| 41 var lowFrequency = 10; | 42 var lowFrequency = 10; |
| 42 var highFrequency = nyquist + 2000; // go slightly higher than nyquist to make s ure we generate silence there | 43 var highFrequency = nyquist + 2000; // go slightly higher than nyquist to make s ure we generate silence there |
| 43 var context = 0; | 44 var context = 0; |
| 44 | 45 |
| 45 // Scaling factor for converting the 16-bit WAV data to float (and vice-versa). | 46 // Scaling factor for converting the 16-bit WAV data to float (and vice-versa). |
| 46 var waveScaleFactor = 32768; | 47 var waveScaleFactor = 32768; |
| 47 | 48 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 } | 103 } |
| 103 | 104 |
| 104 function calculateSNR(sPower, nPower) | 105 function calculateSNR(sPower, nPower) |
| 105 { | 106 { |
| 106 if (nPower == 0 && sPower > 0) { | 107 if (nPower == 0 && sPower > 0) { |
| 107 return 1000; | 108 return 1000; |
| 108 } | 109 } |
| 109 return 10 * Math.log10(sPower / nPower); | 110 return 10 * Math.log10(sPower / nPower); |
| 110 } | 111 } |
| 111 | 112 |
| 112 function loadReferenceAndRunTest(oscType) { | 113 function loadReferenceAndRunTest(context, oscType, task, should) { |
| 113 var bufferLoader = new BufferLoader( | 114 var bufferLoader = new BufferLoader( |
| 114 context, | 115 context, |
| 115 [ "../Oscillator/oscillator-" + oscType + "-expected.wav" ], | 116 [ "../Oscillator/oscillator-" + oscType + "-expected.wav" ], |
| 116 function (bufferList) { | 117 function (bufferList) { |
| 117 reference = bufferList[0].getChannelData(0); | 118 reference = bufferList[0].getChannelData(0); |
| 118 generateExponentialOscillatorSweep(context, oscType); | 119 generateExponentialOscillatorSweep(context, oscType); |
| 119 context.oncomplete = checkResult; | 120 context.oncomplete = () => { |
| 121 checkResult(event, should); | |
| 122 task.done(); | |
| 123 }; | |
| 120 context.startRendering(); | 124 context.startRendering(); |
| 121 }); | 125 }); |
| 122 | 126 |
| 123 bufferLoader.load(); | 127 bufferLoader.load(); |
| 124 } | 128 } |
| 125 | 129 |
| 126 function checkResult (event) { | 130 function checkResult (event, should) { |
| 127 renderedData = event.renderedBuffer.getChannelData(0); | 131 renderedData = event.renderedBuffer.getChannelData(0); |
| 128 // Compute signal to noise ratio between the result and the reference. Also keep track | 132 // Compute signal to noise ratio between the result and the reference. Also keep track |
| 129 // of the max difference (and position). | 133 // of the max difference (and position). |
| 130 | 134 |
| 131 var maxError = -1; | 135 var maxError = -1; |
| 132 var errorPosition = -1; | 136 var errorPosition = -1; |
| 133 var diffCount = 0; | 137 var diffCount = 0; |
| 134 | 138 |
| 135 for (var k = 0; k < renderedData.length; ++k) { | 139 for (var k = 0; k < renderedData.length; ++k) { |
| 136 var diff = renderedData[k] - reference[k]; | 140 var diff = renderedData[k] - reference[k]; |
| 137 noisePower += diff * diff; | 141 noisePower += diff * diff; |
| 138 signalPower += reference[k] * reference[k]; | 142 signalPower += reference[k] * reference[k]; |
| 139 if (Math.abs(diff) > maxError) { | 143 if (Math.abs(diff) > maxError) { |
| 140 maxError = Math.abs(diff); | 144 maxError = Math.abs(diff); |
| 141 errorPosition = k; | 145 errorPosition = k; |
| 142 } | 146 } |
| 143 // The reference file is a 16-bit WAV file, so we will almost never get an exact match | 147 // The reference file is a 16-bit WAV file, so we will almost never get an exact match |
| 144 // between it and the actual floating-point result. | 148 // between it and the actual floating-point result. |
| 145 if (diff > 1/waveScaleFactor) { | 149 if (diff > 1/waveScaleFactor) { |
| 146 diffCount++; | 150 diffCount++; |
| 147 } | 151 } |
| 148 } | 152 } |
| 149 | 153 |
| 150 var snr = calculateSNR(signalPower, noisePower); | 154 var snr = calculateSNR(signalPower, noisePower); |
| 151 if (snr >= thresholdSNR) { | 155 should(snr, "SNR") |
| 152 testPassed("Exceeded SNR threshold of " + thresholdSNR + " dB"); | 156 .beGreaterThanOrEqualTo(thresholdSNR); |
| 153 } else { | 157 should(maxError * waveScaleFactor, "Maximum difference in ulp (16-bits)") |
| 154 testFailed("Expected SNR of " + thresholdSNR + " dB, but actual SNR is " + snr + " dB"); | 158 .beLessThanOrEqualTo(thresholdDiff * waveScaleFactor); |
| 155 } | |
| 156 | 159 |
| 157 if (maxError <= thresholdDiff) { | 160 should(diffCount, |
| 158 testPassed("Maximum difference below threshold of " | 161 "Number of differences between actual and expected result out of " |
| 159 + (thresholdDiff * waveScaleFactor) + " ulp (16-bits)"); | 162 + renderedData.length + " frames") |
| 160 } else { | 163 .beLessThanOrEqualTo(thresholdDiffCount); |
| 161 testFailed("Maximum difference of " + (maxError * waveScaleFactor) + " a t " | |
| 162 + errorPosition + " exceeded threshold of " + (thresholdDiff * waveScaleFactor) | |
| 163 + " ulp (16-bits)"); | |
| 164 } | |
| 165 | |
| 166 if (diffCount <= thresholdDiffCount) { | |
| 167 testPassed("Number of differences between actual and expected result is less than " + thresholdDiffCount | |
| 168 + " out of " + renderedData.length); | |
| 169 } else { | |
| 170 testFailed(diffCount + " differences found but expected no more than " + thresholdDiffCount | |
| 171 + " out of " + renderedData.length); | |
| 172 } | |
| 173 | |
| 174 finishJSTest(); | |
| 175 } | 164 } |
| 176 | 165 |
| 177 function setThresholds(thresholds) { | 166 function setThresholds(thresholds) { |
| 178 thresholdSNR = thresholds.snr; | 167 thresholdSNR = thresholds.snr; |
| 179 thresholdDiff = thresholds.maxDiff / waveScaleFactor; | 168 thresholdDiff = thresholds.maxDiff / waveScaleFactor; |
| 180 thresholdDiffCount = thresholds.diffCount; | 169 thresholdDiffCount = thresholds.diffCount; |
| 181 } | 170 } |
| 182 | 171 |
| 183 function runTest(oscType) { | 172 function runTest(context, oscType, description, task, should) { |
| 184 window.jsTestIsAsync = true; | 173 loadReferenceAndRunTest(context, oscType, task, should); |
| 185 context = new OfflineAudioContext(1, sampleRate * lengthInSeconds, sampleRat e); | |
| 186 loadReferenceAndRunTest(oscType); | |
| 187 } | 174 } |
| 188 | 175 |
| 189 function createNewReference(oscType) { | 176 function createNewReference(oscType) { |
| 190 if (!window.testRunner) | 177 if (!window.testRunner) |
| 191 return; | 178 return; |
| 192 | 179 |
| 193 context = new OfflineAudioContext(1, sampleRate * lengthInSeconds, sampleRa te); | 180 context = new OfflineAudioContext(1, sampleRate * lengthInSeconds, sampleRa te); |
| 194 generateExponentialOscillatorSweep(context, oscType); | 181 generateExponentialOscillatorSweep(context, oscType); |
| 195 | 182 |
| 196 context.oncomplete = finishAudioTest; | 183 context.oncomplete = finishAudioTest; |
| 197 context.startRendering(); | 184 context.startRendering(); |
| 198 | 185 |
| 199 testRunner.waitUntilDone(); | 186 testRunner.waitUntilDone(); |
| 200 } | 187 } |
| 201 | 188 |
| 202 return { | 189 return { |
| 203 sampleRate: sampleRate, | 190 sampleRate: sampleRate, |
| 204 lengthInSeconds: lengthInSeconds, | 191 lengthInSeconds: lengthInSeconds, |
| 205 thresholdSNR: thresholdSNR, | 192 thresholdSNR: thresholdSNR, |
| 206 thresholdDiff: thresholdDiff, | 193 thresholdDiff: thresholdDiff, |
| 207 thresholdDiffCount: thresholdDiffCount, | 194 thresholdDiffCount: thresholdDiffCount, |
| 208 waveScaleFactor: waveScaleFactor, | 195 waveScaleFactor: waveScaleFactor, |
| 209 setThresholds: setThresholds, | 196 setThresholds: setThresholds, |
| 210 loadReferenceAndRunTest: loadReferenceAndRunTest, | |
| 211 runTest: runTest, | 197 runTest: runTest, |
| 212 createNewReference: createNewReference, | 198 createNewReference: createNewReference, |
| 213 }; | 199 }; |
| 214 | 200 |
| 215 }()); | 201 }()); |
| OLD | NEW |