bug 1201854 handle stop time precisely even when resampling r=padenot
authorKarl Tomlinson <karlt+@karlt.net>
Fri, 04 Sep 2015 22:05:49 +1200
changeset 294150 253dc0ad68e639adddc7ff16f41d58b178394d19
parent 294149 d2b08c513afec90c82d2ba13cd0085f46ff42f4c
child 294151 c0d655ae3cb5c7c15c6ea45174e6882c0bd36195
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1201854
milestone43.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 1201854 handle stop time precisely even when resampling r=padenot
dom/media/webaudio/AudioBufferSourceNode.cpp
--- a/dom/media/webaudio/AudioBufferSourceNode.cpp
+++ b/dom/media/webaudio/AudioBufferSourceNode.cpp
@@ -217,33 +217,31 @@ public:
   // 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).
   void CopyFromInputBufferWithResampling(AudioNodeStream* aStream,
                                          AudioBlock* aOutput,
                                          uint32_t aChannels,
                                          uint32_t* aOffsetWithinBlock,
+                                         uint32_t aAvailableInOutput,
                                          StreamTime* aCurrentPosition,
                                          int32_t aBufferMax) {
-    // TODO: adjust for mStop (see bug 913854 comment 9).
-    uint32_t availableInOutputBuffer =
-      WEBAUDIO_BLOCK_SIZE - *aOffsetWithinBlock;
     SpeexResamplerState* resampler = mResampler;
     MOZ_ASSERT(aChannels > 0);
 
     if (mBufferPosition < aBufferMax) {
       uint32_t availableInInputBuffer = aBufferMax - mBufferPosition;
       uint32_t ratioNum, ratioDen;
       speex_resampler_get_ratio(resampler, &ratioNum, &ratioDen);
       // Limit the number of input samples copied and possibly
       // format-converted for resampling by estimating how many will be used.
       // This may be a little small if still filling the resampler with
       // initial data, but we'll get called again and it will work out.
-      uint32_t inputLimit = availableInOutputBuffer * ratioNum / ratioDen + 10;
+      uint32_t inputLimit = aAvailableInOutput * ratioNum / ratioDen + 10;
       if (!BegunResampling()) {
         // First time the resampler is used.
         uint32_t inputLatency = speex_resampler_get_input_latency(resampler);
         inputLimit += inputLatency;
         // If starting after mStart, then play from the beginning of the
         // buffer, but correct for input latency.  If starting before mStart,
         // then align the resampler so that the time corresponding to the
         // first input sample is mStart.
@@ -260,17 +258,17 @@ public:
         mBeginProcessing = -STREAM_TIME_MAX;
       }
       inputLimit = std::min(inputLimit, availableInInputBuffer);
 
       for (uint32_t i = 0; true; ) {
         uint32_t inSamples = inputLimit;
         const float* inputData = mBuffer->GetData(i) + mBufferPosition;
 
-        uint32_t outSamples = availableInOutputBuffer;
+        uint32_t outSamples = aAvailableInOutput;
         float* outputData =
           aOutput->ChannelFloatsForWrite(i) + *aOffsetWithinBlock;
 
         WebAudioUtils::SpeexResamplerProcess(resampler, i,
                                              inputData, &inSamples,
                                              outputData, &outSamples);
         if (++i == aChannels) {
           mBufferPosition += inSamples;
@@ -285,17 +283,17 @@ public:
               2 * speex_resampler_get_input_latency(resampler) - 1;
           }
           return;
         }
       }
     } else {
       for (uint32_t i = 0; true; ) {
         uint32_t inSamples = mRemainingResamplerTail;
-        uint32_t outSamples = availableInOutputBuffer;
+        uint32_t outSamples = aAvailableInOutput;
         float* outputData =
           aOutput->ChannelFloatsForWrite(i) + *aOffsetWithinBlock;
 
         // AudioDataValue* for aIn selects the function that does not try to
         // copy and format-convert input data.
         WebAudioUtils::SpeexResamplerProcess(resampler, i,
                          static_cast<AudioDataValue*>(nullptr), &inSamples,
                          outputData, &outSamples);
@@ -352,20 +350,21 @@ public:
   void CopyFromBuffer(AudioNodeStream* aStream,
                       AudioBlock* aOutput,
                       uint32_t aChannels,
                       uint32_t* aOffsetWithinBlock,
                       StreamTime* aCurrentPosition,
                       int32_t aBufferMax)
   {
     MOZ_ASSERT(*aCurrentPosition < mStop);
-    uint32_t numFrames =
-      std::min(std::min<StreamTime>(WEBAUDIO_BLOCK_SIZE - *aOffsetWithinBlock,
-                                    aBufferMax - mBufferPosition),
-               mStop - *aCurrentPosition);
+    uint32_t availableInOutput =
+      std::min<StreamTime>(WEBAUDIO_BLOCK_SIZE - *aOffsetWithinBlock,
+                           mStop - *aCurrentPosition);
+    uint32_t numFrames = std::min<uint32_t>(aBufferMax - mBufferPosition,
+                                            availableInOutput);
     if (numFrames == WEBAUDIO_BLOCK_SIZE && !mResampler) {
       MOZ_ASSERT(mBufferPosition < aBufferMax);
       BorrowFromInputBuffer(aOutput, aChannels);
       *aOffsetWithinBlock += numFrames;
       *aCurrentPosition += numFrames;
       mBufferPosition += numFrames;
     } else {
       if (*aOffsetWithinBlock == 0) {
@@ -373,17 +372,19 @@ public:
       }
       if (!mResampler) {
         MOZ_ASSERT(mBufferPosition < aBufferMax);
         CopyFromInputBuffer(aOutput, aChannels, *aOffsetWithinBlock, numFrames);
         *aOffsetWithinBlock += numFrames;
         *aCurrentPosition += numFrames;
         mBufferPosition += numFrames;
       } else {
-        CopyFromInputBufferWithResampling(aStream, aOutput, aChannels, aOffsetWithinBlock, aCurrentPosition, aBufferMax);
+        CopyFromInputBufferWithResampling(aStream, aOutput, aChannels,
+                                          aOffsetWithinBlock, availableInOutput,
+                                          aCurrentPosition, aBufferMax);
       }
     }
   }
 
   int32_t ComputeFinalOutSampleRate(float aPlaybackRate, float aDetune)
   {
     float computedPlaybackRate = aPlaybackRate * pow(2, aDetune / 1200.f);
     // Make sure the playback rate and the doppler shift are something