1 <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN">
4 <script src=
"resources/compatibility.js"></script>
5 <script src=
"resources/audio-testing.js"></script>
6 <script src=
"../resources/js-test.js"></script>
10 <div id=
"description"></div>
11 <div id=
"console"></div>
14 // These are global to make debugging a little easier.
24 // Context sample rate.
25 var sampleRate
= 48000;
26 // The sample rate of the buffer.
27 var bufferRate
= 3000;
28 // The audio buffer is a sine wave of this frequency.
29 var toneFrequency
= 440;
31 var lengthInSeconds
= 0.5;
32 // The maximum allowed peak error between the actual and true output. This value was
33 // experimentally determined for the given bufferRate.
34 var peakThreshold
= 0.11;
35 // The minimum SNR allowed between the actual and true output.
36 var snrThreshold
= 22.35;
38 description("Test resampling of an AudioBuffer at " + bufferRate
+ " Hz");
41 return Math
.log(x
)/Math
.LN10
;
44 // Generate a sine wave in an AudioBuffer using the given |freq|. The AudioBuffer has the
45 // sample rate of |rate|.
46 function createSineBuffer(context
, freq
, rate
) {
47 var buf
= context
.createBuffer(1, lengthInSeconds
* rate
, rate
);
48 var omega
= 2 * Math
.PI
* freq
/ rate
;
49 var signal
= buf
.getChannelData(0);
50 var length
= signal
.length
;
51 for (var k
= 0; k
< length
; ++k
)
52 signal
[k
] = Math
.sin(omega
* k
);
57 // Check the output against the expected output.
58 function checkResult(event
) {
59 renderedData
= event
.renderedBuffer
.getChannelData(0);
60 var length
= renderedData
.length
;
61 // Generate a reference sine wave at the context rate
62 var trueReference
= createSineBuffer(context
, toneFrequency
, context
.sampleRate
);
63 trueData
= trueReference
.getChannelData(0);
65 // To compare the actual output against the reference, we compute the peak error and the
66 // SNR between the two.
73 // Compute the peak error and the SNR.
74 for (var k
= 0; k
< length
/ 2; ++k
) {
75 var diff
= renderedData
[k
] - trueData
[k
];
76 noiseEnergy
+= diff
* diff
;
77 signalEnergy
+= trueData
[k
] * trueData
[k
];
78 if (Math
.abs(diff
) > maxError
)
79 maxError
= Math
.abs(diff
);
87 snr
= 10 * log10(signalEnergy
/ noiseEnergy
);
89 if (maxError
< peakThreshold
) {
90 testPassed("Peak error between actual and reference data below threshold of " +
93 testFailed("Peak error of " + maxError
+ " exceeds threshold of " +
98 if (snr
> snrThreshold
) {
99 testPassed("SNR exceeds threshold of " + snrThreshold
+ " dB.");
101 testFailed("SNR of " + snr
+ " is below the threshold of " + snrThreshold
+ ".");
106 testPassed("AudioBuffer resampling is accurate for buffer rate of " +
107 bufferRate
+ " Hz.");
109 testFailed("AudioBuffer resampling is not accurate enough for buffer rate of " +
110 bufferRate
+ " Hz.");
116 if (window
.testRunner
) {
117 testRunner
.dumpAsText();
118 testRunner
.waitUntilDone();
121 window
.jsTestIsAsync
= true;
123 context
= new OfflineAudioContext(1, lengthInSeconds
* sampleRate
, sampleRate
);
125 // Create a sine wave in a buffer that's different from the context rate to test
127 buffer
= createSineBuffer(context
, toneFrequency
, bufferRate
);
128 source
= context
.createBufferSource();
129 source
.buffer
= buffer
;
130 source
.connect(context
.destination
);
133 context
.oncomplete
= checkResult
;
134 context
.startRendering();
137 successfullyParsed
= true;