tor-browser

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

AudioRingBuffer.cpp (20409B)


      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 #include "AudioRingBuffer.h"
      7 
      8 #include "MediaData.h"
      9 #include "mozilla/Assertions.h"
     10 #include "mozilla/Maybe.h"
     11 #include "mozilla/PodOperations.h"
     12 
     13 namespace mozilla {
     14 
     15 /**
     16 * RingBuffer is used to preallocate a buffer of a specific size in bytes and
     17 * then to use it for writing and reading values without requiring re-allocation
     18 * or memory moving. Note that re-allocations can happen if the length of the
     19 * buffer is explicitly set to something larger than is already allocated.
     20 * Also note that the total byte size of the buffer modulo the size of the
     21 * chosen type must be zero. The RingBuffer has been created with audio sample
     22 * values types in mind which are integer or float. However, it can be used with
     23 * any trivial type. It is _not_ thread-safe! The constructor can be called on
     24 * any thread but the reads and write must happen on the same thread, which can
     25 * be different than the construction thread.
     26 */
     27 template <typename T>
     28 class RingBuffer final {
     29 public:
     30  explicit RingBuffer(AlignedByteBuffer&& aMemoryBuffer)
     31      : mStorage(ConvertToSpan(aMemoryBuffer)),
     32        mMemoryBuffer(std::move(aMemoryBuffer)) {
     33    MOZ_ASSERT(std::is_trivial<T>::value);
     34  }
     35 
     36  /**
     37   * Write `aSamples` number of zeros in the buffer, before any existing data.
     38   */
     39  uint32_t PrependSilence(uint32_t aSamples) {
     40    MOZ_ASSERT(aSamples);
     41    return Prepend(Span<T>(), aSamples);
     42  }
     43 
     44  /**
     45   * Write `aSamples` number of zeros in the buffer.
     46   */
     47  uint32_t WriteSilence(uint32_t aSamples) {
     48    MOZ_ASSERT(aSamples);
     49    return Write(Span<T>(), aSamples);
     50  }
     51 
     52  /**
     53   * Copy `aBuffer` to the RingBuffer.
     54   */
     55  uint32_t Write(const Span<const T>& aBuffer) {
     56    MOZ_ASSERT(!aBuffer.IsEmpty());
     57    return Write(aBuffer, aBuffer.Length());
     58  }
     59 
     60 private:
     61  /**
     62   * Copy `aSamples` number of elements from `aBuffer` to the beginning of the
     63   * RingBuffer. If `aBuffer` is empty prepend `aSamples` of zeros.
     64   */
     65  uint32_t Prepend(const Span<const T>& aBuffer, uint32_t aSamples) {
     66    MOZ_ASSERT(aSamples > 0);
     67    MOZ_ASSERT(aBuffer.IsEmpty() || aBuffer.Length() == aSamples);
     68 
     69    if (IsFull()) {
     70      return 0;
     71    }
     72 
     73    uint32_t toWrite = std::min(AvailableWrite(), aSamples);
     74    uint32_t part2 = std::min(mReadIndex, toWrite);
     75    uint32_t part1 = toWrite - part2;
     76 
     77    Span<T> part2Buffer = mStorage.Subspan(mReadIndex - part2, part2);
     78    Span<T> part1Buffer = mStorage.Subspan(Capacity() - part1, part1);
     79 
     80    if (!aBuffer.IsEmpty()) {
     81      Span<const T> fromPart1 = aBuffer.To(part1);
     82      Span<const T> fromPart2 = aBuffer.Subspan(part1, part2);
     83 
     84      CopySpan(part1Buffer, fromPart1);
     85      CopySpan(part2Buffer, fromPart2);
     86    } else {
     87      // aBuffer is empty, prepend zeros.
     88      PodZero(part1Buffer.Elements(), part1Buffer.Length());
     89      PodZero(part2Buffer.Elements(), part2Buffer.Length());
     90    }
     91 
     92    mReadIndex = NextIndex(mReadIndex, Capacity() - toWrite);
     93 
     94    return toWrite;
     95  }
     96 
     97  /**
     98   * Copy `aSamples` number of elements from `aBuffer` to the RingBuffer. If
     99   * `aBuffer` is empty append `aSamples` of zeros.
    100   */
    101  uint32_t Write(const Span<const T>& aBuffer, uint32_t aSamples) {
    102    MOZ_ASSERT(aSamples > 0);
    103    MOZ_ASSERT(aBuffer.IsEmpty() || aBuffer.Length() == aSamples);
    104 
    105    if (IsFull()) {
    106      return 0;
    107    }
    108 
    109    uint32_t toWrite = std::min(AvailableWrite(), aSamples);
    110    uint32_t part1 = std::min(Capacity() - mWriteIndex, toWrite);
    111    uint32_t part2 = toWrite - part1;
    112 
    113    Span<T> part1Buffer = mStorage.Subspan(mWriteIndex, part1);
    114    Span<T> part2Buffer = mStorage.To(part2);
    115 
    116    if (!aBuffer.IsEmpty()) {
    117      Span<const T> fromPart1 = aBuffer.To(part1);
    118      Span<const T> fromPart2 = aBuffer.Subspan(part1, part2);
    119 
    120      CopySpan(part1Buffer, fromPart1);
    121      CopySpan(part2Buffer, fromPart2);
    122    } else {
    123      // The aBuffer is empty, append zeros.
    124      PodZero(part1Buffer.Elements(), part1Buffer.Length());
    125      PodZero(part2Buffer.Elements(), part2Buffer.Length());
    126    }
    127 
    128    mWriteIndex = NextIndex(mWriteIndex, toWrite);
    129 
    130    return toWrite;
    131  }
    132 
    133 public:
    134  /**
    135   * Copy `aSamples` number of elements from `aBuffer` to the RingBuffer. The
    136   * `aBuffer` does not change.
    137   */
    138  uint32_t Write(const RingBuffer& aBuffer, uint32_t aSamples) {
    139    MOZ_ASSERT(aSamples);
    140 
    141    if (IsFull()) {
    142      return 0;
    143    }
    144 
    145    uint32_t toWriteThis = std::min(AvailableWrite(), aSamples);
    146    uint32_t toReadThat = std::min(aBuffer.AvailableRead(), toWriteThis);
    147    uint32_t part1 =
    148        std::min(aBuffer.Capacity() - aBuffer.mReadIndex, toReadThat);
    149    uint32_t part2 = toReadThat - part1;
    150 
    151    Span<T> part1Buffer = aBuffer.mStorage.Subspan(aBuffer.mReadIndex, part1);
    152    DebugOnly<uint32_t> ret = Write(part1Buffer);
    153    MOZ_ASSERT(ret == part1);
    154    if (part2) {
    155      Span<T> part2Buffer = aBuffer.mStorage.To(part2);
    156      ret = Write(part2Buffer);
    157      MOZ_ASSERT(ret == part2);
    158    }
    159 
    160    return toReadThat;
    161  }
    162 
    163  /**
    164   * Copy `aBuffer.Length()` number of elements from RingBuffer to `aBuffer`.
    165   */
    166  uint32_t Read(const Span<T>& aBuffer) {
    167    MOZ_ASSERT(!aBuffer.IsEmpty());
    168    MOZ_ASSERT(aBuffer.size() <= std::numeric_limits<uint32_t>::max());
    169 
    170    if (IsEmpty()) {
    171      return 0;
    172    }
    173 
    174    uint32_t toRead = std::min<uint32_t>(AvailableRead(), aBuffer.Length());
    175    uint32_t part1 = std::min(Capacity() - mReadIndex, toRead);
    176    uint32_t part2 = toRead - part1;
    177 
    178    Span<T> part1Buffer = mStorage.Subspan(mReadIndex, part1);
    179    Span<T> part2Buffer = mStorage.To(part2);
    180 
    181    Span<T> toPart1 = aBuffer.To(part1);
    182    Span<T> toPart2 = aBuffer.Subspan(part1, part2);
    183 
    184    CopySpan(toPart1, part1Buffer);
    185    CopySpan(toPart2, part2Buffer);
    186 
    187    mReadIndex = NextIndex(mReadIndex, toRead);
    188 
    189    return toRead;
    190  }
    191 
    192  /**
    193   * Provide `aCallable` that will be called with the internal linear read
    194   * buffers and the number of samples available for reading. The `aCallable`
    195   * will be called at most 2 times. The `aCallable` must return the number of
    196   * samples that have been actually read. If that number is smaller than the
    197   * available number of samples, provided in the argument, the `aCallable` will
    198   * not be called again. The RingBuffer's available read samples will be
    199   * decreased by the number returned from the `aCallable`.
    200   *
    201   * The important aspects of this method are that first, it makes it possible
    202   * to avoid extra copies to an intermediates buffer, and second, each buffer
    203   * provided to `aCallable is a linear piece of memory which can be used
    204   * directly to a resampler for example.
    205   *
    206   * In general, the problem with ring buffers is that they cannot provide one
    207   * linear chunk of memory so extra copies, to a linear buffer, are often
    208   * needed. This method bridge that gap by breaking the ring buffer's
    209   * internal read memory into linear pieces and making it available through
    210   * the `aCallable`. In the body of the `aCallable` those buffers can be used
    211   * directly without any copy or intermediate steps.
    212   */
    213  uint32_t ReadNoCopy(
    214      std::function<uint32_t(const Span<const T>&)>&& aCallable) {
    215    if (IsEmpty()) {
    216      return 0;
    217    }
    218 
    219    uint32_t part1 = std::min(Capacity() - mReadIndex, AvailableRead());
    220    uint32_t part2 = AvailableRead() - part1;
    221 
    222    Span<T> part1Buffer = mStorage.Subspan(mReadIndex, part1);
    223    uint32_t toRead = aCallable(part1Buffer);
    224    MOZ_ASSERT(toRead <= part1);
    225 
    226    if (toRead == part1 && part2) {
    227      Span<T> part2Buffer = mStorage.To(part2);
    228      toRead += aCallable(part2Buffer);
    229      MOZ_ASSERT(toRead <= part1 + part2);
    230    }
    231 
    232    mReadIndex = NextIndex(mReadIndex, toRead);
    233 
    234    return toRead;
    235  }
    236 
    237  /**
    238   * Remove the next `aSamples` number of samples from the ring buffer.
    239   */
    240  uint32_t Discard(uint32_t aSamples) {
    241    MOZ_ASSERT(aSamples);
    242 
    243    if (IsEmpty()) {
    244      return 0;
    245    }
    246 
    247    uint32_t toDiscard = std::min(AvailableRead(), aSamples);
    248    mReadIndex = NextIndex(mReadIndex, toDiscard);
    249 
    250    return toDiscard;
    251  }
    252 
    253  /**
    254   * Empty the ring buffer.
    255   */
    256  uint32_t Clear() {
    257    if (IsEmpty()) {
    258      return 0;
    259    }
    260 
    261    uint32_t toDiscard = AvailableRead();
    262    mReadIndex = NextIndex(mReadIndex, toDiscard);
    263 
    264    return toDiscard;
    265  }
    266 
    267  /**
    268   * Set the ring buffer to the requested size. NB: In bytes.
    269   *
    270   * Re-allocates memory if a larger buffer is requested than what is already
    271   * allocated.
    272   */
    273  bool EnsureLengthBytes(uint32_t aLengthBytes) {
    274    MOZ_ASSERT(aLengthBytes % sizeof(T) == 0,
    275               "Length in bytes is not a whole number of samples");
    276 
    277    if (mMemoryBuffer.Length() >= aLengthBytes) {
    278      return true;
    279    }
    280    uint32_t lengthSamples = aLengthBytes / sizeof(T);
    281    uint32_t oldLengthSamples = Capacity();
    282    uint32_t availableRead = AvailableRead();
    283    if (!mMemoryBuffer.SetLength(aLengthBytes)) {
    284      return false;
    285    }
    286 
    287    // mStorage may now have been deallocated.
    288    mStorage = ConvertToSpan(mMemoryBuffer);
    289    if (mWriteIndex < mReadIndex) {
    290      // The old data wrapped around the end of the (old) buffer. It needs to be
    291      // moved so it is continuous.
    292      const uint32_t toMove = mWriteIndex;
    293 
    294      // The bit that goes between the old and the new end of the buffer.
    295      const uint32_t toMove1 =
    296          std::min(lengthSamples - oldLengthSamples, toMove);
    297      {
    298        // [0, toMove1) -> [oldLength, oldLength + toMove1).
    299        Span<T> from1 = mStorage.Subspan(0, toMove1);
    300        Span<T> to1 = mStorage.Subspan(oldLengthSamples, toMove1);
    301        PodMove(to1.Elements(), from1.Elements(), toMove1);
    302      }
    303 
    304      // The last bit of data that starts at 0. Could be empty.
    305      const uint32_t toMove2 = toMove - toMove1;
    306      {
    307        // [toMove1, toMove) -> [0, toMove2).
    308        Span<T> from2 = mStorage.Subspan(toMove1, toMove2);
    309        Span<T> to2 = mStorage.Subspan(0, toMove2);
    310        PodMove(to2.Elements(), from2.Elements(), toMove2);
    311      }
    312 
    313      mWriteIndex = NextIndex(mReadIndex, availableRead);
    314    }
    315 
    316    return true;
    317  }
    318 
    319  /**
    320   * Returns true if the full capacity of the ring buffer is being used. When
    321   * full any attempt to write more samples to the ring buffer will fail.
    322   */
    323  bool IsFull() const { return (mWriteIndex + 1) % Capacity() == mReadIndex; }
    324 
    325  /**
    326   * Returns true if the ring buffer is empty. When empty any attempt to read
    327   * more samples from the ring buffer will fail.
    328   */
    329  bool IsEmpty() const { return mWriteIndex == mReadIndex; }
    330 
    331  /**
    332   * The number of samples available for writing.
    333   */
    334  uint32_t AvailableWrite() const {
    335    /* We subtract one element here to always keep at least one sample
    336     * free in the buffer, to distinguish between full and empty array. */
    337    uint32_t rv = mReadIndex - mWriteIndex - 1;
    338    if (mWriteIndex >= mReadIndex) {
    339      rv += Capacity();
    340    }
    341    return rv;
    342  }
    343 
    344  /**
    345   * The number of samples available for reading.
    346   */
    347  uint32_t AvailableRead() const {
    348    if (mWriteIndex >= mReadIndex) {
    349      return mWriteIndex - mReadIndex;
    350    }
    351    return mWriteIndex + Capacity() - mReadIndex;
    352  }
    353 
    354  /**
    355   * The number of samples this ring buffer can hold.
    356   */
    357  uint32_t Capacity() const { return mStorage.Length(); }
    358 
    359 private:
    360  uint32_t NextIndex(uint32_t aIndex, uint32_t aStep) const {
    361    MOZ_ASSERT(aStep < Capacity());
    362    MOZ_ASSERT(aIndex < Capacity());
    363    return (aIndex + aStep) % Capacity();
    364  }
    365 
    366  Span<T> ConvertToSpan(const AlignedByteBuffer& aOther) const {
    367    MOZ_ASSERT(aOther.Length() % sizeof(T) == 0);
    368    return Span<T>(reinterpret_cast<T*>(aOther.Data()),
    369                   aOther.Length() / sizeof(T));
    370  }
    371 
    372  void CopySpan(Span<T>& aTo, const Span<const T>& aFrom) {
    373    MOZ_ASSERT(aTo.Length() == aFrom.Length());
    374    std::copy(aFrom.cbegin(), aFrom.cend(), aTo.begin());
    375  }
    376 
    377 private:
    378  uint32_t mReadIndex = 0;
    379  uint32_t mWriteIndex = 0;
    380  /* Points to the mMemoryBuffer. */
    381  Span<T> mStorage;
    382  /* The actual allocated memory set from outside. It is set in the ctor and it
    383   * is not used again. It is here to control the lifetime of the memory. The
    384   * memory is accessed through the mStorage. The idea is that the memory used
    385   * from the RingBuffer can be pre-allocated. Note that a re-allocation will
    386   * happen if the length in bytes is set to something larger than is already
    387   * allocated. */
    388  AlignedByteBuffer mMemoryBuffer;
    389 };
    390 
    391 /** AudioRingBuffer **/
    392 
    393 /* The private members of AudioRingBuffer. */
    394 class AudioRingBuffer::AudioRingBufferPrivate {
    395 public:
    396  AudioSampleFormat mSampleFormat = AUDIO_FORMAT_SILENCE;
    397  Maybe<RingBuffer<float>> mFloatRingBuffer;
    398  Maybe<RingBuffer<int16_t>> mIntRingBuffer;
    399  Maybe<AlignedByteBuffer> mBackingBuffer;
    400 };
    401 
    402 AudioRingBuffer::AudioRingBuffer(uint32_t aSizeInBytes)
    403    : mPtr(MakeUnique<AudioRingBufferPrivate>()) {
    404  mPtr->mBackingBuffer.emplace(aSizeInBytes);
    405  MOZ_ASSERT(mPtr->mBackingBuffer);
    406 }
    407 
    408 AudioRingBuffer::~AudioRingBuffer() = default;
    409 
    410 void AudioRingBuffer::SetSampleFormat(AudioSampleFormat aFormat) {
    411  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_SILENCE);
    412  MOZ_ASSERT(aFormat == AUDIO_FORMAT_S16 || aFormat == AUDIO_FORMAT_FLOAT32);
    413  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    414  MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    415  MOZ_ASSERT(mPtr->mBackingBuffer);
    416 
    417  mPtr->mSampleFormat = aFormat;
    418  if (mPtr->mSampleFormat == AUDIO_FORMAT_S16) {
    419    mPtr->mIntRingBuffer.emplace(mPtr->mBackingBuffer.extract());
    420    MOZ_ASSERT(!mPtr->mBackingBuffer);
    421    return;
    422  }
    423  mPtr->mFloatRingBuffer.emplace(mPtr->mBackingBuffer.extract());
    424  MOZ_ASSERT(!mPtr->mBackingBuffer);
    425 }
    426 
    427 uint32_t AudioRingBuffer::Write(const Span<const float>& aBuffer) {
    428  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    429  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    430  MOZ_ASSERT(!mPtr->mBackingBuffer);
    431  return mPtr->mFloatRingBuffer->Write(aBuffer);
    432 }
    433 
    434 uint32_t AudioRingBuffer::Write(const Span<const int16_t>& aBuffer) {
    435  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16);
    436  MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    437  MOZ_ASSERT(!mPtr->mBackingBuffer);
    438  return mPtr->mIntRingBuffer->Write(aBuffer);
    439 }
    440 
    441 uint32_t AudioRingBuffer::Write(const AudioRingBuffer& aBuffer,
    442                                uint32_t aSamples) {
    443  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16 ||
    444             mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    445  MOZ_ASSERT(!mPtr->mBackingBuffer);
    446  if (mPtr->mSampleFormat == AUDIO_FORMAT_S16) {
    447    MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    448    return mPtr->mIntRingBuffer->Write(aBuffer.mPtr->mIntRingBuffer.ref(),
    449                                       aSamples);
    450  }
    451  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    452  return mPtr->mFloatRingBuffer->Write(aBuffer.mPtr->mFloatRingBuffer.ref(),
    453                                       aSamples);
    454 }
    455 
    456 uint32_t AudioRingBuffer::PrependSilence(uint32_t aSamples) {
    457  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16 ||
    458             mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    459  MOZ_ASSERT(!mPtr->mBackingBuffer);
    460  if (mPtr->mSampleFormat == AUDIO_FORMAT_S16) {
    461    MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    462    return mPtr->mIntRingBuffer->PrependSilence(aSamples);
    463  }
    464  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    465  return mPtr->mFloatRingBuffer->PrependSilence(aSamples);
    466 }
    467 
    468 uint32_t AudioRingBuffer::WriteSilence(uint32_t aSamples) {
    469  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16 ||
    470             mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    471  MOZ_ASSERT(!mPtr->mBackingBuffer);
    472  if (mPtr->mSampleFormat == AUDIO_FORMAT_S16) {
    473    MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    474    return mPtr->mIntRingBuffer->WriteSilence(aSamples);
    475  }
    476  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    477  return mPtr->mFloatRingBuffer->WriteSilence(aSamples);
    478 }
    479 
    480 uint32_t AudioRingBuffer::Read(const Span<float>& aBuffer) {
    481  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    482  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    483  MOZ_ASSERT(!mPtr->mBackingBuffer);
    484  return mPtr->mFloatRingBuffer->Read(aBuffer);
    485 }
    486 
    487 uint32_t AudioRingBuffer::Read(const Span<int16_t>& aBuffer) {
    488  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16);
    489  MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    490  MOZ_ASSERT(!mPtr->mBackingBuffer);
    491  return mPtr->mIntRingBuffer->Read(aBuffer);
    492 }
    493 
    494 uint32_t AudioRingBuffer::ReadNoCopy(
    495    std::function<uint32_t(const Span<const float>&)>&& aCallable) {
    496  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    497  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    498  MOZ_ASSERT(!mPtr->mBackingBuffer);
    499  return mPtr->mFloatRingBuffer->ReadNoCopy(std::move(aCallable));
    500 }
    501 
    502 uint32_t AudioRingBuffer::ReadNoCopy(
    503    std::function<uint32_t(const Span<const int16_t>&)>&& aCallable) {
    504  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16);
    505  MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    506  MOZ_ASSERT(!mPtr->mBackingBuffer);
    507  return mPtr->mIntRingBuffer->ReadNoCopy(std::move(aCallable));
    508 }
    509 
    510 uint32_t AudioRingBuffer::Discard(uint32_t aSamples) {
    511  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16 ||
    512             mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    513  MOZ_ASSERT(!mPtr->mBackingBuffer);
    514  if (mPtr->mSampleFormat == AUDIO_FORMAT_S16) {
    515    MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    516    return mPtr->mIntRingBuffer->Discard(aSamples);
    517  }
    518  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    519  return mPtr->mFloatRingBuffer->Discard(aSamples);
    520 }
    521 
    522 uint32_t AudioRingBuffer::Clear() {
    523  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16 ||
    524             mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    525  MOZ_ASSERT(!mPtr->mBackingBuffer);
    526  if (mPtr->mSampleFormat == AUDIO_FORMAT_S16) {
    527    MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    528    MOZ_ASSERT(mPtr->mIntRingBuffer);
    529    return mPtr->mIntRingBuffer->Clear();
    530  }
    531  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    532  MOZ_ASSERT(mPtr->mFloatRingBuffer);
    533  return mPtr->mFloatRingBuffer->Clear();
    534 }
    535 
    536 bool AudioRingBuffer::EnsureLengthBytes(uint32_t aLengthBytes) {
    537  if (mPtr->mFloatRingBuffer) {
    538    return mPtr->mFloatRingBuffer->EnsureLengthBytes(aLengthBytes);
    539  }
    540  if (mPtr->mIntRingBuffer) {
    541    return mPtr->mIntRingBuffer->EnsureLengthBytes(aLengthBytes);
    542  }
    543  if (mPtr->mBackingBuffer) {
    544    if (mPtr->mBackingBuffer->Length() >= aLengthBytes) {
    545      return true;
    546    }
    547    return mPtr->mBackingBuffer->SetLength(aLengthBytes);
    548  }
    549  MOZ_ASSERT_UNREACHABLE("Unexpected");
    550  return true;
    551 }
    552 
    553 uint32_t AudioRingBuffer::Capacity() const {
    554  if (mPtr->mFloatRingBuffer) {
    555    return mPtr->mFloatRingBuffer->Capacity();
    556  }
    557  if (mPtr->mIntRingBuffer) {
    558    return mPtr->mIntRingBuffer->Capacity();
    559  }
    560  MOZ_ASSERT_UNREACHABLE("Unexpected");
    561  return 0;
    562 }
    563 
    564 bool AudioRingBuffer::IsFull() const {
    565  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16 ||
    566             mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    567  MOZ_ASSERT(!mPtr->mBackingBuffer);
    568  if (mPtr->mSampleFormat == AUDIO_FORMAT_S16) {
    569    MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    570    return mPtr->mIntRingBuffer->IsFull();
    571  }
    572  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    573  return mPtr->mFloatRingBuffer->IsFull();
    574 }
    575 
    576 bool AudioRingBuffer::IsEmpty() const {
    577  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16 ||
    578             mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    579  MOZ_ASSERT(!mPtr->mBackingBuffer);
    580  if (mPtr->mSampleFormat == AUDIO_FORMAT_S16) {
    581    MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    582    return mPtr->mIntRingBuffer->IsEmpty();
    583  }
    584  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    585  return mPtr->mFloatRingBuffer->IsEmpty();
    586 }
    587 
    588 uint32_t AudioRingBuffer::AvailableWrite() const {
    589  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16 ||
    590             mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    591  MOZ_ASSERT(!mPtr->mBackingBuffer);
    592  if (mPtr->mSampleFormat == AUDIO_FORMAT_S16) {
    593    MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    594    return mPtr->mIntRingBuffer->AvailableWrite();
    595  }
    596  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    597  return mPtr->mFloatRingBuffer->AvailableWrite();
    598 }
    599 
    600 uint32_t AudioRingBuffer::AvailableRead() const {
    601  MOZ_ASSERT(mPtr->mSampleFormat == AUDIO_FORMAT_S16 ||
    602             mPtr->mSampleFormat == AUDIO_FORMAT_FLOAT32);
    603  MOZ_ASSERT(!mPtr->mBackingBuffer);
    604  if (mPtr->mSampleFormat == AUDIO_FORMAT_S16) {
    605    MOZ_ASSERT(!mPtr->mFloatRingBuffer);
    606    return mPtr->mIntRingBuffer->AvailableRead();
    607  }
    608  MOZ_ASSERT(!mPtr->mIntRingBuffer);
    609  return mPtr->mFloatRingBuffer->AvailableRead();
    610 }
    611 
    612 }  // namespace mozilla