| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "base/time/time.h" | 13 #include "base/time/time.h" |
| 14 #include "build/build_config.h" | 14 #include "build/build_config.h" |
| 15 #include "media/base/audio_bus.h" | 15 #include "media/base/audio_bus.h" |
| 16 #include "media/base/audio_parameters.h" | 16 #include "media/base/audio_parameters.h" |
| 17 #include "media/base/audio_sample_types.h" |
| 17 #include "media/base/channel_layout.h" | 18 #include "media/base/channel_layout.h" |
| 18 #include "media/base/fake_audio_render_callback.h" | 19 #include "media/base/fake_audio_render_callback.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 21 |
| 21 namespace media { | 22 namespace media { |
| 22 | 23 |
| 23 static const int kChannels = 6; | 24 static const int kChannels = 6; |
| 24 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_5_1; | 25 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_5_1; |
| 25 // Use a buffer size which is intentionally not a multiple of kChannelAlignment. | 26 // Use a buffer size which is intentionally not a multiple of kChannelAlignment. |
| 26 static const int kFrameCount = media::AudioBus::kChannelAlignment * 32 - 1; | 27 static const int kFrameCount = media::AudioBus::kChannelAlignment * 32 - 1; |
| 27 static const int kSampleRate = 48000; | 28 static const int kSampleRate = 48000; |
| 28 | 29 |
| 29 class AudioBusTest : public testing::Test { | 30 class AudioBusTest : public testing::Test { |
| 30 public: | 31 public: |
| 31 AudioBusTest() {} | 32 AudioBusTest() {} |
| 32 ~AudioBusTest() override { | 33 ~AudioBusTest() override { |
| 33 for (size_t i = 0; i < data_.size(); ++i) | 34 for (size_t i = 0; i < data_.size(); ++i) |
| 34 base::AlignedFree(data_[i]); | 35 base::AlignedFree(data_[i]); |
| 35 } | 36 } |
| 36 | 37 |
| 37 // Validate parameters returned by AudioBus v.s. the constructed parameters. | 38 void VerifyChannelAndFrameCount(AudioBus* bus) { |
| 38 void VerifyParams(AudioBus* bus) { | |
| 39 EXPECT_EQ(kChannels, bus->channels()); | 39 EXPECT_EQ(kChannels, bus->channels()); |
| 40 EXPECT_EQ(kFrameCount, bus->frames()); | 40 EXPECT_EQ(kFrameCount, bus->frames()); |
| 41 } | 41 } |
| 42 | 42 |
| 43 void VerifyValue(const float data[], int size, float value) { | 43 void VerifyArrayIsFilledWithValue(const float data[], int size, float value) { |
| 44 for (int i = 0; i < size; ++i) | 44 for (int i = 0; i < size; ++i) |
| 45 ASSERT_FLOAT_EQ(value, data[i]) << "i=" << i; | 45 ASSERT_FLOAT_EQ(value, data[i]) << "i=" << i; |
| 46 } | 46 } |
| 47 | 47 |
| 48 // Verify values for each channel in |result| are within |epsilon| of | 48 // Verify values for each channel in |result| are within |epsilon| of |
| 49 // |expected|. If |epsilon| exactly equals 0, uses FLOAT_EQ macro. | 49 // |expected|. If |epsilon| exactly equals 0, uses FLOAT_EQ macro. |
| 50 void VerifyBusWithEpsilon(const AudioBus* result, const AudioBus* expected, | 50 void VerifyAreEqualWithEpsilon(const AudioBus* result, |
| 51 float epsilon) { | 51 const AudioBus* expected, |
| 52 float epsilon) { |
| 52 ASSERT_EQ(expected->channels(), result->channels()); | 53 ASSERT_EQ(expected->channels(), result->channels()); |
| 53 ASSERT_EQ(expected->frames(), result->frames()); | 54 ASSERT_EQ(expected->frames(), result->frames()); |
| 54 for (int ch = 0; ch < result->channels(); ++ch) { | 55 for (int ch = 0; ch < result->channels(); ++ch) { |
| 55 for (int i = 0; i < result->frames(); ++i) { | 56 for (int i = 0; i < result->frames(); ++i) { |
| 56 SCOPED_TRACE(base::StringPrintf("ch=%d, i=%d", ch, i)); | 57 SCOPED_TRACE(base::StringPrintf("ch=%d, i=%d", ch, i)); |
| 58 |
| 57 if (epsilon == 0) { | 59 if (epsilon == 0) { |
| 58 ASSERT_FLOAT_EQ(expected->channel(ch)[i], result->channel(ch)[i]); | 60 ASSERT_FLOAT_EQ(expected->channel(ch)[i], result->channel(ch)[i]); |
| 59 } else { | 61 } else { |
| 60 ASSERT_NEAR(expected->channel(ch)[i], result->channel(ch)[i], | 62 ASSERT_NEAR(expected->channel(ch)[i], result->channel(ch)[i], |
| 61 epsilon); | 63 epsilon); |
| 62 } | 64 } |
| 63 } | 65 } |
| 64 } | 66 } |
| 65 } | 67 } |
| 66 | 68 |
| 67 // Verify values for each channel in |result| against |expected|. | 69 // Verify values for each channel in |result| against |expected|. |
| 68 void VerifyBus(const AudioBus* result, const AudioBus* expected) { | 70 void VerifyAreEqual(const AudioBus* result, const AudioBus* expected) { |
| 69 VerifyBusWithEpsilon(result, expected, 0); | 71 VerifyAreEqualWithEpsilon(result, expected, 0); |
| 70 } | 72 } |
| 71 | 73 |
| 72 // Read and write to the full extent of the allocated channel data. Also test | 74 // Read and write to the full extent of the allocated channel data. Also test |
| 73 // the Zero() method and verify it does as advertised. Also test data if data | 75 // the Zero() method and verify it does as advertised. Also test data if data |
| 74 // is 16-byte aligned as advertised (see kChannelAlignment in audio_bus.h). | 76 // is 16-byte aligned as advertised (see kChannelAlignment in audio_bus.h). |
| 75 void VerifyChannelData(AudioBus* bus) { | 77 void VerifyReadWriteAndAlignment(AudioBus* bus) { |
| 76 for (int i = 0; i < bus->channels(); ++i) { | 78 for (int i = 0; i < bus->channels(); ++i) { |
| 79 // Verify that the address returned by channel(i) is a multiple of |
| 80 // AudioBus::kChannelAlignment. |
| 77 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>( | 81 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>( |
| 78 bus->channel(i)) & (AudioBus::kChannelAlignment - 1)); | 82 bus->channel(i)) & (AudioBus::kChannelAlignment - 1)); |
| 83 |
| 84 // Write into the channel buffer. |
| 79 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i); | 85 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i); |
| 80 } | 86 } |
| 81 | 87 |
| 82 for (int i = 0; i < bus->channels(); ++i) | 88 for (int i = 0; i < bus->channels(); ++i) |
| 83 VerifyValue(bus->channel(i), bus->frames(), i); | 89 VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), i); |
| 84 | 90 |
| 85 bus->Zero(); | 91 bus->Zero(); |
| 86 for (int i = 0; i < bus->channels(); ++i) | 92 for (int i = 0; i < bus->channels(); ++i) |
| 87 VerifyValue(bus->channel(i), bus->frames(), 0); | 93 VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0); |
| 88 } | 94 } |
| 89 | 95 |
| 90 // Verify copying to and from |bus1| and |bus2|. | 96 // Verify copying to and from |bus1| and |bus2|. |
| 91 void CopyTest(AudioBus* bus1, AudioBus* bus2) { | 97 void CopyTest(AudioBus* bus1, AudioBus* bus2) { |
| 92 // Fill |bus1| with dummy data. | 98 // Fill |bus1| with dummy data. |
| 93 for (int i = 0; i < bus1->channels(); ++i) | 99 for (int i = 0; i < bus1->channels(); ++i) |
| 94 std::fill(bus1->channel(i), bus1->channel(i) + bus1->frames(), i); | 100 std::fill(bus1->channel(i), bus1->channel(i) + bus1->frames(), i); |
| 95 | 101 |
| 96 // Verify copy from |bus1| to |bus2|. | 102 // Verify copy from |bus1| to |bus2|. |
| 97 bus2->Zero(); | 103 bus2->Zero(); |
| 98 bus1->CopyTo(bus2); | 104 bus1->CopyTo(bus2); |
| 99 VerifyBus(bus1, bus2); | 105 VerifyAreEqual(bus1, bus2); |
| 100 | 106 |
| 101 // Verify copy from |bus2| to |bus1|. | 107 // Verify copy from |bus2| to |bus1|. |
| 102 bus1->Zero(); | 108 bus1->Zero(); |
| 103 bus2->CopyTo(bus1); | 109 bus2->CopyTo(bus1); |
| 104 VerifyBus(bus2, bus1); | 110 VerifyAreEqual(bus2, bus1); |
| 105 } | 111 } |
| 106 | 112 |
| 107 protected: | 113 protected: |
| 108 std::vector<float*> data_; | 114 std::vector<float*> data_; |
| 109 | 115 |
| 110 DISALLOW_COPY_AND_ASSIGN(AudioBusTest); | 116 DISALLOW_COPY_AND_ASSIGN(AudioBusTest); |
| 111 }; | 117 }; |
| 112 | 118 |
| 113 // Verify basic Create(...) method works as advertised. | 119 // Verify basic Create(...) method works as advertised. |
| 114 TEST_F(AudioBusTest, Create) { | 120 TEST_F(AudioBusTest, Create) { |
| 115 std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount); | 121 std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount); |
| 116 VerifyParams(bus.get()); | 122 VerifyChannelAndFrameCount(bus.get()); |
| 117 VerifyChannelData(bus.get()); | 123 VerifyReadWriteAndAlignment(bus.get()); |
| 118 } | 124 } |
| 119 | 125 |
| 120 // Verify Create(...) using AudioParameters works as advertised. | 126 // Verify Create(...) using AudioParameters works as advertised. |
| 121 TEST_F(AudioBusTest, CreateUsingAudioParameters) { | 127 TEST_F(AudioBusTest, CreateUsingAudioParameters) { |
| 122 std::unique_ptr<AudioBus> bus = AudioBus::Create( | 128 std::unique_ptr<AudioBus> bus = AudioBus::Create( |
| 123 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, | 129 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, |
| 124 kSampleRate, 32, kFrameCount)); | 130 kSampleRate, 32, kFrameCount)); |
| 125 VerifyParams(bus.get()); | 131 VerifyChannelAndFrameCount(bus.get()); |
| 126 VerifyChannelData(bus.get()); | 132 VerifyReadWriteAndAlignment(bus.get()); |
| 127 } | 133 } |
| 128 | 134 |
| 129 // Verify an AudioBus created via wrapping a vector works as advertised. | 135 // Verify an AudioBus created via wrapping a vector works as advertised. |
| 130 TEST_F(AudioBusTest, WrapVector) { | 136 TEST_F(AudioBusTest, WrapVector) { |
| 131 data_.reserve(kChannels); | 137 data_.reserve(kChannels); |
| 132 for (int i = 0; i < kChannels; ++i) { | 138 for (int i = 0; i < kChannels; ++i) { |
| 133 data_.push_back(static_cast<float*>(base::AlignedAlloc( | 139 data_.push_back(static_cast<float*>(base::AlignedAlloc( |
| 134 sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment))); | 140 sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment))); |
| 135 } | 141 } |
| 136 | 142 |
| 137 std::unique_ptr<AudioBus> bus = AudioBus::WrapVector(kFrameCount, data_); | 143 std::unique_ptr<AudioBus> bus = AudioBus::WrapVector(kFrameCount, data_); |
| 138 VerifyParams(bus.get()); | 144 VerifyChannelAndFrameCount(bus.get()); |
| 139 VerifyChannelData(bus.get()); | 145 VerifyReadWriteAndAlignment(bus.get()); |
| 140 } | 146 } |
| 141 | 147 |
| 142 // Verify an AudioBus created via wrapping a memory block works as advertised. | 148 // Verify an AudioBus created via wrapping a memory block works as advertised. |
| 143 TEST_F(AudioBusTest, WrapMemory) { | 149 TEST_F(AudioBusTest, WrapMemory) { |
| 144 AudioParameters params( | 150 AudioParameters params( |
| 145 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32, | 151 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32, |
| 146 kFrameCount); | 152 kFrameCount); |
| 147 int data_size = AudioBus::CalculateMemorySize(params); | 153 int data_size = AudioBus::CalculateMemorySize(params); |
| 148 std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( | 154 std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( |
| 149 base::AlignedAlloc(data_size, AudioBus::kChannelAlignment))); | 155 base::AlignedAlloc(data_size, AudioBus::kChannelAlignment))); |
| 150 | 156 |
| 151 // Fill the memory with a test value we can check for after wrapping. | 157 // Fill the memory with a test value we can check for after wrapping. |
| 152 static const float kTestValue = 3; | 158 static const float kTestValue = 3; |
| 153 std::fill( | 159 std::fill( |
| 154 data.get(), data.get() + data_size / sizeof(*data.get()), kTestValue); | 160 data.get(), data.get() + data_size / sizeof(*data.get()), kTestValue); |
| 155 | 161 |
| 156 std::unique_ptr<AudioBus> bus = AudioBus::WrapMemory(params, data.get()); | 162 std::unique_ptr<AudioBus> bus = AudioBus::WrapMemory(params, data.get()); |
| 157 // Verify the test value we filled prior to wrapping. | 163 // Verify the test value we filled prior to wrapping. |
| 158 for (int i = 0; i < bus->channels(); ++i) | 164 for (int i = 0; i < bus->channels(); ++i) |
| 159 VerifyValue(bus->channel(i), bus->frames(), kTestValue); | 165 VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), kTestValue); |
| 160 VerifyParams(bus.get()); | 166 VerifyChannelAndFrameCount(bus.get()); |
| 161 VerifyChannelData(bus.get()); | 167 VerifyReadWriteAndAlignment(bus.get()); |
| 162 | 168 |
| 163 // Verify the channel vectors lie within the provided memory block. | 169 // Verify the channel vectors lie within the provided memory block. |
| 164 EXPECT_GE(bus->channel(0), data.get()); | 170 EXPECT_GE(bus->channel(0), data.get()); |
| 165 EXPECT_LT(bus->channel(bus->channels() - 1) + bus->frames(), | 171 EXPECT_LT(bus->channel(bus->channels() - 1) + bus->frames(), |
| 166 data.get() + data_size / sizeof(*data.get())); | 172 data.get() + data_size / sizeof(*data.get())); |
| 167 } | 173 } |
| 168 | 174 |
| 169 // Simulate a shared memory transfer and verify results. | 175 // Simulate a shared memory transfer and verify results. |
| 170 TEST_F(AudioBusTest, CopyTo) { | 176 TEST_F(AudioBusTest, CopyTo) { |
| 171 // Create one bus with AudioParameters and the other through direct values to | 177 // Create one bus with AudioParameters and the other through direct values to |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 | 216 |
| 211 // Fill the bus with dummy data. | 217 // Fill the bus with dummy data. |
| 212 for (int i = 0; i < bus->channels(); ++i) | 218 for (int i = 0; i < bus->channels(); ++i) |
| 213 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1); | 219 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1); |
| 214 EXPECT_FALSE(bus->AreFramesZero()); | 220 EXPECT_FALSE(bus->AreFramesZero()); |
| 215 | 221 |
| 216 // Zero first half the frames of each channel. | 222 // Zero first half the frames of each channel. |
| 217 bus->ZeroFrames(kFrameCount / 2); | 223 bus->ZeroFrames(kFrameCount / 2); |
| 218 for (int i = 0; i < bus->channels(); ++i) { | 224 for (int i = 0; i < bus->channels(); ++i) { |
| 219 SCOPED_TRACE("First Half Zero"); | 225 SCOPED_TRACE("First Half Zero"); |
| 220 VerifyValue(bus->channel(i), kFrameCount / 2, 0); | 226 VerifyArrayIsFilledWithValue(bus->channel(i), kFrameCount / 2, 0); |
| 221 VerifyValue(bus->channel(i) + kFrameCount / 2, | 227 VerifyArrayIsFilledWithValue(bus->channel(i) + kFrameCount / 2, |
| 222 kFrameCount - kFrameCount / 2, i + 1); | 228 kFrameCount - kFrameCount / 2, i + 1); |
| 223 } | 229 } |
| 224 EXPECT_FALSE(bus->AreFramesZero()); | 230 EXPECT_FALSE(bus->AreFramesZero()); |
| 225 | 231 |
| 226 // Fill the bus with dummy data. | 232 // Fill the bus with dummy data. |
| 227 for (int i = 0; i < bus->channels(); ++i) | 233 for (int i = 0; i < bus->channels(); ++i) |
| 228 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1); | 234 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1); |
| 229 | 235 |
| 230 // Zero the last half of the frames. | 236 // Zero the last half of the frames. |
| 231 bus->ZeroFramesPartial(kFrameCount / 2, kFrameCount - kFrameCount / 2); | 237 bus->ZeroFramesPartial(kFrameCount / 2, kFrameCount - kFrameCount / 2); |
| 232 for (int i = 0; i < bus->channels(); ++i) { | 238 for (int i = 0; i < bus->channels(); ++i) { |
| 233 SCOPED_TRACE("Last Half Zero"); | 239 SCOPED_TRACE("Last Half Zero"); |
| 234 VerifyValue(bus->channel(i) + kFrameCount / 2, | 240 VerifyArrayIsFilledWithValue(bus->channel(i) + kFrameCount / 2, |
| 235 kFrameCount - kFrameCount / 2, 0); | 241 kFrameCount - kFrameCount / 2, 0); |
| 236 VerifyValue(bus->channel(i), kFrameCount / 2, i + 1); | 242 VerifyArrayIsFilledWithValue(bus->channel(i), kFrameCount / 2, i + 1); |
| 237 } | 243 } |
| 238 EXPECT_FALSE(bus->AreFramesZero()); | 244 EXPECT_FALSE(bus->AreFramesZero()); |
| 239 | 245 |
| 240 // Fill the bus with dummy data. | 246 // Fill the bus with dummy data. |
| 241 for (int i = 0; i < bus->channels(); ++i) | 247 for (int i = 0; i < bus->channels(); ++i) |
| 242 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1); | 248 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1); |
| 243 | 249 |
| 244 // Zero all the frames of each channel. | 250 // Zero all the frames of each channel. |
| 245 bus->Zero(); | 251 bus->Zero(); |
| 246 for (int i = 0; i < bus->channels(); ++i) { | 252 for (int i = 0; i < bus->channels(); ++i) { |
| 247 SCOPED_TRACE("All Zero"); | 253 SCOPED_TRACE("All Zero"); |
| 248 VerifyValue(bus->channel(i), bus->frames(), 0); | 254 VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0); |
| 249 } | 255 } |
| 250 EXPECT_TRUE(bus->AreFramesZero()); | 256 EXPECT_TRUE(bus->AreFramesZero()); |
| 251 } | 257 } |
| 252 | 258 |
| 253 // Each test vector represents two channels of data in the following arbitrary | 259 // Each test vector represents two channels of data in the following arbitrary |
| 254 // layout: <min, zero, max, min, max / 2, min / 2, zero, max, zero, zero>. | 260 // layout: <min, zero, max, min, max / 2, min / 2, zero, max, zero, zero>. |
| 255 static const int kTestVectorSize = 10; | 261 static const int kTestVectorSize = 10; |
| 256 static const uint8_t kTestVectorUint8[kTestVectorSize] = { | 262 static const uint8_t kTestVectorUint8[kTestVectorSize] = { |
| 257 0, -INT8_MIN, UINT8_MAX, | 263 0, -INT8_MIN, UINT8_MAX, |
| 258 0, INT8_MAX / 2 + 128, INT8_MIN / 2 + 128, | 264 0, INT8_MAX / 2 + 128, INT8_MIN / 2 + 128, |
| 259 -INT8_MIN, UINT8_MAX, -INT8_MIN, | 265 -INT8_MIN, UINT8_MAX, -INT8_MIN, |
| 260 -INT8_MIN}; | 266 -INT8_MIN}; |
| 261 static const int16_t kTestVectorInt16[kTestVectorSize] = { | 267 static const int16_t kTestVectorInt16[kTestVectorSize] = { |
| 262 INT16_MIN, 0, INT16_MAX, INT16_MIN, INT16_MAX / 2, | 268 INT16_MIN, 0, INT16_MAX, INT16_MIN, INT16_MAX / 2, |
| 263 INT16_MIN / 2, 0, INT16_MAX, 0, 0}; | 269 INT16_MIN / 2, 0, INT16_MAX, 0, 0}; |
| 264 static const int32_t kTestVectorInt32[kTestVectorSize] = { | 270 static const int32_t kTestVectorInt32[kTestVectorSize] = { |
| 265 INT32_MIN, 0, INT32_MAX, INT32_MIN, INT32_MAX / 2, | 271 INT32_MIN, 0, INT32_MAX, INT32_MIN, INT32_MAX / 2, |
| 266 INT32_MIN / 2, 0, INT32_MAX, 0, 0}; | 272 INT32_MIN / 2, 0, INT32_MAX, 0, 0}; |
| 273 static const float kTestVectorFloat32[kTestVectorSize] = { |
| 274 -1.0f, 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f}; |
| 267 | 275 |
| 268 // Expected results. | 276 // Expected results. |
| 269 static const int kTestVectorFrames = kTestVectorSize / 2; | 277 static const int kTestVectorFrameCount = kTestVectorSize / 2; |
| 270 static const float kTestVectorResult[][kTestVectorFrames] = { | 278 static const float kTestVectorResult[][kTestVectorFrameCount] = { |
| 271 { -1, 1, 0.5, 0, 0 }, { 0, -1, -0.5, 1, 0 }}; | 279 {-1.0f, 1.0f, 0.5f, 0.0f, 0.0f}, |
| 272 static const int kTestVectorChannels = arraysize(kTestVectorResult); | 280 {0.0f, -1.0f, -0.5f, 1.0f, 0.0f}}; |
| 281 static const int kTestVectorChannelCount = arraysize(kTestVectorResult); |
| 273 | 282 |
| 274 // Verify FromInterleaved() deinterleaves audio in supported formats correctly. | 283 // Verify FromInterleaved() deinterleaves audio in supported formats correctly. |
| 275 TEST_F(AudioBusTest, FromInterleaved) { | 284 TEST_F(AudioBusTest, FromInterleaved) { |
| 276 std::unique_ptr<AudioBus> bus = | 285 std::unique_ptr<AudioBus> bus = |
| 277 AudioBus::Create(kTestVectorChannels, kTestVectorFrames); | 286 AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
| 278 std::unique_ptr<AudioBus> expected = | 287 std::unique_ptr<AudioBus> expected = |
| 279 AudioBus::Create(kTestVectorChannels, kTestVectorFrames); | 288 AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
| 280 for (int ch = 0; ch < kTestVectorChannels; ++ch) { | 289 for (int ch = 0; ch < kTestVectorChannelCount; ++ch) { |
| 281 memcpy(expected->channel(ch), kTestVectorResult[ch], | 290 memcpy(expected->channel(ch), kTestVectorResult[ch], |
| 282 kTestVectorFrames * sizeof(*expected->channel(ch))); | 291 kTestVectorFrameCount * sizeof(*expected->channel(ch))); |
| 283 } | 292 } |
| 293 |
| 294 // Test deprecated version that takes |bytes_per_sample| as an input. |
| 284 { | 295 { |
| 285 SCOPED_TRACE("uint8_t"); | 296 SCOPED_TRACE("uint8_t"); |
| 286 bus->Zero(); | 297 bus->Zero(); |
| 287 bus->FromInterleaved( | 298 bus->FromInterleaved(kTestVectorUint8, kTestVectorFrameCount, |
| 288 kTestVectorUint8, kTestVectorFrames, sizeof(*kTestVectorUint8)); | 299 sizeof(*kTestVectorUint8)); |
| 300 |
| 289 // Biased uint8_t calculations have poor precision, so the epsilon here is | 301 // Biased uint8_t calculations have poor precision, so the epsilon here is |
| 290 // slightly more permissive than int16_t and int32_t calculations. | 302 // slightly more permissive than int16_t and int32_t calculations. |
| 291 VerifyBusWithEpsilon(bus.get(), expected.get(), | 303 VerifyAreEqualWithEpsilon(bus.get(), expected.get(), |
| 292 1.0f / (std::numeric_limits<uint8_t>::max() - 1)); | 304 1.0f / (std::numeric_limits<uint8_t>::max() - 1)); |
| 293 } | 305 } |
| 294 { | 306 { |
| 295 SCOPED_TRACE("int16_t"); | 307 SCOPED_TRACE("int16_t"); |
| 296 bus->Zero(); | 308 bus->Zero(); |
| 297 bus->FromInterleaved( | 309 bus->FromInterleaved(kTestVectorInt16, kTestVectorFrameCount, |
| 298 kTestVectorInt16, kTestVectorFrames, sizeof(*kTestVectorInt16)); | 310 sizeof(*kTestVectorInt16)); |
| 299 VerifyBusWithEpsilon(bus.get(), expected.get(), | 311 VerifyAreEqualWithEpsilon( |
| 300 1.0f / (std::numeric_limits<uint16_t>::max() + 1.0f)); | 312 bus.get(), expected.get(), |
| 313 1.0f / (std::numeric_limits<uint16_t>::max() + 1.0f)); |
| 301 } | 314 } |
| 302 { | 315 { |
| 303 SCOPED_TRACE("int32_t"); | 316 SCOPED_TRACE("int32_t"); |
| 304 bus->Zero(); | 317 bus->Zero(); |
| 305 bus->FromInterleaved( | 318 bus->FromInterleaved(kTestVectorInt32, kTestVectorFrameCount, |
| 306 kTestVectorInt32, kTestVectorFrames, sizeof(*kTestVectorInt32)); | 319 sizeof(*kTestVectorInt32)); |
| 307 VerifyBusWithEpsilon(bus.get(), expected.get(), | 320 |
| 308 1.0f / (std::numeric_limits<uint32_t>::max() + 1.0f)); | 321 VerifyAreEqualWithEpsilon( |
| 322 bus.get(), expected.get(), |
| 323 1.0f / (std::numeric_limits<uint32_t>::max() + 1.0f)); |
| 324 } |
| 325 |
| 326 // Test non-deprecated version that takes SampleTypeTraits as a template |
| 327 // parameter. |
| 328 { |
| 329 SCOPED_TRACE("UnsignedInt8SampleTypeTraits"); |
| 330 bus->Zero(); |
| 331 bus->FromInterleaved<UnsignedInt8SampleTypeTraits>(kTestVectorUint8, |
| 332 kTestVectorFrameCount); |
| 333 // Biased uint8_t calculations have poor precision, so the epsilon here is |
| 334 // slightly more permissive than int16_t and int32_t calculations. |
| 335 VerifyAreEqualWithEpsilon(bus.get(), expected.get(), |
| 336 1.0f / (std::numeric_limits<uint8_t>::max() - 1)); |
| 337 } |
| 338 { |
| 339 SCOPED_TRACE("SignedInt16SampleTypeTraits"); |
| 340 bus->Zero(); |
| 341 bus->FromInterleaved<SignedInt16SampleTypeTraits>(kTestVectorInt16, |
| 342 kTestVectorFrameCount); |
| 343 VerifyAreEqualWithEpsilon( |
| 344 bus.get(), expected.get(), |
| 345 1.0f / (std::numeric_limits<uint16_t>::max() + 1.0f)); |
| 346 } |
| 347 { |
| 348 SCOPED_TRACE("SignedInt32SampleTypeTraits"); |
| 349 bus->Zero(); |
| 350 bus->FromInterleaved<SignedInt32SampleTypeTraits>(kTestVectorInt32, |
| 351 kTestVectorFrameCount); |
| 352 VerifyAreEqualWithEpsilon( |
| 353 bus.get(), expected.get(), |
| 354 1.0f / (std::numeric_limits<uint32_t>::max() + 1.0f)); |
| 355 } |
| 356 { |
| 357 SCOPED_TRACE("Float32SampleTypeTraits"); |
| 358 bus->Zero(); |
| 359 bus->FromInterleaved<Float32SampleTypeTraits>(kTestVectorFloat32, |
| 360 kTestVectorFrameCount); |
| 361 VerifyAreEqual(bus.get(), expected.get()); |
| 309 } | 362 } |
| 310 } | 363 } |
| 311 | 364 |
| 312 // Verify FromInterleavedPartial() deinterleaves audio correctly. | 365 // Verify FromInterleavedPartial() deinterleaves audio correctly. |
| 313 TEST_F(AudioBusTest, FromInterleavedPartial) { | 366 TEST_F(AudioBusTest, FromInterleavedPartial) { |
| 314 // Only deinterleave the middle two frames in each channel. | 367 // Only deinterleave the middle two frames in each channel. |
| 315 static const int kPartialStart = 1; | 368 static const int kPartialStart = 1; |
| 316 static const int kPartialFrames = 2; | 369 static const int kPartialFrames = 2; |
| 317 ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrames); | 370 ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrameCount); |
| 318 | 371 |
| 319 std::unique_ptr<AudioBus> bus = | 372 std::unique_ptr<AudioBus> bus = |
| 320 AudioBus::Create(kTestVectorChannels, kTestVectorFrames); | 373 AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
| 321 std::unique_ptr<AudioBus> expected = | 374 std::unique_ptr<AudioBus> expected = |
| 322 AudioBus::Create(kTestVectorChannels, kTestVectorFrames); | 375 AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
| 323 expected->Zero(); | 376 expected->Zero(); |
| 324 for (int ch = 0; ch < kTestVectorChannels; ++ch) { | 377 for (int ch = 0; ch < kTestVectorChannelCount; ++ch) { |
| 325 memcpy(expected->channel(ch) + kPartialStart, | 378 memcpy(expected->channel(ch) + kPartialStart, |
| 326 kTestVectorResult[ch] + kPartialStart, | 379 kTestVectorResult[ch] + kPartialStart, |
| 327 kPartialFrames * sizeof(*expected->channel(ch))); | 380 kPartialFrames * sizeof(*expected->channel(ch))); |
| 328 } | 381 } |
| 329 | 382 |
| 330 bus->Zero(); | 383 // Test deprecated version that takes |bytes_per_sample| as an input. |
| 331 bus->FromInterleavedPartial( | 384 { |
| 332 kTestVectorInt32 + kPartialStart * bus->channels(), kPartialStart, | 385 SCOPED_TRACE("int32_t"); |
| 333 kPartialFrames, sizeof(*kTestVectorInt32)); | 386 bus->Zero(); |
| 334 VerifyBus(bus.get(), expected.get()); | 387 bus->FromInterleavedPartial( |
| 388 kTestVectorInt32 + kPartialStart * bus->channels(), kPartialStart, |
| 389 kPartialFrames, sizeof(*kTestVectorInt32)); |
| 390 VerifyAreEqual(bus.get(), expected.get()); |
| 391 } |
| 392 |
| 393 // Test non-deprecated version that takes SampleTypeTraits as a template |
| 394 // parameter. |
| 395 { |
| 396 SCOPED_TRACE("SignedInt32SampleTypeTraits"); |
| 397 bus->Zero(); |
| 398 bus->FromInterleavedPartial<SignedInt32SampleTypeTraits>( |
| 399 kTestVectorInt32 + kPartialStart * bus->channels(), kPartialStart, |
| 400 kPartialFrames); |
| 401 VerifyAreEqual(bus.get(), expected.get()); |
| 402 } |
| 335 } | 403 } |
| 336 | 404 |
| 337 // Verify ToInterleaved() interleaves audio in suported formats correctly. | 405 // Verify ToInterleaved() interleaves audio in suported formats correctly. |
| 338 TEST_F(AudioBusTest, ToInterleaved) { | 406 TEST_F(AudioBusTest, ToInterleaved) { |
| 339 std::unique_ptr<AudioBus> bus = | 407 std::unique_ptr<AudioBus> bus = |
| 340 AudioBus::Create(kTestVectorChannels, kTestVectorFrames); | 408 AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
| 341 // Fill the bus with our test vector. | 409 // Fill the bus with our test vector. |
| 342 for (int ch = 0; ch < bus->channels(); ++ch) { | 410 for (int ch = 0; ch < bus->channels(); ++ch) { |
| 343 memcpy(bus->channel(ch), kTestVectorResult[ch], | 411 memcpy(bus->channel(ch), kTestVectorResult[ch], |
| 344 kTestVectorFrames * sizeof(*bus->channel(ch))); | 412 kTestVectorFrameCount * sizeof(*bus->channel(ch))); |
| 345 } | 413 } |
| 414 |
| 415 // Test deprecated version that takes |bytes_per_sample| as an input. |
| 346 { | 416 { |
| 347 SCOPED_TRACE("uint8_t"); | 417 SCOPED_TRACE("uint8_t"); |
| 348 uint8_t test_array[arraysize(kTestVectorUint8)]; | 418 uint8_t test_array[arraysize(kTestVectorUint8)]; |
| 349 bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorUint8), test_array); | 419 bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorUint8), test_array); |
| 350 ASSERT_EQ(memcmp( | 420 ASSERT_EQ(0, |
| 351 test_array, kTestVectorUint8, sizeof(kTestVectorUint8)), 0); | 421 memcmp(test_array, kTestVectorUint8, sizeof(kTestVectorUint8))); |
| 352 } | 422 } |
| 353 { | 423 { |
| 354 SCOPED_TRACE("int16_t"); | 424 SCOPED_TRACE("int16_t"); |
| 355 int16_t test_array[arraysize(kTestVectorInt16)]; | 425 int16_t test_array[arraysize(kTestVectorInt16)]; |
| 356 bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt16), test_array); | 426 bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt16), test_array); |
| 357 ASSERT_EQ(memcmp( | 427 ASSERT_EQ(0, |
| 358 test_array, kTestVectorInt16, sizeof(kTestVectorInt16)), 0); | 428 memcmp(test_array, kTestVectorInt16, sizeof(kTestVectorInt16))); |
| 359 } | 429 } |
| 360 { | 430 { |
| 361 SCOPED_TRACE("int32_t"); | 431 SCOPED_TRACE("int32_t"); |
| 362 int32_t test_array[arraysize(kTestVectorInt32)]; | 432 int32_t test_array[arraysize(kTestVectorInt32)]; |
| 363 bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt32), test_array); | 433 bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt32), test_array); |
| 364 | 434 |
| 365 // Some compilers get better precision than others on the half-max test, so | 435 // Some compilers get better precision than others on the half-max test, so |
| 366 // let the test pass with an off by one check on the half-max. | 436 // let the test pass with an off by one check on the half-max. |
| 367 int32_t fixed_test_array[arraysize(kTestVectorInt32)]; | 437 int32_t alternative_acceptable_result[arraysize(kTestVectorInt32)]; |
| 368 memcpy(fixed_test_array, kTestVectorInt32, sizeof(kTestVectorInt32)); | 438 memcpy(alternative_acceptable_result, kTestVectorInt32, |
| 369 ASSERT_EQ(fixed_test_array[4], std::numeric_limits<int32_t>::max() / 2); | 439 sizeof(kTestVectorInt32)); |
| 370 fixed_test_array[4]++; | 440 ASSERT_EQ(alternative_acceptable_result[4], |
| 441 std::numeric_limits<int32_t>::max() / 2); |
| 442 alternative_acceptable_result[4]++; |
| 371 | 443 |
| 372 ASSERT_TRUE( | 444 ASSERT_TRUE( |
| 373 memcmp(test_array, kTestVectorInt32, sizeof(kTestVectorInt32)) == 0 || | 445 memcmp(test_array, kTestVectorInt32, sizeof(kTestVectorInt32)) == 0 || |
| 374 memcmp(test_array, fixed_test_array, sizeof(fixed_test_array)) == 0); | 446 memcmp(test_array, alternative_acceptable_result, |
| 447 sizeof(alternative_acceptable_result)) == 0); |
| 448 } |
| 449 |
| 450 // Test non-deprecated version that takes SampleTypeTraits as a template |
| 451 // parameter. |
| 452 { |
| 453 SCOPED_TRACE("UnsignedInt8SampleTypeTraits"); |
| 454 uint8_t test_array[arraysize(kTestVectorUint8)]; |
| 455 bus->ToInterleaved<UnsignedInt8SampleTypeTraits>(bus->frames(), test_array); |
| 456 ASSERT_EQ(0, |
| 457 memcmp(test_array, kTestVectorUint8, sizeof(kTestVectorUint8))); |
| 458 } |
| 459 { |
| 460 SCOPED_TRACE("SignedInt16SampleTypeTraits"); |
| 461 int16_t test_array[arraysize(kTestVectorInt16)]; |
| 462 bus->ToInterleaved<SignedInt16SampleTypeTraits>(bus->frames(), test_array); |
| 463 ASSERT_EQ(0, |
| 464 memcmp(test_array, kTestVectorInt16, sizeof(kTestVectorInt16))); |
| 465 } |
| 466 { |
| 467 SCOPED_TRACE("SignedInt32SampleTypeTraits"); |
| 468 int32_t test_array[arraysize(kTestVectorInt32)]; |
| 469 bus->ToInterleaved<SignedInt32SampleTypeTraits>(bus->frames(), test_array); |
| 470 |
| 471 // Some compilers get better precision than others on the half-max test, so |
| 472 // let the test pass with an off by one check on the half-max. |
| 473 int32_t alternative_acceptable_result[arraysize(kTestVectorInt32)]; |
| 474 memcpy(alternative_acceptable_result, kTestVectorInt32, |
| 475 sizeof(kTestVectorInt32)); |
| 476 ASSERT_EQ(alternative_acceptable_result[4], |
| 477 std::numeric_limits<int32_t>::max() / 2); |
| 478 alternative_acceptable_result[4]++; |
| 479 |
| 480 ASSERT_TRUE( |
| 481 memcmp(test_array, kTestVectorInt32, sizeof(kTestVectorInt32)) == 0 || |
| 482 memcmp(test_array, alternative_acceptable_result, |
| 483 sizeof(alternative_acceptable_result)) == 0); |
| 484 } |
| 485 { |
| 486 SCOPED_TRACE("Float32SampleTypeTraits"); |
| 487 float test_array[arraysize(kTestVectorFloat32)]; |
| 488 bus->ToInterleaved<Float32SampleTypeTraits>(bus->frames(), test_array); |
| 489 ASSERT_EQ( |
| 490 0, memcmp(test_array, kTestVectorFloat32, sizeof(kTestVectorFloat32))); |
| 375 } | 491 } |
| 376 } | 492 } |
| 377 | 493 |
| 378 // Verify ToInterleavedPartial() interleaves audio correctly. | 494 // Verify ToInterleavedPartial() interleaves audio correctly. |
| 379 TEST_F(AudioBusTest, ToInterleavedPartial) { | 495 TEST_F(AudioBusTest, ToInterleavedPartial) { |
| 380 // Only interleave the middle two frames in each channel. | 496 // Only interleave the middle two frames in each channel. |
| 381 static const int kPartialStart = 1; | 497 static const int kPartialStart = 1; |
| 382 static const int kPartialFrames = 2; | 498 static const int kPartialFrames = 2; |
| 383 ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrames); | 499 ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrameCount); |
| 384 | 500 |
| 385 std::unique_ptr<AudioBus> expected = | 501 std::unique_ptr<AudioBus> expected = |
| 386 AudioBus::Create(kTestVectorChannels, kTestVectorFrames); | 502 AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount); |
| 387 for (int ch = 0; ch < kTestVectorChannels; ++ch) { | 503 for (int ch = 0; ch < kTestVectorChannelCount; ++ch) { |
| 388 memcpy(expected->channel(ch), kTestVectorResult[ch], | 504 memcpy(expected->channel(ch), kTestVectorResult[ch], |
| 389 kTestVectorFrames * sizeof(*expected->channel(ch))); | 505 kTestVectorFrameCount * sizeof(*expected->channel(ch))); |
| 390 } | 506 } |
| 391 | 507 |
| 392 int16_t test_array[arraysize(kTestVectorInt16)]; | 508 // Test deprecated version that takes |bytes_per_sample| as an input. |
| 393 expected->ToInterleavedPartial( | 509 { |
| 394 kPartialStart, kPartialFrames, sizeof(*kTestVectorInt16), test_array); | 510 SCOPED_TRACE("int16_t"); |
| 395 ASSERT_EQ(memcmp( | 511 int16_t test_array[arraysize(kTestVectorInt16)]; |
| 396 test_array, kTestVectorInt16 + kPartialStart * kTestVectorChannels, | 512 expected->ToInterleavedPartial(kPartialStart, kPartialFrames, |
| 397 kPartialFrames * sizeof(*kTestVectorInt16) * kTestVectorChannels), 0); | 513 sizeof(*kTestVectorInt16), test_array); |
| 514 ASSERT_EQ(0, memcmp(test_array, kTestVectorInt16 + |
| 515 kPartialStart * kTestVectorChannelCount, |
| 516 kPartialFrames * sizeof(*kTestVectorInt16) * |
| 517 kTestVectorChannelCount)); |
| 518 } |
| 519 |
| 520 // Test non-deprecated version that takes SampleTypeTraits as a template |
| 521 // parameter. |
| 522 { |
| 523 SCOPED_TRACE("Float32SampleTypeTraits"); |
| 524 float test_array[arraysize(kTestVectorFloat32)]; |
| 525 expected->ToInterleavedPartial<Float32SampleTypeTraits>( |
| 526 kPartialStart, kPartialFrames, test_array); |
| 527 ASSERT_EQ(0, memcmp(test_array, kTestVectorFloat32 + |
| 528 kPartialStart * kTestVectorChannelCount, |
| 529 kPartialFrames * sizeof(*kTestVectorFloat32) * |
| 530 kTestVectorChannelCount)); |
| 531 } |
| 532 } |
| 533 |
| 534 struct ZeroingOutTestData { |
| 535 static constexpr int kChannelCount = 2; |
| 536 static constexpr int kFrameCount = 10; |
| 537 static constexpr int kInterleavedFrameCount = 3; |
| 538 |
| 539 std::unique_ptr<AudioBus> bus_under_test; |
| 540 std::vector<float> interleaved_dummy_frames; |
| 541 |
| 542 ZeroingOutTestData() { |
| 543 // Create a bus and fill each channel with a test pattern of form |
| 544 // [1.0, 2.0, 3.0, ...] |
| 545 bus_under_test = AudioBus::Create(kChannelCount, kFrameCount); |
| 546 for (int ch = 0; ch < kChannelCount; ++ch) { |
| 547 auto sample_array_for_current_channel = bus_under_test->channel(ch); |
| 548 for (int frame_index = 0; frame_index < kFrameCount; frame_index++) { |
| 549 sample_array_for_current_channel[frame_index] = |
| 550 static_cast<float>(frame_index + 1); |
| 551 } |
| 552 } |
| 553 |
| 554 // Create a vector containing dummy interleaved samples. |
| 555 static const float kDummySampleValue = 0.123f; |
| 556 interleaved_dummy_frames.resize(kChannelCount * kInterleavedFrameCount); |
| 557 std::fill(interleaved_dummy_frames.begin(), interleaved_dummy_frames.end(), |
| 558 kDummySampleValue); |
| 559 } |
| 560 }; |
| 561 |
| 562 TEST_F(AudioBusTest, FromInterleavedZerosOutUntouchedFrames) { |
| 563 ZeroingOutTestData test_data; |
| 564 |
| 565 // Exercise |
| 566 test_data.bus_under_test->FromInterleaved<Float32SampleTypeTraits>( |
| 567 &test_data.interleaved_dummy_frames[0], test_data.kInterleavedFrameCount); |
| 568 |
| 569 // Verification |
| 570 for (int ch = 0; ch < test_data.kChannelCount; ++ch) { |
| 571 auto sample_array_for_current_channel = |
| 572 test_data.bus_under_test->channel(ch); |
| 573 for (int frame_index = test_data.kInterleavedFrameCount; |
| 574 frame_index < test_data.kFrameCount; frame_index++) { |
| 575 ASSERT_EQ(0.0f, sample_array_for_current_channel[frame_index]); |
| 576 } |
| 577 } |
| 578 } |
| 579 |
| 580 TEST_F(AudioBusTest, FromInterleavedPartialDoesNotZeroOutUntouchedFrames) { |
| 581 { |
| 582 SCOPED_TRACE("Zero write offset"); |
| 583 |
| 584 ZeroingOutTestData test_data; |
| 585 static const int kWriteOffsetInFrames = 0; |
| 586 |
| 587 // Exercise |
| 588 test_data.bus_under_test->FromInterleavedPartial<Float32SampleTypeTraits>( |
| 589 &test_data.interleaved_dummy_frames[0], kWriteOffsetInFrames, |
| 590 test_data.kInterleavedFrameCount); |
| 591 |
| 592 // Verification |
| 593 for (int ch = 0; ch < test_data.kChannelCount; ++ch) { |
| 594 auto sample_array_for_current_channel = |
| 595 test_data.bus_under_test->channel(ch); |
| 596 for (int frame_index = |
| 597 test_data.kInterleavedFrameCount + kWriteOffsetInFrames; |
| 598 frame_index < test_data.kFrameCount; frame_index++) { |
| 599 ASSERT_EQ(frame_index + 1, |
| 600 sample_array_for_current_channel[frame_index]); |
| 601 } |
| 602 } |
| 603 } |
| 604 { |
| 605 SCOPED_TRACE("Positive write offset"); |
| 606 |
| 607 ZeroingOutTestData test_data; |
| 608 static const int kWriteOffsetInFrames = 2; |
| 609 |
| 610 // Exercise |
| 611 test_data.bus_under_test->FromInterleavedPartial<Float32SampleTypeTraits>( |
| 612 &test_data.interleaved_dummy_frames[0], kWriteOffsetInFrames, |
| 613 test_data.kInterleavedFrameCount); |
| 614 |
| 615 // Verification |
| 616 for (int ch = 0; ch < test_data.kChannelCount; ++ch) { |
| 617 auto sample_array_for_current_channel = |
| 618 test_data.bus_under_test->channel(ch); |
| 619 // Check untouched frames before write offset |
| 620 for (int frame_index = 0; frame_index < kWriteOffsetInFrames; |
| 621 frame_index++) { |
| 622 ASSERT_EQ(frame_index + 1, |
| 623 sample_array_for_current_channel[frame_index]); |
| 624 } |
| 625 // Check untouched frames after write |
| 626 for (int frame_index = |
| 627 test_data.kInterleavedFrameCount + kWriteOffsetInFrames; |
| 628 frame_index < test_data.kFrameCount; frame_index++) { |
| 629 ASSERT_EQ(frame_index + 1, |
| 630 sample_array_for_current_channel[frame_index]); |
| 631 } |
| 632 } |
| 633 } |
| 398 } | 634 } |
| 399 | 635 |
| 400 TEST_F(AudioBusTest, Scale) { | 636 TEST_F(AudioBusTest, Scale) { |
| 401 std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount); | 637 std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount); |
| 402 | 638 |
| 403 // Fill the bus with dummy data. | 639 // Fill the bus with dummy data. |
| 404 static const float kFillValue = 1; | 640 static const float kFillValue = 1; |
| 405 for (int i = 0; i < bus->channels(); ++i) | 641 for (int i = 0; i < bus->channels(); ++i) |
| 406 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), kFillValue); | 642 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), kFillValue); |
| 407 | 643 |
| 408 // Adjust by an invalid volume and ensure volume is unchanged. | 644 // Adjust by an invalid volume and ensure volume is unchanged. |
| 409 bus->Scale(-1); | 645 bus->Scale(-1); |
| 410 for (int i = 0; i < bus->channels(); ++i) { | 646 for (int i = 0; i < bus->channels(); ++i) { |
| 411 SCOPED_TRACE("Invalid Scale"); | 647 SCOPED_TRACE("Invalid Scale"); |
| 412 VerifyValue(bus->channel(i), bus->frames(), kFillValue); | 648 VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), kFillValue); |
| 413 } | 649 } |
| 414 | 650 |
| 415 // Verify correct volume adjustment. | 651 // Verify correct volume adjustment. |
| 416 static const float kVolume = 0.5; | 652 static const float kVolume = 0.5; |
| 417 bus->Scale(kVolume); | 653 bus->Scale(kVolume); |
| 418 for (int i = 0; i < bus->channels(); ++i) { | 654 for (int i = 0; i < bus->channels(); ++i) { |
| 419 SCOPED_TRACE("Half Scale"); | 655 SCOPED_TRACE("Half Scale"); |
| 420 VerifyValue(bus->channel(i), bus->frames(), kFillValue * kVolume); | 656 VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), |
| 657 kFillValue * kVolume); |
| 421 } | 658 } |
| 422 | 659 |
| 423 // Verify zero volume case. | 660 // Verify zero volume case. |
| 424 bus->Scale(0); | 661 bus->Scale(0); |
| 425 for (int i = 0; i < bus->channels(); ++i) { | 662 for (int i = 0; i < bus->channels(); ++i) { |
| 426 SCOPED_TRACE("Zero Scale"); | 663 SCOPED_TRACE("Zero Scale"); |
| 427 VerifyValue(bus->channel(i), bus->frames(), 0); | 664 VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0); |
| 428 } | 665 } |
| 429 } | 666 } |
| 430 | 667 |
| 431 } // namespace media | 668 } // namespace media |
| OLD | NEW |