OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 <html> | |
3 <head> | |
4 <title>AudioBufferSourceNode - playbackRate test</title> | |
5 <script src="../resources/js-test.js"></script> | |
6 <script src="resources/compatibility.js"></script> | |
7 <script src="resources/audit-util.js"></script> | |
8 <script src="resources/audio-testing.js"></script> | |
9 </head> | |
10 <body> | |
11 <script> | |
12 description("Test if AudioBufferSourceNode.playbackRate can playback at differ
ent rates properly."); | |
13 window.jsTestIsAsync = true; | |
14 | |
15 // Any sample rate mutiple of 128 is valid for this test, but here it uses | |
16 // 48000Hz because it is a commonly used number that happens to be multiple | |
17 // of 128. | |
18 var sampleRate = 48000; | |
19 | |
20 // The test iterates over 60 pitches starting from 36. (MIDI pitch of C2) | |
21 var fundamentalPitch = 36; | |
22 var numberOfPitches = 60; | |
23 | |
24 var noteDuration = 0.025; | |
25 var totalDuration = noteDuration * numberOfPitches; | |
26 | |
27 // Test constraints for each octave. | |
28 var testConstraints = [{ | |
29 thresholdSNR: 103.8508, | |
30 thresholdDiffULP: 0.3028 | |
31 }, { | |
32 thresholdSNR: 103.8657, | |
33 thresholdDiffULP: 0.3029 | |
34 }, { | |
35 thresholdSNR: 103.8141, | |
36 thresholdDiffULP: 0.3047 | |
37 }, { | |
38 thresholdSNR: 103.6818, | |
39 thresholdDiffULP: 0.3262 | |
40 }, { | |
41 thresholdSNR: 103.1514, | |
42 thresholdDiffULP: 0.3946 | |
43 }]; | |
44 | |
45 function pitchToFrequency(midiPitch) { | |
46 return 440 * Math.pow(2, (Math.floor(midiPitch) - 69) / 12); | |
47 } | |
48 | |
49 function pitchDiffToPlaybackRate(midiPitchDiff) { | |
50 return Math.pow(2, midiPitchDiff / 12); | |
51 } | |
52 | |
53 function createSineWaveBuffer(context, frequency, duration) { | |
54 var buffer = context.createBuffer(1, duration * sampleRate, sampleRate); | |
55 var data = buffer.getChannelData(0); | |
56 var omega = 2 * Math.PI * frequency / sampleRate; | |
57 for (var i = 0; i < data.length; i++) | |
58 data[i] = Math.sin(omega * i); | |
59 | |
60 return buffer; | |
61 } | |
62 | |
63 var context = new OfflineAudioContext(2, totalDuration * sampleRate, sampleRat
e); | |
64 | |
65 // This is the fundamental buffer for playbackRate modulation. The duration of | |
66 // this buffer is arbitrary but long enough to produce the sound without | |
67 // running short. | |
68 var fundamentalBuffer = createSineWaveBuffer(context, pitchToFrequency(fundame
ntalPitch), totalDuration); | |
69 | |
70 // A unit test consists of 2 sources: the 'actual' source runs a buffer with | |
71 // the playback rate modulated and the 'expected' source runs a mathmatically | |
72 // generated sound buffer. | |
73 function runUnitTest(context, noteStart, notePitch) { | |
74 var actualSrc = context.createBufferSource(); | |
75 var expectedSrc = context.createBufferSource(); | |
76 var merger = context.createChannelMerger(2); | |
77 | |
78 actualSrc.buffer = fundamentalBuffer; | |
79 expectedSrc.buffer = createSineWaveBuffer(context, pitchToFrequency(notePitc
h), noteDuration); | |
80 actualSrc.playbackRate.value = pitchDiffToPlaybackRate(notePitch - fundament
alPitch); | |
81 | |
82 actualSrc.connect(merger, 0, 0); | |
83 expectedSrc.connect(merger, 0, 1); | |
84 merger.connect(context.destination); | |
85 | |
86 actualSrc.start(noteStart); | |
87 actualSrc.stop(noteStart + noteDuration); | |
88 expectedSrc.start(noteStart); | |
89 expectedSrc.stop(noteStart + noteDuration); | |
90 } | |
91 | |
92 // Schedule tests up to 60 pitches above from the fundamental pitch. | |
93 for (var iteration = 0; iteration < numberOfPitches; iteration++) | |
94 runUnitTest(context, noteDuration * iteration, fundamentalPitch + iteration)
; | |
95 | |
96 // Once the rendering is complete, split the buffer into 5 octaves. Then | |
97 // perform the SNR and the maximum difference ULP check for each octave with | |
98 // different constraints. | |
99 context.startRendering().then(function (renderedBuffer) { | |
100 var actual = renderedBuffer.getChannelData(0); | |
101 var expected = renderedBuffer.getChannelData(1); | |
102 var octaveLength = Math.floor(noteDuration * 12 * sampleRate); | |
103 | |
104 for (var i = 0; i < numberOfPitches / 12; i++) { | |
105 var start = i * octaveLength, end = (i + 1) * octaveLength; | |
106 var octaveActual = actual.subarray(start, end); | |
107 var octaveExpected = expected.subarray(start, end); | |
108 | |
109 compareBuffersWithConstraints(octaveActual, octaveExpected, testConstraint
s[i]); | |
110 } | |
111 | |
112 finishJSTest(); | |
113 }); | |
114 | |
115 successfullyParsed = true; | |
116 </script> | |
117 </body> | |
118 </html> | |
OLD | NEW |