Chromium Code Reviews| Index: third_party/WebKit/LayoutTests/webaudio/resources/mixing-rules.js |
| diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/mixing-rules.js b/third_party/WebKit/LayoutTests/webaudio/resources/mixing-rules.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4d434869586781bfd486d3116aa3096fa7c42463 |
| --- /dev/null |
| +++ b/third_party/WebKit/LayoutTests/webaudio/resources/mixing-rules.js |
| @@ -0,0 +1,345 @@ |
| +// 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) { |
| + var shiftedImpulseBuffer = context.createBuffer(numberOfChannels, frameLength, context.sampleRate); |
| + for (var channel = 0; channel < numberOfChannels; ++channel) { |
| + var data = shiftedImpulseBuffer.getChannelData(channel); |
| + data[channel] = 1; |
| + } |
| + |
| + return shiftedImpulseBuffer; |
| +} |
| + |
| +/** |
| + * Create a string displays the content of AudioBuffer. |
|
Raymond Toy
2016/03/09 22:14:19
"string displays" -> "string that displays"
hongchan
2016/03/09 23:26:11
Done.
|
| + * @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); |
| + |
| + var stringifiedBuffer = ''; |
| + for (var channel = 0; channel < audioBuffer.numberOfChannels; ++channel) { |
| + var channelData = audioBuffer.getChannelData(channel); |
| + for (var i = 0; i < frameLength; ++i) |
| + stringifiedBuffer += channelData[i + frameOffset] + ' '; |
| + stringifiedBuffer += '\n'; |
| + } |
| + |
| + return stringifiedBuffer; |
| +} |
| + |
| +/** |
| + * Compute number of channels from the connection. |
| + * @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. |
| + var computedNumberOfChannels = 1; |
| + |
| + // Compute "computedNumberOfChannels" based on all the connections. |
| + for (var i = 0; i < connections.length; ++i) { |
| + var 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 (var channel = 0; channel < output.numberOfChannels; ++channel) { |
| + var inputChannel = input.getChannelData(channel); |
| + var outputChannel = output.getChannelData(channel); |
| + for (var 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 + ')'; |
| + } |
| + |
| + var numberOfChannels = Math.min(input.numberOfChannels, output.numberOfChannels) |
| + |
| + for (var channel = 0; channel < numberOfChannels; ++channel) { |
| + var inputChannel = input.getChannelData(channel); |
| + var outputChannel = output.getChannelData(channel); |
| + for (var i = 0; i < outputChannel.length; i++) |
| + outputChannel[i] += inputChannel[i]; |
| + } |
| +} |
| + |
| +/** |
| + * Perform up-mix by in-place summing to |output| buffer. |
|
Raymond Toy
2016/03/09 22:14:19
For consistency, you probably want to add this com
hongchan
2016/03/09 23:26:11
Done.
|
| + * @param {AudioBuffer} input Input audio buffer. |
| + * @param {AudioBuffer} output Output audio buffer. |
| + */ |
| +function processUpMix(input, output) { |
| + var numberOfInputChannels = input.numberOfChannels; |
| + var numberOfOutputChannels = output.numberOfChannels; |
| + var 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)) { |
| + var inputChannel = input.getChannelData(0); |
| + var outputChannel0 = output.getChannelData(0); |
| + var 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) { |
| + var inputChannel = input.getChannelData(0); |
| + var 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)) { |
| + var inputChannel0 = input.getChannelData(0); |
| + var inputChannel1 = input.getChannelData(1); |
| + var outputChannel0 = output.getChannelData(0); |
| + var 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) { |
| + var inputChannel0 = input.getChannelData(0); // input.L |
| + var inputChannel1 = input.getChannelData(1); // input.R |
| + var inputChannel2 = input.getChannelData(2); // input.SL |
| + var inputChannel3 = input.getChannelData(3); // input.SR |
| + var outputChannel0 = output.getChannelData(0); // output.L |
| + var outputChannel1 = output.getChannelData(1); // output.R |
| + var outputChannel4 = output.getChannelData(4); // output.SL |
| + var 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); |
| +} |
| + |
| +/** |
| + * Process down-mix from source to destination by summing into the existing data. |
| + * @param {AudioBuffer} input Input audio buffer. |
| + * @param {AudioBuffer} output Output audio buffer. |
| + */ |
| +function processDownMix(input, output) { |
| + var numberOfInputChannels = input.numberOfChannels; |
| + var numberOfOutputChannels = output.numberOfChannels; |
| + var i, length = output.length; |
| + |
| + // Down-mixing: 2 -> 1 |
| + // output += 0.5 * (input.L + input.R) |
| + if (numberOfInputChannels === 2 && numberOfOutputChannels === 1) { |
| + var inputChannel0 = input.getChannelData(0); // input.L |
| + var inputChannel1 = input.getChannelData(1); // input.R |
| + var 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) { |
| + var inputChannel0 = input.getChannelData(0); // input.L |
| + var inputChannel1 = input.getChannelData(1); // input.R |
| + var inputChannel2 = input.getChannelData(2); // input.SL |
| + var inputChannel3 = input.getChannelData(3); // input.SR |
| + var 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) { |
| + var inputChannel0 = input.getChannelData(0); // input.L |
| + var inputChannel1 = input.getChannelData(1); // input.R |
| + var inputChannel2 = input.getChannelData(2); // input.C |
| + var inputChannel4 = input.getChannelData(4); // input.SL |
| + var inputChannel5 = input.getChannelData(5); // input.SR |
| + var outputChannel0 = output.getChannelData(0); |
| + var 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) { |
| + var inputChannel0 = input.getChannelData(0); // input.L |
| + var inputChannel1 = input.getChannelData(1); // input.R |
| + var inputChannel2 = input.getChannelData(2); // input.SL |
| + var inputChannel3 = input.getChannelData(3); // input.SR |
| + var outputChannel0 = output.getChannelData(0); // output.L |
| + var 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) { |
| + var inputChannel0 = input.getChannelData(0); // input.L |
| + var inputChannel1 = input.getChannelData(1); // input.R |
| + var inputChannel2 = input.getChannelData(2); // input.C |
| + var inputChannel4 = input.getChannelData(4); // input.SL |
| + var inputChannel5 = input.getChannelData(5); // input.SR |
| + var outputChannel0 = output.getChannelData(0); // output.L |
| + var outputChannel1 = output.getChannelData(1); // output.R |
| + var 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) { |
| + var inputChannel0 = input.getChannelData(0); // input.L |
| + var inputChannel1 = input.getChannelData(1); // input.R |
| + var inputChannel2 = input.getChannelData(2); // input.C |
| + var inputChannel4 = input.getChannelData(4); // input.SL |
| + var inputChannel5 = input.getChannelData(5); // input.SR |
| + var outputChannel0 = output.getChannelData(0); // output.L |
| + var outputChannel1 = output.getChannelData(1); // output.R |
| + var outputChannel2 = output.getChannelData(2); // output.SL |
| + var outputChannel3 = output.getChannelData(3); // output.SR |
| + var 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); |
| +} |