Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  TestAudioRingBuffer.cpp

  Sprache: C
 

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "AudioRingBuffer.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "mozilla/PodOperations.h"

using namespace mozilla;
using testing::ElementsAre;

TEST(TestAudioRingBuffer, BasicFloat)
{
  AudioRingBuffer ringBuffer(11 * sizeof(float));
  ringBuffer.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);

  uint32_t rv = ringBuffer.WriteSilence(4);
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 6u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 4u);

  float in[4] = {.1, .2, .3, .4};
  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 2u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 8u);

  rv = ringBuffer.WriteSilence(4);
  EXPECT_EQ(rv, 2u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 0u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 10u);

  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 0u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 0u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 10u);

  float out[4] = {};
  rv = ringBuffer.Read(Span(out, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 4u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 6u);
  for (float f : out) {
    EXPECT_FLOAT_EQ(f, 0.0);
  }

  rv = ringBuffer.Read(Span(out, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 8u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 2u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_FLOAT_EQ(in[i], out[i]);
  }

  rv = ringBuffer.Read(Span(out, 4));
  EXPECT_EQ(rv, 2u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < 2; ++i) {
    EXPECT_FLOAT_EQ(out[i], 0.0);
  }

  rv = ringBuffer.Clear();
  EXPECT_EQ(rv, 0u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
}

TEST(TestAudioRingBuffer, BasicShort)
{
  AudioRingBuffer ringBuffer(11 * sizeof(short));
  ringBuffer.SetSampleFormat(AUDIO_FORMAT_S16);

  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);

  uint32_t rv = ringBuffer.WriteSilence(4);
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 6u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 4u);

  short in[4] = {1, 2, 3, 4};
  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 2u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 8u);

  rv = ringBuffer.WriteSilence(4);
  EXPECT_EQ(rv, 2u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 0u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 10u);

  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 0u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 0u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 10u);

  short out[4] = {};
  rv = ringBuffer.Read(Span(out, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 4u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 6u);
  for (float f : out) {
    EXPECT_EQ(f, 0);
  }

  rv = ringBuffer.Read(Span(out, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 8u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 2u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_EQ(in[i], out[i]);
  }

  rv = ringBuffer.Read(Span(out, 4));
  EXPECT_EQ(rv, 2u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < 2; ++i) {
    EXPECT_EQ(out[i], 0);
  }

  rv = ringBuffer.Clear();
  EXPECT_EQ(rv, 0u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
}

TEST(TestAudioRingBuffer, BasicFloat2)
{
  AudioRingBuffer ringBuffer(11 * sizeof(float));
  ringBuffer.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);

  float in[4] = {.1, .2, .3, .4};
  uint32_t rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 6u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 4u);

  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 2u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 8u);

  float out[4] = {};
  rv = ringBuffer.Read(Span(out, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 6u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 4u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_FLOAT_EQ(in[i], out[i]);
  }

  // WriteIndex = 12
  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 2u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 8u);

  rv = ringBuffer.Read(Span(out, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 6u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 4u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_FLOAT_EQ(in[i], out[i]);
  }

  rv = ringBuffer.Read(Span(out, 8));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_FLOAT_EQ(in[i], out[i]);
  }

  rv = ringBuffer.Read(Span(out, 8));
  EXPECT_EQ(rv, 0u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_FLOAT_EQ(in[i], out[i]);
  }

  // WriteIndex = 16
  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 6u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 4u);

  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 2u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 8u);

  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 2u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 0u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 10u);

  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 0u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 0u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 10u);
}

TEST(TestAudioRingBuffer, BasicShort2)
{
  AudioRingBuffer ringBuffer(11 * sizeof(int16_t));
  ringBuffer.SetSampleFormat(AUDIO_FORMAT_S16);

  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);

  int16_t in[4] = {1, 2, 3, 4};
  uint32_t rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 6u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 4u);

  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 2u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 8u);

  int16_t out[4] = {};
  rv = ringBuffer.Read(Span(out, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 6u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 4u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_EQ(in[i], out[i]);
  }

  // WriteIndex = 12
  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 2u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 8u);

  rv = ringBuffer.Read(Span(out, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 6u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 4u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_EQ(in[i], out[i]);
  }

  rv = ringBuffer.Read(Span(out, 8));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_EQ(in[i], out[i]);
  }

  rv = ringBuffer.Read(Span(out, 8));
  EXPECT_EQ(rv, 0u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_EQ(in[i], out[i]);
  }

  // WriteIndex = 16
  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 6u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 4u);

  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 2u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 8u);

  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 2u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 0u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 10u);

  rv = ringBuffer.Write(Span(in, 4));
  EXPECT_EQ(rv, 0u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 0u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 10u);
}

TEST(TestAudioRingBuffer, NoCopyFloat)
{
  AudioRingBuffer ringBuffer(11 * sizeof(float));
  ringBuffer.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in[8] = {.0, .1, .2, .3, .4, .5, .6, .7};
  ringBuffer.Write(Span(in, 6));
  //  v ReadIndex
  // [x0: .0, x1: .1, x2: .2, x3: .3, x4: .4,
  //  x5: .5, x6: .0, x7: .0, x8: .0, x9: .0, x10: .0]

  float out[10] = {};
  float* out_ptr = out;

  uint32_t rv =
      ringBuffer.ReadNoCopy([&out_ptr](const Span<const float> aInBuffer) {
        PodMove(out_ptr, aInBuffer.data(), aInBuffer.Length());
        out_ptr += aInBuffer.Length();
        return aInBuffer.Length();
      });
  EXPECT_EQ(rv, 6u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_FLOAT_EQ(out[i], in[i]);
  }

  ringBuffer.Write(Span(in, 8));
  // Now the buffer contains:
  // [x0: .5, x1: .6, x2: .2, x3: .3, x4: .4,
  //  x5: .5, x6: .0, x7: .1, x8: .2, x9: .3, x10: .4
  //          ^ ReadIndex
  out_ptr = out;  // reset the pointer before lambdas reuse
  rv = ringBuffer.ReadNoCopy([&out_ptr](const Span<const float> aInBuffer) {
    PodMove(out_ptr, aInBuffer.data(), aInBuffer.Length());
    out_ptr += aInBuffer.Length();
    return aInBuffer.Length();
  });
  EXPECT_EQ(rv, 8u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_FLOAT_EQ(out[i], in[i]);
  }
}

TEST(TestAudioRingBuffer, NoCopyShort)
{
  AudioRingBuffer ringBuffer(11 * sizeof(short));
  ringBuffer.SetSampleFormat(AUDIO_FORMAT_S16);

  short in[8] = {0, 1, 2, 3, 4, 5, 6, 7};
  ringBuffer.Write(Span(in, 6));
  //  v ReadIndex
  // [x0: 0, x1: 1, x2: 2, x3: 3, x4: 4,
  //  x5: 5, x6: 0, x7: 0, x8: 0, x9: 0, x10: 0]

  short out[10] = {};
  short* out_ptr = out;

  uint32_t rv =
      ringBuffer.ReadNoCopy([&out_ptr](const Span<const short> aInBuffer) {
        PodMove(out_ptr, aInBuffer.data(), aInBuffer.Length());
        out_ptr += aInBuffer.Length();
        return aInBuffer.Length();
      });
  EXPECT_EQ(rv, 6u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_EQ(out[i], in[i]);
  }

  ringBuffer.Write(Span(in, 8));
  // Now the buffer contains:
  // [x0: 5, x1: 6, x2: 2, x3: 3, x4: 4,
  //  x5: 5, x6: 0, x7: 1, x8: 2, x9: 3, x10: 4
  //          ^ ReadIndex
  out_ptr = out;  // reset the pointer before lambdas reuse
  rv = ringBuffer.ReadNoCopy([&out_ptr](const Span<const short> aInBuffer) {
    PodMove(out_ptr, aInBuffer.data(), aInBuffer.Length());
    out_ptr += aInBuffer.Length();
    return aInBuffer.Length();
  });
  EXPECT_EQ(rv, 8u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_EQ(out[i], in[i]);
  }
}

TEST(TestAudioRingBuffer, NoCopyFloat2)
{
  AudioRingBuffer ringBuffer(11 * sizeof(float));
  ringBuffer.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in[8] = {.0, .1, .2, .3, .4, .5, .6, .7};
  ringBuffer.Write(Span(in, 6));
  //  v ReadIndex
  // [x0: .0, x1: .1, x2: .2, x3: .3, x4: .4,
  //  x5: .5, x6: .0, x7: .0, x8: .0, x9: .0, x10: .0]

  float out[10] = {};
  float* out_ptr = out;
  uint32_t total_frames = 3;

  uint32_t rv = ringBuffer.ReadNoCopy(
      [&out_ptr, &total_frames](const Span<const float>& aInBuffer) {
        uint32_t inFramesUsed =
            std::min<uint32_t>(total_frames, aInBuffer.Length());
        PodMove(out_ptr, aInBuffer.data(), inFramesUsed);
        out_ptr += inFramesUsed;
        total_frames -= inFramesUsed;
        return inFramesUsed;
      });
  //                          v ReadIndex
  // [x0: .0, x1: .1, x2: .2, x3: .3, x4: .4,
  //  x5: .5, x6: .0, x7: .0, x8: .0, x9: .0, x10: .0]
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 7u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 3u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_FLOAT_EQ(out[i], in[i]);
  }

  total_frames = 3;
  rv = ringBuffer.ReadNoCopy(
      [&out_ptr, &total_frames](const Span<const float>& aInBuffer) {
        uint32_t inFramesUsed =
            std::min<uint32_t>(total_frames, aInBuffer.Length());
        PodMove(out_ptr, aInBuffer.data(), inFramesUsed);
        out_ptr += inFramesUsed;
        total_frames -= inFramesUsed;
        return inFramesUsed;
      });
  // [x0: .0, x1: .1, x2: .2, x3: .3, x4: .4,
  //  x5: .5, x6: .0, x7: .0, x8: .0, x9: .0, x10: .0]
  //          ^ ReadIndex
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_FLOAT_EQ(out[i + 3], in[i + 3]);
  }

  ringBuffer.Write(Span(in, 8));
  // Now the buffer contains:
  // [x0: .5, x1: .6, x2: .7, x3: .3, x4: .4,
  //  x5: .5, x6: .0, x7: .1, x8: .2, x9: .3, x10: .4
  //          ^ ReadIndex

  // reset the pointer before lambdas reuse
  out_ptr = out;
  total_frames = 3;
  rv = ringBuffer.ReadNoCopy(
      [&out_ptr, &total_frames](const Span<const float>& aInBuffer) {
        uint32_t inFramesUsed =
            std::min<uint32_t>(total_frames, aInBuffer.Length());
        PodMove(out_ptr, aInBuffer.data(), inFramesUsed);
        out_ptr += inFramesUsed;
        total_frames -= inFramesUsed;
        return inFramesUsed;
      });
  // Now the buffer contains:
  // [x0: .5, x1: .6, x2: .2, x3: .3, x4: .4,
  //  x5: .5, x6: .0, x7: .1, x8: .2, x9: .3, x10: .4
  //                                  ^ ReadIndex
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 5u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 5u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_FLOAT_EQ(out[i], in[i]);
  }

  total_frames = 3;
  rv = ringBuffer.ReadNoCopy(
      [&out_ptr, &total_frames](const Span<const float>& aInBuffer) {
        uint32_t inFramesUsed =
            std::min<uint32_t>(total_frames, aInBuffer.Length());
        PodMove(out_ptr, aInBuffer.data(), inFramesUsed);
        out_ptr += inFramesUsed;
        total_frames -= inFramesUsed;
        return inFramesUsed;
      });
  // Now the buffer contains:
  //          v ReadIndex
  // [x0: .5, x1: .6, x2: .7, x3: .3, x4: .4,
  //  x5: .5, x6: .0, x7: .1, x8: .2, x9: .3, x10: .4
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 8u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 2u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_FLOAT_EQ(out[i + 3], in[i + 3]);
  }

  total_frames = 3;
  rv = ringBuffer.ReadNoCopy(
      [&out_ptr, &total_frames](const Span<const float>& aInBuffer) {
        uint32_t inFramesUsed =
            std::min<uint32_t>(total_frames, aInBuffer.Length());
        PodMove(out_ptr, aInBuffer.data(), inFramesUsed);
        out_ptr += inFramesUsed;
        total_frames -= inFramesUsed;
        return inFramesUsed;
      });
  // Now the buffer contains:
  //                          v ReadIndex
  // [x0: .5, x1: .6, x2: .7, x3: .3, x4: .4,
  //  x5: .5, x6: .0, x7: .1, x8: .2, x9: .3, x10: .4
  EXPECT_EQ(rv, 2u);
  EXPECT_EQ(total_frames, 1u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_FLOAT_EQ(out[i + 6], in[i + 6]);
  }
}

TEST(TestAudioRingBuffer, NoCopyShort2)
{
  AudioRingBuffer ringBuffer(11 * sizeof(short));
  ringBuffer.SetSampleFormat(AUDIO_FORMAT_S16);

  short in[8] = {0, 1, 2, 3, 4, 5, 6, 7};
  ringBuffer.Write(Span(in, 6));
  //  v ReadIndex
  // [x0: 0, x1: 1, x2: 2, x3: 3, x4: 4,
  //  x5: 5, x6: 0, x7: 0, x8: 0, x9: 0, x10: 0]

  short out[10] = {};
  short* out_ptr = out;
  uint32_t total_frames = 3;

  uint32_t rv = ringBuffer.ReadNoCopy(
      [&out_ptr, &total_frames](const Span<const short>& aInBuffer) {
        uint32_t inFramesUsed =
            std::min<uint32_t>(total_frames, aInBuffer.Length());
        PodMove(out_ptr, aInBuffer.data(), inFramesUsed);
        out_ptr += inFramesUsed;
        total_frames -= inFramesUsed;
        return inFramesUsed;
      });
  //                       v ReadIndex
  // [x0: 0, x1: 1, x2: 2, x3: 3, x4: 4,
  //  x5: 5, x6: 0, x7: 0, x8: 0, x9: 0, x10: 0]
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 7u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 3u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_EQ(out[i], in[i]);
  }

  total_frames = 3;
  rv = ringBuffer.ReadNoCopy(
      [&out_ptr, &total_frames](const Span<const short>& aInBuffer) {
        uint32_t inFramesUsed =
            std::min<uint32_t>(total_frames, aInBuffer.Length());
        PodMove(out_ptr, aInBuffer.data(), inFramesUsed);
        out_ptr += inFramesUsed;
        total_frames -= inFramesUsed;
        return inFramesUsed;
      });
  // [x0: 0, x1: 1, x2: 2, x3: 3, x4: 4,
  //  x5: 5, x6: 0, x7: 0, x8: 0, x9: 0, x10: .0]
  //         ^ ReadIndex
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_EQ(out[i + 3], in[i + 3]);
  }

  ringBuffer.Write(Span(in, 8));
  // Now the buffer contains:
  // [x0: 5, x1: 6, x2: 7, x3: 3, x4: 4,
  //  x5: 5, x6: 0, x7: 1, x8: 2, x9: 3, x10: 4
  //         ^ ReadIndex

  // reset the pointer before lambdas reuse
  out_ptr = out;
  total_frames = 3;
  rv = ringBuffer.ReadNoCopy(
      [&out_ptr, &total_frames](const Span<const short>& aInBuffer) {
        uint32_t inFramesUsed =
            std::min<uint32_t>(total_frames, aInBuffer.Length());
        PodMove(out_ptr, aInBuffer.data(), inFramesUsed);
        out_ptr += inFramesUsed;
        total_frames -= inFramesUsed;
        return inFramesUsed;
      });
  // Now the buffer contains:
  // [x0: 5, x1: 6, x2: 2, x3: 3, x4: 4,
  //  x5: 5, x6: 0, x7: 1, x8: 2, x9: 3, x10: 4
  //                              ^ ReadIndex
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 5u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 5u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_EQ(out[i], in[i]);
  }

  total_frames = 3;
  rv = ringBuffer.ReadNoCopy(
      [&out_ptr, &total_frames](const Span<const short>& aInBuffer) {
        uint32_t inFramesUsed =
            std::min<uint32_t>(total_frames, aInBuffer.Length());
        PodMove(out_ptr, aInBuffer.data(), inFramesUsed);
        out_ptr += inFramesUsed;
        total_frames -= inFramesUsed;
        return inFramesUsed;
      });
  // Now the buffer contains:
  //         v ReadIndex
  // [x0: 5, x1: 6, x2: 7, x3: 3, x4: 4,
  //  x5: 5, x6: 0, x7: 1, x8: 2, x9: 3, x10: 4
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 8u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 2u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_EQ(out[i + 3], in[i + 3]);
  }

  total_frames = 3;
  rv = ringBuffer.ReadNoCopy(
      [&out_ptr, &total_frames](const Span<const short>& aInBuffer) {
        uint32_t inFramesUsed =
            std::min<uint32_t>(total_frames, aInBuffer.Length());
        PodMove(out_ptr, aInBuffer.data(), inFramesUsed);
        out_ptr += inFramesUsed;
        total_frames -= inFramesUsed;
        return inFramesUsed;
      });
  // Now the buffer contains:
  //                       v ReadIndex
  // [x0: 5, x1: 6, x2: 7, x3: 3, x4: 4,
  //  x5: 5, x6: 0, x7: 1, x8: 2, x9: 3, x10: 4
  EXPECT_EQ(rv, 2u);
  EXPECT_EQ(total_frames, 1u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_EQ(out[i + 6], in[i + 6]);
  }
}

TEST(TestAudioRingBuffer, DiscardFloat)
{
  AudioRingBuffer ringBuffer(11 * sizeof(float));
  ringBuffer.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in[8] = {.0, .1, .2, .3, .4, .5, .6, .7};
  ringBuffer.Write(Span(in, 8));

  uint32_t rv = ringBuffer.Discard(3);
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 5u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 5u);

  float out[8] = {};
  rv = ringBuffer.Read(Span(out, 3));
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 8u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 2u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_FLOAT_EQ(out[i], in[i + 3]);
  }

  rv = ringBuffer.Discard(3);
  EXPECT_EQ(rv, 2u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);

  ringBuffer.WriteSilence(4);
  rv = ringBuffer.Discard(6);
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
}

TEST(TestAudioRingBuffer, DiscardShort)
{
  AudioRingBuffer ringBuffer(11 * sizeof(short));
  ringBuffer.SetSampleFormat(AUDIO_FORMAT_S16);

  short in[8] = {0, 1, 2, 3, 4, 5, 6, 7};
  ringBuffer.Write(Span(in, 8));

  uint32_t rv = ringBuffer.Discard(3);
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 5u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 5u);

  short out[8] = {};
  rv = ringBuffer.Read(Span(out, 3));
  EXPECT_EQ(rv, 3u);
  EXPECT_TRUE(!ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 8u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 2u);
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_EQ(out[i], in[i + 3]);
  }

  rv = ringBuffer.Discard(3);
  EXPECT_EQ(rv, 2u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);

  ringBuffer.WriteSilence(4);
  rv = ringBuffer.Discard(6);
  EXPECT_EQ(rv, 4u);
  EXPECT_TRUE(ringBuffer.IsEmpty());
  EXPECT_TRUE(!ringBuffer.IsFull());
  EXPECT_EQ(ringBuffer.AvailableWrite(), 10u);
  EXPECT_EQ(ringBuffer.AvailableRead(), 0u);
}

TEST(TestRingBuffer, WriteFromRing1)
{
  AudioRingBuffer ringBuffer1(11 * sizeof(float));
  ringBuffer1.SetSampleFormat(AUDIO_FORMAT_FLOAT32);
  AudioRingBuffer ringBuffer2(11 * sizeof(float));
  ringBuffer2.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in[4] = {.1, .2, .3, .4};
  uint32_t rv = ringBuffer1.Write(Span<const float>(in, 4));
  EXPECT_EQ(rv, 4u);

  EXPECT_EQ(ringBuffer2.AvailableRead(), 0u);
  rv = ringBuffer2.Write(ringBuffer1, 4);
  EXPECT_EQ(rv, 4u);
  EXPECT_EQ(ringBuffer2.AvailableRead(), 4u);

  float out[4] = {};
  rv = ringBuffer2.Read(Span<float>(out, 4));
  EXPECT_EQ(rv, 4u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_FLOAT_EQ(in[i], out[i]);
  }
}

TEST(TestRingBuffer, WriteFromRing2)
{
  AudioRingBuffer ringBuffer1(11 * sizeof(float));
  ringBuffer1.SetSampleFormat(AUDIO_FORMAT_FLOAT32);
  AudioRingBuffer ringBuffer2(11 * sizeof(float));
  ringBuffer2.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  // Advance the index
  ringBuffer2.WriteSilence(8);
  ringBuffer2.Clear();

  float in[4] = {.1, .2, .3, .4};
  uint32_t rv = ringBuffer1.Write(Span<const float>(in, 4));
  EXPECT_EQ(rv, 4u);
  rv = ringBuffer2.Write(ringBuffer1, 4);
  EXPECT_EQ(rv, 4u);
  EXPECT_EQ(ringBuffer2.AvailableRead(), 4u);

  float out[4] = {};
  rv = ringBuffer2.Read(Span<float>(out, 4));
  EXPECT_EQ(rv, 4u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_FLOAT_EQ(in[i], out[i]);
  }
}

TEST(TestRingBuffer, WriteFromRing3)
{
  AudioRingBuffer ringBuffer1(11 * sizeof(float));
  ringBuffer1.SetSampleFormat(AUDIO_FORMAT_FLOAT32);
  AudioRingBuffer ringBuffer2(11 * sizeof(float));
  ringBuffer2.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  // Advance the index
  ringBuffer2.WriteSilence(8);
  ringBuffer2.Clear();
  ringBuffer2.WriteSilence(4);
  ringBuffer2.Clear();

  float in[4] = {.1, .2, .3, .4};
  uint32_t rv = ringBuffer1.Write(Span<const float>(in, 4));
  EXPECT_EQ(rv, 4u);
  rv = ringBuffer2.Write(ringBuffer1, 4);
  EXPECT_EQ(rv, 4u);
  EXPECT_EQ(ringBuffer2.AvailableRead(), 4u);

  float out[4] = {};
  rv = ringBuffer2.Read(Span<float>(out, 4));
  EXPECT_EQ(rv, 4u);
  for (uint32_t i = 0; i < 4; ++i) {
    EXPECT_FLOAT_EQ(in[i], out[i]);
  }
}

TEST(TestAudioRingBuffer, WriteFromRingShort)
{
  AudioRingBuffer ringBuffer1(11 * sizeof(short));
  ringBuffer1.SetSampleFormat(AUDIO_FORMAT_S16);

  short in[8] = {0, 1, 2, 3, 4, 5, 6, 7};
  uint32_t rv = ringBuffer1.Write(Span(in, 8));
  EXPECT_EQ(rv, 8u);

  AudioRingBuffer ringBuffer2(11 * sizeof(short));
  ringBuffer2.SetSampleFormat(AUDIO_FORMAT_S16);

  rv = ringBuffer2.Write(ringBuffer1, 4);
  EXPECT_EQ(rv, 4u);
  EXPECT_EQ(ringBuffer2.AvailableRead(), 4u);
  EXPECT_EQ(ringBuffer1.AvailableRead(), 8u);

  short out[4] = {};
  rv = ringBuffer2.Read(Span(out, 4));
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_EQ(out[i], in[i]);
  }

  rv = ringBuffer2.Write(ringBuffer1, 4);
  EXPECT_EQ(rv, 4u);
  EXPECT_EQ(ringBuffer2.AvailableRead(), 4u);
  EXPECT_EQ(ringBuffer1.AvailableRead(), 8u);

  ringBuffer1.Discard(4);
  rv = ringBuffer2.Write(ringBuffer1, 4);
  EXPECT_EQ(rv, 4u);
  EXPECT_EQ(ringBuffer2.AvailableRead(), 8u);
  EXPECT_EQ(ringBuffer1.AvailableRead(), 4u);

  short out2[8] = {};
  rv = ringBuffer2.Read(Span(out2, 8));
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_EQ(out2[i], in[i]);
  }
}

TEST(TestAudioRingBuffer, WriteFromRingFloat)
{
  AudioRingBuffer ringBuffer1(11 * sizeof(float));
  ringBuffer1.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in[8] = {.0, .1, .2, .3, .4, .5, .6, .7};
  uint32_t rv = ringBuffer1.Write(Span(in, 8));
  EXPECT_EQ(rv, 8u);

  AudioRingBuffer ringBuffer2(11 * sizeof(float));
  ringBuffer2.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  rv = ringBuffer2.Write(ringBuffer1, 4);
  EXPECT_EQ(rv, 4u);
  EXPECT_EQ(ringBuffer2.AvailableRead(), 4u);
  EXPECT_EQ(ringBuffer1.AvailableRead(), 8u);

  float out[4] = {};
  rv = ringBuffer2.Read(Span(out, 4));
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_FLOAT_EQ(out[i], in[i]);
  }

  rv = ringBuffer2.Write(ringBuffer1, 4);
  EXPECT_EQ(rv, 4u);
  EXPECT_EQ(ringBuffer2.AvailableRead(), 4u);
  EXPECT_EQ(ringBuffer1.AvailableRead(), 8u);

  ringBuffer1.Discard(4);
  rv = ringBuffer2.Write(ringBuffer1, 4);
  EXPECT_EQ(rv, 4u);
  EXPECT_EQ(ringBuffer2.AvailableRead(), 8u);
  EXPECT_EQ(ringBuffer1.AvailableRead(), 4u);

  float out2[8] = {};
  rv = ringBuffer2.Read(Span(out2, 8));
  for (uint32_t i = 0; i < rv; ++i) {
    EXPECT_FLOAT_EQ(out2[i], in[i]);
  }
}

TEST(TestAudioRingBuffer, PrependSilenceWrapsFloat)
{
  AudioRingBuffer rb(9 * sizeof(float));
  rb.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in[6] = {.2, .3, .4, .5, .6, .7};
  uint32_t rv = rb.Write(Span(in, 6));
  EXPECT_EQ(rv, 6u);

  float out[8] = {};
  auto outSpan = Span(out, 8);
  rv = rb.Read(outSpan.Subspan(0, 1));
  EXPECT_EQ(rv, 1u);

  // PrependSilence will have to wrap around the start and put the silent
  // samples at indices 0 and 8 of the ring buffer.
  rv = rb.PrependSilence(2);
  EXPECT_EQ(rv, 2u);

  rv = rb.Read(outSpan.Subspan(1, 7));
  EXPECT_EQ(rv, 7u);

  EXPECT_THAT(out, ElementsAre(.2, 0, 0, .3, .4, .5, .6, .7));
}

TEST(TestAudioRingBuffer, PrependSilenceWrapsShort)
{
  AudioRingBuffer rb(9 * sizeof(short));
  rb.SetSampleFormat(AUDIO_FORMAT_S16);

  short in[6] = {2, 3, 4, 5, 6, 7};
  uint32_t rv = rb.Write(Span(in, 6));
  EXPECT_EQ(rv, 6u);

  short out[8] = {};
  auto outSpan = Span(out, 8);
  rv = rb.Read(outSpan.Subspan(0, 1));
  EXPECT_EQ(rv, 1u);

  // PrependSilence will have to wrap around the start and put the silent
  // samples at indices 0 and 8 of the ring buffer.
  rv = rb.PrependSilence(2);
  EXPECT_EQ(rv, 2u);

  rv = rb.Read(outSpan.Subspan(1, 7));
  EXPECT_EQ(rv, 7u);

  EXPECT_THAT(out, ElementsAre(2, 0, 0, 3, 4, 5, 6, 7));
}

TEST(TestAudioRingBuffer, PrependSilenceNoWrapFloat)
{
  AudioRingBuffer rb(9 * sizeof(float));
  rb.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in[6] = {.2, .3, .4, .5, .6, .7};
  uint32_t rv = rb.Write(Span(in, 6));
  EXPECT_EQ(rv, 6u);

  float out[8] = {};
  auto outSpan = Span(out, 8);
  rv = rb.Read(outSpan.To(4));
  EXPECT_EQ(rv, 4u);

  // PrependSilence will put the silent samples at indices 2 and 3 of the ring
  // buffer.
  rv = rb.PrependSilence(2);
  EXPECT_EQ(rv, 2u);

  rv = rb.Read(outSpan.Subspan(4, 4));
  EXPECT_EQ(rv, 4u);

  EXPECT_THAT(out, ElementsAre(.2, .3, .4, .5, 0, 0, .6, .7));
}

TEST(TestAudioRingBuffer, PrependSilenceNoWrapShort)
{
  AudioRingBuffer rb(9 * sizeof(short));
  rb.SetSampleFormat(AUDIO_FORMAT_S16);

  short in[6] = {2, 3, 4, 5, 6, 7};
  uint32_t rv = rb.Write(Span(in, 6));
  EXPECT_EQ(rv, 6u);

  short out[8] = {};
  auto outSpan = Span(out, 8);
  rv = rb.Read(outSpan.To(4));
  EXPECT_EQ(rv, 4u);

  // PrependSilence will put the silent samples at indices 2 and 3 of the ring
  // buffer.
  rv = rb.PrependSilence(2);
  EXPECT_EQ(rv, 2u);

  rv = rb.Read(outSpan.Subspan(4, 4));
  EXPECT_EQ(rv, 4u);

  EXPECT_THAT(out, ElementsAre(2, 3, 4, 5, 0, 0, 6, 7));
}

TEST(TestAudioRingBuffer, EnsureLengthBytesNoWrapFloat)
{
  AudioRingBuffer rb(6 * sizeof(float));
  rb.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in[5] = {.1, .2, .3, .4, .5};
  uint32_t rv = rb.Write(Span(in, 5));
  EXPECT_EQ(rv, 5u);
  EXPECT_EQ(rb.AvailableRead(), 5u);
  EXPECT_EQ(rb.AvailableWrite(), 0u);
  EXPECT_EQ(rb.Capacity(), 6u);

  EXPECT_TRUE(rb.EnsureLengthBytes(11 * sizeof(float)));
  float out[10] = {};
  rv = rb.Read(Span(out, 10));
  EXPECT_EQ(rv, 5u);
  EXPECT_EQ(rb.AvailableRead(), 0u);
  EXPECT_EQ(rb.AvailableWrite(), 10u);
  EXPECT_EQ(rb.Capacity(), 11u);
  EXPECT_THAT(out, ElementsAre(.1, .2, .3, .4, .5, 0, 0, 0, 0, 0));
}

TEST(TestAudioRingBuffer, EnsureLengthBytesNoWrapShort)
{
  AudioRingBuffer rb(6 * sizeof(short));
  rb.SetSampleFormat(AUDIO_FORMAT_S16);

  short in[5] = {1, 2, 3, 4, 5};
  uint32_t rv = rb.Write(Span(in, 5));
  EXPECT_EQ(rv, 5u);
  EXPECT_EQ(rb.AvailableRead(), 5u);
  EXPECT_EQ(rb.AvailableWrite(), 0u);
  EXPECT_EQ(rb.Capacity(), 6u);

  EXPECT_TRUE(rb.EnsureLengthBytes(11 * sizeof(short)));
  short out[10] = {};
  rv = rb.Read(Span(out, 10));
  EXPECT_EQ(rv, 5u);
  EXPECT_EQ(rb.AvailableRead(), 0u);
  EXPECT_EQ(rb.AvailableWrite(), 10u);
  EXPECT_EQ(rb.Capacity(), 11u);
  EXPECT_THAT(out, ElementsAre(1, 2, 3, 4, 5, 0, 0, 0, 0, 0));
}

TEST(TestAudioRingBuffer, EnsureLengthBytesWrap1PartFloat)
{
  AudioRingBuffer rb(6 * sizeof(float));
  rb.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  EXPECT_EQ(rb.WriteSilence(3), 3u);
  EXPECT_EQ(rb.AvailableRead(), 3u);
  EXPECT_EQ(rb.AvailableWrite(), 2u);
  EXPECT_EQ(rb.Capacity(), 6u);

  float outSilence[3] = {};
  EXPECT_EQ(rb.Read(Span(outSilence, 3)), 3u);
  EXPECT_EQ(rb.AvailableRead(), 0u);
  EXPECT_EQ(rb.AvailableWrite(), 5u);

  float in[5] = {.1, .2, .3, .4, .5};
  EXPECT_EQ(rb.Write(Span(in, 5)), 5u);
  EXPECT_EQ(rb.AvailableRead(), 5u);
  EXPECT_EQ(rb.AvailableWrite(), 0u);

  EXPECT_TRUE(rb.EnsureLengthBytes(11 * sizeof(float)));
  EXPECT_EQ(rb.AvailableRead(), 5u);
  EXPECT_EQ(rb.AvailableWrite(), 5u);

  float in2[2] = {.6, .7};
  EXPECT_EQ(rb.Write(Span(in2, 2)), 2u);
  EXPECT_EQ(rb.AvailableRead(), 7u);
  EXPECT_EQ(rb.AvailableWrite(), 3u);

  float out[10] = {};
  EXPECT_EQ(rb.Read(Span(out, 10)), 7u);
  EXPECT_EQ(rb.AvailableRead(), 0u);
  EXPECT_EQ(rb.AvailableWrite(), 10u);
  EXPECT_EQ(rb.Capacity(), 11u);
  EXPECT_THAT(out, ElementsAre(.1, .2, .3, .4, .5, .6, .7, 0, 0, 0));
}

TEST(TestAudioRingBuffer, EnsureLengthBytesWrap1PartShort)
{
  AudioRingBuffer rb(6 * sizeof(short));
  rb.SetSampleFormat(AUDIO_FORMAT_S16);

  EXPECT_EQ(rb.WriteSilence(3), 3u);
  EXPECT_EQ(rb.AvailableRead(), 3u);
  EXPECT_EQ(rb.AvailableWrite(), 2u);
  EXPECT_EQ(rb.Capacity(), 6u);

  short outSilence[3] = {};
  EXPECT_EQ(rb.Read(Span(outSilence, 3)), 3u);
  EXPECT_EQ(rb.AvailableRead(), 0u);
  EXPECT_EQ(rb.AvailableWrite(), 5u);

  short in[5] = {1, 2, 3, 4, 5};
  EXPECT_EQ(rb.Write(Span(in, 5)), 5u);
  EXPECT_EQ(rb.AvailableRead(), 5u);
  EXPECT_EQ(rb.AvailableWrite(), 0u);

  EXPECT_TRUE(rb.EnsureLengthBytes(11 * sizeof(short)));
  EXPECT_EQ(rb.AvailableRead(), 5u);
  EXPECT_EQ(rb.AvailableWrite(), 5u);

  short in2[2] = {6, 7};
  EXPECT_EQ(rb.Write(Span(in2, 2)), 2u);
  EXPECT_EQ(rb.AvailableRead(), 7u);
  EXPECT_EQ(rb.AvailableWrite(), 3u);

  short out[10] = {};
  EXPECT_EQ(rb.Read(Span(out, 10)), 7u);
  EXPECT_EQ(rb.AvailableRead(), 0u);
  EXPECT_EQ(rb.AvailableWrite(), 10u);
  EXPECT_EQ(rb.Capacity(), 11u);
  EXPECT_THAT(out, ElementsAre(1, 2, 3, 4, 5, 6, 7, 0, 0, 0));
}

TEST(TestAudioRingBuffer, EnsureLengthBytesWrap2PartsFloat)
{
  AudioRingBuffer rb(6 * sizeof(float));
  rb.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  EXPECT_EQ(rb.WriteSilence(3), 3u);
  EXPECT_EQ(rb.AvailableRead(), 3u);
  EXPECT_EQ(rb.AvailableWrite(), 2u);
  EXPECT_EQ(rb.Capacity(), 6u);

  float outSilence[3] = {};
  EXPECT_EQ(rb.Read(Span(outSilence, 3)), 3u);
  EXPECT_EQ(rb.AvailableRead(), 0u);
  EXPECT_EQ(rb.AvailableWrite(), 5u);

  float in[5] = {.1, .2, .3, .4, .5};
  EXPECT_EQ(rb.Write(Span(in, 5)), 5u);
  EXPECT_EQ(rb.AvailableRead(), 5u);
  EXPECT_EQ(rb.AvailableWrite(), 0u);

  EXPECT_TRUE(rb.EnsureLengthBytes(8 * sizeof(float)));
  EXPECT_EQ(rb.AvailableRead(), 5u);
  EXPECT_EQ(rb.AvailableWrite(), 2u);

  float in2[2] = {.6, .7};
  EXPECT_EQ(rb.Write(Span(in2, 2)), 2u);
  EXPECT_EQ(rb.AvailableRead(), 7u);
  EXPECT_EQ(rb.AvailableWrite(), 0u);

  float out[8] = {};
  EXPECT_EQ(rb.Read(Span(out, 8)), 7u);
  EXPECT_EQ(rb.AvailableRead(), 0u);
  EXPECT_EQ(rb.AvailableWrite(), 7u);
  EXPECT_EQ(rb.Capacity(), 8u);
  EXPECT_THAT(out, ElementsAre(.1, .2, .3, .4, .5, .6, .7, 0));
}

TEST(TestAudioRingBuffer, EnsureLengthBytesWrap2PartsShort)
{
  AudioRingBuffer rb(6 * sizeof(short));
  rb.SetSampleFormat(AUDIO_FORMAT_S16);

  EXPECT_EQ(rb.WriteSilence(3), 3u);
  EXPECT_EQ(rb.AvailableRead(), 3u);
  EXPECT_EQ(rb.AvailableWrite(), 2u);
  EXPECT_EQ(rb.Capacity(), 6u);

  short outSilence[3] = {};
  EXPECT_EQ(rb.Read(Span(outSilence, 3)), 3u);
  EXPECT_EQ(rb.AvailableRead(), 0u);
  EXPECT_EQ(rb.AvailableWrite(), 5u);

  short in[5] = {1, 2, 3, 4, 5};
  EXPECT_EQ(rb.Write(Span(in, 5)), 5u);
  EXPECT_EQ(rb.AvailableRead(), 5u);
  EXPECT_EQ(rb.AvailableWrite(), 0u);

  EXPECT_TRUE(rb.EnsureLengthBytes(8 * sizeof(short)));
  EXPECT_EQ(rb.AvailableRead(), 5u);
  EXPECT_EQ(rb.AvailableWrite(), 2u);

  short in2[2] = {6, 7};
  EXPECT_EQ(rb.Write(Span(in2, 2)), 2u);
  EXPECT_EQ(rb.AvailableRead(), 7u);
  EXPECT_EQ(rb.AvailableWrite(), 0u);

  short out[8] = {};
  EXPECT_EQ(rb.Read(Span(out, 8)), 7u);
  EXPECT_EQ(rb.AvailableRead(), 0u);
  EXPECT_EQ(rb.AvailableWrite(), 7u);
  EXPECT_EQ(rb.Capacity(), 8u);
  EXPECT_THAT(out, ElementsAre(1, 2, 3, 4, 5, 6, 7, 0));
}

TEST(TestAudioRingBuffer, EnsureLengthShorter)
{
  AudioRingBuffer rb(5 * sizeof(float));
  rb.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in[5] = {.1, .2, .3, .4, .5};
  EXPECT_EQ(rb.Write(Span(in, 5)), 4u);
  EXPECT_EQ(rb.AvailableRead(), 4u);
  EXPECT_EQ(rb.AvailableWrite(), 0u);
  EXPECT_EQ(rb.Capacity(), 5u);

  float out[5] = {};
  EXPECT_EQ(rb.Read(Span(out, 3)), 3u);
  EXPECT_THAT(out, ElementsAre(.1, .2, .3, 0, 0));
  EXPECT_EQ(rb.AvailableRead(), 1u);
  EXPECT_EQ(rb.AvailableWrite(), 3u);

  EXPECT_TRUE(rb.EnsureLengthBytes(3 * sizeof(float)));
  EXPECT_EQ(rb.AvailableRead(), 1u);
  EXPECT_EQ(rb.AvailableWrite(), 3u);
  EXPECT_EQ(rb.Capacity(), 5u);
  EXPECT_EQ(rb.Write(Span(in, 5)), 3u);
  EXPECT_EQ(rb.Read(Span(out, 5)), 4u);
  EXPECT_THAT(out, ElementsAre(.4, .1, .2, .3, 0));
}

Messung V0.5 in Prozent
C=94 H=71 G=83

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet am  2026-04-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge