83 lines
2.8 KiB
HTML
83 lines
2.8 KiB
HTML
<!DOCTYPE html>
|
|
<title>Test normalization of convolution buffers</title>
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script>
|
|
// Constants from
|
|
// https://www.w3.org/TR/2015/WD-webaudio-20151208/#widl-ConvolverNode-normalize
|
|
const GainCalibration = 0.00125;
|
|
const GainCalibrationSampleRate = 44100;
|
|
|
|
const sampleRate = GainCalibrationSampleRate;
|
|
const LENGTH = 12800;
|
|
// tolerate 16-bit math.
|
|
const EPSILON = 1.0 / Math.pow(2, 15);
|
|
|
|
function test_normalization_via_response_concat()
|
|
{
|
|
var context = new OfflineAudioContext(1, LENGTH, sampleRate);
|
|
|
|
var impulse = context.createBuffer(1, 1, sampleRate);
|
|
impulse.getChannelData(0)[0] = 1.0;
|
|
var source = context.createBufferSource();
|
|
source.buffer = impulse;
|
|
source.start(0);
|
|
|
|
// Construct a set of adjacent responses in such a way that, when each is
|
|
// convolved with the impulse, they can be merged to produce a constant.
|
|
|
|
// The 5/4 ratio provides a range of lengths with different offsets within
|
|
// blocks.
|
|
var i = 0;
|
|
for (var responseEnd = 1;
|
|
i < LENGTH;
|
|
responseEnd = Math.floor((5 * responseEnd) / 4) + 1) {
|
|
var responseBuffer = context.createBuffer(1, responseEnd, sampleRate);
|
|
var response = responseBuffer.getChannelData(0);
|
|
var responseStart = i;
|
|
// The values in the response should be normalized, and so the output
|
|
// should not be dependent on the value. Pick a changing value to test
|
|
// this.
|
|
var value = responseStart + 1;
|
|
for (; i < responseEnd; ++i) {
|
|
response[i] = value;
|
|
}
|
|
var convolver = context.createConvolver();
|
|
convolver.normalize = true;
|
|
convolver.buffer = responseBuffer;
|
|
convolver.connect(context.destination);
|
|
// Undo the normalization calibration by scaling the impulse so as to
|
|
// expect unit pulse output from the convolver.
|
|
var gain = context.createGain();
|
|
gain.gain.value =
|
|
Math.sqrt((responseEnd - responseStart) / responseEnd) / GainCalibration;
|
|
gain.connect(convolver);
|
|
source.connect(gain);
|
|
}
|
|
|
|
return context.startRendering().
|
|
then((buffer) => {
|
|
var output = buffer.getChannelData(0);
|
|
var max = output[0];
|
|
var maxIndex = 0;
|
|
var min = max;
|
|
var minIndex = 0;
|
|
for (var i = 1; i < buffer.length; ++i) {
|
|
if (output[i] > max) {
|
|
max = output[i];
|
|
maxIndex = i;
|
|
} else if (output[i] < min) {
|
|
min = output[i];
|
|
minIndex = i;
|
|
}
|
|
}
|
|
assert_approx_equals(output[maxIndex], 1.0, EPSILON,
|
|
"max output at " + maxIndex);
|
|
assert_approx_equals(output[minIndex], 1.0, EPSILON,
|
|
"min output at " + minIndex);
|
|
});
|
|
}
|
|
|
|
promise_test(test_normalization_via_response_concat,
|
|
"via response concatenation");
|
|
</script>
|