diff options
Diffstat (limited to 'testing/web-platform/tests/webaudio/resources/mixing-rules.js')
-rw-r--r-- | testing/web-platform/tests/webaudio/resources/mixing-rules.js | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webaudio/resources/mixing-rules.js b/testing/web-platform/tests/webaudio/resources/mixing-rules.js new file mode 100644 index 0000000000..e06a1468a3 --- /dev/null +++ b/testing/web-platform/tests/webaudio/resources/mixing-rules.js @@ -0,0 +1,350 @@ +// Utilities for mixing rule testing. +// http://webaudio.github.io/web-audio-api/#channel-up-mixing-and-down-mixing + + +/** + * Create an n-channel buffer, with all sample data zero except for a shifted + * impulse. The impulse position depends on the channel index. For example, for + * a 4-channel buffer: + * channel 0: 1 0 0 0 0 0 0 0 + * channel 1: 0 1 0 0 0 0 0 0 + * channel 2: 0 0 1 0 0 0 0 0 + * channel 3: 0 0 0 1 0 0 0 0 + * @param {AudioContext} context Associated AudioContext. + * @param {Number} numberOfChannels Number of channels of test buffer. + * @param {Number} frameLength Buffer length in frames. + * @return {AudioBuffer} + */ +function createShiftedImpulseBuffer(context, numberOfChannels, frameLength) { + let shiftedImpulseBuffer = + context.createBuffer(numberOfChannels, frameLength, context.sampleRate); + for (let channel = 0; channel < numberOfChannels; ++channel) { + let data = shiftedImpulseBuffer.getChannelData(channel); + data[channel] = 1; + } + + return shiftedImpulseBuffer; +} + +/** + * Create a string that displays the content of AudioBuffer. + * @param {AudioBuffer} audioBuffer AudioBuffer object to stringify. + * @param {Number} frameLength Number of frames to be printed. + * @param {Number} frameOffset Starting frame position for printing. + * @return {String} + */ +function stringifyBuffer(audioBuffer, frameLength, frameOffset) { + frameOffset = (frameOffset || 0); + + let stringifiedBuffer = ''; + for (let channel = 0; channel < audioBuffer.numberOfChannels; ++channel) { + let channelData = audioBuffer.getChannelData(channel); + for (let i = 0; i < frameLength; ++i) + stringifiedBuffer += channelData[i + frameOffset] + ' '; + stringifiedBuffer += '\n'; + } + + return stringifiedBuffer; +} + +/** + * Compute number of channels from the connection. + * http://webaudio.github.io/web-audio-api/#dfn-computednumberofchannels + * @param {String} connections A string specifies the connection. For + * example, the string "128" means 3 + * connections, having 1, 2, and 8 channels + * respectively. + * @param {Number} channelCount Channel count. + * @param {String} channelCountMode Channel count mode. + * @return {Number} Computed number of channels. + */ +function computeNumberOfChannels(connections, channelCount, channelCountMode) { + if (channelCountMode == 'explicit') + return channelCount; + + // Must have at least one channel. + let computedNumberOfChannels = 1; + + // Compute "computedNumberOfChannels" based on all the connections. + for (let i = 0; i < connections.length; ++i) { + let connectionNumberOfChannels = parseInt(connections[i]); + computedNumberOfChannels = + Math.max(computedNumberOfChannels, connectionNumberOfChannels); + } + + if (channelCountMode == 'clamped-max') + computedNumberOfChannels = Math.min(computedNumberOfChannels, channelCount); + + return computedNumberOfChannels; +} + +/** + * Apply up/down-mixing (in-place summing) based on 'speaker' interpretation. + * @param {AudioBuffer} input Input audio buffer. + * @param {AudioBuffer} output Output audio buffer. + */ +function speakersSum(input, output) { + if (input.length != output.length) { + throw '[mixing-rules.js] speakerSum(): buffer lengths mismatch (input: ' + + input.length + ', output: ' + output.length + ')'; + } + + if (input.numberOfChannels === output.numberOfChannels) { + for (let channel = 0; channel < output.numberOfChannels; ++channel) { + let inputChannel = input.getChannelData(channel); + let outputChannel = output.getChannelData(channel); + for (let i = 0; i < outputChannel.length; i++) + outputChannel[i] += inputChannel[i]; + } + } else if (input.numberOfChannels < output.numberOfChannels) { + processUpMix(input, output); + } else { + processDownMix(input, output); + } +} + +/** + * In-place summing to |output| based on 'discrete' channel interpretation. + * @param {AudioBuffer} input Input audio buffer. + * @param {AudioBuffer} output Output audio buffer. + */ +function discreteSum(input, output) { + if (input.length != output.length) { + throw '[mixing-rules.js] speakerSum(): buffer lengths mismatch (input: ' + + input.length + ', output: ' + output.length + ')'; + } + + let numberOfChannels = + Math.min(input.numberOfChannels, output.numberOfChannels) + + for (let channel = 0; channel < numberOfChannels; ++channel) { + let inputChannel = input.getChannelData(channel); + let outputChannel = output.getChannelData(channel); + for (let i = 0; i < outputChannel.length; i++) + outputChannel[i] += inputChannel[i]; + } +} + +/** + * Perform up-mix by in-place summing to |output| buffer. + * @param {AudioBuffer} input Input audio buffer. + * @param {AudioBuffer} output Output audio buffer. + */ +function processUpMix(input, output) { + let numberOfInputChannels = input.numberOfChannels; + let numberOfOutputChannels = output.numberOfChannels; + let i, length = output.length; + + // Up-mixing: 1 -> 2, 1 -> 4 + // output.L += input + // output.R += input + // output.SL += 0 (in the case of 1 -> 4) + // output.SR += 0 (in the case of 1 -> 4) + if ((numberOfInputChannels === 1 && numberOfOutputChannels === 2) || + (numberOfInputChannels === 1 && numberOfOutputChannels === 4)) { + let inputChannel = input.getChannelData(0); + let outputChannel0 = output.getChannelData(0); + let outputChannel1 = output.getChannelData(1); + for (i = 0; i < length; i++) { + outputChannel0[i] += inputChannel[i]; + outputChannel1[i] += inputChannel[i]; + } + + return; + } + + // Up-mixing: 1 -> 5.1 + // output.L += 0 + // output.R += 0 + // output.C += input + // output.LFE += 0 + // output.SL += 0 + // output.SR += 0 + if (numberOfInputChannels == 1 && numberOfOutputChannels == 6) { + let inputChannel = input.getChannelData(0); + let outputChannel2 = output.getChannelData(2); + for (i = 0; i < length; i++) + outputChannel2[i] += inputChannel[i]; + + return; + } + + // Up-mixing: 2 -> 4, 2 -> 5.1 + // output.L += input.L + // output.R += input.R + // output.C += 0 (in the case of 2 -> 5.1) + // output.LFE += 0 (in the case of 2 -> 5.1) + // output.SL += 0 + // output.SR += 0 + if ((numberOfInputChannels === 2 && numberOfOutputChannels === 4) || + (numberOfInputChannels === 2 && numberOfOutputChannels === 6)) { + let inputChannel0 = input.getChannelData(0); + let inputChannel1 = input.getChannelData(1); + let outputChannel0 = output.getChannelData(0); + let outputChannel1 = output.getChannelData(1); + for (i = 0; i < length; i++) { + outputChannel0[i] += inputChannel0[i]; + outputChannel1[i] += inputChannel1[i]; + } + + return; + } + + // Up-mixing: 4 -> 5.1 + // output.L += input.L + // output.R += input.R + // output.C += 0 + // output.LFE += 0 + // output.SL += input.SL + // output.SR += input.SR + if (numberOfInputChannels === 4 && numberOfOutputChannels === 6) { + let inputChannel0 = input.getChannelData(0); // input.L + let inputChannel1 = input.getChannelData(1); // input.R + let inputChannel2 = input.getChannelData(2); // input.SL + let inputChannel3 = input.getChannelData(3); // input.SR + let outputChannel0 = output.getChannelData(0); // output.L + let outputChannel1 = output.getChannelData(1); // output.R + let outputChannel4 = output.getChannelData(4); // output.SL + let outputChannel5 = output.getChannelData(5); // output.SR + for (i = 0; i < length; i++) { + outputChannel0[i] += inputChannel0[i]; + outputChannel1[i] += inputChannel1[i]; + outputChannel4[i] += inputChannel2[i]; + outputChannel5[i] += inputChannel3[i]; + } + + return; + } + + // All other cases, fall back to the discrete sum. + discreteSum(input, output); +} + +/** + * Perform down-mix by in-place summing to |output| buffer. + * @param {AudioBuffer} input Input audio buffer. + * @param {AudioBuffer} output Output audio buffer. + */ +function processDownMix(input, output) { + let numberOfInputChannels = input.numberOfChannels; + let numberOfOutputChannels = output.numberOfChannels; + let i, length = output.length; + + // Down-mixing: 2 -> 1 + // output += 0.5 * (input.L + input.R) + if (numberOfInputChannels === 2 && numberOfOutputChannels === 1) { + let inputChannel0 = input.getChannelData(0); // input.L + let inputChannel1 = input.getChannelData(1); // input.R + let outputChannel0 = output.getChannelData(0); + for (i = 0; i < length; i++) + outputChannel0[i] += 0.5 * (inputChannel0[i] + inputChannel1[i]); + + return; + } + + // Down-mixing: 4 -> 1 + // output += 0.25 * (input.L + input.R + input.SL + input.SR) + if (numberOfInputChannels === 4 && numberOfOutputChannels === 1) { + let inputChannel0 = input.getChannelData(0); // input.L + let inputChannel1 = input.getChannelData(1); // input.R + let inputChannel2 = input.getChannelData(2); // input.SL + let inputChannel3 = input.getChannelData(3); // input.SR + let outputChannel0 = output.getChannelData(0); + for (i = 0; i < length; i++) { + outputChannel0[i] += 0.25 * + (inputChannel0[i] + inputChannel1[i] + inputChannel2[i] + + inputChannel3[i]); + } + + return; + } + + // Down-mixing: 5.1 -> 1 + // output += sqrt(1/2) * (input.L + input.R) + input.C + // + 0.5 * (input.SL + input.SR) + if (numberOfInputChannels === 6 && numberOfOutputChannels === 1) { + let inputChannel0 = input.getChannelData(0); // input.L + let inputChannel1 = input.getChannelData(1); // input.R + let inputChannel2 = input.getChannelData(2); // input.C + let inputChannel4 = input.getChannelData(4); // input.SL + let inputChannel5 = input.getChannelData(5); // input.SR + let outputChannel0 = output.getChannelData(0); + let scaleSqrtHalf = Math.sqrt(0.5); + for (i = 0; i < length; i++) { + outputChannel0[i] += + scaleSqrtHalf * (inputChannel0[i] + inputChannel1[i]) + + inputChannel2[i] + 0.5 * (inputChannel4[i] + inputChannel5[i]); + } + + return; + } + + // Down-mixing: 4 -> 2 + // output.L += 0.5 * (input.L + input.SL) + // output.R += 0.5 * (input.R + input.SR) + if (numberOfInputChannels == 4 && numberOfOutputChannels == 2) { + let inputChannel0 = input.getChannelData(0); // input.L + let inputChannel1 = input.getChannelData(1); // input.R + let inputChannel2 = input.getChannelData(2); // input.SL + let inputChannel3 = input.getChannelData(3); // input.SR + let outputChannel0 = output.getChannelData(0); // output.L + let outputChannel1 = output.getChannelData(1); // output.R + for (i = 0; i < length; i++) { + outputChannel0[i] += 0.5 * (inputChannel0[i] + inputChannel2[i]); + outputChannel1[i] += 0.5 * (inputChannel1[i] + inputChannel3[i]); + } + + return; + } + + // Down-mixing: 5.1 -> 2 + // output.L += input.L + sqrt(1/2) * (input.C + input.SL) + // output.R += input.R + sqrt(1/2) * (input.C + input.SR) + if (numberOfInputChannels == 6 && numberOfOutputChannels == 2) { + let inputChannel0 = input.getChannelData(0); // input.L + let inputChannel1 = input.getChannelData(1); // input.R + let inputChannel2 = input.getChannelData(2); // input.C + let inputChannel4 = input.getChannelData(4); // input.SL + let inputChannel5 = input.getChannelData(5); // input.SR + let outputChannel0 = output.getChannelData(0); // output.L + let outputChannel1 = output.getChannelData(1); // output.R + let scaleSqrtHalf = Math.sqrt(0.5); + for (i = 0; i < length; i++) { + outputChannel0[i] += inputChannel0[i] + + scaleSqrtHalf * (inputChannel2[i] + inputChannel4[i]); + outputChannel1[i] += inputChannel1[i] + + scaleSqrtHalf * (inputChannel2[i] + inputChannel5[i]); + } + + return; + } + + // Down-mixing: 5.1 -> 4 + // output.L += input.L + sqrt(1/2) * input.C + // output.R += input.R + sqrt(1/2) * input.C + // output.SL += input.SL + // output.SR += input.SR + if (numberOfInputChannels === 6 && numberOfOutputChannels === 4) { + let inputChannel0 = input.getChannelData(0); // input.L + let inputChannel1 = input.getChannelData(1); // input.R + let inputChannel2 = input.getChannelData(2); // input.C + let inputChannel4 = input.getChannelData(4); // input.SL + let inputChannel5 = input.getChannelData(5); // input.SR + let outputChannel0 = output.getChannelData(0); // output.L + let outputChannel1 = output.getChannelData(1); // output.R + let outputChannel2 = output.getChannelData(2); // output.SL + let outputChannel3 = output.getChannelData(3); // output.SR + let scaleSqrtHalf = Math.sqrt(0.5); + for (i = 0; i < length; i++) { + outputChannel0[i] += inputChannel0[i] + scaleSqrtHalf * inputChannel2[i]; + outputChannel1[i] += inputChannel1[i] + scaleSqrtHalf * inputChannel2[i]; + outputChannel2[i] += inputChannel4[i]; + outputChannel3[i] += inputChannel5[i]; + } + + return; + } + + // All other cases, fall back to the discrete sum. + discreteSum(input, output); +} |