Bug 1890689 Change AudioRingBuffer::SetLengthBytes() to EnsureLengthBytes() r=pehrsons
[gecko.git] / dom / media / AudioRingBuffer.cpp
blobcbeb64a2f644f1bc0b029041996db1cf01b810f0
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 "AudioRingBuffer.h"
8 #include "MediaData.h"
9 #include "mozilla/Assertions.h"
10 #include "mozilla/Maybe.h"
11 #include "mozilla/PodOperations.h"
13 namespace mozilla {
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.
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);
36 /**
37 * Write `aSamples` number of zeros in the buffer, before any existing data.
39 uint32_t PrependSilence(uint32_t aSamples) {
40 MOZ_ASSERT(aSamples);
41 return Prepend(Span<T>(), aSamples);
44 /**
45 * Write `aSamples` number of zeros in the buffer.
47 uint32_t WriteSilence(uint32_t aSamples) {
48 MOZ_ASSERT(aSamples);
49 return Write(Span<T>(), aSamples);
52 /**
53 * Copy `aBuffer` to the RingBuffer.
55 uint32_t Write(const Span<const T>& aBuffer) {
56 MOZ_ASSERT(!aBuffer.IsEmpty());
57 return Write(aBuffer, aBuffer.Length());
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.
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);
69 if (IsFull()) {
70 return 0;
73 uint32_t toWrite = std::min(AvailableWrite(), aSamples);
74 uint32_t part2 = std::min(mReadIndex, toWrite);
75 uint32_t part1 = toWrite - part2;
77 Span<T> part2Buffer = mStorage.Subspan(mReadIndex - part2, part2);
78 Span<T> part1Buffer = mStorage.Subspan(Capacity() - part1, part1);
80 if (!aBuffer.IsEmpty()) {
81 Span<const T> fromPart1 = aBuffer.To(part1);
82 Span<const T> fromPart2 = aBuffer.Subspan(part1, part2);
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());
92 mReadIndex = NextIndex(mReadIndex, Capacity() - toWrite);
94 return toWrite;
97 /**
98 * Copy `aSamples` number of elements from `aBuffer` to the RingBuffer. If
99 * `aBuffer` is empty append `aSamples` of zeros.
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);
105 if (IsFull()) {
106 return 0;
109 uint32_t toWrite = std::min(AvailableWrite(), aSamples);
110 uint32_t part1 = std::min(Capacity() - mWriteIndex, toWrite);
111 uint32_t part2 = toWrite - part1;
113 Span<T> part1Buffer = mStorage.Subspan(mWriteIndex, part1);
114 Span<T> part2Buffer = mStorage.To(part2);
116 if (!aBuffer.IsEmpty()) {
117 Span<const T> fromPart1 = aBuffer.To(part1);
118 Span<const T> fromPart2 = aBuffer.Subspan(part1, part2);
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());
128 mWriteIndex = NextIndex(mWriteIndex, toWrite);
130 return toWrite;
133 public:
135 * Copy `aSamples` number of elements from `aBuffer` to the RingBuffer. The
136 * `aBuffer` does not change.
138 uint32_t Write(const RingBuffer& aBuffer, uint32_t aSamples) {
139 MOZ_ASSERT(aSamples);
141 if (IsFull()) {
142 return 0;
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;
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);
160 return toReadThat;
164 * Copy `aBuffer.Length()` number of elements from RingBuffer to `aBuffer`.
166 uint32_t Read(const Span<T>& aBuffer) {
167 MOZ_ASSERT(!aBuffer.IsEmpty());
168 MOZ_ASSERT(aBuffer.size() <= std::numeric_limits<uint32_t>::max());
170 if (IsEmpty()) {
171 return 0;
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;
178 Span<T> part1Buffer = mStorage.Subspan(mReadIndex, part1);
179 Span<T> part2Buffer = mStorage.To(part2);
181 Span<T> toPart1 = aBuffer.To(part1);
182 Span<T> toPart2 = aBuffer.Subspan(part1, part2);
184 CopySpan(toPart1, part1Buffer);
185 CopySpan(toPart2, part2Buffer);
187 mReadIndex = NextIndex(mReadIndex, toRead);
189 return toRead;
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`.
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.
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.
213 uint32_t ReadNoCopy(
214 std::function<uint32_t(const Span<const T>&)>&& aCallable) {
215 if (IsEmpty()) {
216 return 0;
219 uint32_t part1 = std::min(Capacity() - mReadIndex, AvailableRead());
220 uint32_t part2 = AvailableRead() - part1;
222 Span<T> part1Buffer = mStorage.Subspan(mReadIndex, part1);
223 uint32_t toRead = aCallable(part1Buffer);
224 MOZ_ASSERT(toRead <= part1);
226 if (toRead == part1 && part2) {
227 Span<T> part2Buffer = mStorage.To(part2);
228 toRead += aCallable(part2Buffer);
229 MOZ_ASSERT(toRead <= part1 + part2);
232 mReadIndex = NextIndex(mReadIndex, toRead);
234 return toRead;
238 * Remove the next `aSamples` number of samples from the ring buffer.
240 uint32_t Discard(uint32_t aSamples) {
241 MOZ_ASSERT(aSamples);
243 if (IsEmpty()) {
244 return 0;
247 uint32_t toDiscard = std::min(AvailableRead(), aSamples);
248 mReadIndex = NextIndex(mReadIndex, toDiscard);
250 return toDiscard;
254 * Empty the ring buffer.
256 uint32_t Clear() {
257 if (IsEmpty()) {
258 return 0;
261 uint32_t toDiscard = AvailableRead();
262 mReadIndex = NextIndex(mReadIndex, toDiscard);
264 return toDiscard;
268 * Set the ring buffer to the requested size. NB: In bytes.
270 * Re-allocates memory if a larger buffer is requested than what is already
271 * allocated.
273 bool EnsureLengthBytes(uint32_t aLengthBytes) {
274 MOZ_ASSERT(aLengthBytes % sizeof(T) == 0,
275 "Length in bytes is not a whole number of samples");
277 if (mMemoryBuffer.Length() >= aLengthBytes) {
278 return true;
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;
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;
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);
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);
304 // The last bit of data that starts at 0. Could be empty.
305 const uint32_t toMove2 = toMove - toMove1;
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);
313 mWriteIndex = NextIndex(mReadIndex, availableRead);
316 return true;
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.
323 bool IsFull() const { return (mWriteIndex + 1) % Capacity() == mReadIndex; }
326 * Returns true if the ring buffer is empty. When empty any attempt to read
327 * more samples from the ring buffer will fail.
329 bool IsEmpty() const { return mWriteIndex == mReadIndex; }
332 * The number of samples available for writing.
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();
341 return rv;
345 * The number of samples available for reading.
347 uint32_t AvailableRead() const {
348 if (mWriteIndex >= mReadIndex) {
349 return mWriteIndex - mReadIndex;
351 return mWriteIndex + Capacity() - mReadIndex;
355 * The number of samples this ring buffer can hold.
357 uint32_t Capacity() const { return mStorage.Length(); }
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();
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));
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());
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;
391 /** AudioRingBuffer **/
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;
402 AudioRingBuffer::AudioRingBuffer(uint32_t aSizeInBytes)
403 : mPtr(MakeUnique<AudioRingBufferPrivate>()) {
404 mPtr->mBackingBuffer.emplace(aSizeInBytes);
405 MOZ_ASSERT(mPtr->mBackingBuffer);
408 AudioRingBuffer::~AudioRingBuffer() = default;
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);
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;
423 mPtr->mFloatRingBuffer.emplace(mPtr->mBackingBuffer.extract());
424 MOZ_ASSERT(!mPtr->mBackingBuffer);
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);
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);
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);
451 MOZ_ASSERT(!mPtr->mIntRingBuffer);
452 return mPtr->mFloatRingBuffer->Write(aBuffer.mPtr->mFloatRingBuffer.ref(),
453 aSamples);
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);
464 MOZ_ASSERT(!mPtr->mIntRingBuffer);
465 return mPtr->mFloatRingBuffer->PrependSilence(aSamples);
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);
476 MOZ_ASSERT(!mPtr->mIntRingBuffer);
477 return mPtr->mFloatRingBuffer->WriteSilence(aSamples);
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);
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);
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));
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));
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);
518 MOZ_ASSERT(!mPtr->mIntRingBuffer);
519 return mPtr->mFloatRingBuffer->Discard(aSamples);
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();
531 MOZ_ASSERT(!mPtr->mIntRingBuffer);
532 MOZ_ASSERT(mPtr->mFloatRingBuffer);
533 return mPtr->mFloatRingBuffer->Clear();
536 bool AudioRingBuffer::EnsureLengthBytes(uint32_t aLengthBytes) {
537 if (mPtr->mFloatRingBuffer) {
538 return mPtr->mFloatRingBuffer->EnsureLengthBytes(aLengthBytes);
540 if (mPtr->mIntRingBuffer) {
541 return mPtr->mIntRingBuffer->EnsureLengthBytes(aLengthBytes);
543 if (mPtr->mBackingBuffer) {
544 if (mPtr->mBackingBuffer->Length() >= aLengthBytes) {
545 return true;
547 return mPtr->mBackingBuffer->SetLength(aLengthBytes);
549 MOZ_ASSERT_UNREACHABLE("Unexpected");
550 return true;
553 uint32_t AudioRingBuffer::Capacity() const {
554 if (mPtr->mFloatRingBuffer) {
555 return mPtr->mFloatRingBuffer->Capacity();
557 if (mPtr->mIntRingBuffer) {
558 return mPtr->mIntRingBuffer->Capacity();
560 MOZ_ASSERT_UNREACHABLE("Unexpected");
561 return 0;
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();
572 MOZ_ASSERT(!mPtr->mIntRingBuffer);
573 return mPtr->mFloatRingBuffer->IsFull();
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();
584 MOZ_ASSERT(!mPtr->mIntRingBuffer);
585 return mPtr->mFloatRingBuffer->IsEmpty();
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();
596 MOZ_ASSERT(!mPtr->mIntRingBuffer);
597 return mPtr->mFloatRingBuffer->AvailableWrite();
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();
608 MOZ_ASSERT(!mPtr->mIntRingBuffer);
609 return mPtr->mFloatRingBuffer->AvailableRead();
612 } // namespace mozilla