| <!DOCTYPE html> |
| <html> |
| |
| <head> |
| <script src="../resources/js-test.js"></script> |
| <script src="resources/compatibility.js"></script> |
| <script src="resources/audio-testing.js"></script> |
| </head> |
| |
| <body> |
| <script> |
| description('AudioBufferSourceNode: DC-driven detune modulation.'); |
| window.jsTestIsAsync = true; |
| |
| var sampleRate = 44100; |
| |
| // To get an observable change on detune modulation, the minimum |
| // rendering length should greater than the rendering quantum. |
| var renderLength = 256; |
| var half = renderLength / 2; |
| |
| // With the detune of 0, the duration of impulse buffer should be 4 |
| // samples (which means the interval between impulses is 4). Increasing |
| // detune to 1200 (1 octave) decrease the interval to 2 samples. |
| var impulseLength = 4; |
| |
| var context = new OfflineAudioContext(1, renderLength, sampleRate); |
| var impulseBuffer, dcOffsetBuffer; |
| |
| var audit = Audit.createTaskRunner(); |
| |
| |
| // Task: build an impulse and DC-offset buffers for testing. |
| audit.defineTask('build-buffers', function (done) { |
| // 4-sample impulse sample. |
| impulseBuffer = createImpulseBuffer(context, impulseLength); |
| |
| // Create a DC offset buffer with 2 values [0, 1200] for modulating |
| // detune. The first half of buffer is 0 and the rest is 1200. |
| dcOffsetBuffer = context.createBuffer(1, renderLength, sampleRate); |
| var dcOffsetArray = dcOffsetBuffer.getChannelData(0); |
| for (i = 0; i < dcOffsetArray.length; i++) { |
| |
| // Note that these values will be added to the detune AudioParam |
| // value. For example, 1 DC offset value will result detune of 1200. |
| dcOffsetArray[i] = i < half ? 0 : 1200; |
| } |
| |
| done(); |
| }); |
| |
| |
| // Task: Render the actual buffer and compare with the reference. |
| audit.defineTask('synthesize-verify', function (done) { |
| var impulse = context.createBufferSource(); |
| var dcOffset = context.createBufferSource(); |
| |
| impulse.buffer = impulseBuffer; |
| dcOffset.buffer = dcOffsetBuffer; |
| impulse.loop = true; |
| |
| impulse.connect(context.destination); |
| dcOffset.connect(impulse.detune); |
| |
| impulse.start(); |
| dcOffset.start(); |
| |
| context.startRendering().then(function (renderedBuffer) { |
| var data = renderedBuffer.getChannelData(0); |
| var passed = true, i = 0; |
| var nextImpulseIndex = 0; |
| |
| while (i < renderLength) { |
| if (i === nextImpulseIndex && data[i] === 1) { |
| // From 0 to 127th element, the interval between impulses is 4. On the other |
| // hand, the interval is 2 between 128th and 255th element. |
| nextImpulseIndex += (i < half) ? impulseLength : impulseLength / 2; |
| } else if (data[i] !== 0) { |
| // If a value is neither 0 or 1, break the loop and fail the test. |
| passed = false; |
| break; |
| } |
| |
| i++; |
| } |
| |
| if (passed) { |
| testPassed('Increasing detune to 1200 decreased the interval between impulses to half.'); |
| } else { |
| testFailed('Increasing detune produced the incorrect result' + |
| 'at the index ' + i + '.'); |
| } |
| }).then(done); |
| }); |
| |
| audit.defineTask('finish', function (done) { |
| finishJSTest(); |
| done(); |
| }); |
| |
| audit.runTasks( |
| 'build-buffers', |
| 'synthesize-verify', |
| 'finish' |
| ); |
| |
| successfullyParsed = true; |
| </script> |
| </body> |
| |
| </html> |