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 SetLengthBytes(uint32_t aLengthBytes
) {
274 MOZ_ASSERT(aLengthBytes
% sizeof(T
) == 0,
275 "Length in bytes is not a whole number of samples");
277 uint32_t lengthSamples
= aLengthBytes
/ sizeof(T
);
278 uint32_t oldLengthSamples
= Capacity();
279 uint32_t availableRead
= AvailableRead();
280 if (!mMemoryBuffer
.SetLength(aLengthBytes
)) {
284 // mStorage may now have been deallocated.
285 mStorage
= ConvertToSpan(mMemoryBuffer
);
286 if (mWriteIndex
< mReadIndex
) {
287 // The old data wrapped around the end of the (old) buffer. It needs to be
288 // moved so it is continuous.
289 const uint32_t toMove
= mWriteIndex
;
291 // The bit that goes between the old and the new end of the buffer.
292 const uint32_t toMove1
=
293 std::min(lengthSamples
- oldLengthSamples
, toMove
);
295 // [0, toMove1) -> [oldLength, oldLength + toMove1).
296 Span
<T
> from1
= mStorage
.Subspan(0, toMove1
);
297 Span
<T
> to1
= mStorage
.Subspan(oldLengthSamples
, toMove1
);
298 PodMove(to1
.Elements(), from1
.Elements(), toMove1
);
301 // The last bit of data that starts at 0. Could be empty.
302 const uint32_t toMove2
= toMove
- toMove1
;
304 // [toMove1, toMove) -> [0, toMove2).
305 Span
<T
> from2
= mStorage
.Subspan(toMove1
, toMove2
);
306 Span
<T
> to2
= mStorage
.Subspan(0, toMove2
);
307 PodMove(to2
.Elements(), from2
.Elements(), toMove2
);
310 mWriteIndex
= NextIndex(mReadIndex
, availableRead
);
317 * Returns true if the full capacity of the ring buffer is being used. When
318 * full any attempt to write more samples to the ring buffer will fail.
320 bool IsFull() const { return (mWriteIndex
+ 1) % Capacity() == mReadIndex
; }
323 * Returns true if the ring buffer is empty. When empty any attempt to read
324 * more samples from the ring buffer will fail.
326 bool IsEmpty() const { return mWriteIndex
== mReadIndex
; }
329 * The number of samples available for writing.
331 uint32_t AvailableWrite() const {
332 /* We subtract one element here to always keep at least one sample
333 * free in the buffer, to distinguish between full and empty array. */
334 uint32_t rv
= mReadIndex
- mWriteIndex
- 1;
335 if (mWriteIndex
>= mReadIndex
) {
342 * The number of samples available for reading.
344 uint32_t AvailableRead() const {
345 if (mWriteIndex
>= mReadIndex
) {
346 return mWriteIndex
- mReadIndex
;
348 return mWriteIndex
+ Capacity() - mReadIndex
;
352 * The number of samples this ring buffer can hold.
354 uint32_t Capacity() const { return mStorage
.Length(); }
357 uint32_t NextIndex(uint32_t aIndex
, uint32_t aStep
) const {
358 MOZ_ASSERT(aStep
< Capacity());
359 MOZ_ASSERT(aIndex
< Capacity());
360 return (aIndex
+ aStep
) % Capacity();
363 Span
<T
> ConvertToSpan(const AlignedByteBuffer
& aOther
) const {
364 MOZ_ASSERT(aOther
.Length() % sizeof(T
) == 0);
365 return Span
<T
>(reinterpret_cast<T
*>(aOther
.Data()),
366 aOther
.Length() / sizeof(T
));
369 void CopySpan(Span
<T
>& aTo
, const Span
<const T
>& aFrom
) {
370 MOZ_ASSERT(aTo
.Length() == aFrom
.Length());
371 std::copy(aFrom
.cbegin(), aFrom
.cend(), aTo
.begin());
375 uint32_t mReadIndex
= 0;
376 uint32_t mWriteIndex
= 0;
377 /* Points to the mMemoryBuffer. */
379 /* The actual allocated memory set from outside. It is set in the ctor and it
380 * is not used again. It is here to control the lifetime of the memory. The
381 * memory is accessed through the mStorage. The idea is that the memory used
382 * from the RingBuffer can be pre-allocated. Note that a re-allocation will
383 * happen if the length in bytes is set to something larger than is already
385 AlignedByteBuffer mMemoryBuffer
;
388 /** AudioRingBuffer **/
390 /* The private members of AudioRingBuffer. */
391 class AudioRingBuffer::AudioRingBufferPrivate
{
393 AudioSampleFormat mSampleFormat
= AUDIO_FORMAT_SILENCE
;
394 Maybe
<RingBuffer
<float>> mFloatRingBuffer
;
395 Maybe
<RingBuffer
<int16_t>> mIntRingBuffer
;
396 Maybe
<AlignedByteBuffer
> mBackingBuffer
;
399 AudioRingBuffer::AudioRingBuffer(uint32_t aSizeInBytes
)
400 : mPtr(MakeUnique
<AudioRingBufferPrivate
>()) {
401 mPtr
->mBackingBuffer
.emplace(aSizeInBytes
);
402 MOZ_ASSERT(mPtr
->mBackingBuffer
);
405 AudioRingBuffer::~AudioRingBuffer() = default;
407 void AudioRingBuffer::SetSampleFormat(AudioSampleFormat aFormat
) {
408 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_SILENCE
);
409 MOZ_ASSERT(aFormat
== AUDIO_FORMAT_S16
|| aFormat
== AUDIO_FORMAT_FLOAT32
);
410 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
411 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
412 MOZ_ASSERT(mPtr
->mBackingBuffer
);
414 mPtr
->mSampleFormat
= aFormat
;
415 if (mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
) {
416 mPtr
->mIntRingBuffer
.emplace(mPtr
->mBackingBuffer
.extract());
417 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
420 mPtr
->mFloatRingBuffer
.emplace(mPtr
->mBackingBuffer
.extract());
421 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
424 uint32_t AudioRingBuffer::Write(const Span
<const float>& aBuffer
) {
425 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
426 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
427 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
428 return mPtr
->mFloatRingBuffer
->Write(aBuffer
);
431 uint32_t AudioRingBuffer::Write(const Span
<const int16_t>& aBuffer
) {
432 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
);
433 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
434 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
435 return mPtr
->mIntRingBuffer
->Write(aBuffer
);
438 uint32_t AudioRingBuffer::Write(const AudioRingBuffer
& aBuffer
,
440 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
||
441 mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
442 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
443 if (mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
) {
444 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
445 return mPtr
->mIntRingBuffer
->Write(aBuffer
.mPtr
->mIntRingBuffer
.ref(),
448 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
449 return mPtr
->mFloatRingBuffer
->Write(aBuffer
.mPtr
->mFloatRingBuffer
.ref(),
453 uint32_t AudioRingBuffer::PrependSilence(uint32_t aSamples
) {
454 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
||
455 mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
456 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
457 if (mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
) {
458 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
459 return mPtr
->mIntRingBuffer
->PrependSilence(aSamples
);
461 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
462 return mPtr
->mFloatRingBuffer
->PrependSilence(aSamples
);
465 uint32_t AudioRingBuffer::WriteSilence(uint32_t aSamples
) {
466 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
||
467 mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
468 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
469 if (mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
) {
470 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
471 return mPtr
->mIntRingBuffer
->WriteSilence(aSamples
);
473 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
474 return mPtr
->mFloatRingBuffer
->WriteSilence(aSamples
);
477 uint32_t AudioRingBuffer::Read(const Span
<float>& aBuffer
) {
478 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
479 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
480 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
481 return mPtr
->mFloatRingBuffer
->Read(aBuffer
);
484 uint32_t AudioRingBuffer::Read(const Span
<int16_t>& aBuffer
) {
485 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
);
486 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
487 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
488 return mPtr
->mIntRingBuffer
->Read(aBuffer
);
491 uint32_t AudioRingBuffer::ReadNoCopy(
492 std::function
<uint32_t(const Span
<const float>&)>&& aCallable
) {
493 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
494 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
495 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
496 return mPtr
->mFloatRingBuffer
->ReadNoCopy(std::move(aCallable
));
499 uint32_t AudioRingBuffer::ReadNoCopy(
500 std::function
<uint32_t(const Span
<const int16_t>&)>&& aCallable
) {
501 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
);
502 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
503 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
504 return mPtr
->mIntRingBuffer
->ReadNoCopy(std::move(aCallable
));
507 uint32_t AudioRingBuffer::Discard(uint32_t aSamples
) {
508 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
||
509 mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
510 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
511 if (mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
) {
512 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
513 return mPtr
->mIntRingBuffer
->Discard(aSamples
);
515 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
516 return mPtr
->mFloatRingBuffer
->Discard(aSamples
);
519 uint32_t AudioRingBuffer::Clear() {
520 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
||
521 mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
522 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
523 if (mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
) {
524 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
525 MOZ_ASSERT(mPtr
->mIntRingBuffer
);
526 return mPtr
->mIntRingBuffer
->Clear();
528 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
529 MOZ_ASSERT(mPtr
->mFloatRingBuffer
);
530 return mPtr
->mFloatRingBuffer
->Clear();
533 bool AudioRingBuffer::SetLengthBytes(uint32_t aLengthBytes
) {
534 if (mPtr
->mFloatRingBuffer
) {
535 return mPtr
->mFloatRingBuffer
->SetLengthBytes(aLengthBytes
);
537 if (mPtr
->mIntRingBuffer
) {
538 return mPtr
->mIntRingBuffer
->SetLengthBytes(aLengthBytes
);
540 if (mPtr
->mBackingBuffer
) {
541 return mPtr
->mBackingBuffer
->SetLength(aLengthBytes
);
543 MOZ_ASSERT_UNREACHABLE("Unexpected");
547 uint32_t AudioRingBuffer::Capacity() const {
548 if (mPtr
->mFloatRingBuffer
) {
549 return mPtr
->mFloatRingBuffer
->Capacity();
551 if (mPtr
->mIntRingBuffer
) {
552 return mPtr
->mIntRingBuffer
->Capacity();
554 MOZ_ASSERT_UNREACHABLE("Unexpected");
558 bool AudioRingBuffer::IsFull() const {
559 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
||
560 mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
561 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
562 if (mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
) {
563 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
564 return mPtr
->mIntRingBuffer
->IsFull();
566 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
567 return mPtr
->mFloatRingBuffer
->IsFull();
570 bool AudioRingBuffer::IsEmpty() const {
571 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
||
572 mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
573 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
574 if (mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
) {
575 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
576 return mPtr
->mIntRingBuffer
->IsEmpty();
578 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
579 return mPtr
->mFloatRingBuffer
->IsEmpty();
582 uint32_t AudioRingBuffer::AvailableWrite() const {
583 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
||
584 mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
585 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
586 if (mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
) {
587 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
588 return mPtr
->mIntRingBuffer
->AvailableWrite();
590 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
591 return mPtr
->mFloatRingBuffer
->AvailableWrite();
594 uint32_t AudioRingBuffer::AvailableRead() const {
595 MOZ_ASSERT(mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
||
596 mPtr
->mSampleFormat
== AUDIO_FORMAT_FLOAT32
);
597 MOZ_ASSERT(!mPtr
->mBackingBuffer
);
598 if (mPtr
->mSampleFormat
== AUDIO_FORMAT_S16
) {
599 MOZ_ASSERT(!mPtr
->mFloatRingBuffer
);
600 return mPtr
->mIntRingBuffer
->AvailableRead();
602 MOZ_ASSERT(!mPtr
->mIntRingBuffer
);
603 return mPtr
->mFloatRingBuffer
->AvailableRead();
606 } // namespace mozilla