1 // Copyright (c) 2014 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.
8 #include "media/base/audio_bus.h"
9 #include "media/base/audio_shifter.h"
10 #include "testing/gtest/include/gtest/gtest.h"
14 const int kSampleRate
= 48000;
15 const int kInputPacketSize
= 48;
16 const int kOutputPacketSize
= 24;
20 class AudioShifterTest
:
21 public ::testing::TestWithParam
<::testing::tuple
<int, int, int, bool> > {
24 : shifter_(base::TimeDelta::FromMilliseconds(2000),
25 base::TimeDelta::FromMilliseconds(3),
26 base::TimeDelta::FromMilliseconds(100),
29 end2end_latency_(base::TimeDelta::FromMilliseconds(30)),
30 playback_latency_(base::TimeDelta::FromMilliseconds(10)),
32 expect_smooth_output_(true),
37 void SetupInput(int size
, base::TimeDelta rate
) {
42 scoped_ptr
<AudioBus
> CreateTestInput() {
43 scoped_ptr
<AudioBus
> input(AudioBus::Create(2, input_size_
));
44 for (size_t i
= 0; i
< input_size_
; i
++) {
45 input
->channel(0)[i
] = input
->channel(1)[i
] = input_sample_n_
;
49 input
->channel(0)[0] = 10000000.0;
51 expect_smooth_output_
= false;
56 void SetupOutput(int size
, base::TimeDelta rate
) {
57 test_output_
= AudioBus::Create(2, size
);
61 void SetUp() override
{
63 kInputPacketSize
+ ::testing::get
<0>(GetParam()) - 1,
64 base::TimeDelta::FromMicroseconds(
65 1000 + ::testing::get
<1>(GetParam()) * 5 - 5));
68 base::TimeDelta::FromMicroseconds(
69 500 + ::testing::get
<2>(GetParam()) * 3 - 3));
70 if (::testing::get
<3>(GetParam())) {
71 end2end_latency_
= -end2end_latency_
;
75 void Run(size_t loops
) {
76 for (size_t i
= 0; i
< loops
;) {
77 if (now_
>= time_to_push_
) {
78 shifter_
.Push(CreateTestInput(), now_
+ end2end_latency_
);
79 time_to_push_
+= input_rate_
;
82 if (now_
>= time_to_pull_
) {
83 shifter_
.Pull(test_output_
.get(), now_
+ playback_latency_
);
86 j
< static_cast<size_t>(test_output_
->frames());
88 if (test_output_
->channel(0)[j
] != 0.0) {
90 if (test_output_
->channel(0)[j
] > 3000000.0) {
91 marker_outputs_
.push_back(
92 now_
+ playback_latency_
+
93 base::TimeDelta::FromSeconds(j
) / kSampleRate
);
95 // We don't expect smooth output once we insert a tag,
96 // or in the very beginning.
97 if (expect_smooth_output_
&& output_sample_
> 500.0) {
98 EXPECT_GT(test_output_
->channel(0)[j
], output_sample_
- 3)
100 if (test_output_
->channel(0)[j
] >
101 output_sample_
+ kOutputPacketSize
/ 2) {
102 skip_outputs_
.push_back(now_
+ playback_latency_
);
105 output_sample_
= test_output_
->channel(0)[j
];
110 silent_outputs_
.push_back(now_
);
112 time_to_pull_
+= output_rate_
;
114 now_
+= std::min(time_to_push_
- now_
,
115 time_to_pull_
- now_
);
119 void RunAndCheckSync(size_t loops
) {
121 size_t expected_silent_outputs
= silent_outputs_
.size();
124 CHECK(marker_outputs_
.empty());
125 base::TimeTicks expected_mark_time
= time_to_push_
+ end2end_latency_
;
127 if (end2end_latency_
> base::TimeDelta()) {
128 CHECK(!marker_outputs_
.empty());
129 base::TimeDelta actual_offset
= marker_outputs_
[0] - expected_mark_time
;
130 EXPECT_LT(actual_offset
, base::TimeDelta::FromMicroseconds(100));
131 EXPECT_GT(actual_offset
, base::TimeDelta::FromMicroseconds(-100));
133 EXPECT_GT(marker_outputs_
.size(), 0UL);
135 EXPECT_EQ(expected_silent_outputs
, silent_outputs_
.size());
139 AudioShifter shifter_
;
140 base::TimeDelta input_rate_
;
141 base::TimeDelta output_rate_
;
142 base::TimeDelta end2end_latency_
;
143 base::TimeDelta playback_latency_
;
144 base::TimeTicks time_to_push_
;
145 base::TimeTicks time_to_pull_
;
146 base::TimeTicks now_
;
147 scoped_ptr
<AudioBus
> test_input_
;
148 scoped_ptr
<AudioBus
> test_output_
;
149 std::vector
<base::TimeTicks
> silent_outputs_
;
150 std::vector
<base::TimeTicks
> skip_outputs_
;
151 std::vector
<base::TimeTicks
> marker_outputs_
;
154 bool expect_smooth_output_
;
155 size_t input_sample_n_
;
156 double output_sample_
;
159 TEST_P(AudioShifterTest
, TestSync
) {
160 RunAndCheckSync(1000);
161 EXPECT_EQ(0UL, skip_outputs_
.size());
164 TEST_P(AudioShifterTest
, TestSyncWithPush
) {
165 // Push some extra audio.
166 shifter_
.Push(CreateTestInput().Pass(), now_
- base::TimeDelta(input_rate_
));
167 RunAndCheckSync(1000);
168 EXPECT_LE(skip_outputs_
.size(), 2UL);
171 TEST_P(AudioShifterTest
, TestSyncWithPull
) {
172 // Output should smooth out eventually, but that is not tested yet.
173 expect_smooth_output_
= false;
175 for (int i
= 0; i
< 100; i
++) {
176 shifter_
.Pull(test_output_
.get(),
177 now_
+ base::TimeDelta::FromMilliseconds(i
));
179 RunAndCheckSync(1000);
180 EXPECT_LE(skip_outputs_
.size(), 1UL);
183 TEST_P(AudioShifterTest
, UnderOverFlow
) {
184 expect_smooth_output_
= false;
186 kInputPacketSize
+ ::testing::get
<0>(GetParam()) * 10 - 10,
187 base::TimeDelta::FromMicroseconds(
188 1000 + ::testing::get
<1>(GetParam()) * 100 - 100));
191 base::TimeDelta::FromMicroseconds(
192 500 + ::testing::get
<2>(GetParam()) * 50 - 50));
193 // Sane output is not expected, but let's make sure we don't crash.
197 // Note: First argument is optional and intentionally left blank.
198 // (it's a prefix for the generated test cases)
199 INSTANTIATE_TEST_CASE_P(
202 ::testing::Combine(::testing::Range(0, 3),
203 ::testing::Range(0, 3),
204 ::testing::Range(0, 3),