Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(347)

Side by Side Diff: media/base/audio_bus_unittest.cc

Issue 10824304: Upgrade AudioBus to support wrapping, interleaving. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <limits>
6
7 #include "base/stringprintf.h"
8 #include "base/time.h"
5 #include "media/audio/audio_parameters.h" 9 #include "media/audio/audio_parameters.h"
6 #include "media/base/audio_bus.h" 10 #include "media/base/audio_bus.h"
7 #include "media/base/channel_layout.h" 11 #include "media/base/channel_layout.h"
8 #include "testing/gtest/include/gtest/gtest.h" 12 #include "testing/gtest/include/gtest/gtest.h"
9 13
10 static const int kChannels = 6; 14 static const int kChannels = 6;
11 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_5_1; 15 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_5_1;
12 // Use a buffer size which is intentionally not a multiple of 16; see 16 // Use a buffer size which is intentionally not a multiple of kChannelAlignment.
13 // kChannelAlignment in audio_bus.cc. 17 static const int kFrameCount = media::AudioBus::kChannelAlignment * 128 - 1;
14 static const int kFrameCount = 1234; 18 static const int kSampleRate = 48000;
15 19
16 namespace media { 20 namespace media {
17 21
18 class AudioBusTest : public testing::Test { 22 class AudioBusTest : public testing::Test {
19 public: 23 public:
20 AudioBusTest() {} 24 AudioBusTest() {}
21 ~AudioBusTest() { 25 ~AudioBusTest() {
22 for (size_t i = 0; i < data_.size(); ++i) 26 for (size_t i = 0; i < data_.size(); ++i)
23 base::AlignedFree(data_[i]); 27 base::AlignedFree(data_[i]);
24 } 28 }
25 29
26 // Validate parameters returned by AudioBus v.s. the constructed parameters. 30 // Validate parameters returned by AudioBus v.s. the constructed parameters.
27 void VerifyParams(AudioBus* bus) { 31 void VerifyParams(AudioBus* bus) {
28 EXPECT_EQ(kChannels, bus->channels()); 32 EXPECT_EQ(kChannels, bus->channels());
29 EXPECT_EQ(kFrameCount, bus->frames()); 33 EXPECT_EQ(kFrameCount, bus->frames());
30 } 34 }
31 35
32 void VerifyValue(const float data[], int size, float value) { 36 void VerifyValue(const float data[], int size, float value) {
33 for (int i = 0; i < size; ++i) 37 for (int i = 0; i < size; ++i)
34 ASSERT_FLOAT_EQ(value, data[i]); 38 ASSERT_FLOAT_EQ(value, data[i]);
35 } 39 }
36 40
41 // Verify values for each channel in |result| against |expected|.
42 void VerifyBus(const AudioBus* result, const AudioBus* expected) {
43 ASSERT_EQ(expected->channels(), result->channels());
44 ASSERT_EQ(expected->frames(), result->frames());
45 for (int ch = 0; ch < result->channels(); ++ch) {
46 for (int i = 0; i < result->frames(); ++i) {
47 SCOPED_TRACE(base::StringPrintf("ch=%d, i=%d", ch, i));
48 ASSERT_FLOAT_EQ(expected->channel(ch)[i], result->channel(ch)[i]);
49 }
50 }
51 }
52
37 // Read and write to the full extent of the allocated channel data. Also test 53 // Read and write to the full extent of the allocated channel data. Also test
38 // the Zero() method and verify it does as advertised. Also test data if data 54 // the Zero() method and verify it does as advertised. Also test data if data
39 // is 16-byte aligned as advertised (see kChannelAlignment in audio_bus.cc). 55 // is 16-byte aligned as advertised (see kChannelAlignment in audio_bus.h).
40 void VerifyChannelData(AudioBus* bus) { 56 void VerifyChannelData(AudioBus* bus) {
41 for (int i = 0; i < bus->channels(); ++i) { 57 for (int i = 0; i < bus->channels(); ++i) {
42 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(bus->channel(i)) & 0x0F); 58 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(
59 bus->channel(i)) & (AudioBus::kChannelAlignment - 1));
43 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i); 60 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i);
44 } 61 }
45 62
46 for (int i = 0; i < bus->channels(); ++i) 63 for (int i = 0; i < bus->channels(); ++i)
47 VerifyValue(bus->channel(i), bus->frames(), i); 64 VerifyValue(bus->channel(i), bus->frames(), i);
48 65
49 bus->Zero(); 66 bus->Zero();
50 for (int i = 0; i < bus->channels(); ++i) 67 for (int i = 0; i < bus->channels(); ++i)
51 VerifyValue(bus->channel(i), bus->frames(), 0); 68 VerifyValue(bus->channel(i), bus->frames(), 0);
52 } 69 }
53 70
71 // Verify copying to and from |bus1| and |bus2|.
72 void CopyTest(AudioBus* bus1, AudioBus* bus2) {
73 // Fill |bus1| with dummy data.
74 for (int i = 0; i < bus1->channels(); ++i)
75 std::fill(bus1->channel(i), bus1->channel(i) + bus1->frames(), i);
76
77 // Verify copy from |bus1| to |bus2|.
78 bus2->Zero();
79 bus1->CopyTo(bus2);
80 VerifyBus(bus1, bus2);
81
82 // Verify copy from |bus2| to |bus1|.
83 bus1->Zero();
84 bus2->CopyTo(bus1);
85 VerifyBus(bus2, bus1);
86 }
54 87
55 protected: 88 protected:
56 std::vector<float*> data_; 89 std::vector<float*> data_;
57 90
58 DISALLOW_COPY_AND_ASSIGN(AudioBusTest); 91 DISALLOW_COPY_AND_ASSIGN(AudioBusTest);
59 }; 92 };
60 93
61 // Verify basic Create(...) method works as advertised. 94 // Verify basic Create(...) method works as advertised.
62 TEST_F(AudioBusTest, Create) { 95 TEST_F(AudioBusTest, Create) {
63 scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount); 96 scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
64 VerifyParams(bus.get()); 97 VerifyParams(bus.get());
65 VerifyChannelData(bus.get()); 98 VerifyChannelData(bus.get());
66 } 99 }
67 100
68 // Verify Create(...) using AudioParameters works as advertised. 101 // Verify Create(...) using AudioParameters works as advertised.
69 TEST_F(AudioBusTest, CreateUsingAudioParameters) { 102 TEST_F(AudioBusTest, CreateUsingAudioParameters) {
70 scoped_ptr<AudioBus> bus = AudioBus::Create(AudioParameters( 103 scoped_ptr<AudioBus> bus = AudioBus::Create(AudioParameters(
71 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, 48000, 32, 104 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
72 kFrameCount)); 105 kFrameCount));
73 VerifyParams(bus.get()); 106 VerifyParams(bus.get());
74 VerifyChannelData(bus.get()); 107 VerifyChannelData(bus.get());
75 } 108 }
76 109
77 // Verify an AudioBus created via wrapping works as advertised. 110 // Verify an AudioBus created via wrapping a vector works as advertised.
78 TEST_F(AudioBusTest, Wrap) { 111 TEST_F(AudioBusTest, WrapVector) {
79 data_.reserve(kChannels); 112 data_.reserve(kChannels);
80 for (int i = 0; i < kChannels; ++i) { 113 for (int i = 0; i < kChannels; ++i) {
81 data_.push_back(static_cast<float*>(base::AlignedAlloc( 114 data_.push_back(static_cast<float*>(base::AlignedAlloc(
82 sizeof(*data_[i]) * kFrameCount, 16))); 115 sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
83 } 116 }
84 117
85 scoped_ptr<AudioBus> bus = AudioBus::WrapVector(kFrameCount, data_); 118 scoped_ptr<AudioBus> bus = AudioBus::WrapVector(kFrameCount, data_);
86 VerifyParams(bus.get()); 119 VerifyParams(bus.get());
87 VerifyChannelData(bus.get()); 120 VerifyChannelData(bus.get());
88 } 121 }
89 122
123 // Verify an AudioBus created via wrapping a memory block works as advertised.
124 TEST_F(AudioBusTest, WrapMemory) {
125 AudioParameters params(
126 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
127 kFrameCount);
128 int data_size = AudioBus::CalculateMemorySize(params);
129 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data(static_cast<float*>(
130 base::AlignedAlloc(data_size, AudioBus::kChannelAlignment)));
131
132 // Fill the memory with a test value we can check for after wrapping.
133 static const float kTestValue = 3;
134 std::fill(
135 data.get(), data.get() + data_size / sizeof(*data.get()), kTestValue);
136
137 scoped_ptr<AudioBus> bus = AudioBus::WrapMemory(params, data.get());
138 // Verify the test value we filled prior to wrapping.
139 for (int i = 0; i < bus->channels(); ++i)
140 VerifyValue(bus->channel(i), bus->frames(), kTestValue);
141 VerifyParams(bus.get());
142 VerifyChannelData(bus.get());
143
144 // Verify the channel vectors lie within the provided memory block.
145 EXPECT_GE(bus->channel(0), data.get());
146 EXPECT_LT(bus->channel(bus->channels() - 1) + bus->frames(),
147 data.get() + data_size / sizeof(*data.get()));
148 }
149
90 // Simulate a shared memory transfer and verify results. 150 // Simulate a shared memory transfer and verify results.
91 TEST_F(AudioBusTest, AudioData) { 151 TEST_F(AudioBusTest, CopyTo) {
152 // Create one bus with AudioParameters and the other through direct values to
153 // test for parity between the Create() functions.
154 AudioParameters params(
155 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
156 kFrameCount);
92 scoped_ptr<AudioBus> bus1 = AudioBus::Create(kChannels, kFrameCount); 157 scoped_ptr<AudioBus> bus1 = AudioBus::Create(kChannels, kFrameCount);
93 scoped_ptr<AudioBus> bus2 = AudioBus::Create(kChannels, kFrameCount); 158 scoped_ptr<AudioBus> bus2 = AudioBus::Create(params);
94 159
95 // Fill |bus1| with dummy data and zero out |bus2|. 160 {
96 for (int i = 0; i < bus1->channels(); ++i) 161 SCOPED_TRACE("Created");
97 std::fill(bus1->channel(i), bus1->channel(i) + bus1->frames(), i); 162 CopyTest(bus1.get(), bus2.get());
98 bus2->Zero(); 163 }
164 {
165 SCOPED_TRACE("Wrapped Vector");
166 // Try a copy to an AudioBus wrapping a vector.
167 data_.reserve(kChannels);
168 for (int i = 0; i < kChannels; ++i) {
169 data_.push_back(static_cast<float*>(base::AlignedAlloc(
170 sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
171 }
99 172
100 // Transfer audio data from |bus1| to |bus2|. 173 bus2 = AudioBus::WrapVector(kFrameCount, data_);
101 ASSERT_EQ(bus1->data_size(), bus2->data_size()); 174 CopyTest(bus1.get(), bus2.get());
102 memcpy(bus2->data(), bus1->data(), bus1->data_size()); 175 }
176 {
177 SCOPED_TRACE("Wrapped Memory");
178 // Try a copy to an AudioBus wrapping a memory block.
179 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data(
180 static_cast<float*>(base::AlignedAlloc(
181 AudioBus::CalculateMemorySize(params),
182 AudioBus::kChannelAlignment)));
103 183
104 for (int i = 0; i < bus2->channels(); ++i) 184 bus2 = AudioBus::WrapMemory(params, data.get());
105 VerifyValue(bus2->channel(i), bus2->frames(), i); 185 CopyTest(bus1.get(), bus2.get());
186 }
106 } 187 }
107 188
108 // Verify Zero() and ZeroFrames(...) utility methods work as advertised. 189 // Verify Zero() and ZeroFrames(...) utility methods work as advertised.
109 TEST_F(AudioBusTest, Zero) { 190 TEST_F(AudioBusTest, Zero) {
110 scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount); 191 scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
111 192
112 // First fill the bus with dummy data. 193 // First fill the bus with dummy data.
113 for (int i = 0; i < bus->channels(); ++i) 194 for (int i = 0; i < bus->channels(); ++i)
114 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1); 195 std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
115 196
116 // Zero half the frames of each channel. 197 // Zero half the frames of each channel.
117 bus->ZeroFrames(kFrameCount / 2); 198 bus->ZeroFrames(kFrameCount / 2);
118 for (int i = 0; i < bus->channels(); ++i) 199 for (int i = 0; i < bus->channels(); ++i)
119 VerifyValue(bus->channel(i), kFrameCount / 2, 0); 200 VerifyValue(bus->channel(i), kFrameCount / 2, 0);
120 201
121 // Zero all the frames of each channel. 202 // Zero all the frames of each channel.
122 bus->Zero(); 203 bus->Zero();
123 for (int i = 0; i < bus->channels(); ++i) 204 for (int i = 0; i < bus->channels(); ++i)
124 VerifyValue(bus->channel(i), bus->frames(), 0); 205 VerifyValue(bus->channel(i), bus->frames(), 0);
125 } 206 }
126 207
208 // Each test vector represents two channels of data in the following arbitrary
209 // layout: <min, zero, max, min, zero, max, zero, zero>.
210 static const int kTestVectorSize = 8;
211 static const uint8 kTestVectorUint8[kTestVectorSize] = {
212 0, -kint8min, kuint8max, 0, -kint8min, kuint8max, -kint8min, -kint8min };
213 static const int16 kTestVectorInt16[kTestVectorSize] = {
214 kint16min, 0, kint16max, kint16min, 0, kint16max, 0, 0 };
215 static const int32 kTestVectorInt32[kTestVectorSize] = {
216 kint32min, 0, kint32max, kint32min, 0, kint32max, 0, 0 };
217
218 // Expected results.
219 static const int kTestVectorFrames = kTestVectorSize / 2;
220 static const float kTestVectorResult[][kTestVectorFrames] = {
221 { -1, 1, 0, 0 }, { 0, -1, 1, 0 }};
222 static const int kTestVectorChannels = arraysize(kTestVectorResult);
223
224 // Verify FromInterleaved() deinterleaves audio in supported formats correctly.
225 TEST_F(AudioBusTest, FromInterleaved) {
226 scoped_ptr<AudioBus> bus = AudioBus::Create(
227 kTestVectorChannels, kTestVectorFrames);
228 scoped_ptr<AudioBus> expected = AudioBus::Create(
229 kTestVectorChannels, kTestVectorFrames);
230 for (int ch = 0; ch < kTestVectorChannels; ++ch) {
231 memcpy(expected->channel(ch), kTestVectorResult[ch],
232 kTestVectorFrames * sizeof(*expected->channel(ch)));
233 }
234 {
235 SCOPED_TRACE("uint8");
236 bus->FromInterleaved(
237 kTestVectorUint8, kTestVectorFrames, sizeof(*kTestVectorUint8));
238 VerifyBus(bus.get(), expected.get());
239 }
240 {
241 SCOPED_TRACE("int16");
242 bus->FromInterleaved(
243 kTestVectorInt16, kTestVectorFrames, sizeof(*kTestVectorInt16));
244 VerifyBus(bus.get(), expected.get());
245 }
246 {
247 SCOPED_TRACE("int32");
248 bus->FromInterleaved(
249 kTestVectorInt32, kTestVectorFrames, sizeof(*kTestVectorInt32));
250 VerifyBus(bus.get(), expected.get());
251 }
252 }
253
254 // Verify ToInterleaved() interleaves audio in suported formats correctly.
255 TEST_F(AudioBusTest, ToInterleaved) {
256 scoped_ptr<AudioBus> bus = AudioBus::Create(
257 kTestVectorChannels, kTestVectorFrames);
258 // Fill the bus with our test vector.
259 for (int ch = 0; ch < kTestVectorChannels; ++ch) {
260 memcpy(bus->channel(ch), kTestVectorResult[ch],
261 kTestVectorFrames * sizeof(*bus->channel(ch)));
262 }
263 {
264 SCOPED_TRACE("uint8");
265 uint8 test_array[arraysize(kTestVectorUint8)];
266 bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorUint8), test_array);
267 ASSERT_EQ(memcmp(
268 test_array, kTestVectorUint8, arraysize(kTestVectorUint8)), 0);
269 }
270 {
271 SCOPED_TRACE("int16");
272 int16 test_array[arraysize(kTestVectorInt16)];
273 bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt16), test_array);
274 ASSERT_EQ(memcmp(
275 test_array, kTestVectorInt16, arraysize(kTestVectorInt16)), 0);
276 }
277 {
278 SCOPED_TRACE("int32");
279 int32 test_array[arraysize(kTestVectorInt32)];
280 bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt32), test_array);
281 ASSERT_EQ(memcmp(
282 test_array, kTestVectorInt32, arraysize(kTestVectorInt32)), 0);
283 }
284 }
285
127 } // namespace media 286 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698