bug 1391482 accept int16_t sample buffers in AudioBufferSourceNode r?padenot draft
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 10 Aug 2017 17:26:40 +1200
changeset 654726 64e97b5a17940a8eb592fb8ebb72cf2f931d1e13
parent 654725 0e52651ed2f86512e2b4ba3a3f364150cdd44d78
child 654727 6eeb02b9289db7d4d9a661746ba672bc861fcb82
push id76658
push userktomlinson@mozilla.com
push dateTue, 29 Aug 2017 06:20:42 +0000
reviewerspadenot
bugs1391482
milestone57.0a1
bug 1391482 accept int16_t sample buffers in AudioBufferSourceNode r?padenot MozReview-Commit-ID: I2gCBQdfOEx
dom/media/webaudio/AudioBufferSourceNode.cpp
--- a/dom/media/webaudio/AudioBufferSourceNode.cpp
+++ b/dom/media/webaudio/AudioBufferSourceNode.cpp
@@ -222,26 +222,28 @@ public:
         mBuffer.ChannelData<float>()[i] + mBufferPosition;
     }
     aOutput->mVolume = mBuffer.mVolume;
     aOutput->mBufferFormat = AUDIO_FORMAT_FLOAT32;
   }
 
   // Copy aNumberOfFrames frames from the source buffer at offset aSourceOffset
   // and put it at offset aBufferOffset in the destination buffer.
-  void CopyFromInputBuffer(AudioBlock* aOutput,
-                           uint32_t aChannels,
-                           uintptr_t aOffsetWithinBlock,
-                           uint32_t aNumberOfFrames) {
+  template <typename T> void
+  CopyFromInputBuffer(AudioBlock* aOutput,
+                      uint32_t aChannels,
+                      uintptr_t aOffsetWithinBlock,
+                      uint32_t aNumberOfFrames)
+  {
     MOZ_ASSERT(mBuffer.mVolume == 1.0f);
     for (uint32_t i = 0; i < aChannels; ++i) {
       float* baseChannelData = aOutput->ChannelFloatsForWrite(i);
-      memcpy(baseChannelData + aOffsetWithinBlock,
-             mBuffer.ChannelData<float>()[i] + mBufferPosition,
-             aNumberOfFrames * sizeof(float));
+      ConvertAudioSamples(mBuffer.ChannelData<T>()[i] + mBufferPosition,
+                          baseChannelData + aOffsetWithinBlock,
+                          aNumberOfFrames);
     }
   }
 
   // Resamples input data to an output buffer, according to |mBufferSampleRate| and
   // the playbackRate/detune.
   // The number of frames consumed/produced depends on the amount of space
   // remaining in both the input and output buffer, and the playback rate (that
   // is, the ratio between the output samplerate and the input samplerate).
@@ -290,26 +292,35 @@ public:
 
         mBeginProcessing = -STREAM_TIME_MAX;
       }
       inputLimit = std::min(inputLimit, availableInInputBuffer);
 
       MOZ_ASSERT(mBuffer.mVolume == 1.0f);
       for (uint32_t i = 0; true; ) {
         uint32_t inSamples = inputLimit;
-        const float* inputData =
-          mBuffer.ChannelData<float>()[i] + mBufferPosition;
 
         uint32_t outSamples = aAvailableInOutput;
         float* outputData =
           aOutput->ChannelFloatsForWrite(i) + *aOffsetWithinBlock;
 
-        WebAudioUtils::SpeexResamplerProcess(resampler, i,
-                                             inputData, &inSamples,
-                                             outputData, &outSamples);
+        if (mBuffer.mBufferFormat == AUDIO_FORMAT_FLOAT32) {
+          const float* inputData =
+            mBuffer.ChannelData<float>()[i] + mBufferPosition;
+          WebAudioUtils::SpeexResamplerProcess(resampler, i,
+                                               inputData, &inSamples,
+                                               outputData, &outSamples);
+        } else {
+          MOZ_ASSERT(mBuffer.mBufferFormat == AUDIO_FORMAT_S16);
+          const int16_t* inputData =
+            mBuffer.ChannelData<int16_t>()[i] + mBufferPosition;
+          WebAudioUtils::SpeexResamplerProcess(resampler, i,
+                                               inputData, &inSamples,
+                                               outputData, &outSamples);
+        }
         if (++i == aChannels) {
           mBufferPosition += inSamples;
           MOZ_ASSERT(mBufferPosition <= mBufferEnd || mLoop);
           *aOffsetWithinBlock += outSamples;
           *aCurrentPosition += outSamples;
           if (inSamples == availableInInputBuffer && !mLoop) {
             // We'll feed in enough zeros to empty out the resampler's memory.
             // This handles the output latency as well as capturing the low
@@ -417,32 +428,42 @@ public:
         mBufferSampleRate / mResamplerOutRate;
       mBufferPosition += end - start;
       return;
     }
 
     uint32_t numFrames = std::min(aBufferMax - mBufferPosition,
                                   availableInOutput);
 
-    bool inputBufferAligned = true;
-    for (uint32_t i = 0; i < aChannels; ++i) {
-      if (!IS_ALIGNED16(mBuffer.ChannelData<float>()[i] + mBufferPosition)) {
-        inputBufferAligned = false;
+    bool shouldBorrow = false;
+    if (numFrames == WEBAUDIO_BLOCK_SIZE &&
+        mBuffer.mBufferFormat == AUDIO_FORMAT_FLOAT32) {
+      shouldBorrow = true;
+      for (uint32_t i = 0; i < aChannels; ++i) {
+        if (!IS_ALIGNED16(mBuffer.ChannelData<float>()[i] + mBufferPosition)) {
+          shouldBorrow = false;
+          break;
+        }
       }
     }
-
-    if (numFrames == WEBAUDIO_BLOCK_SIZE && inputBufferAligned) {
-      MOZ_ASSERT(mBufferPosition < aBufferMax);
+    MOZ_ASSERT(mBufferPosition < aBufferMax);
+    if (shouldBorrow) {
       BorrowFromInputBuffer(aOutput, aChannels);
     } else {
       if (*aOffsetWithinBlock == 0) {
         aOutput->AllocateChannels(aChannels);
       }
-      MOZ_ASSERT(mBufferPosition < aBufferMax);
-      CopyFromInputBuffer(aOutput, aChannels, *aOffsetWithinBlock, numFrames);
+      if (mBuffer.mBufferFormat == AUDIO_FORMAT_FLOAT32) {
+        CopyFromInputBuffer<float>(aOutput, aChannels,
+                                   *aOffsetWithinBlock, numFrames);
+      } else {
+        MOZ_ASSERT(mBuffer.mBufferFormat == AUDIO_FORMAT_S16);
+        CopyFromInputBuffer<int16_t>(aOutput, aChannels,
+                                     *aOffsetWithinBlock, numFrames);
+      }
     }
     *aOffsetWithinBlock += numFrames;
     *aCurrentPosition += numFrames;
     mBufferPosition += numFrames;
   }
 
   int32_t ComputeFinalOutSampleRate(float aPlaybackRate, float aDetune)
   {