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..7e9423e9dba7e823034eca403f3fecd6bc29f2a7 |
| --- /dev/null |
| +++ b/third_party/WebKit/LayoutTests/webaudio/resources/mixing-rules.js |
| @@ -0,0 +1,343 @@ |
| +// 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 {Number} numberOfChannels Number of channels of test buffer. |
|
Raymond Toy
2016/03/08 18:04:06
If you're going to document the code this way, don
hongchan
2016/03/08 23:53:34
Done.
|
| + * @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; |
| +} |
| + |
| +/** |
| + * Stringify AudioBuffer content with options. |
|
Raymond Toy
2016/03/08 18:04:07
Not obvious how you want to stringify the AudioBuf
hongchan
2016/03/08 23:53:35
Done.
|
| + * @param {AudioBuffer} audioBuffer AudioBuffer object to stringify. |
|
Raymond Toy
2016/03/08 18:04:07
The other parameters/outputs have the description
hongchan
2016/03/08 23:53:34
Done.
|
| + * @param {Number} frameLength Length to print. |
| + * @param {Number} frameOffset Offset frames to print. |
|
Raymond Toy
2016/03/08 18:04:07
This description of frameOffset doesn't really say
hongchan
2016/03/08 23:53:34
Done.
|
| + * @return {String} Assembled string for printing. |
| + */ |
| +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; |
| +} |
| + |
| +/** |
| + * Computer number of channels from the connection. |
|
Raymond Toy
2016/03/08 18:04:06
Typo: "Computer" -> "Compute"
hongchan
2016/03/08 23:53:35
Done.
|
| + * @param {String} connections A string specifies the connection. The |
| + * string "128" means 3 connections, having |
|
Raymond Toy
2016/03/08 18:04:06
Description doesn't line up with the rest of the d
hongchan
2016/03/08 23:53:34
Done.
|
| + * 1, 2, and 8 channels respectively. |
| + * @param {Number} channelCount Channel count. |
| + * @param {String} channelCountMode Channel count mode. |
| + * @return {Number} A computed number of channels. |
|
Raymond Toy
2016/03/08 18:04:06
A link to the spec would be nice. I can never reme
hongchan
2016/03/08 23:53:35
URL is at the top of this file, and I don't think
Raymond Toy
2016/03/08 23:56:54
That link is for the mixing rules. This function
hongchan
2016/03/09 19:34:24
It does not have a separate section, but a definit
|
| + */ |
| +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 rules based on 'speaker' interpretation. |
| + * @param {AudioBuffer} source Source audio buffer. |
| + * @param {AudioBuffer} destination Destination audio buffer. |
| + */ |
| +function speakersSum(source, destination) { |
| + if (source.length != destination.length) |
| + throw "[mixing-rules.js] speakerSum(): buffer lengths mismatch"; |
|
Raymond Toy
2016/03/08 18:04:06
Since you know the lengths, print them out in the
hongchan
2016/03/08 23:53:35
Done.
|
| + |
| + if (source.numberOfChannels === destination.numberOfChannels) { |
| + for (var channel = 0; channel < destination.numberOfChannels; ++channel) { |
| + var sourceChannel = source.getChannelData(channel); |
| + var destinationChannel = destination.getChannelData(channel); |
| + for (var i = 0; i < destinationChannel.length; i++) |
| + destinationChannel[i] += sourceChannel[i]; |
| + } |
| + |
| + return; |
| + } |
| + |
| + if (source.numberOfChannels < destination.numberOfChannels) |
|
Raymond Toy
2016/03/08 18:04:07
I find this style confusing. I think it's clearer
hongchan
2016/03/08 23:53:34
Done.
|
| + processUpMix(source, destination); |
| + else |
| + processDownMix(source, destination); |
| +} |
| + |
| +/** |
| + * Discrete channel interpretation mixing. |
| + * @param {AudioBuffer} source Source audio buffer. |
| + * @param {AudioBuffer} destination Destination audio buffer. |
|
Raymond Toy
2016/03/08 18:04:07
Since nothing is returned, I suggest saying that t
hongchan
2016/03/08 23:53:34
Done.
|
| + */ |
| +function discreteSum(source, destination) { |
| + if (source.length != destination.length) |
| + throw "[mixing-rules.js] discreteSum(): buffer lengths mismatch"; |
|
Raymond Toy
2016/03/08 18:04:06
Give lengths in message.
hongchan
2016/03/08 23:53:35
Done.
|
| + |
| + var numberOfChannels = source.numberOfChannels < destination.numberOfChannels |
| + ? source.numberOfChannels |
| + : destination.numberOfChannels; |
|
Raymond Toy
2016/03/08 18:04:07
numberOfChannels = Math.min(source.numberOfChannel
hongchan
2016/03/08 23:53:34
Done. I was following the original test code - but
|
| + |
| + for (var channel = 0; channel < numberOfChannels; ++channel) { |
| + var sourceChannel = source.getChannelData(channel); |
| + var destinationChannel = destination.getChannelData(channel); |
| + for (var i = 0; i < destinationChannel.length; i++) |
| + destinationChannel[i] += sourceChannel[i]; |
| + } |
| +} |
| + |
| +/** |
| + * Process up-mix. |
| + * @param {AudioBuffer} source Source audio buffer. |
| + * @param {AudioBuffer} destination Destination audio buffer. |
|
Raymond Toy
2016/03/08 18:04:07
Say that the destination is modified.
hongchan
2016/03/08 23:53:35
Done.
|
| + */ |
| +function processUpMix(source, destination) { |
| + var numberOfSourceChannels = source.numberOfChannels; |
| + var numberOfDestinationChannels = destination.numberOfChannels; |
| + var i, length = destination.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) |
|
Raymond Toy
2016/03/08 18:04:06
Make comment notation match code notation more clo
hongchan
2016/03/08 23:53:35
Done.
|
| + if ((numberOfSourceChannels === 1 && numberOfDestinationChannels === 2) || |
| + (numberOfSourceChannels === 1 && numberOfDestinationChannels === 4)) { |
| + var sourceChannel = source.getChannelData(0); |
| + var destinationChannel0 = destination.getChannelData(0); |
| + var destinationChannel1 = destination.getChannelData(1); |
| + for (i = 0; i < length; i++) { |
| + destinationChannel0[i] += sourceChannel[i]; |
|
Raymond Toy
2016/03/08 18:04:06
This doesn't match the comment. You're summing the
hongchan
2016/03/08 23:53:34
Done.
|
| + destinationChannel1[i] += sourceChannel[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 (numberOfSourceChannels == 1 && numberOfDestinationChannels == 6) { |
| + var sourceChannel = source.getChannelData(0); |
| + var destinationChannel2 = destination.getChannelData(2); |
| + for (i = 0; i < length; i++) |
| + destinationChannel2[i] += sourceChannel[i]; |
|
Raymond Toy
2016/03/08 18:04:06
Again, this doesn't match the comment. Update com
hongchan
2016/03/08 23:53:34
Done.
|
| + |
| + 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 ((numberOfSourceChannels === 2 && numberOfDestinationChannels === 4) || |
| + (numberOfSourceChannels === 2 && numberOfDestinationChannels === 6)) { |
| + var sourceChannel0 = source.getChannelData(0); |
| + var sourceChannel1 = source.getChannelData(1); |
| + var destinationChannel0 = destination.getChannelData(0); |
| + var destinationChannel1 = destination.getChannelData(1); |
| + for (i = 0; i < length; i++) { |
| + destinationChannel0[i] += sourceChannel0[i]; |
| + destinationChannel1[i] += sourceChannel1[i]; |
|
Raymond Toy
2016/03/08 18:04:07
Again, this doesn't match the comment. Update com
hongchan
2016/03/08 23:53:35
Done.
|
| + } |
| + |
| + 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 (numberOfSourceChannels === 4 && numberOfDestinationChannels === 6) { |
| + var sourceChannel0 = source.getChannelData(0); |
| + var sourceChannel1 = source.getChannelData(1); |
| + var sourceChannel2 = source.getChannelData(2); |
| + var sourceChannel3 = source.getChannelData(3); |
| + var destinationChannel0 = destination.getChannelData(0); |
| + var destinationChannel1 = destination.getChannelData(1); |
| + var destinationChannel4 = destination.getChannelData(4); |
| + var destinationChannel5 = destination.getChannelData(5); |
| + for (i = 0; i < length; i++) { |
| + destinationChannel0[i] += sourceChannel0[i]; |
| + destinationChannel1[i] += sourceChannel1[i]; |
| + destinationChannel4[i] += sourceChannel2[i]; |
| + destinationChannel5[i] += sourceChannel3[i]; |
| + } |
| + |
| + return; |
| + } |
| + |
| + // All other cases, fall back to the discrete sum. |
| + discreteSum(source, destination); |
| +} |
| + |
| +/** |
| + * Process down-mix from source to destination by summing into the existing data. |
| + * @param {AudioBuffer} source Source audio buffer. |
| + * @param {AudioBuffer} destination Destination audio buffer. |
| + */ |
| +function processDownMix(source, destination) { |
| + var numberOfSourceChannels = source.numberOfChannels; |
| + var numberOfDestinationChannels = destination.numberOfChannels; |
| + var i, length = destination.length; |
| + |
| + // Down-mixing: 2 -> 1 |
| + // output = 0.5 * (input.L + input.R) |
| + if (numberOfSourceChannels === 2 && numberOfDestinationChannels === 1) { |
| + var sourceChannel0 = source.getChannelData(0); |
| + var sourceChannel1 = source.getChannelData(1); |
| + var destinationChannel0 = destination.getChannelData(0); |
| + for (i = 0; i < length; i++) |
| + destinationChannel0[i] += 0.5 * (sourceChannel0[i] + sourceChannel1[i]); |
|
Raymond Toy
2016/03/08 18:04:07
Again, this doesn't match the comment. Update com
hongchan
2016/03/08 23:53:35
Done.
|
| + |
| + return; |
| + } |
| + |
| + // Down-mixing: 4 -> 1 |
| + // output = 0.25 * (input.L + input.R + input.SL + input.SR) |
| + if (numberOfSourceChannels === 4 && numberOfDestinationChannels === 1) { |
| + var sourceChannel0 = source.getChannelData(0); |
| + var sourceChannel1 = source.getChannelData(1); |
| + var sourceChannel2 = source.getChannelData(2); |
| + var sourceChannel3 = source.getChannelData(3); |
| + var destinationChannel0 = destination.getChannelData(0); |
| + for (i = 0; i < length; i++) { |
| + destinationChannel0[i] += 0.25 * (sourceChannel0[i] + sourceChannel1[i] |
|
Raymond Toy
2016/03/08 18:04:07
Again, this doesn't match the comment. Update com
hongchan
2016/03/08 23:53:35
Done.
|
| + + sourceChannel2[i] + sourceChannel3[i]); |
| + } |
| + |
| + return; |
| + } |
| + |
| + // Down-mixing: 5.1 -> 1 |
| + // output = sqrt(1/2) * (input.L + input.R) + input.C |
| + // + 0.5 * (input.SL + input.SR) |
| + if (numberOfSourceChannels === 6 && numberOfDestinationChannels === 1) { |
| + var sourceChannel0 = source.getChannelData(0); |
| + var sourceChannel1 = source.getChannelData(1); |
| + var sourceChannel2 = source.getChannelData(2); |
| + var sourceChannel4 = source.getChannelData(4); |
| + var sourceChannel5 = source.getChannelData(5); |
| + var destinationChannel0 = destination.getChannelData(0); |
| + var scaleSqrtHalf = Math.sqrt(0.5); |
| + for (i = 0; i < length; i++) { |
| + destinationChannel0[i] += |
|
Raymond Toy
2016/03/08 18:04:07
This doesn't match the comment. Update comment or
hongchan
2016/03/08 23:53:34
Done.
|
| + scaleSqrtHalf * (sourceChannel0[i] + sourceChannel1[i]) |
| + + sourceChannel2[i] + 0.5 * (sourceChannel4[i] + sourceChannel5[i]); |
| + } |
| + |
| + return; |
| + } |
| + |
| + // Down-mixing: 4 -> 2 |
| + // output.L = 0.5 * (input.L + input.SL) |
| + // output.R = 0.5 * (input.R + input.SR) |
| + if (numberOfSourceChannels == 4 && numberOfDestinationChannels == 2) { |
| + var sourceChannel0 = source.getChannelData(0); |
|
Raymond Toy
2016/03/08 18:04:07
Probably want to say how sourceChannel<n> is assig
hongchan
2016/03/08 23:53:34
Done.
|
| + var sourceChannel1 = source.getChannelData(1); |
| + var sourceChannel2 = source.getChannelData(2); |
| + var sourceChannel3 = source.getChannelData(3); |
| + var destinationChannel0 = destination.getChannelData(0); |
| + var destinationChannel1 = destination.getChannelData(1); |
| + for (i = 0; i < length; i++) { |
| + destinationChannel0[i] += 0.5 * (sourceChannel0[i] + sourceChannel2[i]); |
| + destinationChannel1[i] += 0.5 * (sourceChannel1[i] + sourceChannel3[i]); |
|
Raymond Toy
2016/03/08 18:04:07
This doesn't match the comment. Update comment or
hongchan
2016/03/08 23:53:35
Done.
|
| + } |
| + |
| + 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 (numberOfSourceChannels == 6 && numberOfDestinationChannels == 2) { |
| + var sourceChannel0 = source.getChannelData(0); |
| + var sourceChannel1 = source.getChannelData(1); |
| + var sourceChannel2 = source.getChannelData(2); |
| + var sourceChannel4 = source.getChannelData(4); |
| + var sourceChannel5 = source.getChannelData(5); |
| + var destinationChannel0 = destination.getChannelData(0); |
| + var destinationChannel1 = destination.getChannelData(1); |
| + var scaleSqrtHalf = Math.sqrt(0.5); |
| + for (i = 0; i < length; i++) { |
| + destinationChannel0[i] += sourceChannel0[i] |
| + + scaleSqrtHalf * (sourceChannel2[i] + sourceChannel4[i]); |
| + destinationChannel1[i] += sourceChannel1[i] |
| + + scaleSqrtHalf * (sourceChannel2[i] + sourceChannel5[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 (numberOfSourceChannels === 6 && numberOfDestinationChannels === 4) { |
| + var sourceChannel0 = source.getChannelData(0); |
| + var sourceChannel1 = source.getChannelData(1); |
| + var sourceChannel2 = source.getChannelData(2); |
| + var sourceChannel4 = source.getChannelData(4); |
| + var sourceChannel5 = source.getChannelData(5); |
| + var destinationChannel0 = destination.getChannelData(0); |
| + var destinationChannel1 = destination.getChannelData(1); |
| + var destinationChannel2 = destination.getChannelData(2); |
| + var destinationChannel3 = destination.getChannelData(3); |
| + var scaleSqrtHalf = Math.sqrt(0.5); |
| + for (i = 0; i < length; i++) { |
| + destinationChannel0[i] += sourceChannel0[i] + scaleSqrtHalf * sourceChannel2[i]; |
| + destinationChannel1[i] += sourceChannel1[i] + scaleSqrtHalf * sourceChannel2[i]; |
| + destinationChannel2[i] += sourceChannel4[i]; |
| + destinationChannel3[i] += sourceChannel5[i]; |
| + } |
| + |
| + return; |
| + } |
| + |
| + // All other cases, fall back to the discrete sum. |
| + discreteSum(source, destination); |
| +} |