// Time step when each panner node starts. var timeStep = 0.001;
// Length of the impulse signal. var pulseLengthFrames = Math.round(timeStep * sampleRate);
// How many panner nodes to create for the test var nodesToCreate = 100;
// Be sure we render long enough for all of our nodes. var renderLengthSeconds = timeStep * (nodesToCreate + 1);
// These are global mostly for debugging. var context; var impulse; var bufferSource; var panner; var position; var time;
var renderedBuffer; var renderedLeft; var renderedRight;
function createGraph(context, nodeCount) {
bufferSource = new Array(nodeCount);
panner = new Array(nodeCount);
position = new Array(nodeCount);
time = new Array(nodeCount); // Angle between panner locations. (nodeCount - 1 because we want // to include both 0 and 180 deg. var angleStep = Math.PI / (nodeCount - 1);
// Map our position angle to the azimuth angle (in degrees). // // An angle of 0 corresponds to an azimuth of 90 deg; pi, to -90 deg. function angleToAzimuth(angle) { return 90 - angle * 180 / Math.PI;
}
// The gain caused by the EQUALPOWER panning model function equalPowerGain(angle) { var azimuth = angleToAzimuth(angle);
if (numberOfChannels == 1) { var panPosition = (azimuth + 90) / 180;
var gainL = Math.cos(0.5 * Math.PI * panPosition); var gainR = Math.sin(0.5 * Math.PI * panPosition);
return { left : gainL, right : gainR };
} else { if (azimuth <= 0) { var panPosition = (azimuth + 90) / 90;
var gainL = 1 + Math.cos(0.5 * Math.PI * panPosition); var gainR = Math.sin(0.5 * Math.PI * panPosition);
return { left : gainL, right : gainR };
} else { var panPosition = azimuth / 90;
var gainL = Math.cos(0.5 * Math.PI * panPosition); var gainR = 1 + Math.sin(0.5 * Math.PI * panPosition);
// 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. var maxAllowedError = 1.3e-6;
var success = true;
// Number of impulses found in the rendered result. var impulseCount = 0;
// Max (relative) error and the index of the maxima for the left // and right channels. var maxErrorL = 0; var maxErrorIndexL = 0; var maxErrorR = 0; var maxErrorIndexR = 0;
// Number of impulses that don't match our expected locations. var timeCount = 0;
// Locations of where the impulses aren't at the expected locations. var timeErrors = new Array();
for (var k = 0; k < renderedLeft.length; ++k) { // We assume that the left and right channels start at the same instant. if (renderedLeft[k] != 0 || renderedRight[k] != 0) { // The expected gain for the left and right channels. var pannerGain = equalPowerGain(position[impulseCount].angle); var expectedL = pannerGain.left; var expectedR = pannerGain.right;
// Absolute error in the gain. var errorL = Math.abs(renderedLeft[k] - expectedL); var errorR = Math.abs(renderedRight[k] - expectedR);
// Keep track of the impulses that didn't show up where we // expected them to be. var expectedOffset = timeToSampleFrame(time[impulseCount], sampleRate); if (k != expectedOffset) {
timeErrors[timeCount] = { actual : k, expected : expectedOffset};
++timeCount;
}
++impulseCount;
}
}
if (impulseCount == nodesToCreate) {
testPassed("Number of impulses matches the number of panner nodes.");
} else {
testFailed("Number of impulses is incorrect. (Found " + impulseCount + " but expected " + nodesToCreate + ")");
success = false;
}
if (timeErrors.length > 0) {
success = false;
testFailed(timeErrors.length + " timing errors found in " + nodesToCreate + " panner nodes."); for (var k = 0; k < timeErrors.length; ++k) {
testFailed("Impulse at sample " + timeErrors[k].actual + " but expected " + timeErrors[k].expected);
}
} else {
testPassed("All impulses at expected offsets.");
}
if (maxErrorL <= maxAllowedError) {
testPassed("Left channel gain values are correct.");
} else {
testFailed("Left channel gain values are incorrect. Max error = " + maxErrorL + " at time " + time[maxErrorIndexL] + " (threshold = " + maxAllowedError + ")");
success = false;
}
if (maxErrorR <= maxAllowedError) {
testPassed("Right channel gain values are correct.");
} else {
testFailed("Right channel gain values are incorrect. Max error = " + maxErrorR + " at time " + time[maxErrorIndexR] + " (threshold = " + maxAllowedError + ")");
success = false;
}
if (success) {
testPassed("EqualPower panner test passed");
} else {
testFailed("EqualPower panner test failed");
}
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.