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

Side by Side Diff: chromecast/media/cma/backend/alsa/slew_volume_unittests.cc

Issue 2860673003: [Chromecast] Correct libcast_governor behavior. (Closed)
Patch Set: Add SlewVolume unittests. Created 3 years, 7 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
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <cmath>
6 #include <cstdint>
7 #include <limits>
8 #include <string>
9 #include <vector>
10
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/memory/ptr_util.h"
14 #include "chromecast/media/cma/backend/alsa/slew_volume.h"
15 #include "media/base/audio_bus.h"
16 #include "media/base/vector_math.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace chromecast {
20 namespace media {
21
22 namespace {
23
24 const int kNumChannels = 2;
25 const int kNumFrames = 100;
26 const float kSinFrequency = 1.0f / kNumFrames;
27 const int kBytesPerSample = sizeof(int32_t);
28
29 // Frequency is in frames (frequency = frequency_in_hz / sample rate)
30 std::unique_ptr<::media::AudioBus> GetSineData(size_t frames, float frequency) {
31 auto data = ::media::AudioBus::Create(kNumChannels, frames);
32 std::vector<int32_t> sine(frames * 2);
33 for (size_t i = 0; i < frames; ++i) {
34 // Offset by 1 because sin(0) = 0 and the first value is a special case.
35 sine[i * 2] = sin(static_cast<float>(i + 1) * frequency * 2 * M_PI) *
36 std::numeric_limits<int32_t>::max();
37 sine[i * 2 + 1] = cos(static_cast<float>(i + 1) * frequency * 2 * M_PI) *
38 std::numeric_limits<int32_t>::max();
39 }
40 data->FromInterleaved(sine.data(), frames, kBytesPerSample);
41 return data;
42 }
43
44 // Gets pointers to the data in an audiobus.
45 // If |swapped| is true, the channel order will be swapped.
46 std::vector<float*> GetDataChannels(::media::AudioBus* audio,
47 bool swapped = false) {
48 std::vector<float*> data(kNumChannels);
49 for (int i = 0; i < kNumChannels; ++i) {
50 int source_channel = swapped ? (i + 1) % kNumChannels : i;
51 data[i] = audio->channel(source_channel);
52 }
53 return data;
54 }
55
56 void ScaleData(const std::vector<float*>& data, int frames, float scale) {
57 for (size_t ch = 0; ch < data.size(); ++ch) {
58 for (int f = 0; f < frames; ++f) {
59 data[ch][f] *= scale;
60 }
61 }
62 }
63
64 void CompareDataPartial(const std::vector<float*>& expected,
65 const std::vector<float*>& actual,
66 int start,
67 int end) {
68 ASSERT_GE(start, 0);
69 ASSERT_LT(start, end);
70 ASSERT_EQ(expected.size(), actual.size());
71
72 for (size_t ch = 0; ch < expected.size(); ++ch) {
73 for (int f = start; f < end; ++f) {
74 EXPECT_FLOAT_EQ(expected[ch][f], actual[ch][f])
75 << "ch: " << ch << " f: " << f;
76 }
77 }
78 }
79
80 } // namespace
81
82 class SlewVolumeBaseTest : public ::testing::Test {
83 protected:
84 SlewVolumeBaseTest() = default;
85 ~SlewVolumeBaseTest() override = default;
86
87 void SetUp() override {
88 slew_volume_ = base::MakeUnique<SlewVolume>();
89 slew_volume_->Interrupted();
90 MakeData(kNumFrames);
91 }
92
93 void MakeData(int num_frames) {
94 num_frames_ = num_frames;
95 data_bus_ = GetSineData(num_frames_, kSinFrequency);
96 data_bus_2_ = GetSineData(num_frames_, kSinFrequency);
97 expected_bus_ = GetSineData(num_frames_, kSinFrequency);
98 data_ = GetDataChannels(data_bus_.get());
99 data_2_ = GetDataChannels(data_bus_2_.get(), true /* swapped */);
100 expected_ = GetDataChannels(expected_bus_.get());
101 }
102
103 void CompareBuffers(int start = 0, int end = -1) {
104 if (end == -1) {
105 end = num_frames_;
106 }
107 ASSERT_LE(end, num_frames_);
bcf 2017/05/04 03:45:06 ASSERT_GE(end, 0)
bshaya 2017/05/04 18:15:41 Done.
108 CompareDataPartial(expected_, data_, start, end);
109 }
110
111 void ClearInterrupted() {
112 float throwaway __attribute__((__aligned__(16))) = 0.0f;
113 slew_volume_->ProcessFMUL(false, &throwaway, 1, &throwaway);
114 }
115
116 int num_frames_;
117
118 std::unique_ptr<SlewVolume> slew_volume_;
119 std::unique_ptr<::media::AudioBus> data_bus_;
120 std::unique_ptr<::media::AudioBus> data_bus_2_;
121 std::unique_ptr<::media::AudioBus> expected_bus_;
122 std::vector<float*> data_;
123 std::vector<float*> data_2_;
124 std::vector<float*> expected_;
125
126 private:
127 DISALLOW_COPY_AND_ASSIGN(SlewVolumeBaseTest);
128 };
129
130 TEST_F(SlewVolumeBaseTest, BadSampleRate) {
131 ASSERT_DEATH(slew_volume_->SetSampleRate(0), "sample_rate");
132 }
133
134 TEST_F(SlewVolumeBaseTest, BadSlewTime) {
135 ASSERT_DEATH(slew_volume_->SetMaxSlewTimeMs(-1), "");
136 }
137
138 class SlewVolumeSteadyStateTest : public SlewVolumeBaseTest {
139 protected:
140 SlewVolumeSteadyStateTest() = default;
141 ~SlewVolumeSteadyStateTest() override = default;
142
143 void SetUp() override {
144 SlewVolumeBaseTest::SetUp();
145 slew_volume_->Interrupted();
146 }
147
148 private:
149 DISALLOW_COPY_AND_ASSIGN(SlewVolumeSteadyStateTest);
150 };
151
152 TEST_F(SlewVolumeSteadyStateTest, FMULNoOp) {
153 slew_volume_->SetVolume(1.0f);
154
155 slew_volume_->ProcessFMUL(false /* repeat transition */, data_[0],
156 num_frames_, data_[0]);
157 slew_volume_->ProcessFMUL(true /* repeat transition */, data_[1], num_frames_,
158 data_[1]);
159 CompareBuffers();
160 }
161
162 TEST_F(SlewVolumeSteadyStateTest, FMULCopy) {
163 slew_volume_->SetVolume(1.0f);
164
165 slew_volume_->ProcessFMUL(false /* repeat transition */, data_2_[0],
166 num_frames_, data_[0]);
167 slew_volume_->ProcessFMUL(true /* repeat transition */, data_2_[1],
168 num_frames_, data_[1]);
169 CompareDataPartial(data_2_, data_, 0, num_frames_);
170 }
171
172 TEST_F(SlewVolumeSteadyStateTest, FMULZero) {
173 slew_volume_->SetVolume(0.0f);
174 slew_volume_->ProcessFMUL(false, /* repeat transition */
175 data_[0], num_frames_, data_[0]);
176 slew_volume_->ProcessFMUL(true /* repeat transition */, data_[1], num_frames_,
177 data_[1]);
178
179 for (size_t ch = 0; ch < data_.size(); ++ch) {
180 for (int f = 0; f < num_frames_; ++f) {
181 EXPECT_EQ(0.0f, data_[ch][f]) << "at ch " << ch << "frame " << f;
182 }
183 }
184 }
185
186 TEST_F(SlewVolumeSteadyStateTest, FMULInterrupted) {
187 float volume = 0.6f;
188 slew_volume_->SetVolume(volume);
189
190 slew_volume_->ProcessFMUL(false /* repeat transition */,
191 data_[0] /* source */, num_frames_,
192 data_[0] /* dst */);
193 slew_volume_->ProcessFMUL(true /* repeat transition */, data_[1] /* source */,
194 num_frames_, data_[1] /* dst */);
195 ScaleData(expected_, num_frames_, volume);
196 CompareBuffers();
197 }
198
199 TEST_F(SlewVolumeSteadyStateTest, FMACNoOp) {
200 slew_volume_->SetVolume(0.0f);
201 slew_volume_->ProcessFMAC(false /* repeat transition */,
202 data_2_[0] /* source */, num_frames_,
203 data_[0] /* dst */);
204 slew_volume_->ProcessFMAC(false /* repeat transition */,
205 data_2_[1] /* source */, num_frames_,
206 data_[1] /*dst */);
207 CompareBuffers();
208 }
209
210 class SlewVolumeDynamicTest
211 : public SlewVolumeBaseTest,
212 public ::testing::WithParamInterface<std::tuple<int, int>> {
213 protected:
214 SlewVolumeDynamicTest() = default;
215 ~SlewVolumeDynamicTest() override = default;
216
217 void SetUp() override {
218 SlewVolumeBaseTest::SetUp();
219 sample_rate_ = std::get<0>(GetParam());
220 slew_time_ms_ = std::get<1>(GetParam());
221 slew_time_frames_ = sample_rate_ * slew_time_ms_ / 1000;
222 slew_volume_->SetSampleRate(sample_rate_);
223 slew_volume_->SetMaxSlewTimeMs(slew_time_ms_);
224
225 int num_frames = slew_time_frames_ + 2; // +2 frames for numeric errors.
226 ASSERT_GE(num_frames, 1);
227 MakeData(num_frames);
228 }
229
230 // Checks data_ = slew_volume_(expected_)
231 void CheckSlewMUL(double start_vol, double end_vol) {
232 for (size_t ch = 0; ch < data_.size(); ++ch) {
233 // First value should have original scaling applied.
234 EXPECT_FLOAT_EQ(expected_[ch][0] * start_vol, data_[ch][0]) << ch;
235
236 // Steady state have final scaling applied
237 int f = num_frames_ - 1;
238 EXPECT_FLOAT_EQ(expected_[ch][f] * end_vol, data_[ch][f]) << ch;
239 }
240 }
241
242 // Checks data_ = expected_ + slew_volume_(data_2_)
243 void CheckSlewMAC(double start_vol, double end_vol) {
244 for (size_t ch = 0; ch < data_.size(); ++ch) {
245 // First value should have original scaling applied.
246 EXPECT_FLOAT_EQ(expected_[ch][0] + data_2_[ch][0] * start_vol,
247 data_[ch][0])
248 << ch;
249
250 // Steady state have final scaling applied
251 int f = num_frames_ - 1;
252 EXPECT_FLOAT_EQ(expected_[ch][f] + data_2_[ch][f] * end_vol, data_[ch][f])
253 << ch << " " << f;
254 }
255 }
256
257 int sample_rate_;
258 int slew_time_ms_;
259 int slew_time_frames_;
260
261 private:
262 DISALLOW_COPY_AND_ASSIGN(SlewVolumeDynamicTest);
263 };
264
265 TEST_P(SlewVolumeDynamicTest, FMULRampUp) {
266 double start = 0.0;
267 double end = 1.0;
268 slew_volume_->SetVolume(start);
269 ClearInterrupted();
270
271 slew_volume_->SetVolume(end);
272 slew_volume_->ProcessFMUL(false, data_[0], num_frames_, data_[0]);
273 slew_volume_->ProcessFMUL(true, data_[1], num_frames_, data_[1]);
274 CheckSlewMUL(start, end);
275 }
276
277 TEST_P(SlewVolumeDynamicTest, FMULRampDown) {
278 double start = 1.0;
279 double end = 0.0;
280 slew_volume_->SetVolume(start);
281 ClearInterrupted();
282
283 slew_volume_->SetVolume(end);
284 slew_volume_->ProcessFMUL(false, data_[0], num_frames_, data_[0]);
285 slew_volume_->ProcessFMUL(true, data_[1], num_frames_, data_[1]);
286 CheckSlewMUL(start, end);
287 }
288
289 // Provide data as small buffers.
290 TEST_P(SlewVolumeDynamicTest, FMULRampDownByParts) {
291 double start = 1.0;
292 double end = 0.0;
293 slew_volume_->SetVolume(start);
294 ClearInterrupted();
295
296 slew_volume_->SetVolume(end);
297 int frame_step = ::media::vector_math::kRequiredAlignment / kBytesPerSample;
298 int f;
299 for (f = 0; f < num_frames_; f += frame_step) {
300 // Process any remaining samples in the last step.
301 if (num_frames_ - f < frame_step * 2) {
302 frame_step = num_frames_ - f;
303 }
304 slew_volume_->ProcessFMUL(false, expected_[0] + f, frame_step,
305 data_[0] + f);
306 slew_volume_->ProcessFMUL(true, expected_[1] + f, frame_step, data_[1] + f);
307 }
308 ASSERT_EQ(num_frames_, f);
309 CheckSlewMUL(start, end);
310 }
311
312 TEST_P(SlewVolumeDynamicTest, FMACRampUp) {
313 double start = 0.0;
314 double end = 1.0;
315 slew_volume_->SetVolume(start);
316 ClearInterrupted();
317
318 slew_volume_->SetVolume(end);
319 slew_volume_->ProcessFMAC(false, data_2_[0], num_frames_, data_[0]);
320 slew_volume_->ProcessFMAC(true, data_2_[1], num_frames_, data_[1]);
321 CheckSlewMAC(start, end);
322 }
323
324 TEST_P(SlewVolumeDynamicTest, FMACRampDown) {
325 double start = 1.0;
326 double end = 0.0;
327 slew_volume_->SetVolume(start);
328 ClearInterrupted();
329
330 slew_volume_->SetVolume(end);
331 slew_volume_->ProcessFMAC(false, data_2_[0], num_frames_, data_[0]);
332 slew_volume_->ProcessFMAC(true, data_2_[1], num_frames_, data_[1]);
333 CheckSlewMAC(start, end);
334 }
335
336 // Provide data as small buffers.
337 TEST_P(SlewVolumeDynamicTest, FMACRampUpByParts) {
338 double start = 0.0;
339 double end = 1.0;
340 slew_volume_->SetVolume(start);
341 ClearInterrupted();
342
343 slew_volume_->SetVolume(end);
344 int frame_step = ::media::vector_math::kRequiredAlignment / kBytesPerSample;
345 int f;
346 for (f = 0; f < num_frames_; f += frame_step) {
347 // Process any remaining samples in the last step.
348 if (num_frames_ - f < frame_step * 2) {
349 frame_step = num_frames_ - f;
350 }
351 slew_volume_->ProcessFMAC(false, data_2_[0] + f, frame_step, data_[0] + f);
352 slew_volume_->ProcessFMAC(true, data_2_[1] + f, frame_step, data_[1] + f);
353 }
354 ASSERT_EQ(num_frames_, f);
355 CheckSlewMAC(start, end);
356 }
357
358 INSTANTIATE_TEST_CASE_P(SingleBufferSlew,
359 SlewVolumeDynamicTest,
360 ::testing::Combine(::testing::Values(44100, 48000),
361 ::testing::Values(0, 15, 100)));
362 } // namespace media
363 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698