| Index: media/base/audio_bus_unittest.cc
|
| diff --git a/media/base/audio_bus_unittest.cc b/media/base/audio_bus_unittest.cc
|
| index 1f60c326fefb8b5659177dc132262b407a08bdfd..f6c4b64339bb6b130534153e5d7c5aa914ce7b29 100644
|
| --- a/media/base/audio_bus_unittest.cc
|
| +++ b/media/base/audio_bus_unittest.cc
|
| @@ -2,6 +2,10 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#include <limits>
|
| +
|
| +#include "base/stringprintf.h"
|
| +#include "base/time.h"
|
| #include "media/audio/audio_parameters.h"
|
| #include "media/base/audio_bus.h"
|
| #include "media/base/channel_layout.h"
|
| @@ -9,9 +13,9 @@
|
|
|
| static const int kChannels = 6;
|
| static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_5_1;
|
| -// Use a buffer size which is intentionally not a multiple of 16; see
|
| -// kChannelAlignment in audio_bus.cc.
|
| -static const int kFrameCount = 1234;
|
| +// Use a buffer size which is intentionally not a multiple of kChannelAlignment.
|
| +static const int kFrameCount = media::AudioBus::kChannelAlignment * 128 - 1;
|
| +static const int kSampleRate = 48000;
|
|
|
| namespace media {
|
|
|
| @@ -34,12 +38,25 @@ class AudioBusTest : public testing::Test {
|
| ASSERT_FLOAT_EQ(value, data[i]);
|
| }
|
|
|
| + // Verify values for each channel in |result| against |expected|.
|
| + void VerifyBus(const AudioBus* result, const AudioBus* expected) {
|
| + 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));
|
| + ASSERT_FLOAT_EQ(expected->channel(ch)[i], result->channel(ch)[i]);
|
| + }
|
| + }
|
| + }
|
| +
|
| // Read and write to the full extent of the allocated channel data. Also test
|
| // the Zero() method and verify it does as advertised. Also test data if data
|
| - // is 16-byte aligned as advertised (see kChannelAlignment in audio_bus.cc).
|
| + // is 16-byte aligned as advertised (see kChannelAlignment in audio_bus.h).
|
| void VerifyChannelData(AudioBus* bus) {
|
| for (int i = 0; i < bus->channels(); ++i) {
|
| - ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(bus->channel(i)) & 0x0F);
|
| + ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(
|
| + bus->channel(i)) & (AudioBus::kChannelAlignment - 1));
|
| std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i);
|
| }
|
|
|
| @@ -51,6 +68,22 @@ class AudioBusTest : public testing::Test {
|
| VerifyValue(bus->channel(i), bus->frames(), 0);
|
| }
|
|
|
| + // Verify copying to and from |bus1| and |bus2|.
|
| + void CopyTest(AudioBus* bus1, AudioBus* bus2) {
|
| + // Fill |bus1| with dummy data.
|
| + for (int i = 0; i < bus1->channels(); ++i)
|
| + std::fill(bus1->channel(i), bus1->channel(i) + bus1->frames(), i);
|
| +
|
| + // Verify copy from |bus1| to |bus2|.
|
| + bus2->Zero();
|
| + bus1->CopyTo(bus2);
|
| + VerifyBus(bus1, bus2);
|
| +
|
| + // Verify copy from |bus2| to |bus1|.
|
| + bus1->Zero();
|
| + bus2->CopyTo(bus1);
|
| + VerifyBus(bus2, bus1);
|
| + }
|
|
|
| protected:
|
| std::vector<float*> data_;
|
| @@ -68,18 +101,18 @@ TEST_F(AudioBusTest, Create) {
|
| // Verify Create(...) using AudioParameters works as advertised.
|
| TEST_F(AudioBusTest, CreateUsingAudioParameters) {
|
| scoped_ptr<AudioBus> bus = AudioBus::Create(AudioParameters(
|
| - AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, 48000, 32,
|
| + AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
|
| kFrameCount));
|
| VerifyParams(bus.get());
|
| VerifyChannelData(bus.get());
|
| }
|
|
|
| -// Verify an AudioBus created via wrapping works as advertised.
|
| -TEST_F(AudioBusTest, Wrap) {
|
| +// Verify an AudioBus created via wrapping a vector works as advertised.
|
| +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, 16)));
|
| + sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
|
| }
|
|
|
| scoped_ptr<AudioBus> bus = AudioBus::WrapVector(kFrameCount, data_);
|
| @@ -87,22 +120,70 @@ TEST_F(AudioBusTest, Wrap) {
|
| VerifyChannelData(bus.get());
|
| }
|
|
|
| +// Verify an AudioBus created via wrapping a memory block works as advertised.
|
| +TEST_F(AudioBusTest, WrapMemory) {
|
| + AudioParameters params(
|
| + AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
|
| + kFrameCount);
|
| + int data_size = AudioBus::CalculateMemorySize(params);
|
| + scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data(static_cast<float*>(
|
| + base::AlignedAlloc(data_size, AudioBus::kChannelAlignment)));
|
| +
|
| + // Fill the memory with a test value we can check for after wrapping.
|
| + 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());
|
| + // Verify the test value we filled prior to wrapping.
|
| + for (int i = 0; i < bus->channels(); ++i)
|
| + VerifyValue(bus->channel(i), bus->frames(), kTestValue);
|
| + VerifyParams(bus.get());
|
| + VerifyChannelData(bus.get());
|
| +
|
| + // Verify the channel vectors lie within the provided memory block.
|
| + EXPECT_GE(bus->channel(0), data.get());
|
| + EXPECT_LT(bus->channel(bus->channels() - 1) + bus->frames(),
|
| + data.get() + data_size / sizeof(*data.get()));
|
| +}
|
| +
|
| // Simulate a shared memory transfer and verify results.
|
| -TEST_F(AudioBusTest, AudioData) {
|
| +TEST_F(AudioBusTest, CopyTo) {
|
| + // Create one bus with AudioParameters and the other through direct values to
|
| + // test for parity between the Create() functions.
|
| + AudioParameters params(
|
| + AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
|
| + kFrameCount);
|
| scoped_ptr<AudioBus> bus1 = AudioBus::Create(kChannels, kFrameCount);
|
| - scoped_ptr<AudioBus> bus2 = AudioBus::Create(kChannels, kFrameCount);
|
| + scoped_ptr<AudioBus> bus2 = AudioBus::Create(params);
|
|
|
| - // Fill |bus1| with dummy data and zero out |bus2|.
|
| - for (int i = 0; i < bus1->channels(); ++i)
|
| - std::fill(bus1->channel(i), bus1->channel(i) + bus1->frames(), i);
|
| - bus2->Zero();
|
| + {
|
| + SCOPED_TRACE("Created");
|
| + CopyTest(bus1.get(), bus2.get());
|
| + }
|
| + {
|
| + SCOPED_TRACE("Wrapped Vector");
|
| + // Try a copy to an AudioBus wrapping a 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)));
|
| + }
|
|
|
| - // Transfer audio data from |bus1| to |bus2|.
|
| - ASSERT_EQ(bus1->data_size(), bus2->data_size());
|
| - memcpy(bus2->data(), bus1->data(), bus1->data_size());
|
| + bus2 = AudioBus::WrapVector(kFrameCount, data_);
|
| + CopyTest(bus1.get(), bus2.get());
|
| + }
|
| + {
|
| + SCOPED_TRACE("Wrapped Memory");
|
| + // Try a copy to an AudioBus wrapping a memory block.
|
| + scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data(
|
| + static_cast<float*>(base::AlignedAlloc(
|
| + AudioBus::CalculateMemorySize(params),
|
| + AudioBus::kChannelAlignment)));
|
|
|
| - for (int i = 0; i < bus2->channels(); ++i)
|
| - VerifyValue(bus2->channel(i), bus2->frames(), i);
|
| + bus2 = AudioBus::WrapMemory(params, data.get());
|
| + CopyTest(bus1.get(), bus2.get());
|
| + }
|
| }
|
|
|
| // Verify Zero() and ZeroFrames(...) utility methods work as advertised.
|
| @@ -124,4 +205,82 @@ TEST_F(AudioBusTest, Zero) {
|
| VerifyValue(bus->channel(i), bus->frames(), 0);
|
| }
|
|
|
| +// Each test vector represents two channels of data in the following arbitrary
|
| +// layout: <min, zero, max, min, zero, max, zero, zero>.
|
| +static const int kTestVectorSize = 8;
|
| +static const uint8 kTestVectorUint8[kTestVectorSize] = {
|
| + 0, -kint8min, kuint8max, 0, -kint8min, kuint8max, -kint8min, -kint8min };
|
| +static const int16 kTestVectorInt16[kTestVectorSize] = {
|
| + kint16min, 0, kint16max, kint16min, 0, kint16max, 0, 0 };
|
| +static const int32 kTestVectorInt32[kTestVectorSize] = {
|
| + kint32min, 0, kint32max, kint32min, 0, kint32max, 0, 0 };
|
| +
|
| +// Expected results.
|
| +static const int kTestVectorFrames = kTestVectorSize / 2;
|
| +static const float kTestVectorResult[][kTestVectorFrames] = {
|
| + { -1, 1, 0, 0 }, { 0, -1, 1, 0 }};
|
| +static const int kTestVectorChannels = arraysize(kTestVectorResult);
|
| +
|
| +// Verify FromInterleaved() deinterleaves audio in supported formats correctly.
|
| +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->FromInterleaved(
|
| + kTestVectorUint8, kTestVectorFrames, sizeof(*kTestVectorUint8));
|
| + VerifyBus(bus.get(), expected.get());
|
| + }
|
| + {
|
| + SCOPED_TRACE("int16");
|
| + bus->FromInterleaved(
|
| + kTestVectorInt16, kTestVectorFrames, sizeof(*kTestVectorInt16));
|
| + VerifyBus(bus.get(), expected.get());
|
| + }
|
| + {
|
| + SCOPED_TRACE("int32");
|
| + bus->FromInterleaved(
|
| + kTestVectorInt32, kTestVectorFrames, sizeof(*kTestVectorInt32));
|
| + VerifyBus(bus.get(), expected.get());
|
| + }
|
| +}
|
| +
|
| +// Verify ToInterleaved() interleaves audio in suported formats correctly.
|
| +TEST_F(AudioBusTest, ToInterleaved) {
|
| + scoped_ptr<AudioBus> bus = AudioBus::Create(
|
| + kTestVectorChannels, kTestVectorFrames);
|
| + // Fill the bus with our test vector.
|
| + for (int ch = 0; ch < kTestVectorChannels; ++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, arraysize(kTestVectorUint8)), 0);
|
| + }
|
| + {
|
| + SCOPED_TRACE("int16");
|
| + int16 test_array[arraysize(kTestVectorInt16)];
|
| + bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt16), test_array);
|
| + ASSERT_EQ(memcmp(
|
| + test_array, kTestVectorInt16, arraysize(kTestVectorInt16)), 0);
|
| + }
|
| + {
|
| + SCOPED_TRACE("int32");
|
| + int32 test_array[arraysize(kTestVectorInt32)];
|
| + bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt32), test_array);
|
| + ASSERT_EQ(memcmp(
|
| + test_array, kTestVectorInt32, arraysize(kTestVectorInt32)), 0);
|
| + }
|
| +}
|
| +
|
| } // namespace media
|
|
|