From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../webaudio/resources/note-grain-on-testing.js | 165 +++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 testing/web-platform/tests/webaudio/resources/note-grain-on-testing.js (limited to 'testing/web-platform/tests/webaudio/resources/note-grain-on-testing.js') diff --git a/testing/web-platform/tests/webaudio/resources/note-grain-on-testing.js b/testing/web-platform/tests/webaudio/resources/note-grain-on-testing.js new file mode 100644 index 0000000000..ad0631670d --- /dev/null +++ b/testing/web-platform/tests/webaudio/resources/note-grain-on-testing.js @@ -0,0 +1,165 @@ +// 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. 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 + grainGap; + +// 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; + +let context; +let renderedData; + +// Create a buffer containing the data that we want. The function f +// returns the desired value at sample frame k. +function createSignalBuffer(context, f) { + // Make sure the buffer has enough data for all of the possible + // grain offsets and durations. The additional 1 is for any + // round-off errors. + let signalLength = + Math.floor(1 + sampleRate * (numberOfTests * grainOffsetStep + duration)); + + let buffer = context.createBuffer(2, signalLength, sampleRate); + let data = buffer.getChannelData(0); + + for (let k = 0; k < signalLength; ++k) { + data[k] = f(k); + } + + return buffer; +} + +// From the data array, find the start and end sample frame for each +// grain. This depends on the data having 0's between grain, and +// that the grain is always strictly non-zero. +function findStartAndEndSamples(data) { + let nSamples = data.length; + + let startTime = []; + let endTime = []; + let lookForStart = true; + + // Look through the rendered data to find the start and stop + // times of each grain. + for (let k = 0; k < nSamples; ++k) { + if (lookForStart) { + // Find a non-zero point and record the start. We're not + // concerned with the value in this test, only that the + // grain started here. + if (renderedData[k]) { + startTime.push(k); + lookForStart = false; + } + } else { + // Find a zero and record the end of the grain. + if (!renderedData[k]) { + endTime.push(k); + lookForStart = true; + } + } + } + + return {start: startTime, end: endTime}; +} + +function playGrain(context, source, time, offset, duration) { + let bufferSource = context.createBufferSource(); + + bufferSource.buffer = source; + bufferSource.connect(context.destination); + bufferSource.start(time, offset, duration); +} + +// Play out all grains. Returns a object containing two arrays, one +// for the start time and one for the grain offset time. +function playAllGrains(context, source, numberOfNotes) { + let startTimes = new Array(numberOfNotes); + let offsets = new Array(numberOfNotes); + + for (let k = 0; k < numberOfNotes; ++k) { + let timeOffset = k * timeStep; + let grainOffset = k * grainOffsetStep; + + playGrain(context, source, timeOffset, grainOffset, duration); + startTimes[k] = timeOffset; + offsets[k] = grainOffset; + } + + return {startTimes: startTimes, grainOffsetTimes: offsets}; +} + +// Verify that the start and end frames for each grain match our +// expected start and end frames. +function verifyStartAndEndFrames(startEndFrames, should) { + let startFrames = startEndFrames.start; + let endFrames = startEndFrames.end; + + // Count of how many grains started at the incorrect time. + let errorCountStart = 0; + + // Count of how many grains ended at the incorrect time. + let errorCountEnd = 0; + + should( + startFrames.length == endFrames.length, 'Found all grain starts and ends') + .beTrue(); + + should(startFrames.length, 'Number of start frames').beEqualTo(numberOfTests); + should(endFrames.length, 'Number of end frames').beEqualTo(numberOfTests); + + // Examine the start and stop times to see if they match our + // expectations. + for (let k = 0; k < startFrames.length; ++k) { + let expectedStart = timeToSampleFrame(k * timeStep, sampleRate); + // The end point is the duration. + let expectedEnd = expectedStart + + grainLengthInSampleFrames(k * grainOffsetStep, duration, sampleRate); + + if (startFrames[k] != expectedStart) + ++errorCountStart; + if (endFrames[k] != expectedEnd) + ++errorCountEnd; + + should([startFrames[k], endFrames[k]], 'Pulse ' + k + ' boundary') + .beEqualToArray([expectedStart, expectedEnd]); + } + + // Check that all the grains started or ended at the correct time. + if (!errorCountStart) { + should( + startFrames.length, 'Number of grains that started at the correct time') + .beEqualTo(numberOfTests); + } else { + should( + errorCountStart, + 'Number of grains out of ' + numberOfTests + + 'that started at the wrong time') + .beEqualTo(0); + } + + if (!errorCountEnd) { + should(endFrames.length, 'Number of grains that ended at the correct time') + .beEqualTo(numberOfTests); + } else { + should( + errorCountEnd, + 'Number of grains out of ' + numberOfTests + + ' that ended at the wrong time') + .beEqualTo(0); + } +} -- cgit v1.2.3