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