This source file includes following definitions.
- VerifyParams
- VerifyValue
- VerifyBusWithEpsilon
- VerifyBus
- VerifyChannelData
- CopyTest
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_bus.h"
#include "media/base/channel_layout.h"
#include "media/base/fake_audio_render_callback.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
static const int kChannels = 6;
static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_5_1;
static const int kFrameCount = media::AudioBus::kChannelAlignment * 32 - 1;
static const int kSampleRate = 48000;
class AudioBusTest : public testing::Test {
public:
AudioBusTest() {}
virtual ~AudioBusTest() {
for (size_t i = 0; i < data_.size(); ++i)
base::AlignedFree(data_[i]);
}
void VerifyParams(AudioBus* bus) {
EXPECT_EQ(kChannels, bus->channels());
EXPECT_EQ(kFrameCount, bus->frames());
}
void VerifyValue(const float data[], int size, float value) {
for (int i = 0; i < size; ++i)
ASSERT_FLOAT_EQ(value, data[i]) << "i=" << i;
}
void VerifyBusWithEpsilon(const AudioBus* result, const AudioBus* expected,
float epsilon) {
ASSERT_EQ(expected->channels(), result->channels());
ASSERT_EQ(expected->frames(), result->frames());
for (int ch = 0; ch < result->channels(); ++ch) {
for (int i = 0; i < result->frames(); ++i) {
SCOPED_TRACE(base::StringPrintf("ch=%d, i=%d", ch, i));
if (epsilon == 0) {
ASSERT_FLOAT_EQ(expected->channel(ch)[i], result->channel(ch)[i]);
} else {
ASSERT_NEAR(expected->channel(ch)[i], result->channel(ch)[i],
epsilon);
}
}
}
}
void VerifyBus(const AudioBus* result, const AudioBus* expected) {
VerifyBusWithEpsilon(result, expected, 0);
}
void VerifyChannelData(AudioBus* bus) {
for (int i = 0; i < bus->channels(); ++i) {
ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(
bus->channel(i)) & (AudioBus::kChannelAlignment - 1));
std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i);
}
for (int i = 0; i < bus->channels(); ++i)
VerifyValue(bus->channel(i), bus->frames(), i);
bus->Zero();
for (int i = 0; i < bus->channels(); ++i)
VerifyValue(bus->channel(i), bus->frames(), 0);
}
void CopyTest(AudioBus* bus1, AudioBus* bus2) {
for (int i = 0; i < bus1->channels(); ++i)
std::fill(bus1->channel(i), bus1->channel(i) + bus1->frames(), i);
bus2->Zero();
bus1->CopyTo(bus2);
VerifyBus(bus1, bus2);
bus1->Zero();
bus2->CopyTo(bus1);
VerifyBus(bus2, bus1);
}
protected:
std::vector<float*> data_;
DISALLOW_COPY_AND_ASSIGN(AudioBusTest);
};
TEST_F(AudioBusTest, Create) {
scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
VerifyParams(bus.get());
VerifyChannelData(bus.get());
}
TEST_F(AudioBusTest, CreateUsingAudioParameters) {
scoped_ptr<AudioBus> bus = AudioBus::Create(AudioParameters(
AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
kFrameCount));
VerifyParams(bus.get());
VerifyChannelData(bus.get());
}
TEST_F(AudioBusTest, WrapVector) {
data_.reserve(kChannels);
for (int i = 0; i < kChannels; ++i) {
data_.push_back(static_cast<float*>(base::AlignedAlloc(
sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
}
scoped_ptr<AudioBus> bus = AudioBus::WrapVector(kFrameCount, data_);
VerifyParams(bus.get());
VerifyChannelData(bus.get());
}
TEST_F(AudioBusTest, WrapMemory) {
AudioParameters params(
AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
kFrameCount);
int data_size = AudioBus::CalculateMemorySize(params);
scoped_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>(
base::AlignedAlloc(data_size, AudioBus::kChannelAlignment)));
static const float kTestValue = 3;
std::fill(
data.get(), data.get() + data_size / sizeof(*data.get()), kTestValue);
scoped_ptr<AudioBus> bus = AudioBus::WrapMemory(params, data.get());
for (int i = 0; i < bus->channels(); ++i)
VerifyValue(bus->channel(i), bus->frames(), kTestValue);
VerifyParams(bus.get());
VerifyChannelData(bus.get());
EXPECT_GE(bus->channel(0), data.get());
EXPECT_LT(bus->channel(bus->channels() - 1) + bus->frames(),
data.get() + data_size / sizeof(*data.get()));
}
TEST_F(AudioBusTest, CopyTo) {
AudioParameters params(
AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
kFrameCount);
scoped_ptr<AudioBus> bus1 = AudioBus::Create(kChannels, kFrameCount);
scoped_ptr<AudioBus> bus2 = AudioBus::Create(params);
{
SCOPED_TRACE("Created");
CopyTest(bus1.get(), bus2.get());
}
{
SCOPED_TRACE("Wrapped Vector");
data_.reserve(kChannels);
for (int i = 0; i < kChannels; ++i) {
data_.push_back(static_cast<float*>(base::AlignedAlloc(
sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
}
bus2 = AudioBus::WrapVector(kFrameCount, data_);
CopyTest(bus1.get(), bus2.get());
}
{
SCOPED_TRACE("Wrapped Memory");
scoped_ptr<float, base::AlignedFreeDeleter> data(
static_cast<float*>(base::AlignedAlloc(
AudioBus::CalculateMemorySize(params),
AudioBus::kChannelAlignment)));
bus2 = AudioBus::WrapMemory(params, data.get());
CopyTest(bus1.get(), bus2.get());
}
}
TEST_F(AudioBusTest, Zero) {
scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
for (int i = 0; i < bus->channels(); ++i)
std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
bus->ZeroFrames(kFrameCount / 2);
for (int i = 0; i < bus->channels(); ++i) {
SCOPED_TRACE("First Half Zero");
VerifyValue(bus->channel(i), kFrameCount / 2, 0);
VerifyValue(bus->channel(i) + kFrameCount / 2,
kFrameCount - kFrameCount / 2, i + 1);
}
for (int i = 0; i < bus->channels(); ++i)
std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
bus->ZeroFramesPartial(kFrameCount / 2, kFrameCount - kFrameCount / 2);
for (int i = 0; i < bus->channels(); ++i) {
SCOPED_TRACE("Last Half Zero");
VerifyValue(bus->channel(i) + kFrameCount / 2,
kFrameCount - kFrameCount / 2, 0);
VerifyValue(bus->channel(i), kFrameCount / 2, i + 1);
}
for (int i = 0; i < bus->channels(); ++i)
std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
bus->Zero();
for (int i = 0; i < bus->channels(); ++i) {
SCOPED_TRACE("All Zero");
VerifyValue(bus->channel(i), bus->frames(), 0);
}
}
static const int kTestVectorSize = 10;
static const uint8 kTestVectorUint8[kTestVectorSize] = {
0, -kint8min, kuint8max, 0, kint8max / 2 + 128, kint8min / 2 + 128,
-kint8min, kuint8max, -kint8min, -kint8min };
static const int16 kTestVectorInt16[kTestVectorSize] = {
kint16min, 0, kint16max, kint16min, kint16max / 2, kint16min / 2,
0, kint16max, 0, 0 };
static const int32 kTestVectorInt32[kTestVectorSize] = {
kint32min, 0, kint32max, kint32min, kint32max / 2, kint32min / 2,
0, kint32max, 0, 0 };
static const int kTestVectorFrames = kTestVectorSize / 2;
static const float kTestVectorResult[][kTestVectorFrames] = {
{ -1, 1, 0.5, 0, 0 }, { 0, -1, -0.5, 1, 0 }};
static const int kTestVectorChannels = arraysize(kTestVectorResult);
TEST_F(AudioBusTest, FromInterleaved) {
scoped_ptr<AudioBus> bus = AudioBus::Create(
kTestVectorChannels, kTestVectorFrames);
scoped_ptr<AudioBus> expected = AudioBus::Create(
kTestVectorChannels, kTestVectorFrames);
for (int ch = 0; ch < kTestVectorChannels; ++ch) {
memcpy(expected->channel(ch), kTestVectorResult[ch],
kTestVectorFrames * sizeof(*expected->channel(ch)));
}
{
SCOPED_TRACE("uint8");
bus->Zero();
bus->FromInterleaved(
kTestVectorUint8, kTestVectorFrames, sizeof(*kTestVectorUint8));
VerifyBusWithEpsilon(bus.get(), expected.get(), 1.0f / (kuint8max - 1));
}
{
SCOPED_TRACE("int16");
bus->Zero();
bus->FromInterleaved(
kTestVectorInt16, kTestVectorFrames, sizeof(*kTestVectorInt16));
VerifyBusWithEpsilon(bus.get(), expected.get(), 1.0f / (kuint16max + 1.0f));
}
{
SCOPED_TRACE("int32");
bus->Zero();
bus->FromInterleaved(
kTestVectorInt32, kTestVectorFrames, sizeof(*kTestVectorInt32));
VerifyBusWithEpsilon(bus.get(), expected.get(), 1.0f / (kuint32max + 1.0f));
}
}
TEST_F(AudioBusTest, FromInterleavedPartial) {
static const int kPartialStart = 1;
static const int kPartialFrames = 2;
ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrames);
scoped_ptr<AudioBus> bus = AudioBus::Create(
kTestVectorChannels, kTestVectorFrames);
scoped_ptr<AudioBus> expected = AudioBus::Create(
kTestVectorChannels, kTestVectorFrames);
expected->Zero();
for (int ch = 0; ch < kTestVectorChannels; ++ch) {
memcpy(expected->channel(ch) + kPartialStart,
kTestVectorResult[ch] + kPartialStart,
kPartialFrames * sizeof(*expected->channel(ch)));
}
bus->Zero();
bus->FromInterleavedPartial(
kTestVectorInt32 + kPartialStart * bus->channels(), kPartialStart,
kPartialFrames, sizeof(*kTestVectorInt32));
VerifyBus(bus.get(), expected.get());
}
TEST_F(AudioBusTest, ToInterleaved) {
scoped_ptr<AudioBus> bus = AudioBus::Create(
kTestVectorChannels, kTestVectorFrames);
for (int ch = 0; ch < bus->channels(); ++ch) {
memcpy(bus->channel(ch), kTestVectorResult[ch],
kTestVectorFrames * sizeof(*bus->channel(ch)));
}
{
SCOPED_TRACE("uint8");
uint8 test_array[arraysize(kTestVectorUint8)];
bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorUint8), test_array);
ASSERT_EQ(memcmp(
test_array, kTestVectorUint8, sizeof(kTestVectorUint8)), 0);
}
{
SCOPED_TRACE("int16");
int16 test_array[arraysize(kTestVectorInt16)];
bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt16), test_array);
ASSERT_EQ(memcmp(
test_array, kTestVectorInt16, sizeof(kTestVectorInt16)), 0);
}
{
SCOPED_TRACE("int32");
int32 test_array[arraysize(kTestVectorInt32)];
bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt32), test_array);
int32 fixed_test_array[arraysize(kTestVectorInt32)];
memcpy(fixed_test_array, kTestVectorInt32, sizeof(kTestVectorInt32));
ASSERT_EQ(fixed_test_array[4], kint32max / 2);
fixed_test_array[4]++;
ASSERT_TRUE(
memcmp(test_array, kTestVectorInt32, sizeof(kTestVectorInt32)) == 0 ||
memcmp(test_array, fixed_test_array, sizeof(fixed_test_array)) == 0);
}
}
TEST_F(AudioBusTest, ToInterleavedPartial) {
static const int kPartialStart = 1;
static const int kPartialFrames = 2;
ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrames);
scoped_ptr<AudioBus> expected = AudioBus::Create(
kTestVectorChannels, kTestVectorFrames);
for (int ch = 0; ch < kTestVectorChannels; ++ch) {
memcpy(expected->channel(ch), kTestVectorResult[ch],
kTestVectorFrames * sizeof(*expected->channel(ch)));
}
int16 test_array[arraysize(kTestVectorInt16)];
expected->ToInterleavedPartial(
kPartialStart, kPartialFrames, sizeof(*kTestVectorInt16), test_array);
ASSERT_EQ(memcmp(
test_array, kTestVectorInt16 + kPartialStart * kTestVectorChannels,
kPartialFrames * sizeof(*kTestVectorInt16) * kTestVectorChannels), 0);
}
TEST_F(AudioBusTest, Scale) {
scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
static const float kFillValue = 1;
for (int i = 0; i < bus->channels(); ++i)
std::fill(bus->channel(i), bus->channel(i) + bus->frames(), kFillValue);
bus->Scale(-1);
for (int i = 0; i < bus->channels(); ++i) {
SCOPED_TRACE("Invalid Scale");
VerifyValue(bus->channel(i), bus->frames(), kFillValue);
}
static const float kVolume = 0.5;
bus->Scale(kVolume);
for (int i = 0; i < bus->channels(); ++i) {
SCOPED_TRACE("Half Scale");
VerifyValue(bus->channel(i), bus->frames(), kFillValue * kVolume);
}
bus->Scale(0);
for (int i = 0; i < bus->channels(); ++i) {
SCOPED_TRACE("Zero Scale");
VerifyValue(bus->channel(i), bus->frames(), 0);
}
}
}