tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AudioMixer.h (3608B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef MOZILLA_AUDIOMIXER_H_
      7 #define MOZILLA_AUDIOMIXER_H_
      8 
      9 #include "AudioSampleFormat.h"
     10 #include "AudioSegment.h"
     11 #include "AudioStream.h"
     12 #include "mozilla/PodOperations.h"
     13 #include "nsTArray.h"
     14 
     15 namespace mozilla {
     16 
     17 struct MixerCallbackReceiver {
     18  // MixerCallback MAY modify aMixedBuffer but MUST clear
     19  // aMixedBuffer->mBuffer if its data is to live longer than the duration of
     20  // the callback.
     21  virtual void MixerCallback(AudioChunk* aMixedBuffer,
     22                             uint32_t aSampleRate) = 0;
     23 };
     24 /**
     25 * This class mixes multiple streams of audio together to output a single audio
     26 * stream.
     27 *
     28 * AudioMixer::Mix is to be called repeatedly with buffers that have the same
     29 * length, sample rate, sample format and channel count. This class works with
     30 * planar buffers.
     31 *
     32 * When all the tracks have been mixed, calling MixedChunk() will provide
     33 * a buffer containing the mixed audio data.
     34 *
     35 * This class is not thread safe.
     36 */
     37 class AudioMixer {
     38 public:
     39  AudioMixer() { mChunk.mBufferFormat = AUDIO_OUTPUT_FORMAT; }
     40 
     41  ~AudioMixer() = default;
     42 
     43  void StartMixing() {
     44    mChunk.mDuration = 0;
     45    mSampleRate = 0;
     46  }
     47 
     48  /* Get the data from the mixer. This is supposed to be called when all the
     49   * tracks have been mixed in. The caller MAY modify the chunk but MUST clear
     50   * mBuffer if its data needs to survive the next call to Mix(). */
     51  AudioChunk* MixedChunk() {
     52    MOZ_ASSERT(mSampleRate, "Mix not called for this cycle?");
     53    mSampleRate = 0;
     54    return &mChunk;
     55  };
     56 
     57  /* Add a buffer to the mix. The buffer can be null if there's nothing to mix
     58   * but the callback is still needed. */
     59  void Mix(AudioDataValue* aSamples, uint32_t aChannels, uint32_t aFrames,
     60           uint32_t aSampleRate) {
     61    if (!mChunk.mDuration) {
     62      mChunk.mDuration = aFrames;
     63      MOZ_ASSERT(aChannels > 0);
     64      mChunk.mChannelData.SetLength(aChannels);
     65      mSampleRate = aSampleRate;
     66      EnsureCapacityAndSilence();
     67    }
     68 
     69    MOZ_ASSERT(aFrames == mChunk.mDuration);
     70    MOZ_ASSERT(aChannels == mChunk.ChannelCount());
     71    MOZ_ASSERT(aSampleRate == mSampleRate);
     72 
     73    if (!aSamples) {
     74      return;
     75    }
     76 
     77    for (uint32_t i = 0; i < aFrames * aChannels; i++) {
     78      mChunk.ChannelDataForWrite<AudioDataValue>(0)[i] += aSamples[i];
     79    }
     80  }
     81 
     82 private:
     83  void EnsureCapacityAndSilence() {
     84    uint32_t sampleCount = mChunk.mDuration * mChunk.ChannelCount();
     85    if (!mChunk.mBuffer || sampleCount > mSampleCapacity) {
     86      CheckedInt<size_t> bufferSize(sizeof(AudioDataValue));
     87      bufferSize *= sampleCount;
     88      mChunk.mBuffer = SharedBuffer::Create(bufferSize);
     89      mSampleCapacity = sampleCount;
     90    }
     91    MOZ_ASSERT(!mChunk.mBuffer->IsShared());
     92    mChunk.mChannelData[0] =
     93        static_cast<SharedBuffer*>(mChunk.mBuffer.get())->Data();
     94    for (size_t i = 1; i < mChunk.ChannelCount(); ++i) {
     95      mChunk.mChannelData[i] =
     96          mChunk.ChannelData<AudioDataValue>()[0] + i * mChunk.mDuration;
     97    }
     98    PodZero(mChunk.ChannelDataForWrite<AudioDataValue>(0), sampleCount);
     99  }
    100 
    101  /* Buffer containing the mixed audio data. */
    102  AudioChunk mChunk;
    103  /* Size allocated for mChunk.mBuffer. */
    104  uint32_t mSampleCapacity = 0;
    105  /* Sample rate the of the mixed data. */
    106  uint32_t mSampleRate = 0;
    107 };
    108 
    109 }  // namespace mozilla
    110 
    111 #endif  // MOZILLA_AUDIOMIXER_H_