WebAudio/AudioBuffer tests: Audit.js to testharness.js
This change migrates WebAudio tests from the custom `audit.js` framework to the W3C-standard `testharness.js` specifically targeting dir third_party/blink/web_tests/webaudio/AudioBuffer/ , supporting Chromium's ongoing effort to deprecate `audit.js` in favor of a more consistent testing approach. The following test files have been updated: - audiobuffer-resample.html These updates remove the dependency on `audit.js`, improving maintainability and aligning Chromium's web tests with the W3C test harness. Bug: 396477778 Change-Id: Ia2e9c862a6d07ecf979e7ee99a8fc7b8aef7a52d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6342655 Commit-Queue: Michael Wilson <mjwilson@chromium.org> Reviewed-by: Michael Wilson <mjwilson@chromium.org> Reviewed-by: Hongchan Choi <hongchan@chromium.org> Cr-Commit-Position: refs/heads/main@{#1432878}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
1c5a3e0a2b
commit
a4efd11d2b
1
AUTHORS
1
AUTHORS
@@ -1042,6 +1042,7 @@ Momoko Hattori <momohatt10@gmail.com>
|
|||||||
Mostafa Sedaghat joo <mostafa.sedaghat@gmail.com>
|
Mostafa Sedaghat joo <mostafa.sedaghat@gmail.com>
|
||||||
Mrunal Kapade <mrunal.kapade@intel.com>
|
Mrunal Kapade <mrunal.kapade@intel.com>
|
||||||
Muhammad Mahad <mahadtxt@gmail.com>
|
Muhammad Mahad <mahadtxt@gmail.com>
|
||||||
|
Muhammad Saqlain <2mesaqlain@gmail.com>
|
||||||
Munira Tursunova <moonira@google.com>
|
Munira Tursunova <moonira@google.com>
|
||||||
Myeongjin Cho <myeongjin.cho@navercorp.com>
|
Myeongjin Cho <myeongjin.cho@navercorp.com>
|
||||||
Myles C. Maxfield <mymax@amazon.com>
|
Myles C. Maxfield <mymax@amazon.com>
|
||||||
|
@@ -1,115 +1,95 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>
|
<title>AudioBuffer Resampling</title>
|
||||||
audiobuffer-resample.html
|
|
||||||
</title>
|
|
||||||
<script src="../../resources/testharness.js"></script>
|
<script src="../../resources/testharness.js"></script>
|
||||||
<script src="../../resources/testharnessreport.js"></script>
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
<script src="../resources/audit-util.js"></script>
|
<script src="../resources/audit-util.js"></script>
|
||||||
<script src="../resources/audit.js"></script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script id="layout-test-code">
|
<script>
|
||||||
let audit = Audit.createTaskRunner();
|
"use strict";
|
||||||
|
|
||||||
// These are global to make debugging a little easier.
|
|
||||||
let context;
|
let context;
|
||||||
let buffer;
|
// Frequency of the sine wave.
|
||||||
let source;
|
const TONE_FREQUENCY = 440;
|
||||||
let renderedData;
|
// Duration of the test.
|
||||||
let trueData;
|
const LENGTH_SECONDS = 0.5;
|
||||||
let signalEnergy;
|
|
||||||
let noiseEnergy;
|
|
||||||
let maxError;
|
|
||||||
|
|
||||||
// Context sample rate.
|
/**
|
||||||
let sampleRate = 48000;
|
* Generates a sine wave in a mono AudioBuffer.
|
||||||
// The sample rate of the buffer.
|
* @param {BaseAudioContext} context - The audio context.
|
||||||
let bufferRate = 3000;
|
* @param {number} frequency - Frequency of the sine wave.
|
||||||
// The audio buffer is a sine wave of this frequency.
|
* @param {number} sampleRate - Sample rate for the buffer.
|
||||||
let toneFrequency = 440;
|
* @return {AudioBuffer} The generated AudioBuffer.
|
||||||
// How long test is
|
*/
|
||||||
let lengthInSeconds = 0.5;
|
function createSineBuffer(context, frequency, sampleRate) {
|
||||||
// The maximum allowed peak error between the actual and true output. This
|
const buffer = new AudioBuffer({
|
||||||
// value was experimentally determined for the given bufferRate.
|
numberOfChannels: 1,
|
||||||
let peakThreshold = 0.11;
|
length: LENGTH_SECONDS * sampleRate,
|
||||||
// The minimum SNR allowed between the actual and true output.
|
sampleRate: sampleRate
|
||||||
let snrThreshold = 22.35;
|
});
|
||||||
|
|
||||||
|
const omega = 2 * Math.PI * frequency / sampleRate;
|
||||||
// Generate a sine wave in an AudioBuffer using the given |freq|. The
|
const channelData = buffer.getChannelData(0);
|
||||||
// AudioBuffer has the sample rate of |rate|.
|
for (let k = 0; k < channelData.length; ++k) {
|
||||||
function createSineBuffer(context, freq, rate) {
|
channelData[k] = Math.sin(omega * k);
|
||||||
let buf = context.createBuffer(1, lengthInSeconds * rate, rate);
|
}
|
||||||
let omega = 2 * Math.PI * freq / rate;
|
return buffer;
|
||||||
let signal = buf.getChannelData(0);
|
|
||||||
let length = signal.length;
|
|
||||||
for (let k = 0; k < length; ++k)
|
|
||||||
signal[k] = Math.sin(omega * k);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the output against the expected output.
|
/**
|
||||||
function checkResult(buffer, should) {
|
* Checks the rendered audio against a reference sine wave.
|
||||||
renderedData = buffer.getChannelData(0);
|
* Computes peak error and SNR, and asserts that they meet thresholds.
|
||||||
let length = renderedData.length;
|
* @param {AudioBuffer} buffer - The rendered audio buffer.
|
||||||
// Generate a reference sine wave at the context rate
|
*/
|
||||||
let trueReference =
|
function checkResult(buffer) {
|
||||||
createSineBuffer(context, toneFrequency, context.sampleRate);
|
let renderedData = buffer.getChannelData(0);
|
||||||
trueData = trueReference.getChannelData(0);
|
// Generate reference sine wave at the context's sample rate.
|
||||||
|
const referenceBuffer = createSineBuffer(
|
||||||
// To compare the actual output against the reference, we compute the
|
context, TONE_FREQUENCY, context.sampleRate);
|
||||||
// peak error and the SNR between the two.
|
const referenceData = referenceBuffer.getChannelData(0);
|
||||||
signalEnergy = 0;
|
let signalEnergy = 0;
|
||||||
noiseEnergy = 0;
|
let noiseEnergy = 0;
|
||||||
maxError = -1;
|
let maxError = -1;
|
||||||
|
const halfLength = Math.floor(renderedData.length / 2);
|
||||||
let success = true;
|
for (let k = 0; k < halfLength; ++k) {
|
||||||
|
const diff = renderedData[k] - referenceData[k];
|
||||||
// Compute the peak error and the SNR.
|
|
||||||
for (let k = 0; k < length / 2; ++k) {
|
|
||||||
let diff = renderedData[k] - trueData[k];
|
|
||||||
noiseEnergy += diff * diff;
|
noiseEnergy += diff * diff;
|
||||||
signalEnergy += trueData[k] * trueData[k];
|
signalEnergy += referenceData[k] * referenceData[k];
|
||||||
if (Math.abs(diff) > maxError)
|
maxError = Math.max(maxError, Math.abs(diff));
|
||||||
maxError = Math.abs(diff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let snr;
|
// Minimum allowed signal-to-noise ratio.
|
||||||
|
const SNR_THRESHOLD = 22.35;
|
||||||
if (noiseEnergy == 0)
|
// Maximum allowed peak error.
|
||||||
snr = 1000;
|
const PEAK_THRESHOLD = 0.11;
|
||||||
else
|
const snr =
|
||||||
snr = 10 * Math.log10(signalEnergy / noiseEnergy);
|
noiseEnergy === 0
|
||||||
|
? 1000
|
||||||
should(maxError, 'Peak error between actual and reference data')
|
: 10 * Math.log10(signalEnergy / noiseEnergy);
|
||||||
.beLessThan(peakThreshold);
|
assert_less_than(
|
||||||
|
maxError, PEAK_THRESHOLD, "Peak error should be within threshold");
|
||||||
should(snr, 'SNR').beGreaterThan(snrThreshold);
|
assert_greater_than(
|
||||||
|
snr, SNR_THRESHOLD, "SNR should be above threshold");
|
||||||
}
|
}
|
||||||
|
|
||||||
audit.define('Test resampling of an AudioBuffer', function(task, should) {
|
// Define the asynchronous test using promise_test().
|
||||||
|
promise_test(async () => {
|
||||||
|
// Context sample rate.
|
||||||
|
const SAMPLE_RATE = 48000;
|
||||||
|
// Buffer's sample rate.
|
||||||
|
const BUFFER_RATE = 3000;
|
||||||
context = new OfflineAudioContext(
|
context = new OfflineAudioContext(
|
||||||
1, lengthInSeconds * sampleRate, sampleRate);
|
1, LENGTH_SECONDS * SAMPLE_RATE, SAMPLE_RATE);
|
||||||
|
// Create a sine buffer at a different sample rate to force resampling.
|
||||||
// Create a sine wave in a buffer that's different from the context rate
|
const buffer = createSineBuffer(context, TONE_FREQUENCY, BUFFER_RATE);
|
||||||
// to test resampling.
|
let source = new AudioBufferSourceNode(context);
|
||||||
buffer = createSineBuffer(context, toneFrequency, bufferRate);
|
|
||||||
source = context.createBufferSource();
|
|
||||||
source.buffer = buffer;
|
source.buffer = buffer;
|
||||||
source.connect(context.destination);
|
source.connect(context.destination);
|
||||||
source.start();
|
source.start();
|
||||||
|
const renderedBuffer = await context.startRendering();
|
||||||
context.startRendering()
|
checkResult(renderedBuffer);
|
||||||
.then(function(buffer) {
|
}, "Resampling of an AudioBuffer");
|
||||||
checkResult(buffer, should);
|
|
||||||
})
|
|
||||||
.then(task.done.bind(task));
|
|
||||||
});
|
|
||||||
|
|
||||||
audit.run();
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Reference in New Issue
Block a user