diff --git a/webaudio/resources/biquad-testing.js b/webaudio/resources/biquad-testing.js index 7a0b6e6c1f8a3d..7f90a1f72bec6b 100644 --- a/webaudio/resources/biquad-testing.js +++ b/webaudio/resources/biquad-testing.js @@ -5,15 +5,16 @@ let signal; let renderedBuffer; let renderedData; -let sampleRate = 44100.0; +// Use a power of two to eliminate round-off in converting frame to time +let sampleRate = 32768; let pulseLengthFrames = .1 * sampleRate; // Maximum allowed error for the test to succeed. Experimentally determined. let maxAllowedError = 5.9e-8; -// This must be large enough so that the filtered result is -// essentially zero. See comments for createTestAndRun. -let timeStep = .1; +// This must be large enough so that the filtered result is essentially zero. +// See comments for createTestAndRun. This must be a whole number of frames. +let timeStep = Math.ceil(.1 * sampleRate) / sampleRate; // Maximum number of filters we can process (mostly for setting the // render length correctly.) diff --git a/webaudio/resources/distance-model-testing.js b/webaudio/resources/distance-model-testing.js index 1b9adde403e379..f8a6cf940a96f1 100644 --- a/webaudio/resources/distance-model-testing.js +++ b/webaudio/resources/distance-model-testing.js @@ -1,10 +1,13 @@ -let sampleRate = 44100.0; +// Use a power of two to eliminate round-off when converting frames to time and +// vice versa. +let sampleRate = 32768; // How many panner nodes to create for the test. let nodesToCreate = 100; -// Time step when each panner node starts. -let timeStep = 0.001; +// Time step when each panner node starts. Make sure it starts on a frame +// boundary. +let timeStep = Math.floor(0.001 * sampleRate) / sampleRate; // Make sure we render long enough to get all of our nodes. let renderLengthSeconds = timeStep * (nodesToCreate + 1); @@ -134,7 +137,7 @@ function checkDistanceResult(renderedBuffer, model, should) { // The max allowed error between the actual gain and the expected // value. This is determined experimentally. Set to 0 to see // what the actual errors are. - let maxAllowedError = 3.3e-6; + let maxAllowedError = 2.2720e-6; let success = true; diff --git a/webaudio/resources/note-grain-on-testing.js b/webaudio/resources/note-grain-on-testing.js index 1e941897161228..ad0631670df932 100644 --- a/webaudio/resources/note-grain-on-testing.js +++ b/webaudio/resources/note-grain-on-testing.js @@ -1,17 +1,23 @@ -let sampleRate = 44100.0; +// Use a power of two to eliminate round-off converting from frames to time. +let sampleRate = 32768; // How many grains to play. let numberOfTests = 100; -// Duration of each grain to be played -let duration = 0.01; +// Duration of each grain to be played. Make a whole number of frames +let duration = Math.floor(0.01 * sampleRate) / sampleRate; + +// A little extra bit of silence between grain boundaries. Must be a whole +// number of frames. +let grainGap = Math.floor(0.005 * sampleRate) / sampleRate; // Time step between the start of each grain. We need to add a little // bit of silence so we can detect grain boundaries -let timeStep = duration + .005; +let timeStep = duration + grainGap; -// Time step between the start for each grain. -let grainOffsetStep = 0.001; +// Time step between the start for each grain. Must be a whole number of +// frames. +let grainOffsetStep = Math.floor(0.001 * sampleRate) / sampleRate; // How long to render to cover all of the grains. let renderTime = (numberOfTests + 1) * timeStep; diff --git a/webaudio/resources/panner-model-testing.js b/webaudio/resources/panner-model-testing.js index 662fb1d68c5361..4df3e178134210 100644 --- a/webaudio/resources/panner-model-testing.js +++ b/webaudio/resources/panner-model-testing.js @@ -1,9 +1,12 @@ -let sampleRate = 44100.0; +// Use a power of two to eliminate round-off when converting frames to time and +// vice versa. +let sampleRate = 32768; let numberOfChannels = 1; -// Time step when each panner node starts. -let timeStep = 0.001; +// Time step when each panner node starts. Make sure it starts on a frame +// boundary. +let timeStep = Math.floor(0.001 * sampleRate) / sampleRate; // Length of the impulse signal. let pulseLengthFrames = Math.round(timeStep * sampleRate); @@ -114,7 +117,7 @@ function checkResult(renderedBuffer, should) { // The max error we allow between the rendered impulse and the // expected value. This value is experimentally determined. Set // to 0 to make the test fail to see what the actual error is. - let maxAllowedError = 1.3e-6; + let maxAllowedError = 1.1597e-6; let success = true; diff --git a/webaudio/resources/stereopanner-testing.js b/webaudio/resources/stereopanner-testing.js index d6238a9cd367b0..2778493e3b6c12 100644 --- a/webaudio/resources/stereopanner-testing.js +++ b/webaudio/resources/stereopanner-testing.js @@ -3,10 +3,12 @@ let StereoPannerTest = (function() { // Constants let PI_OVER_TWO = Math.PI * 0.5; - let gSampleRate = 44100; + // Use a power of two to eliminate any round-off when converting frames to + // time. + let gSampleRate = 32768; - // Time step when each panner node starts. - let gTimeStep = 0.001; + // Time step when each panner node starts. Make sure this is on a frame boundary. + let gTimeStep = Math.floor(0.001 * gSampleRate) / gSampleRate; // How many panner nodes to create for the test let gNodesToCreate = 100; @@ -77,7 +79,7 @@ let StereoPannerTest = (function() { // The max error we allow between the rendered impulse and the // expected value. This value is experimentally determined. Set // to 0 to make the test fail to see what the actual error is. - this.maxAllowedError = 1.3e-6; + this.maxAllowedError = 9.8015e-8; // Max (absolute) error and the index of the maxima for the left // and right channels. diff --git a/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-zero.html b/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-zero.html index 58ee49e42d279e..5624054e3289a1 100644 --- a/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-zero.html +++ b/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-zero.html @@ -74,6 +74,42 @@ .then(() => task.done()); }); + audit.define('subsample start with playback rate 0', (task, should) => { + let context = new OfflineAudioContext(1, renderLength, sampleRate); + let rampBuffer = new AudioBuffer( + {length: renderLength, sampleRate: context.sampleRate}); + let data = new Float32Array(renderLength); + let startValue = 5; + for (let k = 0; k < data.length; ++k) { + data[k] = k + startValue; + } + rampBuffer.copyToChannel(data, 0); + + let src = new AudioBufferSourceNode( + context, {buffer: rampBuffer, playbackRate: 0}); + + src.connect(context.destination); + + // Purposely start the source between frame boundaries + let startFrame = 27.3; + src.start(startFrame / context.sampleRate); + + context.startRendering() + .then(audioBuffer => { + let actualStartFrame = Math.ceil(startFrame); + let audio = audioBuffer.getChannelData(0); + + should( + audio.slice(0, actualStartFrame), + `output[0:${actualStartFrame - 1}]`) + .beConstantValueOf(0); + should( + audio.slice(actualStartFrame), `output[${actualStartFrame}:]`) + .beConstantValueOf(startValue); + }) + .then(() => task.done()); + }); + audit.run();
+ +diff --git a/webaudio/the-audio-api/the-audiobuffersourcenode-interface/resources/sub-sample-scheduling.html b/webaudio/the-audio-api/the-audiobuffersourcenode-interface/resources/sub-sample-scheduling.html new file mode 100644 index 00000000000000..27ac0984a79ef2 --- /dev/null +++ b/webaudio/the-audio-api/the-audiobuffersourcenode-interface/resources/sub-sample-scheduling.html @@ -0,0 +1,423 @@ + + +
+
+ + + + + +
+