Index: media/base/audio_bus_unittest.cc |
diff --git a/media/base/audio_bus_unittest.cc b/media/base/audio_bus_unittest.cc |
index 02809db72379db083e913e5fe79b29a32a399e96..66585b2a9a195c4c00789eb68290d3493fcdfc6e 100644 |
--- a/media/base/audio_bus_unittest.cc |
+++ b/media/base/audio_bus_unittest.cc |
@@ -14,6 +14,7 @@ |
#include "build/build_config.h" |
#include "media/base/audio_bus.h" |
#include "media/base/audio_parameters.h" |
+#include "media/base/audio_sample_types.h" |
#include "media/base/channel_layout.h" |
#include "media/base/fake_audio_render_callback.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -34,26 +35,27 @@ class AudioBusTest : public testing::Test { |
base::AlignedFree(data_[i]); |
} |
- // Validate parameters returned by AudioBus v.s. the constructed parameters. |
- void VerifyParams(AudioBus* bus) { |
+ void VerifyChannelAndFrameCount(AudioBus* bus) { |
EXPECT_EQ(kChannels, bus->channels()); |
EXPECT_EQ(kFrameCount, bus->frames()); |
} |
- void VerifyValue(const float data[], int size, float value) { |
+ void VerifyArrayIsFilledWithValue(const float data[], int size, float value) { |
for (int i = 0; i < size; ++i) |
ASSERT_FLOAT_EQ(value, data[i]) << "i=" << i; |
} |
// Verify values for each channel in |result| are within |epsilon| of |
// |expected|. If |epsilon| exactly equals 0, uses FLOAT_EQ macro. |
- void VerifyBusWithEpsilon(const AudioBus* result, const AudioBus* expected, |
- float epsilon) { |
+ void VerifyAreEqualWithEpsilon(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 { |
@@ -65,26 +67,30 @@ class AudioBusTest : public testing::Test { |
} |
// Verify values for each channel in |result| against |expected|. |
- void VerifyBus(const AudioBus* result, const AudioBus* expected) { |
- VerifyBusWithEpsilon(result, expected, 0); |
+ void VerifyAreEqual(const AudioBus* result, const AudioBus* expected) { |
+ VerifyAreEqualWithEpsilon(result, expected, 0); |
} |
// 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.h). |
- void VerifyChannelData(AudioBus* bus) { |
+ void VerifyReadWriteAndAlignment(AudioBus* bus) { |
for (int i = 0; i < bus->channels(); ++i) { |
+ // Verify that the address returned by channel(i) is a multiple of |
+ // AudioBus::kChannelAlignment. |
ASSERT_EQ(0U, reinterpret_cast<uintptr_t>( |
bus->channel(i)) & (AudioBus::kChannelAlignment - 1)); |
+ |
+ // Write into the channel buffer. |
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); |
+ VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), i); |
bus->Zero(); |
for (int i = 0; i < bus->channels(); ++i) |
- VerifyValue(bus->channel(i), bus->frames(), 0); |
+ VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0); |
} |
// Verify copying to and from |bus1| and |bus2|. |
@@ -96,12 +102,12 @@ class AudioBusTest : public testing::Test { |
// Verify copy from |bus1| to |bus2|. |
bus2->Zero(); |
bus1->CopyTo(bus2); |
- VerifyBus(bus1, bus2); |
+ VerifyAreEqual(bus1, bus2); |
// Verify copy from |bus2| to |bus1|. |
bus1->Zero(); |
bus2->CopyTo(bus1); |
- VerifyBus(bus2, bus1); |
+ VerifyAreEqual(bus2, bus1); |
} |
protected: |
@@ -113,8 +119,8 @@ class AudioBusTest : public testing::Test { |
// Verify basic Create(...) method works as advertised. |
TEST_F(AudioBusTest, Create) { |
std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount); |
- VerifyParams(bus.get()); |
- VerifyChannelData(bus.get()); |
+ VerifyChannelAndFrameCount(bus.get()); |
+ VerifyReadWriteAndAlignment(bus.get()); |
} |
// Verify Create(...) using AudioParameters works as advertised. |
@@ -122,8 +128,8 @@ TEST_F(AudioBusTest, CreateUsingAudioParameters) { |
std::unique_ptr<AudioBus> bus = AudioBus::Create( |
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, |
kSampleRate, 32, kFrameCount)); |
- VerifyParams(bus.get()); |
- VerifyChannelData(bus.get()); |
+ VerifyChannelAndFrameCount(bus.get()); |
+ VerifyReadWriteAndAlignment(bus.get()); |
} |
// Verify an AudioBus created via wrapping a vector works as advertised. |
@@ -135,8 +141,8 @@ TEST_F(AudioBusTest, WrapVector) { |
} |
std::unique_ptr<AudioBus> bus = AudioBus::WrapVector(kFrameCount, data_); |
- VerifyParams(bus.get()); |
- VerifyChannelData(bus.get()); |
+ VerifyChannelAndFrameCount(bus.get()); |
+ VerifyReadWriteAndAlignment(bus.get()); |
} |
// Verify an AudioBus created via wrapping a memory block works as advertised. |
@@ -156,9 +162,9 @@ TEST_F(AudioBusTest, WrapMemory) { |
std::unique_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()); |
+ VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), kTestValue); |
+ VerifyChannelAndFrameCount(bus.get()); |
+ VerifyReadWriteAndAlignment(bus.get()); |
// Verify the channel vectors lie within the provided memory block. |
EXPECT_GE(bus->channel(0), data.get()); |
@@ -217,9 +223,9 @@ TEST_F(AudioBusTest, Zero) { |
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); |
+ VerifyArrayIsFilledWithValue(bus->channel(i), kFrameCount / 2, 0); |
+ VerifyArrayIsFilledWithValue(bus->channel(i) + kFrameCount / 2, |
+ kFrameCount - kFrameCount / 2, i + 1); |
} |
EXPECT_FALSE(bus->AreFramesZero()); |
@@ -231,9 +237,9 @@ TEST_F(AudioBusTest, Zero) { |
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); |
+ VerifyArrayIsFilledWithValue(bus->channel(i) + kFrameCount / 2, |
+ kFrameCount - kFrameCount / 2, 0); |
+ VerifyArrayIsFilledWithValue(bus->channel(i), kFrameCount / 2, i + 1); |
} |
EXPECT_FALSE(bus->AreFramesZero()); |
@@ -245,7 +251,7 @@ TEST_F(AudioBusTest, Zero) { |
bus->Zero(); |
for (int i = 0; i < bus->channels(); ++i) { |
SCOPED_TRACE("All Zero"); |
- VerifyValue(bus->channel(i), bus->frames(), 0); |
+ VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0); |
} |
EXPECT_TRUE(bus->AreFramesZero()); |
} |
@@ -264,48 +270,95 @@ static const int16_t kTestVectorInt16[kTestVectorSize] = { |
static const int32_t kTestVectorInt32[kTestVectorSize] = { |
INT32_MIN, 0, INT32_MAX, INT32_MIN, INT32_MAX / 2, |
INT32_MIN / 2, 0, INT32_MAX, 0, 0}; |
+static const float kTestVectorFloat32[kTestVectorSize] = { |
+ -1.0f, 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f}; |
// Expected results. |
-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); |
+static const int kTestVectorFrameCount = kTestVectorSize / 2; |
+static const float kTestVectorResult[][kTestVectorFrameCount] = { |
+ {-1.0f, 1.0f, 0.5f, 0.0f, 0.0f}, |
+ {0.0f, -1.0f, -0.5f, 1.0f, 0.0f}}; |
+static const int kTestVectorChannelCount = arraysize(kTestVectorResult); |
// Verify FromInterleaved() deinterleaves audio in supported formats correctly. |
TEST_F(AudioBusTest, FromInterleaved) { |
std::unique_ptr<AudioBus> bus = |
- AudioBus::Create(kTestVectorChannels, kTestVectorFrames); |
+ AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
std::unique_ptr<AudioBus> expected = |
- AudioBus::Create(kTestVectorChannels, kTestVectorFrames); |
- for (int ch = 0; ch < kTestVectorChannels; ++ch) { |
+ AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
+ for (int ch = 0; ch < kTestVectorChannelCount; ++ch) { |
memcpy(expected->channel(ch), kTestVectorResult[ch], |
- kTestVectorFrames * sizeof(*expected->channel(ch))); |
+ kTestVectorFrameCount * sizeof(*expected->channel(ch))); |
} |
+ |
+ // Test deprecated version that takes |bytes_per_sample| as an input. |
{ |
SCOPED_TRACE("uint8_t"); |
bus->Zero(); |
- bus->FromInterleaved( |
- kTestVectorUint8, kTestVectorFrames, sizeof(*kTestVectorUint8)); |
+ bus->FromInterleaved(kTestVectorUint8, kTestVectorFrameCount, |
+ sizeof(*kTestVectorUint8)); |
+ |
// Biased uint8_t calculations have poor precision, so the epsilon here is |
// slightly more permissive than int16_t and int32_t calculations. |
- VerifyBusWithEpsilon(bus.get(), expected.get(), |
- 1.0f / (std::numeric_limits<uint8_t>::max() - 1)); |
+ VerifyAreEqualWithEpsilon(bus.get(), expected.get(), |
+ 1.0f / (std::numeric_limits<uint8_t>::max() - 1)); |
} |
{ |
SCOPED_TRACE("int16_t"); |
bus->Zero(); |
- bus->FromInterleaved( |
- kTestVectorInt16, kTestVectorFrames, sizeof(*kTestVectorInt16)); |
- VerifyBusWithEpsilon(bus.get(), expected.get(), |
- 1.0f / (std::numeric_limits<uint16_t>::max() + 1.0f)); |
+ bus->FromInterleaved(kTestVectorInt16, kTestVectorFrameCount, |
+ sizeof(*kTestVectorInt16)); |
+ VerifyAreEqualWithEpsilon( |
+ bus.get(), expected.get(), |
+ 1.0f / (std::numeric_limits<uint16_t>::max() + 1.0f)); |
} |
{ |
SCOPED_TRACE("int32_t"); |
bus->Zero(); |
- bus->FromInterleaved( |
- kTestVectorInt32, kTestVectorFrames, sizeof(*kTestVectorInt32)); |
- VerifyBusWithEpsilon(bus.get(), expected.get(), |
- 1.0f / (std::numeric_limits<uint32_t>::max() + 1.0f)); |
+ bus->FromInterleaved(kTestVectorInt32, kTestVectorFrameCount, |
+ sizeof(*kTestVectorInt32)); |
+ |
+ VerifyAreEqualWithEpsilon( |
+ bus.get(), expected.get(), |
+ 1.0f / (std::numeric_limits<uint32_t>::max() + 1.0f)); |
+ } |
+ |
+ // Test non-deprecated version that takes SampleTypeTraits as a template |
+ // parameter. |
+ { |
+ SCOPED_TRACE("UnsignedInt8SampleTypeTraits"); |
+ bus->Zero(); |
+ bus->FromInterleaved<UnsignedInt8SampleTypeTraits>(kTestVectorUint8, |
+ kTestVectorFrameCount); |
+ // Biased uint8_t calculations have poor precision, so the epsilon here is |
+ // slightly more permissive than int16_t and int32_t calculations. |
+ VerifyAreEqualWithEpsilon(bus.get(), expected.get(), |
+ 1.0f / (std::numeric_limits<uint8_t>::max() - 1)); |
+ } |
+ { |
+ SCOPED_TRACE("SignedInt16SampleTypeTraits"); |
+ bus->Zero(); |
+ bus->FromInterleaved<SignedInt16SampleTypeTraits>(kTestVectorInt16, |
+ kTestVectorFrameCount); |
+ VerifyAreEqualWithEpsilon( |
+ bus.get(), expected.get(), |
+ 1.0f / (std::numeric_limits<uint16_t>::max() + 1.0f)); |
+ } |
+ { |
+ SCOPED_TRACE("SignedInt32SampleTypeTraits"); |
+ bus->Zero(); |
+ bus->FromInterleaved<SignedInt32SampleTypeTraits>(kTestVectorInt32, |
+ kTestVectorFrameCount); |
+ VerifyAreEqualWithEpsilon( |
+ bus.get(), expected.get(), |
+ 1.0f / (std::numeric_limits<uint32_t>::max() + 1.0f)); |
+ } |
+ { |
+ SCOPED_TRACE("Float32SampleTypeTraits"); |
+ bus->Zero(); |
+ bus->FromInterleaved<Float32SampleTypeTraits>(kTestVectorFloat32, |
+ kTestVectorFrameCount); |
+ VerifyAreEqual(bus.get(), expected.get()); |
} |
} |
@@ -314,48 +367,65 @@ TEST_F(AudioBusTest, FromInterleavedPartial) { |
// Only deinterleave the middle two frames in each channel. |
static const int kPartialStart = 1; |
static const int kPartialFrames = 2; |
- ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrames); |
+ ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrameCount); |
std::unique_ptr<AudioBus> bus = |
- AudioBus::Create(kTestVectorChannels, kTestVectorFrames); |
+ AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
std::unique_ptr<AudioBus> expected = |
- AudioBus::Create(kTestVectorChannels, kTestVectorFrames); |
+ AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
expected->Zero(); |
- for (int ch = 0; ch < kTestVectorChannels; ++ch) { |
+ for (int ch = 0; ch < kTestVectorChannelCount; ++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 deprecated version that takes |bytes_per_sample| as an input. |
+ { |
+ SCOPED_TRACE("int32_t"); |
+ bus->Zero(); |
+ bus->FromInterleavedPartial( |
+ kTestVectorInt32 + kPartialStart * bus->channels(), kPartialStart, |
+ kPartialFrames, sizeof(*kTestVectorInt32)); |
+ VerifyAreEqual(bus.get(), expected.get()); |
+ } |
+ |
+ // Test non-deprecated version that takes SampleTypeTraits as a template |
+ // parameter. |
+ { |
+ SCOPED_TRACE("SignedInt32SampleTypeTraits"); |
+ bus->Zero(); |
+ bus->FromInterleavedPartial<SignedInt32SampleTypeTraits>( |
+ kTestVectorInt32 + kPartialStart * bus->channels(), kPartialStart, |
+ kPartialFrames); |
+ VerifyAreEqual(bus.get(), expected.get()); |
+ } |
} |
// Verify ToInterleaved() interleaves audio in suported formats correctly. |
TEST_F(AudioBusTest, ToInterleaved) { |
std::unique_ptr<AudioBus> bus = |
- AudioBus::Create(kTestVectorChannels, kTestVectorFrames); |
+ AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
// Fill the bus with our test vector. |
for (int ch = 0; ch < bus->channels(); ++ch) { |
memcpy(bus->channel(ch), kTestVectorResult[ch], |
- kTestVectorFrames * sizeof(*bus->channel(ch))); |
+ kTestVectorFrameCount * sizeof(*bus->channel(ch))); |
} |
+ |
+ // Test deprecated version that takes |bytes_per_sample| as an input. |
{ |
SCOPED_TRACE("uint8_t"); |
uint8_t test_array[arraysize(kTestVectorUint8)]; |
bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorUint8), test_array); |
- ASSERT_EQ(memcmp( |
- test_array, kTestVectorUint8, sizeof(kTestVectorUint8)), 0); |
+ ASSERT_EQ(0, |
+ memcmp(test_array, kTestVectorUint8, sizeof(kTestVectorUint8))); |
} |
{ |
SCOPED_TRACE("int16_t"); |
int16_t test_array[arraysize(kTestVectorInt16)]; |
bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt16), test_array); |
- ASSERT_EQ(memcmp( |
- test_array, kTestVectorInt16, sizeof(kTestVectorInt16)), 0); |
+ ASSERT_EQ(0, |
+ memcmp(test_array, kTestVectorInt16, sizeof(kTestVectorInt16))); |
} |
{ |
SCOPED_TRACE("int32_t"); |
@@ -364,14 +434,60 @@ TEST_F(AudioBusTest, ToInterleaved) { |
// Some compilers get better precision than others on the half-max test, so |
// let the test pass with an off by one check on the half-max. |
- int32_t fixed_test_array[arraysize(kTestVectorInt32)]; |
- memcpy(fixed_test_array, kTestVectorInt32, sizeof(kTestVectorInt32)); |
- ASSERT_EQ(fixed_test_array[4], std::numeric_limits<int32_t>::max() / 2); |
- fixed_test_array[4]++; |
+ int32_t alternative_acceptable_result[arraysize(kTestVectorInt32)]; |
+ memcpy(alternative_acceptable_result, kTestVectorInt32, |
+ sizeof(kTestVectorInt32)); |
+ ASSERT_EQ(alternative_acceptable_result[4], |
+ std::numeric_limits<int32_t>::max() / 2); |
+ alternative_acceptable_result[4]++; |
ASSERT_TRUE( |
- memcmp(test_array, kTestVectorInt32, sizeof(kTestVectorInt32)) == 0 || |
- memcmp(test_array, fixed_test_array, sizeof(fixed_test_array)) == 0); |
+ memcmp(test_array, kTestVectorInt32, sizeof(kTestVectorInt32)) == 0 || |
+ memcmp(test_array, alternative_acceptable_result, |
+ sizeof(alternative_acceptable_result)) == 0); |
+ } |
+ |
+ // Test non-deprecated version that takes SampleTypeTraits as a template |
+ // parameter. |
+ { |
+ SCOPED_TRACE("UnsignedInt8SampleTypeTraits"); |
+ uint8_t test_array[arraysize(kTestVectorUint8)]; |
+ bus->ToInterleaved<UnsignedInt8SampleTypeTraits>(bus->frames(), test_array); |
+ ASSERT_EQ(0, |
+ memcmp(test_array, kTestVectorUint8, sizeof(kTestVectorUint8))); |
+ } |
+ { |
+ SCOPED_TRACE("SignedInt16SampleTypeTraits"); |
+ int16_t test_array[arraysize(kTestVectorInt16)]; |
+ bus->ToInterleaved<SignedInt16SampleTypeTraits>(bus->frames(), test_array); |
+ ASSERT_EQ(0, |
+ memcmp(test_array, kTestVectorInt16, sizeof(kTestVectorInt16))); |
+ } |
+ { |
+ SCOPED_TRACE("SignedInt32SampleTypeTraits"); |
+ int32_t test_array[arraysize(kTestVectorInt32)]; |
+ bus->ToInterleaved<SignedInt32SampleTypeTraits>(bus->frames(), test_array); |
+ |
+ // Some compilers get better precision than others on the half-max test, so |
+ // let the test pass with an off by one check on the half-max. |
+ int32_t alternative_acceptable_result[arraysize(kTestVectorInt32)]; |
+ memcpy(alternative_acceptable_result, kTestVectorInt32, |
+ sizeof(kTestVectorInt32)); |
+ ASSERT_EQ(alternative_acceptable_result[4], |
+ std::numeric_limits<int32_t>::max() / 2); |
+ alternative_acceptable_result[4]++; |
+ |
+ ASSERT_TRUE( |
+ memcmp(test_array, kTestVectorInt32, sizeof(kTestVectorInt32)) == 0 || |
+ memcmp(test_array, alternative_acceptable_result, |
+ sizeof(alternative_acceptable_result)) == 0); |
+ } |
+ { |
+ SCOPED_TRACE("Float32SampleTypeTraits"); |
+ float test_array[arraysize(kTestVectorFloat32)]; |
+ bus->ToInterleaved<Float32SampleTypeTraits>(bus->frames(), test_array); |
+ ASSERT_EQ( |
+ 0, memcmp(test_array, kTestVectorFloat32, sizeof(kTestVectorFloat32))); |
} |
} |
@@ -380,21 +496,141 @@ TEST_F(AudioBusTest, ToInterleavedPartial) { |
// Only interleave the middle two frames in each channel. |
static const int kPartialStart = 1; |
static const int kPartialFrames = 2; |
- ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrames); |
+ ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrameCount); |
std::unique_ptr<AudioBus> expected = |
- AudioBus::Create(kTestVectorChannels, kTestVectorFrames); |
- for (int ch = 0; ch < kTestVectorChannels; ++ch) { |
+ AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
+ for (int ch = 0; ch < kTestVectorChannelCount; ++ch) { |
memcpy(expected->channel(ch), kTestVectorResult[ch], |
- kTestVectorFrames * sizeof(*expected->channel(ch))); |
+ kTestVectorFrameCount * sizeof(*expected->channel(ch))); |
+ } |
+ |
+ // Test deprecated version that takes |bytes_per_sample| as an input. |
+ { |
+ SCOPED_TRACE("int16_t"); |
+ int16_t test_array[arraysize(kTestVectorInt16)]; |
+ expected->ToInterleavedPartial(kPartialStart, kPartialFrames, |
+ sizeof(*kTestVectorInt16), test_array); |
+ ASSERT_EQ(0, memcmp(test_array, kTestVectorInt16 + |
+ kPartialStart * kTestVectorChannelCount, |
+ kPartialFrames * sizeof(*kTestVectorInt16) * |
+ kTestVectorChannelCount)); |
+ } |
+ |
+ // Test non-deprecated version that takes SampleTypeTraits as a template |
+ // parameter. |
+ { |
+ SCOPED_TRACE("Float32SampleTypeTraits"); |
+ float test_array[arraysize(kTestVectorFloat32)]; |
+ expected->ToInterleavedPartial<Float32SampleTypeTraits>( |
+ kPartialStart, kPartialFrames, test_array); |
+ ASSERT_EQ(0, memcmp(test_array, kTestVectorFloat32 + |
+ kPartialStart * kTestVectorChannelCount, |
+ kPartialFrames * sizeof(*kTestVectorFloat32) * |
+ kTestVectorChannelCount)); |
+ } |
+} |
+ |
+struct ZeroingOutTestData { |
+ static constexpr int kChannelCount = 2; |
+ static constexpr int kFrameCount = 10; |
+ static constexpr int kInterleavedFrameCount = 3; |
+ |
+ std::unique_ptr<AudioBus> bus_under_test; |
+ std::vector<float> interleaved_dummy_frames; |
+ |
+ ZeroingOutTestData() { |
+ // Create a bus and fill each channel with a test pattern of form |
+ // [1.0, 2.0, 3.0, ...] |
+ bus_under_test = AudioBus::Create(kChannelCount, kFrameCount); |
+ for (int ch = 0; ch < kChannelCount; ++ch) { |
+ auto sample_array_for_current_channel = bus_under_test->channel(ch); |
+ for (int frame_index = 0; frame_index < kFrameCount; frame_index++) { |
+ sample_array_for_current_channel[frame_index] = |
+ static_cast<float>(frame_index + 1); |
+ } |
+ } |
+ |
+ // Create a vector containing dummy interleaved samples. |
+ static const float kDummySampleValue = 0.123f; |
+ interleaved_dummy_frames.resize(kChannelCount * kInterleavedFrameCount); |
+ std::fill(interleaved_dummy_frames.begin(), interleaved_dummy_frames.end(), |
+ kDummySampleValue); |
+ } |
+}; |
+ |
+TEST_F(AudioBusTest, FromInterleavedZerosOutUntouchedFrames) { |
+ ZeroingOutTestData test_data; |
+ |
+ // Exercise |
+ test_data.bus_under_test->FromInterleaved<Float32SampleTypeTraits>( |
+ &test_data.interleaved_dummy_frames[0], test_data.kInterleavedFrameCount); |
+ |
+ // Verification |
+ for (int ch = 0; ch < test_data.kChannelCount; ++ch) { |
+ auto sample_array_for_current_channel = |
+ test_data.bus_under_test->channel(ch); |
+ for (int frame_index = test_data.kInterleavedFrameCount; |
+ frame_index < test_data.kFrameCount; frame_index++) { |
+ ASSERT_EQ(0.0f, sample_array_for_current_channel[frame_index]); |
+ } |
} |
+} |
- int16_t 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, FromInterleavedPartialDoesNotZeroOutUntouchedFrames) { |
+ { |
+ SCOPED_TRACE("Zero write offset"); |
+ |
+ ZeroingOutTestData test_data; |
+ static const int kWriteOffsetInFrames = 0; |
+ |
+ // Exercise |
+ test_data.bus_under_test->FromInterleavedPartial<Float32SampleTypeTraits>( |
+ &test_data.interleaved_dummy_frames[0], kWriteOffsetInFrames, |
+ test_data.kInterleavedFrameCount); |
+ |
+ // Verification |
+ for (int ch = 0; ch < test_data.kChannelCount; ++ch) { |
+ auto sample_array_for_current_channel = |
+ test_data.bus_under_test->channel(ch); |
+ for (int frame_index = |
+ test_data.kInterleavedFrameCount + kWriteOffsetInFrames; |
+ frame_index < test_data.kFrameCount; frame_index++) { |
+ ASSERT_EQ(frame_index + 1, |
+ sample_array_for_current_channel[frame_index]); |
+ } |
+ } |
+ } |
+ { |
+ SCOPED_TRACE("Positive write offset"); |
+ |
+ ZeroingOutTestData test_data; |
+ static const int kWriteOffsetInFrames = 2; |
+ |
+ // Exercise |
+ test_data.bus_under_test->FromInterleavedPartial<Float32SampleTypeTraits>( |
+ &test_data.interleaved_dummy_frames[0], kWriteOffsetInFrames, |
+ test_data.kInterleavedFrameCount); |
+ |
+ // Verification |
+ for (int ch = 0; ch < test_data.kChannelCount; ++ch) { |
+ auto sample_array_for_current_channel = |
+ test_data.bus_under_test->channel(ch); |
+ // Check untouched frames before write offset |
+ for (int frame_index = 0; frame_index < kWriteOffsetInFrames; |
+ frame_index++) { |
+ ASSERT_EQ(frame_index + 1, |
+ sample_array_for_current_channel[frame_index]); |
+ } |
+ // Check untouched frames after write |
+ for (int frame_index = |
+ test_data.kInterleavedFrameCount + kWriteOffsetInFrames; |
+ frame_index < test_data.kFrameCount; frame_index++) { |
+ ASSERT_EQ(frame_index + 1, |
+ sample_array_for_current_channel[frame_index]); |
+ } |
+ } |
+ } |
} |
TEST_F(AudioBusTest, Scale) { |
@@ -409,7 +645,7 @@ TEST_F(AudioBusTest, Scale) { |
bus->Scale(-1); |
for (int i = 0; i < bus->channels(); ++i) { |
SCOPED_TRACE("Invalid Scale"); |
- VerifyValue(bus->channel(i), bus->frames(), kFillValue); |
+ VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), kFillValue); |
} |
// Verify correct volume adjustment. |
@@ -417,14 +653,15 @@ TEST_F(AudioBusTest, Scale) { |
bus->Scale(kVolume); |
for (int i = 0; i < bus->channels(); ++i) { |
SCOPED_TRACE("Half Scale"); |
- VerifyValue(bus->channel(i), bus->frames(), kFillValue * kVolume); |
+ VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), |
+ kFillValue * kVolume); |
} |
// Verify zero volume case. |
bus->Scale(0); |
for (int i = 0; i < bus->channels(); ++i) { |
SCOPED_TRACE("Zero Scale"); |
- VerifyValue(bus->channel(i), bus->frames(), 0); |
+ VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0); |
} |
} |