| <!DOCTYPE html> |
| <html> |
| <head> |
| <title> |
| audiobuffersource-detune-modulated-impulse.html |
| </title> |
| <script src="../../imported/w3c/web-platform-tests/resources/testharness.js"></script> |
| <script src="../../resources/testharnessreport.js"></script> |
| <script src="../resources/audit-util.js"></script> |
| <script src="../resources/audit.js"></script> |
| </head> |
| <body> |
| <script id="layout-test-code"> |
| let sampleRate = 44100; |
| |
| // To get an observable change on detune modulation, the minimum |
| // rendering length should greater than the rendering quantum. |
| let renderLength = 256; |
| let 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. |
| let impulseLength = 4; |
| |
| let context = new OfflineAudioContext(1, renderLength, sampleRate); |
| let impulseBuffer, dcOffsetBuffer; |
| |
| let audit = Audit.createTaskRunner(); |
| |
| |
| // Task: build an impulse and DC-offset buffers for testing. |
| audit.define('build-buffers', (task, should) => { |
| should(() => { |
| // 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); |
| let 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; |
| } |
| }, 'Creation of impulse buffers').notThrow(); |
| |
| task.done(); |
| }); |
| |
| |
| // Task: Render the actual buffer and compare with the reference. |
| audit.define('synthesize-verify', (task, should) => { |
| let impulse = context.createBufferSource(); |
| let 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) { |
| let data = renderedBuffer.getChannelData(0); |
| let passed = true, i = 0; |
| let 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++; |
| } |
| |
| should(passed, 'Increasing detune') |
| .message( |
| 'to 1200 decreased the interval between impulses to half', |
| 'produced the incorrect result' + |
| 'at the index ' + i); |
| }) |
| .then(() => task.done()); |
| }); |
| |
| audit.run(); |
| </script> |
| </body> |
| </html> |