tor-browser

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

AudioChunkList.cpp (4129B)


      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 "AudioChunkList.h"
      7 
      8 namespace mozilla {
      9 
     10 AudioChunkList::AudioChunkList(uint32_t aTotalDuration, uint32_t aChannels,
     11                               const PrincipalHandle& aPrincipalHandle)
     12    : mPrincipalHandle(aPrincipalHandle) {
     13  uint32_t numOfChunks = aTotalDuration / mChunkCapacity;
     14  if (aTotalDuration % mChunkCapacity) {
     15    ++numOfChunks;
     16  }
     17  CreateChunks(numOfChunks, aChannels);
     18 }
     19 
     20 void AudioChunkList::CreateChunks(uint32_t aNumOfChunks, uint32_t aChannels) {
     21  MOZ_ASSERT(!mChunks.Length());
     22  MOZ_ASSERT(aNumOfChunks);
     23  MOZ_ASSERT(aChannels);
     24  mChunks.AppendElements(aNumOfChunks);
     25 
     26  for (AudioChunk& chunk : mChunks) {
     27    AutoTArray<nsTArray<float>, 2> buffer;
     28    buffer.AppendElements(aChannels);
     29 
     30    AutoTArray<const float*, 2> bufferPtrs;
     31    bufferPtrs.AppendElements(aChannels);
     32 
     33    for (uint32_t i = 0; i < aChannels; ++i) {
     34      float* ptr = buffer[i].AppendElements(mChunkCapacity);
     35      bufferPtrs[i] = ptr;
     36    }
     37 
     38    chunk.mBuffer = new mozilla::SharedChannelArrayBuffer(std::move(buffer));
     39    chunk.mChannelData.AppendElements(aChannels);
     40    for (uint32_t i = 0; i < aChannels; ++i) {
     41      chunk.mChannelData[i] = bufferPtrs[i];
     42    }
     43  }
     44 }
     45 
     46 void AudioChunkList::UpdateToMonoOrStereo(uint32_t aChannels) {
     47  MOZ_ASSERT(mChunks.Length());
     48  MOZ_ASSERT(mSampleFormat == AUDIO_FORMAT_S16 ||
     49             mSampleFormat == AUDIO_FORMAT_FLOAT32);
     50  MOZ_ASSERT(aChannels == 1 || aChannels == 2);
     51 
     52  for (AudioChunk& chunk : mChunks) {
     53    MOZ_ASSERT(chunk.ChannelCount() != (uint32_t)aChannels);
     54    MOZ_ASSERT(chunk.ChannelCount() == 1 || chunk.ChannelCount() == 2);
     55    chunk.mChannelData.SetLengthAndRetainStorage(aChannels);
     56    if (mSampleFormat == AUDIO_FORMAT_S16) {
     57      SharedChannelArrayBuffer<short>* channelArray =
     58          static_cast<SharedChannelArrayBuffer<short>*>(chunk.mBuffer.get());
     59      channelArray->mBuffers.SetLengthAndRetainStorage(aChannels);
     60      if (aChannels == 2) {
     61        // This an indirect allocation, unfortunately.
     62        channelArray->mBuffers[1].SetLength(mChunkCapacity);
     63        chunk.mChannelData[1] = channelArray->mBuffers[1].Elements();
     64      }
     65    } else {
     66      SharedChannelArrayBuffer<float>* channelArray =
     67          static_cast<SharedChannelArrayBuffer<float>*>(chunk.mBuffer.get());
     68      channelArray->mBuffers.SetLengthAndRetainStorage(aChannels);
     69      if (aChannels == 2) {
     70        // This an indirect allocation, unfortunately.
     71        channelArray->mBuffers[1].SetLength(mChunkCapacity);
     72        chunk.mChannelData[1] = channelArray->mBuffers[1].Elements();
     73      }
     74    }
     75  }
     76 }
     77 
     78 void AudioChunkList::SetSampleFormat(AudioSampleFormat aFormat) {
     79  MOZ_ASSERT(mSampleFormat == AUDIO_FORMAT_SILENCE);
     80  MOZ_ASSERT(aFormat == AUDIO_FORMAT_S16 || aFormat == AUDIO_FORMAT_FLOAT32);
     81  mSampleFormat = aFormat;
     82  if (mSampleFormat == AUDIO_FORMAT_S16) {
     83    mChunkCapacity = 2 * mChunkCapacity;
     84  }
     85 }
     86 
     87 AudioChunk& AudioChunkList::GetNext() {
     88  AudioChunk& chunk = mChunks[mIndex];
     89  MOZ_ASSERT(!chunk.mChannelData.IsEmpty());
     90  MOZ_ASSERT(chunk.mBuffer);
     91  MOZ_ASSERT(!chunk.mBuffer->IsShared());
     92  MOZ_ASSERT(mSampleFormat == AUDIO_FORMAT_S16 ||
     93             mSampleFormat == AUDIO_FORMAT_FLOAT32);
     94  chunk.mDuration = 0;
     95  chunk.mVolume = 1.0f;
     96  chunk.mPrincipalHandle = mPrincipalHandle;
     97  chunk.mBufferFormat = mSampleFormat;
     98  IncrementIndex();
     99  return chunk;
    100 }
    101 
    102 void AudioChunkList::Update(uint32_t aChannels) {
    103  MOZ_ASSERT(mChunks.Length());
    104  if (mChunks[0].ChannelCount() == aChannels) {
    105    return;
    106  }
    107 
    108  // Special handling between mono and stereo to avoid reallocations.
    109  if (aChannels <= 2 && mChunks[0].ChannelCount() <= 2) {
    110    UpdateToMonoOrStereo(aChannels);
    111    return;
    112  }
    113 
    114  uint32_t numOfChunks = mChunks.Length();
    115  mChunks.ClearAndRetainStorage();
    116  CreateChunks(numOfChunks, aChannels);
    117 }
    118 
    119 }  // namespace mozilla