| OLD | NEW |
| 1 <!doctype html> | 1 <!DOCTYPE html> |
| 2 <html> | 2 <html> |
| 3 <head> | 3 <head> |
| 4 <title>Test Custom Oscillator at Very Low Frequency</title> | 4 <title> |
| 5 Test Custom Oscillator at Very Low Frequency |
| 6 </title> |
| 5 <script src="../../resources/testharness.js"></script> | 7 <script src="../../resources/testharness.js"></script> |
| 6 <script src="../../resources/testharnessreport.js"></script> | 8 <script src="../../resources/testharnessreport.js"></script> |
| 7 <script src="../resources/audit-util.js"></script> | 9 <script src="../resources/audit-util.js"></script> |
| 8 <script src="../resources/audit.js"></script> | 10 <script src="../resources/audit.js"></script> |
| 9 </head> | 11 </head> |
| 12 <body> |
| 13 <script id="layout-test-code"> |
| 14 // Create a custom oscillator and verify that the parts of a periodic wave |
| 15 // that should be ignored really are ignored. |
| 10 | 16 |
| 11 <body> | 17 let sampleRate = 48000; |
| 12 <script> | |
| 13 // Create a custom oscillator and verify that the parts of a periodic wave
that should be | |
| 14 // ignored really are ignored. | |
| 15 | 18 |
| 16 var sampleRate = 48000; | 19 // The desired frequency of the oscillator. The value to be used depends |
| 20 // on the implementation of the PeriodicWave and should be less than then |
| 21 // lowest fundamental frequency. The lowest frequency is the Nyquist |
| 22 // frequency divided by the max number of coefficients used for the FFT. |
| 23 // In the current implementation, the max number of coefficients is 2048 |
| 24 // (for a sample rate of 48 kHz) so the lowest frequency is 24000/2048 = |
| 25 // 11.78 Hz. |
| 26 let desiredFrequencyHz = 1; |
| 17 | 27 |
| 18 // The desired frequency of the oscillator. The value to be used depends
on the | 28 // Minimum allowed SNR between the actual oscillator and the expected |
| 19 // implementation of the PeriodicWave and should be less than then lowest
fundamental | 29 // result. Experimentally determined. |
| 20 // frequency. The lowest frequency is the Nyquist frequency divided by the
max number of | 30 let snrThreshold = 130; |
| 21 // coefficients used for the FFT. In the current implementation, the max n
umber of | |
| 22 // coefficients is 2048 (for a sample rate of 48 kHz) so the lowest freque
ncy is 24000/2048 = | |
| 23 // 11.78 Hz. | |
| 24 var desiredFrequencyHz = 1; | |
| 25 | 31 |
| 26 // Minimum allowed SNR between the actual oscillator and the expected resu
lt. Experimentally | 32 let context; |
| 27 // determined. | 33 let osc; |
| 28 var snrThreshold = 130; | 34 let actual; |
| 29 | 35 |
| 30 var context; | 36 let audit = Audit.createTaskRunner(); |
| 31 var osc; | |
| 32 var actual; | |
| 33 | |
| 34 var audit = Audit.createTaskRunner(); | |
| 35 | 37 |
| 36 // Compute the SNR between the actual result and expected cosine wave | 38 // Compute the SNR between the actual result and expected cosine wave |
| 37 function checkCosineResult(should, result, freq, sampleRate) { | 39 function checkCosineResult(should, result, freq, sampleRate) { |
| 38 var signal = 0; | 40 let signal = 0; |
| 39 var noise = 0; | 41 let noise = 0; |
| 40 var omega = 2 * Math.PI * freq / sampleRate; | 42 let omega = 2 * Math.PI * freq / sampleRate; |
| 41 | 43 |
| 42 actual = result.getChannelData(0); | 44 actual = result.getChannelData(0); |
| 43 | 45 |
| 44 for (var k = 0; k < actual.length; ++k) { | 46 for (let k = 0; k < actual.length; ++k) { |
| 45 var x = Math.cos(omega * k); | 47 let x = Math.cos(omega * k); |
| 46 var diff = x - actual[k]; | 48 let diff = x - actual[k]; |
| 47 signal += x * x; | 49 signal += x * x; |
| 48 noise += diff * diff; | 50 noise += diff * diff; |
| 49 } | 51 } |
| 50 | 52 |
| 51 var snr = 10 * Math.log10(signal / noise); | 53 let snr = 10 * Math.log10(signal / noise); |
| 52 | 54 |
| 53 should(snr, "SNR of " + desiredFrequencyHz + " Hz sine wave") | 55 should(snr, 'SNR of ' + desiredFrequencyHz + ' Hz sine wave') |
| 54 .beGreaterThanOrEqualTo(snrThreshold); | 56 .beGreaterThanOrEqualTo(snrThreshold); |
| 55 } | 57 } |
| 56 | 58 |
| 57 audit.define("low-freq-oscillator", (task, should) => { | 59 audit.define('low-freq-oscillator', (task, should) => { |
| 58 context = new OfflineAudioContext(1, sampleRate, sampleRate); | 60 context = new OfflineAudioContext(1, sampleRate, sampleRate); |
| 59 osc = context.createOscillator(); | 61 osc = context.createOscillator(); |
| 60 | 62 |
| 61 // Create the custom oscillator. For simplicity of testing, we use just
a cosine wave, but | 63 // Create the custom oscillator. For simplicity of testing, we use just |
| 62 // the initial elements of the real and imaginary parts are explicitly s
et to non-zero to | 64 // a cosine wave, but the initial elements of the real and imaginary |
| 63 // test that they are ignored. | 65 // parts are explicitly set to non-zero to test that they are ignored. |
| 64 var r = new Float32Array(2); | 66 let r = new Float32Array(2); |
| 65 var i = new Float32Array(2); | 67 let i = new Float32Array(2); |
| 66 r[0] = 1; // DC component to be ignored | 68 r[0] = 1; // DC component to be ignored |
| 67 r[1] = 1; // Fundamental | 69 r[1] = 1; // Fundamental |
| 68 i[0] = 1; // Sine term that doesn't actually exist in a Fourier series | 70 i[0] = 1; // Sine term that doesn't actually exist in a Fourier series |
| 69 i[1] = 0; | 71 i[1] = 0; |
| 70 var wave = context.createPeriodicWave(r, i); | 72 let wave = context.createPeriodicWave(r, i); |
| 71 | 73 |
| 72 osc.setPeriodicWave(wave); | 74 osc.setPeriodicWave(wave); |
| 73 osc.frequency.value = desiredFrequencyHz; | 75 osc.frequency.value = desiredFrequencyHz; |
| 74 osc.connect(context.destination); | 76 osc.connect(context.destination); |
| 75 osc.start(); | 77 osc.start(); |
| 76 context.startRendering().then(function (buffer) { | 78 context.startRendering() |
| 77 checkCosineResult(should, buffer, desiredFrequencyHz, sampleRate); | 79 .then(function(buffer) { |
| 78 }) | 80 checkCosineResult(should, buffer, desiredFrequencyHz, sampleRate); |
| 79 .then(() => task.done()); | 81 }) |
| 82 .then(() => task.done()); |
| 80 }); | 83 }); |
| 81 | 84 |
| 82 audit.run(); | 85 audit.run(); |
| 83 </script> | 86 </script> |
| 84 </body> | 87 </body> |
| 85 </html> | 88 </html> |
| OLD | NEW |