var renderLengthSeconds = 8; var pulseLengthSeconds = 1; var pulseLengthFrames = pulseLengthSeconds * sampleRate;
function createSquarePulseBuffer(context, sampleFrameLength) { var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
var n = audioBuffer.length; var data = audioBuffer.getChannelData(0);
for (var i = 0; i < n; ++i)
data[i] = 1;
return audioBuffer;
}
// The triangle buffer holds the expected result of the convolution. // It linearly ramps up from 0 to its maximum value (at the center) // then linearly ramps down to 0. The center value corresponds to the // point where the two square pulses overlap the most. function createTrianglePulseBuffer(context, sampleFrameLength) { var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
var n = audioBuffer.length; var halfLength = n / 2; var data = audioBuffer.getChannelData(0);
for (var i = 0; i < halfLength; ++i)
data[i] = i + 1;
for (var i = halfLength; i < n; ++i)
data[i] = n - i - 1;
return audioBuffer;
}
function log10(x) { return Math.log(x)/Math.LN10;
}
function linearToDecibel(x) { return 20*log10(x);
}
// Verify that the rendered result is very close to the reference // triangular pulse. function checkTriangularPulse(rendered, reference) { var match = true; var maxDelta = 0; var valueAtMaxDelta = 0; var maxDeltaIndex = 0;
for (var i = 0; i < reference.length; ++i) { var diff = rendered[i] - reference[i]; var x = Math.abs(diff); if (x > maxDelta) {
maxDelta = x;
valueAtMaxDelta = reference[i];
maxDeltaIndex = i;
}
}
// allowedDeviationFraction was determined experimentally. It // is the threshold of the relative error at the maximum // difference between the true triangular pulse and the // rendered pulse. var allowedDeviationDecibels = -129.4; var maxDeviationDecibels = linearToDecibel(maxDelta / valueAtMaxDelta);
if (maxDeviationDecibels <= allowedDeviationDecibels) {
testPassed("Triangular portion of convolution is correct.");
} else {
testFailed("Triangular portion of convolution is not correct. Max deviation = "+ maxDeviationDecibels + " dB at " + maxDeltaIndex);
match = false;
}
return match;
}
// Verify that the rendered data is close to zero for the first part // of the tail. function checkTail1(data, reference, breakpoint) { var isZero = true; var tail1Max = 0;
for (var i = reference.length; i < reference.length + breakpoint; ++i) { var mag = Math.abs(data[i]); if (mag > tail1Max) {
tail1Max = mag;
}
}
// Let's find the peak of the reference (even though we know a // priori what it is). var refMax = 0; for (var i = 0; i < reference.length; ++i) {
refMax = Math.max(refMax, Math.abs(reference[i]));
}
// This threshold is experimentally determined by examining the // value of tail1MaxDecibels. var threshold1 = -129.7;
var tail1MaxDecibels = linearToDecibel(tail1Max/refMax); if (tail1MaxDecibels <= threshold1) {
testPassed("First part of tail of convolution is sufficiently small.");
} else {
testFailed("First part of tail of convolution is not sufficiently small: " + tail1MaxDecibels + " dB");
isZero = false;
}
return isZero;
}
// Verify that the second part of the tail of the convolution is // exactly zero. function checkTail2(data, reference, breakpoint) { var isZero = true; var tail2Max = 0; // For the second part of the tail, the maximum value should be // exactly zero. var threshold2 = 0; for (var i = reference.length + breakpoint; i < data.length; ++i) { if (Math.abs(data[i]) > 0) {
isZero = false; break;
}
}
if (isZero) {
testPassed("Rendered signal after tail of convolution is silent.");
} else {
testFailed("Rendered signal after tail of convolution should be silent.");
}
return isZero;
}
function checkConvolvedResult(trianglePulse) { returnfunction(event) { var renderedBuffer = event.renderedBuffer;
var referenceData = trianglePulse.getChannelData(0); var renderedData = renderedBuffer.getChannelData(0);
var success = true;
// Verify the triangular pulse is actually triangular.
// Make sure that portion after convolved portion is totally // silent. But round-off prevents this from being completely // true. At the end of the triangle, it should be close to // zero. If we go farther out, it should be even closer and // eventually zero.
// For the tail of the convolution (where the result would be // theoretically zero), we partition the tail into two // parts. The first is the at the beginning of the tail, // where we tolerate a small but non-zero value. The second part is // farther along the tail where the result should be zero.
// breakpoint is the point dividing the first two tail parts // we're looking at. Experimentally determined. var breakpoint = 12800;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.