AudioRingBuffer.cpp (20409B)
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 "AudioRingBuffer.h" 7 8 #include "MediaData.h" 9 #include "mozilla/Assertions.h" 10 #include "mozilla/Maybe.h" 11 #include "mozilla/PodOperations.h" 12 13 namespace mozilla { 14 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. 26 */ 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); 34 } 35 36 /** 37 * Write `aSamples` number of zeros in the buffer, before any existing data. 38 */ 39 uint32_t PrependSilence(uint32_t aSamples) { 40 MOZ_ASSERT(aSamples); 41 return Prepend(Span<T>(), aSamples); 42 } 43 44 /** 45 * Write `aSamples` number of zeros in the buffer. 46 */ 47 uint32_t WriteSilence(uint32_t aSamples) { 48 MOZ_ASSERT(aSamples); 49 return Write(Span<T>(), aSamples); 50 } 51 52 /** 53 * Copy `aBuffer` to the RingBuffer. 54 */ 55 uint32_t Write(const Span<const T>& aBuffer) { 56 MOZ_ASSERT(!aBuffer.IsEmpty()); 57 return Write(aBuffer, aBuffer.Length()); 58 } 59 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. 64 */ 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); 68 69 if (IsFull()) { 70 return 0; 71 } 72 73 uint32_t toWrite = std::min(AvailableWrite(), aSamples); 74 uint32_t part2 = std::min(mReadIndex, toWrite); 75 uint32_t part1 = toWrite - part2; 76 77 Span<T> part2Buffer = mStorage.Subspan(mReadIndex - part2, part2); 78 Span<T> part1Buffer = mStorage.Subspan(Capacity() - part1, part1); 79 80 if (!aBuffer.IsEmpty()) { 81 Span<const T> fromPart1 = aBuffer.To(part1); 82 Span<const T> fromPart2 = aBuffer.Subspan(part1, part2); 83 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()); 90 } 91 92 mReadIndex = NextIndex(mReadIndex, Capacity() - toWrite); 93 94 return toWrite; 95 } 96 97 /** 98 * Copy `aSamples` number of elements from `aBuffer` to the RingBuffer. If 99 * `aBuffer` is empty append `aSamples` of zeros. 100 */ 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); 104 105 if (IsFull()) { 106 return 0; 107 } 108 109 uint32_t toWrite = std::min(AvailableWrite(), aSamples); 110 uint32_t part1 = std::min(Capacity() - mWriteIndex, toWrite); 111 uint32_t part2 = toWrite - part1; 112 113 Span<T> part1Buffer = mStorage.Subspan(mWriteIndex, part1); 114 Span<T> part2Buffer = mStorage.To(part2); 115 116 if (!aBuffer.IsEmpty()) { 117 Span<const T> fromPart1 = aBuffer.To(part1); 118 Span<const T> fromPart2 = aBuffer.Subspan(part1, part2); 119 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()); 126 } 127 128 mWriteIndex = NextIndex(mWriteIndex, toWrite); 129 130 return toWrite; 131 } 132 133 public: 134 /** 135 * Copy `aSamples` number of elements from `aBuffer` to the RingBuffer. The 136 * `aBuffer` does not change. 137 */ 138 uint32_t Write(const RingBuffer& aBuffer, uint32_t aSamples) { 139 MOZ_ASSERT(aSamples); 140 141 if (IsFull()) { 142 return 0; 143 } 144 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; 150 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); 158 } 159 160 return toReadThat; 161 } 162 163 /** 164 * Copy `aBuffer.Length()` number of elements from RingBuffer to `aBuffer`. 165 */ 166 uint32_t Read(const Span<T>& aBuffer) { 167 MOZ_ASSERT(!aBuffer.IsEmpty()); 168 MOZ_ASSERT(aBuffer.size() <= std::numeric_limits<uint32_t>::max()); 169 170 if (IsEmpty()) { 171 return 0; 172 } 173 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; 177 178 Span<T> part1Buffer = mStorage.Subspan(mReadIndex, part1); 179 Span<T> part2Buffer = mStorage.To(part2); 180 181 Span<T> toPart1 = aBuffer.To(part1); 182 Span<T> toPart2 = aBuffer.Subspan(part1, part2); 183 184 CopySpan(toPart1, part1Buffer); 185 CopySpan(toPart2, part2Buffer); 186 187 mReadIndex = NextIndex(mReadIndex, toRead); 188 189 return toRead; 190 } 191 192 /** 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`. 200 * 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. 205 * 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. 212 */ 213 uint32_t ReadNoCopy( 214 std::function<uint32_t(const Span<const T>&)>&& aCallable) { 215 if (IsEmpty()) { 216 return 0; 217 } 218 219 uint32_t part1 = std::min(Capacity() - mReadIndex, AvailableRead()); 220 uint32_t part2 = AvailableRead() - part1; 221 222 Span<T> part1Buffer = mStorage.Subspan(mReadIndex, part1); 223 uint32_t toRead = aCallable(part1Buffer); 224 MOZ_ASSERT(toRead <= part1); 225 226 if (toRead == part1 && part2) { 227 Span<T> part2Buffer = mStorage.To(part2); 228 toRead += aCallable(part2Buffer); 229 MOZ_ASSERT(toRead <= part1 + part2); 230 } 231 232 mReadIndex = NextIndex(mReadIndex, toRead); 233 234 return toRead; 235 } 236 237 /** 238 * Remove the next `aSamples` number of samples from the ring buffer. 239 */ 240 uint32_t Discard(uint32_t aSamples) { 241 MOZ_ASSERT(aSamples); 242 243 if (IsEmpty()) { 244 return 0; 245 } 246 247 uint32_t toDiscard = std::min(AvailableRead(), aSamples); 248 mReadIndex = NextIndex(mReadIndex, toDiscard); 249 250 return toDiscard; 251 } 252 253 /** 254 * Empty the ring buffer. 255 */ 256 uint32_t Clear() { 257 if (IsEmpty()) { 258 return 0; 259 } 260 261 uint32_t toDiscard = AvailableRead(); 262 mReadIndex = NextIndex(mReadIndex, toDiscard); 263 264 return toDiscard; 265 } 266 267 /** 268 * Set the ring buffer to the requested size. NB: In bytes. 269 * 270 * Re-allocates memory if a larger buffer is requested than what is already 271 * allocated. 272 */ 273 bool EnsureLengthBytes(uint32_t aLengthBytes) { 274 MOZ_ASSERT(aLengthBytes % sizeof(T) == 0, 275 "Length in bytes is not a whole number of samples"); 276 277 if (mMemoryBuffer.Length() >= aLengthBytes) { 278 return true; 279 } 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; 285 } 286 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; 293 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); 297 { 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); 302 } 303 304 // The last bit of data that starts at 0. Could be empty. 305 const uint32_t toMove2 = toMove - toMove1; 306 { 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); 311 } 312 313 mWriteIndex = NextIndex(mReadIndex, availableRead); 314 } 315 316 return true; 317 } 318 319 /** 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. 322 */ 323 bool IsFull() const { return (mWriteIndex + 1) % Capacity() == mReadIndex; } 324 325 /** 326 * Returns true if the ring buffer is empty. When empty any attempt to read 327 * more samples from the ring buffer will fail. 328 */ 329 bool IsEmpty() const { return mWriteIndex == mReadIndex; } 330 331 /** 332 * The number of samples available for writing. 333 */ 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(); 340 } 341 return rv; 342 } 343 344 /** 345 * The number of samples available for reading. 346 */ 347 uint32_t AvailableRead() const { 348 if (mWriteIndex >= mReadIndex) { 349 return mWriteIndex - mReadIndex; 350 } 351 return mWriteIndex + Capacity() - mReadIndex; 352 } 353 354 /** 355 * The number of samples this ring buffer can hold. 356 */ 357 uint32_t Capacity() const { return mStorage.Length(); } 358 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(); 364 } 365 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)); 370 } 371 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()); 375 } 376 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; 389 }; 390 391 /** AudioRingBuffer **/ 392 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; 400 }; 401 402 AudioRingBuffer::AudioRingBuffer(uint32_t aSizeInBytes) 403 : mPtr(MakeUnique<AudioRingBufferPrivate>()) { 404 mPtr->mBackingBuffer.emplace(aSizeInBytes); 405 MOZ_ASSERT(mPtr->mBackingBuffer); 406 } 407 408 AudioRingBuffer::~AudioRingBuffer() = default; 409 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); 416 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; 422 } 423 mPtr->mFloatRingBuffer.emplace(mPtr->mBackingBuffer.extract()); 424 MOZ_ASSERT(!mPtr->mBackingBuffer); 425 } 426 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); 432 } 433 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); 439 } 440 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); 450 } 451 MOZ_ASSERT(!mPtr->mIntRingBuffer); 452 return mPtr->mFloatRingBuffer->Write(aBuffer.mPtr->mFloatRingBuffer.ref(), 453 aSamples); 454 } 455 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); 463 } 464 MOZ_ASSERT(!mPtr->mIntRingBuffer); 465 return mPtr->mFloatRingBuffer->PrependSilence(aSamples); 466 } 467 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); 475 } 476 MOZ_ASSERT(!mPtr->mIntRingBuffer); 477 return mPtr->mFloatRingBuffer->WriteSilence(aSamples); 478 } 479 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); 485 } 486 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); 492 } 493 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)); 500 } 501 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)); 508 } 509 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); 517 } 518 MOZ_ASSERT(!mPtr->mIntRingBuffer); 519 return mPtr->mFloatRingBuffer->Discard(aSamples); 520 } 521 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(); 530 } 531 MOZ_ASSERT(!mPtr->mIntRingBuffer); 532 MOZ_ASSERT(mPtr->mFloatRingBuffer); 533 return mPtr->mFloatRingBuffer->Clear(); 534 } 535 536 bool AudioRingBuffer::EnsureLengthBytes(uint32_t aLengthBytes) { 537 if (mPtr->mFloatRingBuffer) { 538 return mPtr->mFloatRingBuffer->EnsureLengthBytes(aLengthBytes); 539 } 540 if (mPtr->mIntRingBuffer) { 541 return mPtr->mIntRingBuffer->EnsureLengthBytes(aLengthBytes); 542 } 543 if (mPtr->mBackingBuffer) { 544 if (mPtr->mBackingBuffer->Length() >= aLengthBytes) { 545 return true; 546 } 547 return mPtr->mBackingBuffer->SetLength(aLengthBytes); 548 } 549 MOZ_ASSERT_UNREACHABLE("Unexpected"); 550 return true; 551 } 552 553 uint32_t AudioRingBuffer::Capacity() const { 554 if (mPtr->mFloatRingBuffer) { 555 return mPtr->mFloatRingBuffer->Capacity(); 556 } 557 if (mPtr->mIntRingBuffer) { 558 return mPtr->mIntRingBuffer->Capacity(); 559 } 560 MOZ_ASSERT_UNREACHABLE("Unexpected"); 561 return 0; 562 } 563 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(); 571 } 572 MOZ_ASSERT(!mPtr->mIntRingBuffer); 573 return mPtr->mFloatRingBuffer->IsFull(); 574 } 575 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(); 583 } 584 MOZ_ASSERT(!mPtr->mIntRingBuffer); 585 return mPtr->mFloatRingBuffer->IsEmpty(); 586 } 587 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(); 595 } 596 MOZ_ASSERT(!mPtr->mIntRingBuffer); 597 return mPtr->mFloatRingBuffer->AvailableWrite(); 598 } 599 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(); 607 } 608 MOZ_ASSERT(!mPtr->mIntRingBuffer); 609 return mPtr->mFloatRingBuffer->AvailableRead(); 610 } 611 612 } // namespace mozilla