OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 | |
3 <!-- | 2 <!-- |
4 Tests that GainNode is properly scaling the gain. | 3 Tests that GainNode is properly scaling the gain. |
5 We'll render 11 notes, starting at a gain of 1.0, decreasing in gain by 0.1. | 4 We'll render 11 notes, starting at a gain of 1.0, decreasing in gain by 0.1. |
6 The 11th note will be of gain 0.0, so it should be silent (at the end in the ren
dered output). | 5 The 11th note will be of gain 0.0, so it should be silent (at the end in the ren
dered output). |
7 --> | 6 --> |
| 7 <html> |
| 8 <head> |
| 9 <title> |
| 10 gain.html |
| 11 </title> |
| 12 <script src="../../resources/testharness.js"></script> |
| 13 <script src="../../resources/testharnessreport.js"></script> |
| 14 <script src="../resources/audit-util.js"></script> |
| 15 <script src="../resources/audit.js"></script> |
| 16 <script src="../resources/buffer-loader.js"></script> |
| 17 </head> |
| 18 <body> |
| 19 <script id="layout-test-code"> |
| 20 let audit = Audit.createTaskRunner(); |
8 | 21 |
9 <html> | 22 let sampleRate = 44100.0; |
10 <head> | 23 let bufferDurationSeconds = 0.125; |
11 <script src="../../resources/testharness.js"></script> | 24 let numberOfNotes = 11; |
12 <script src="../../resources/testharnessreport.js"></script> | 25 let noteSpacing = bufferDurationSeconds + |
13 <script src="../resources/audit-util.js"></script> | 26 0.020; // leave 20ms of silence between each "note" |
14 <script src="../resources/audit.js"></script> | 27 let lengthInSeconds = numberOfNotes * noteSpacing; |
15 <script src="../resources/buffer-loader.js"></script> | |
16 </head> | |
17 <body> | |
18 | 28 |
19 <script> | 29 let context = 0; |
20 let audit = Audit.createTaskRunner(); | 30 let sinWaveBuffer = 0; |
| 31 let reference = 0; |
21 | 32 |
22 let sampleRate = 44100.0; | 33 function createSinWaveBuffer(lengthInSeconds, frequency) { |
23 let bufferDurationSeconds = 0.125; | 34 let audioBuffer = |
24 let numberOfNotes = 11; | 35 context.createBuffer(2, lengthInSeconds * sampleRate, sampleRate); |
25 let noteSpacing = | |
26 bufferDurationSeconds + 0.020; // leave 20ms of silence between each "note" | |
27 let lengthInSeconds = numberOfNotes * noteSpacing; | |
28 | 36 |
29 let context = 0; | 37 let n = audioBuffer.length; |
30 let sinWaveBuffer = 0; | 38 let channelL = audioBuffer.getChannelData(0); |
31 let reference = 0; | 39 let channelR = audioBuffer.getChannelData(1); |
32 | 40 |
33 function createSinWaveBuffer(lengthInSeconds, frequency) { | 41 for (let i = 0; i < n; ++i) { |
34 let audioBuffer = | 42 channelL[i] = Math.sin(frequency * 2.0 * Math.PI * i / sampleRate); |
35 context.createBuffer(2, lengthInSeconds * sampleRate, sampleRate); | 43 channelR[i] = channelL[i]; |
| 44 } |
36 | 45 |
37 let n = audioBuffer.length; | 46 return audioBuffer; |
38 let channelL = audioBuffer.getChannelData(0); | 47 } |
39 let channelR = audioBuffer.getChannelData(1); | |
40 | 48 |
41 for (let i = 0; i < n; ++i) { | 49 function playNote(time, gain) { |
42 channelL[i] = Math.sin(frequency * 2.0 * Math.PI * i / sampleRate); | 50 let source = context.createBufferSource(); |
43 channelR[i] = channelL[i]; | 51 source.buffer = sinWaveBuffer; |
44 } | |
45 | 52 |
46 return audioBuffer; | 53 let gainNode = context.createGain(); |
47 } | 54 gainNode.gain.value = gain; |
48 | 55 |
49 function playNote(time, gain) { | 56 source.connect(gainNode); |
50 let source = context.createBufferSource(); | 57 gainNode.connect(context.destination); |
51 source.buffer = sinWaveBuffer; | |
52 | 58 |
53 let gainNode = context.createGain(); | 59 source.start(time); |
54 gainNode.gain.value = gain; | 60 } |
55 | 61 |
56 source.connect(gainNode); | 62 audit.define( |
57 gainNode.connect(context.destination); | 63 {label: 'create context', description: 'Create context for test'}, |
| 64 function(task, should) { |
| 65 // Create offline audio context. |
| 66 context = new OfflineAudioContext( |
| 67 2, sampleRate * lengthInSeconds, sampleRate); |
| 68 task.done(); |
| 69 }); |
58 | 70 |
59 source.start(time); | 71 audit.define( |
60 } | 72 {label: 'load-ref', description: 'Load reference audio file'}, |
| 73 function(task, should) { |
| 74 let bufferLoader = |
| 75 new BufferLoader(context, ['gain-expected.wav'], bufferList => { |
| 76 reference = bufferList[0].getChannelData(0); |
| 77 task.done(); |
| 78 }); |
61 | 79 |
62 audit.define({ | 80 bufferLoader.load(); |
63 label: 'create context', | 81 }); |
64 description: 'Create context for test' | |
65 }, function(task, should) { | |
66 // Create offline audio context. | |
67 context = | |
68 new OfflineAudioContext(2, sampleRate * lengthInSeconds, sampleRate); | |
69 task.done(); | |
70 }); | |
71 | 82 |
72 audit.define({ | 83 audit.define( |
73 label: 'load-ref', | 84 {label: 'test', description: 'GainNode functionality'}, |
74 description: 'Load reference audio file' | 85 function(task, should) { |
75 }, function(task, should) { | |
76 let bufferLoader = | |
77 new BufferLoader(context, ['gain-expected.wav'], bufferList => { | |
78 reference = bufferList[0].getChannelData(0); | |
79 task.done(); | |
80 }); | |
81 | 86 |
82 bufferLoader.load(); | 87 // Create a buffer for a short "note". |
83 }); | 88 sinWaveBuffer = createSinWaveBuffer(bufferDurationSeconds, 880.0); |
84 | 89 |
85 audit.define({ | 90 // Render 11 notes, starting at a gain of 1.0, decreasing in gain by |
86 label: 'test', | 91 // 0.1. The last note will be of gain 0.0, so shouldn't be |
87 description: 'GainNode functionality' | 92 // perceptible in the rendered output. |
88 }, function(task, should) { | 93 for (let i = 0; i < numberOfNotes; ++i) { |
| 94 let time = i * noteSpacing; |
| 95 let gain = 1.0 - i / (numberOfNotes - 1); |
| 96 playNote(time, gain); |
| 97 } |
89 | 98 |
90 // Create a buffer for a short "note". | 99 context.startRendering() |
91 sinWaveBuffer = createSinWaveBuffer(bufferDurationSeconds, 880.0); | 100 .then(buffer => { |
| 101 let actual = buffer.getChannelData(0); |
| 102 should(actual, 'Output from gain node') |
| 103 .beCloseToArray( |
| 104 reference, {absoluteThreshold: 3.0503e-5}); |
| 105 let snr = 10 * Math.log10(computeSNR(actual, reference)); |
| 106 should(snr, 'SNR (in dB)').beGreaterThanOrEqualTo(89.088); |
| 107 let filename = 'gain-actual.wav'; |
| 108 if (downloadAudioBuffer(buffer, filename)) |
| 109 should(true, 'Saved reference file').message(filename, ''); |
| 110 }) |
| 111 .then(() => task.done()); |
| 112 ; |
| 113 }); |
92 | 114 |
93 // Render 11 notes, starting at a gain of 1.0, decreasing in gain by 0.1. | 115 audit.run(); |
94 // The last note will be of gain 0.0, so shouldn't be perceptible in the | 116 </script> |
95 // rendered output. | 117 </body> |
96 for (let i = 0; i < numberOfNotes; ++i) { | |
97 let time = i * noteSpacing; | |
98 let gain = 1.0 - i / (numberOfNotes - 1); | |
99 playNote(time, gain); | |
100 } | |
101 | |
102 context.startRendering() | |
103 .then(buffer => { | |
104 let actual = buffer.getChannelData(0); | |
105 should(actual, 'Output from gain node').beCloseToArray(reference, { | |
106 absoluteThreshold: 3.0503e-5 | |
107 }); | |
108 let snr = 10 * Math.log10(computeSNR(actual, reference)); | |
109 should(snr, 'SNR (in dB)').beGreaterThanOrEqualTo(89.088); | |
110 let filename = 'gain-actual.wav'; | |
111 if (downloadAudioBuffer(buffer, filename)) | |
112 should(true, 'Saved reference file').message(filename, ""); | |
113 }) | |
114 .then(() => task.done()); | |
115 ; | |
116 }); | |
117 | |
118 audit.run(); | |
119 </script> | |
120 | |
121 </body> | |
122 </html> | 118 </html> |
OLD | NEW |