Bug 868855 - Respect the input's volume in ChannelMergerNode and ChannelSplitterNode; r=roc
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 06 May 2013 14:30:47 -0400
changeset 141991 e64c20f04597d15322eac6516ff9f15f743a11c3
parent 141990 75c66fa0109eb60b867adeabe3047796563c0bf2
child 141992 b8f086ab97aa3dc3f10931e0295d237264456593
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs868855
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 868855 - Respect the input's volume in ChannelMergerNode and ChannelSplitterNode; r=roc
content/media/webaudio/ChannelMergerNode.cpp
content/media/webaudio/ChannelSplitterNode.cpp
content/media/webaudio/test/Makefile.in
content/media/webaudio/test/test_channelMergerNodeWithVolume.html
content/media/webaudio/test/test_channelSplitterNodeWithVolume.html
--- a/content/media/webaudio/ChannelMergerNode.cpp
+++ b/content/media/webaudio/ChannelMergerNode.cpp
@@ -41,19 +41,20 @@ public:
       return;
     }
     AllocateAudioBlock(channelCount, &aOutput[0]);
 
     // Append each channel in each input to the output
     uint32_t channelIndex = 0;
     for (uint16_t i = 0; i < InputCount(); ++i) {
       for (uint32_t j = 0; j < aInput[i].mChannelData.Length(); ++j) {
-        PodCopy(static_cast<float*>(const_cast<void*>(aOutput[0].mChannelData[channelIndex])),
-                static_cast<const float*>(aInput[i].mChannelData[j]),
-                WEBAUDIO_BLOCK_SIZE);
+        AudioBlockCopyChannelWithScale(
+            static_cast<const float*>(aInput[i].mChannelData[j]),
+            aInput[i].mVolume,
+            static_cast<float*>(const_cast<void*>(aOutput[0].mChannelData[channelIndex])));
         ++channelIndex;
       }
     }
   }
 };
 
 ChannelMergerNode::ChannelMergerNode(AudioContext* aContext,
                                      uint16_t aInputCount)
--- a/content/media/webaudio/ChannelSplitterNode.cpp
+++ b/content/media/webaudio/ChannelSplitterNode.cpp
@@ -31,19 +31,20 @@ public:
   {
     MOZ_ASSERT(aInput.Length() == 1, "Should only have one input port");
 
     aOutput.SetLength(OutputCount());
     for (uint16_t i = 0; i < OutputCount(); ++i) {
       if (i < aInput[0].mChannelData.Length()) {
         // Split out existing channels
         AllocateAudioBlock(1, &aOutput[i]);
-        PodCopy(static_cast<float*>(const_cast<void*>(aOutput[i].mChannelData[0])),
-                static_cast<const float*>(aInput[0].mChannelData[i]),
-                WEBAUDIO_BLOCK_SIZE);
+        AudioBlockCopyChannelWithScale(
+            static_cast<const float*>(aInput[0].mChannelData[i]),
+            aInput[0].mVolume,
+            static_cast<float*>(const_cast<void*>(aOutput[i].mChannelData[0])));
       } else {
         // Pad with silent channels if needed
         aOutput[i].SetNull(WEBAUDIO_BLOCK_SIZE);
       }
     }
   }
 };
 
--- a/content/media/webaudio/test/Makefile.in
+++ b/content/media/webaudio/test/Makefile.in
@@ -33,17 +33,19 @@ MOCHITEST_FILES := \
   test_audioBufferSourceNodeLazyLoopParam.html \
   test_audioBufferSourceNodeLoop.html \
   test_audioBufferSourceNodeLoopStartEnd.html \
   test_audioBufferSourceNodeLoopStartEndSame.html \
   test_audioBufferSourceNodeNullBuffer.html \
   test_badConnect.html \
   test_biquadFilterNode.html \
   test_channelMergerNode.html \
+  test_channelMergerNodeWithVolume.html \
   test_channelSplitterNode.html \
+  test_channelSplitterNodeWithVolume.html \
   test_currentTime.html \
   test_delayNode.html \
   test_delayNodeWithGain.html \
   test_dynamicsCompressorNode.html \
   test_gainNode.html \
   test_mediaDecoding.html \
   test_mixingRules.html \
   test_nodeToParamConnection.html \
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_channelMergerNodeWithVolume.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test ChannelMergerNode</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="webaudio.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+  SpecialPowers.setBoolPref("media.webaudio.enabled", true);
+
+  var context = new AudioContext();
+  var buffers = [];
+  var expectedBuffers = [];
+  for (var j = 0; j < 4; ++j) {
+    var buffer = context.createBuffer(2, 2048, context.sampleRate);
+    var expectedBuffer = context.createBuffer(2, 2048, context.sampleRate);
+    for (var i = 0; i < 2048; ++i) {
+      buffer.getChannelData(0)[i] = Math.sin(440 * 2 * (j + 1) * Math.PI * i / context.sampleRate);
+      expectedBuffer.getChannelData(0)[i] = buffer.getChannelData(0)[i] / 2;
+      // Second channel is silent
+    }
+    buffers.push(buffer);
+    expectedBuffers.push(expectedBuffer);
+  }
+  var emptyBuffer = context.createBuffer(1, 2048, context.sampleRate);
+
+  var destination = context.destination;
+
+  var merger = context.createChannelMerger();
+  is(merger.channelCount, 2, "merger node has 2 input channels by default");
+  is(merger.channelCountMode, "max", "Correct channelCountMode for the merger node");
+  is(merger.channelInterpretation, "speakers", "Correct channelCountInterpretation for the merger node");
+
+  for (var i = 0; i < 4; ++i) {
+    var source = context.createBufferSource();
+    source.buffer = buffers[i];
+    var gain = context.createGain();
+    gain.gain.value = 0.5;
+    source.connect(gain);
+    gain.connect(merger, 0, i);
+    source.start(0);
+  }
+
+  var sp = context.createScriptProcessor(2048, 8);
+  merger.connect(sp);
+  sp.connect(destination);
+
+  sp.onaudioprocess = function(e) {
+    is(e.inputBuffer.numberOfChannels, 8, "Correct input channel count");
+    for (var i = 0; i < 4; ++i) {
+      compareBuffers(e.inputBuffer.getChannelData(i * 2), expectedBuffers[i].getChannelData(0));
+      compareBuffers(e.inputBuffer.getChannelData(i * 2 + 1), emptyBuffer.getChannelData(0));
+    }
+
+    sp.onaudioprocess = null;
+
+    SpecialPowers.clearUserPref("media.webaudio.enabled");
+    SimpleTest.finish();
+  };
+});
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_channelSplitterNodeWithVolume.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test ChannelSplitterNode</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="webaudio.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+  SpecialPowers.setBoolPref("media.webaudio.enabled", true);
+
+  var context = new AudioContext();
+  var buffer = context.createBuffer(4, 2048, context.sampleRate);
+  var expectedBuffer = context.createBuffer(4, 2048, context.sampleRate);
+  for (var j = 0; j < 4; ++j) {
+    for (var i = 0; i < 2048; ++i) {
+      buffer.getChannelData(j)[i] = Math.sin(440 * 2 * (j + 1) * Math.PI * i / context.sampleRate);
+      expectedBuffer.getChannelData(j)[i] = buffer.getChannelData(j)[i] / 2;
+    }
+  }
+  var emptyBuffer = context.createBuffer(1, 2048, context.sampleRate);
+
+  var destination = context.destination;
+
+  var source = context.createBufferSource();
+
+  var splitter = context.createChannelSplitter();
+  is(splitter.channelCount, 2, "splitter node has 2 input channels by default");
+  is(splitter.channelCountMode, "max", "Correct channelCountMode for the splitter node");
+  is(splitter.channelInterpretation, "speakers", "Correct channelCountInterpretation for the splitter node");
+
+  source.buffer = buffer;
+  var gain = context.createGain();
+  gain.gain.value = 0.5;
+  source.connect(gain);
+  gain.connect(splitter);
+
+  var channelsSeen = 0;
+  function createHandler(i) {
+    return function(e) {
+      is(e.inputBuffer.numberOfChannels, 1, "Correct input channel count");
+      if (i < 4) {
+        compareBuffers(e.inputBuffer.getChannelData(0), expectedBuffer.getChannelData(i));
+      } else {
+        compareBuffers(e.inputBuffer.getChannelData(0), emptyBuffer.getChannelData(0));
+      }
+      e.target.onaudioprocess = null;
+      ++channelsSeen;
+
+      if (channelsSeen == 6) {
+        SpecialPowers.clearUserPref("media.webaudio.enabled");
+        SimpleTest.finish();
+      }
+    };
+  }
+
+  for (var i = 0; i < 6; ++i) {
+    var sp = context.createScriptProcessor(2048, 1);
+    splitter.connect(sp, i);
+    sp.onaudioprocess = createHandler(i);
+    sp.connect(destination);
+  }
+
+  source.start(0);
+});
+
+</script>
+</pre>
+</body>
+</html>