void UpdateSampleRateIfNeeded(AudioNodeStream* aStream, uint32_t aChannels)
  {
    if (mPlaybackRateTimeline.HasSimpleValue()) {
      mPlaybackRate = mPlaybackRateTimeline.GetValue();
    } else {
      mPlaybackRate = mPlaybackRateTimeline.GetValueAtTime(aStream->GetCurrentPosition());
    }

    // Make sure the playback rate and the doppler shift are something
    // our resampler can work with.
    if (ComputeFinalOutSampleRate(aStream->SampleRate()) == 0) {
      mPlaybackRate = 1.0;
      mDopplerShift = 1.0;
    }

    uint32_t currentOutSampleRate, currentInSampleRate;
    if (ShouldResample(aStream->SampleRate())) {
      SpeexResamplerState* resampler = Resampler(aStream, aChannels);
      speex_resampler_get_rate(resampler, &currentInSampleRate, &currentOutSampleRate);
      uint32_t finalSampleRate = ComputeFinalOutSampleRate(aStream->SampleRate());
      if (currentOutSampleRate != finalSampleRate) {
        speex_resampler_set_rate(resampler, currentInSampleRate, finalSampleRate);
      }
    }
  }
  /**
   * Copy as many frames as possible from the source buffer to aOutput, and
   * advance aOffsetWithinBlock and aCurrentPosition based on how many frames
   * we copy.  This will never advance aOffsetWithinBlock past
   * WEBAUDIO_BLOCK_SIZE, or aCurrentPosition past mStop.  It takes data from
   * the buffer at aBufferOffset, and never takes more data than aBufferMax.
   * This function knows when it needs to allocate the output buffer, and also
   * optimizes the case where it can avoid memory allocations.
   */
  void CopyFromBuffer(AudioNodeStream* aStream,
                      AudioChunk* aOutput,
                      uint32_t aChannels,
                      uint32_t* aOffsetWithinBlock,
                      TrackTicks* aCurrentPosition,
                      uint32_t aBufferOffset,
                      uint32_t aBufferMax)
  {
    MOZ_ASSERT(*aCurrentPosition < mStop);
    uint32_t numFrames =
      std::min<TrackTicks>(std::min(WEBAUDIO_BLOCK_SIZE - *aOffsetWithinBlock,
                                    aBufferMax - aBufferOffset),
                           mStop - *aCurrentPosition);
    if (numFrames == WEBAUDIO_BLOCK_SIZE && !ShouldResample(aStream->SampleRate())) {
      BorrowFromInputBuffer(aOutput, aChannels, aBufferOffset);
      *aOffsetWithinBlock += numFrames;
      *aCurrentPosition += numFrames;
      mPosition += numFrames;
    } else {
      if (aOutput->IsNull()) {
        MOZ_ASSERT(*aOffsetWithinBlock == 0);
        AllocateAudioBlock(aChannels, aOutput);
      }
      if (!ShouldResample(aStream->SampleRate())) {
        CopyFromInputBuffer(aOutput, aChannels, aBufferOffset, *aOffsetWithinBlock, numFrames);
        *aOffsetWithinBlock += numFrames;
        *aCurrentPosition += numFrames;
        mPosition += numFrames;
      } else {
        uint32_t framesRead, framesWritten, availableInInputBuffer;

        availableInInputBuffer = aBufferMax - aBufferOffset;

        CopyFromInputBufferWithResampling(aStream, aOutput, aChannels, aBufferOffset, *aOffsetWithinBlock, availableInInputBuffer, framesRead, framesWritten);
        *aOffsetWithinBlock += framesWritten;
        *aCurrentPosition += framesRead;
        mPosition += framesRead;
      }
    }
  }
Пример #3
0
 /**
  * Copy as many frames as possible from the source buffer to aOutput, and
  * advance aOffsetWithinBlock and aCurrentPosition based on how many frames
  * we write.  This will never advance aOffsetWithinBlock past
  * WEBAUDIO_BLOCK_SIZE, or aCurrentPosition past mStop.  It takes data from
  * the buffer at aBufferOffset, and never takes more data than aBufferMax.
  * This function knows when it needs to allocate the output buffer, and also
  * optimizes the case where it can avoid memory allocations.
  */
 void CopyFromBuffer(AudioNodeStream* aStream,
                     AudioChunk* aOutput,
                     uint32_t aChannels,
                     uint32_t* aOffsetWithinBlock,
                     TrackTicks* aCurrentPosition,
                     int32_t aBufferMax)
 {
   MOZ_ASSERT(*aCurrentPosition < mStop);
   uint32_t numFrames =
     std::min(std::min<TrackTicks>(WEBAUDIO_BLOCK_SIZE - *aOffsetWithinBlock,
                                   aBufferMax - mBufferPosition),
              mStop - *aCurrentPosition);
   if (numFrames == WEBAUDIO_BLOCK_SIZE && !ShouldResample(aStream->SampleRate())) {
     MOZ_ASSERT(mBufferPosition < aBufferMax);
     BorrowFromInputBuffer(aOutput, aChannels);
     *aOffsetWithinBlock += numFrames;
     *aCurrentPosition += numFrames;
     mBufferPosition += numFrames;
   } else {
     if (*aOffsetWithinBlock == 0) {
       AllocateAudioBlock(aChannels, aOutput);
     }
     if (!ShouldResample(aStream->SampleRate())) {
       MOZ_ASSERT(mBufferPosition < aBufferMax);
       CopyFromInputBuffer(aOutput, aChannels, *aOffsetWithinBlock, numFrames);
       *aOffsetWithinBlock += numFrames;
       *aCurrentPosition += numFrames;
       mBufferPosition += numFrames;
     } else {
       uint32_t framesWritten;
       CopyFromInputBufferWithResampling(aStream, aOutput, aChannels, *aOffsetWithinBlock, framesWritten, aBufferMax);
       *aOffsetWithinBlock += framesWritten;
       *aCurrentPosition += framesWritten;
     }
   }
 }