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"
9 #include "mozilla/Assertions.h"
10 #include "mozilla/Maybe.h"
11 #include "mozilla/PodOperations.h"
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.
28 class RingBuffer final
{
30 explicit RingBuffer(AlignedByteBuffer
&& aMemoryBuffer
)
31 : mStorage(ConvertToSpan(aMemoryBuffer
)),
32 mMemoryBuffer(std::move(aMemoryBuffer
)) {
33 MOZ_ASSERT(std::is_trivial
<T
>::value
);
37 * Write `aSamples` number of zeros in the buffer, before any existing data.
39 uint32_t PrependSilence(uint32_t aSamples
) {
41 return Prepend(Span
<T
>(), aSamples
);
45 * Write `aSamples` number of zeros in the buffer.
47 uint32_t WriteSilence(uint32_t aSamples
) {
49 return Write(Span
<T
>(), aSamples
);
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());
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
);
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
);
87 // aBuffer is empty, prepend zeros.
88 PodZero(part1Buffer
.Elements(), part1Buffer
.Length());
89 PodZero(part2Buffer
.Elements(), part2Buffer
.Length());
92 mReadIndex
= NextIndex(mReadIndex
, Capacity() - toWrite
);
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
);
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
);
123 // The aBuffer is empty, append zeros.
124 PodZero(part1Buffer
.Elements(), part1Buffer
.Length());
125 PodZero(part2Buffer
.Elements(), part2Buffer
.Length());
128 mWriteIndex
= NextIndex(mWriteIndex
, toWrite
);
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
);
145 uint32_t toWriteThis
= std::min(AvailableWrite(), aSamples
);
146 uint32_t toReadThat
= std::min(aBuffer
.AvailableRead(), toWriteThis
);
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
);
155 Span
<T
> part2Buffer
= aBuffer
.mStorage
.To(part2
);
156 ret
= Write(part2Buffer
);
157 MOZ_ASSERT(ret
== part2
);
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());
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
);
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.
214 std::function
<uint32_t(const Span
<const T
>&)>&& aCallable
) {
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
);
238 * Remove the next `aSamples` number of samples from the ring buffer.
240 uint32_t Discard(uint32_t aSamples
) {
241 MOZ_ASSERT(aSamples
);
247 uint32_t toDiscard
= std::min(AvailableRead(), aSamples
);
248 mReadIndex
= NextIndex(mReadIndex
, toDiscard
);
254 * Empty the ring buffer.
261 uint32_t toDiscard
= AvailableRead();
262 mReadIndex
= NextIndex(mReadIndex
, 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
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
) {
280 uint32_t lengthSamples
= aLengthBytes
/ sizeof(T
);
281 uint32_t oldLengthSamples
= Capacity();
282 uint32_t availableRead
= AvailableRead();
283 if (!mMemoryBuffer
.SetLength(aLengthBytes
)) {
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
);
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
) {
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(); }
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());
378 uint32_t mReadIndex
= 0;
379 uint32_t mWriteIndex
= 0;
380 /* Points to the mMemoryBuffer. */
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
388 AlignedByteBuffer mMemoryBuffer
;
391 /** AudioRingBuffer **/
393 /* The private members of AudioRingBuffer. */
394 class AudioRingBuffer::AudioRingBufferPrivate
{
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
);
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
,
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(),
451 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
452 return mPtr
->mFloatRingBuffer
->Write(aBuffer
.mPtr
->mFloatRingBuffer
.ref(),
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
) {
547 return mPtr
->mBackingBuffer
->SetLength(aLengthBytes
);
549 MOZ_ASSERT_UNREACHABLE("Unexpected");
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");
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