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/. */
6 #include "AudioChunkList.h"
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
) {
17 CreateChunks(numOfChunks
, aChannels
);
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
);
26 for (AudioChunk
& chunk
: mChunks
) {
27 AutoTArray
<nsTArray
<float>, 2> buffer
;
28 buffer
.AppendElements(aChannels
);
30 AutoTArray
<const float*, 2> bufferPtrs
;
31 bufferPtrs
.AppendElements(aChannels
);
33 for (uint32_t i
= 0; i
< aChannels
; ++i
) {
34 float* ptr
= buffer
[i
].AppendElements(mChunkCapacity
);
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
];
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);
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
);
61 // This an indirect allocation, unfortunately.
62 channelArray
->mBuffers
[1].SetLength(mChunkCapacity
);
63 chunk
.mChannelData
[1] = channelArray
->mBuffers
[1].Elements();
66 SharedChannelArrayBuffer
<float>* channelArray
=
67 static_cast<SharedChannelArrayBuffer
<float>*>(chunk
.mBuffer
.get());
68 channelArray
->mBuffers
.SetLengthAndRetainStorage(aChannels
);
70 // This an indirect allocation, unfortunately.
71 channelArray
->mBuffers
[1].SetLength(mChunkCapacity
);
72 chunk
.mChannelData
[1] = channelArray
->mBuffers
[1].Elements();
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
;
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
);
96 chunk
.mPrincipalHandle
= mPrincipalHandle
;
97 chunk
.mBufferFormat
= mSampleFormat
;
102 void AudioChunkList::Update(uint32_t aChannels
) {
103 MOZ_ASSERT(mChunks
.Length());
104 if (mChunks
[0].ChannelCount() == aChannels
) {
108 // Special handling between mono and stereo to avoid reallocations.
109 if (aChannels
<= 2 && mChunks
[0].ChannelCount() <= 2) {
110 UpdateToMonoOrStereo(aChannels
);
114 uint32_t numOfChunks
= mChunks
.Length();
115 mChunks
.ClearAndRetainStorage();
116 CreateChunks(numOfChunks
, aChannels
);
119 } // namespace mozilla