1 // Copyright 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.
4
5 #include "base/memory/scoped_ptr.h"
6 #include "media/base/audio_buffer.h"
7 #include "media/base/audio_buffer_converter.h"
8 #include "media/base/sinc_resampler.h"
9 #include "media/base/test_helpers.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 namespace media {
14
15 // Important: Use an odd buffer size here so SIMD issues are caught.
16 const int kOutFrameSize = 441;
17 const int kOutSampleRate = 44100;
18 const ChannelLayout kOutChannelLayout = CHANNEL_LAYOUT_STEREO;
19 const int kOutChannelCount = 2;
20
MakeTestBuffer(int sample_rate,ChannelLayout channel_layout,int channel_count,int frames)21 static scoped_refptr<AudioBuffer> MakeTestBuffer(int sample_rate,
22 ChannelLayout channel_layout,
23 int channel_count,
24 int frames) {
25 return MakeAudioBuffer<uint8>(kSampleFormatU8,
26 channel_layout,
27 channel_count,
28 sample_rate,
29 0,
30 1,
31 frames,
32 base::TimeDelta::FromSeconds(0));
33 }
34
35 class AudioBufferConverterTest : public ::testing::Test {
36 public:
AudioBufferConverterTest()37 AudioBufferConverterTest()
38 : input_frames_(0),
39 expected_output_frames_(0.0),
40 output_frames_(0),
41 output_params_(AudioParameters::AUDIO_PCM_LOW_LATENCY,
42 kOutChannelLayout,
43 kOutSampleRate,
44 16,
45 kOutFrameSize) {
46 audio_buffer_converter_.reset(new AudioBufferConverter(output_params_));
47 }
48
Reset()49 void Reset() {
50 audio_buffer_converter_->Reset();
51 output_frames_ = expected_output_frames_ = input_frames_ = 0;
52 }
53
AddInput(const scoped_refptr<AudioBuffer> & in)54 void AddInput(const scoped_refptr<AudioBuffer>& in) {
55 if (!in->end_of_stream()) {
56 input_frames_ += in->frame_count();
57 expected_output_frames_ +=
58 in->frame_count() *
59 (static_cast<double>(output_params_.sample_rate()) /
60 in->sample_rate());
61 }
62 audio_buffer_converter_->AddInput(in);
63 }
64
ConsumeOutput()65 void ConsumeOutput() {
66 ASSERT_TRUE(audio_buffer_converter_->HasNextBuffer());
67 scoped_refptr<AudioBuffer> out = audio_buffer_converter_->GetNextBuffer();
68 if (!out->end_of_stream()) {
69 output_frames_ += out->frame_count();
70 EXPECT_EQ(out->sample_rate(), output_params_.sample_rate());
71 EXPECT_EQ(out->channel_layout(), output_params_.channel_layout());
72 EXPECT_EQ(out->channel_count(), output_params_.channels());
73 } else {
74 EXPECT_FALSE(audio_buffer_converter_->HasNextBuffer());
75 }
76 }
77
ConsumeAllOutput()78 void ConsumeAllOutput() {
79 AddInput(AudioBuffer::CreateEOSBuffer());
80 while (audio_buffer_converter_->HasNextBuffer())
81 ConsumeOutput();
82 EXPECT_EQ(output_frames_, ceil(expected_output_frames_));
83 }
84
85 protected:
86 scoped_ptr<AudioBufferConverter> audio_buffer_converter_;
87
88 int input_frames_;
89 double expected_output_frames_;
90 int output_frames_;
91 int input_buffers_;
92 AudioParameters output_params_;
93 };
94
TEST_F(AudioBufferConverterTest,PassThrough)95 TEST_F(AudioBufferConverterTest, PassThrough) {
96 scoped_refptr<AudioBuffer> in =
97 MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512);
98 AddInput(in);
99 ConsumeAllOutput();
100 }
101
TEST_F(AudioBufferConverterTest,Downsample)102 TEST_F(AudioBufferConverterTest, Downsample) {
103 scoped_refptr<AudioBuffer> in =
104 MakeTestBuffer(48000, kOutChannelLayout, kOutChannelCount, 512);
105 AddInput(in);
106 ConsumeAllOutput();
107 }
108
TEST_F(AudioBufferConverterTest,Upsample)109 TEST_F(AudioBufferConverterTest, Upsample) {
110 scoped_refptr<AudioBuffer> in =
111 MakeTestBuffer(8000, kOutChannelLayout, kOutChannelCount, 512);
112 AddInput(in);
113 ConsumeAllOutput();
114 }
115
116 // Test resampling a buffer smaller than the SincResampler's kernel size.
TEST_F(AudioBufferConverterTest,Resample_TinyBuffer)117 TEST_F(AudioBufferConverterTest, Resample_TinyBuffer) {
118 AddInput(MakeTestBuffer(
119 48000, CHANNEL_LAYOUT_STEREO, 2, SincResampler::kKernelSize - 1));
120 ConsumeAllOutput();
121 }
122
TEST_F(AudioBufferConverterTest,Resample_DifferingBufferSizes)123 TEST_F(AudioBufferConverterTest, Resample_DifferingBufferSizes) {
124 const int input_sample_rate = 48000;
125 AddInput(MakeTestBuffer(
126 input_sample_rate, kOutChannelLayout, kOutChannelCount, 100));
127 AddInput(MakeTestBuffer(
128 input_sample_rate, kOutChannelLayout, kOutChannelCount, 200));
129 AddInput(MakeTestBuffer(
130 input_sample_rate, kOutChannelLayout, kOutChannelCount, 300));
131 AddInput(MakeTestBuffer(
132 input_sample_rate, kOutChannelLayout, kOutChannelCount, 400));
133 AddInput(MakeTestBuffer(
134 input_sample_rate, kOutChannelLayout, kOutChannelCount, 500));
135 ConsumeAllOutput();
136 }
137
TEST_F(AudioBufferConverterTest,ChannelDownmix)138 TEST_F(AudioBufferConverterTest, ChannelDownmix) {
139 scoped_refptr<AudioBuffer> in =
140 MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_MONO, 1, 512);
141 AddInput(in);
142 ConsumeAllOutput();
143 }
144
TEST_F(AudioBufferConverterTest,ChannelUpmix)145 TEST_F(AudioBufferConverterTest, ChannelUpmix) {
146 scoped_refptr<AudioBuffer> in =
147 MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_5_1, 6, 512);
148 AddInput(in);
149 ConsumeAllOutput();
150 }
151
TEST_F(AudioBufferConverterTest,ResampleAndRemix)152 TEST_F(AudioBufferConverterTest, ResampleAndRemix) {
153 scoped_refptr<AudioBuffer> in =
154 MakeTestBuffer(48000, CHANNEL_LAYOUT_5_1, 6, 512);
155 AddInput(in);
156 ConsumeAllOutput();
157 }
158
TEST_F(AudioBufferConverterTest,ConfigChange_SampleRate)159 TEST_F(AudioBufferConverterTest, ConfigChange_SampleRate) {
160 AddInput(MakeTestBuffer(48000, kOutChannelLayout, kOutChannelCount, 512));
161 AddInput(MakeTestBuffer(44100, kOutChannelLayout, kOutChannelCount, 512));
162 ConsumeAllOutput();
163 }
164
TEST_F(AudioBufferConverterTest,ConfigChange_ChannelLayout)165 TEST_F(AudioBufferConverterTest, ConfigChange_ChannelLayout) {
166 AddInput(MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_STEREO, 2, 512));
167 AddInput(MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_MONO, 1, 512));
168 ConsumeAllOutput();
169 }
170
TEST_F(AudioBufferConverterTest,ConfigChange_SampleRateAndChannelLayout)171 TEST_F(AudioBufferConverterTest, ConfigChange_SampleRateAndChannelLayout) {
172 AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512));
173 AddInput(MakeTestBuffer(48000, CHANNEL_LAYOUT_MONO, 1, 512));
174 ConsumeAllOutput();
175 }
176
TEST_F(AudioBufferConverterTest,ConfigChange_Multiple)177 TEST_F(AudioBufferConverterTest, ConfigChange_Multiple) {
178 AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512));
179 AddInput(MakeTestBuffer(48000, CHANNEL_LAYOUT_MONO, 1, 512));
180 AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_5_1, 6, 512));
181 AddInput(MakeTestBuffer(22050, CHANNEL_LAYOUT_STEREO, 2, 512));
182 ConsumeAllOutput();
183 }
184
TEST_F(AudioBufferConverterTest,Reset)185 TEST_F(AudioBufferConverterTest, Reset) {
186 AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512));
187 Reset();
188 ConsumeAllOutput();
189 }
190
TEST_F(AudioBufferConverterTest,ResampleThenReset)191 TEST_F(AudioBufferConverterTest, ResampleThenReset) {
192 // Resampling is likely to leave some data buffered in AudioConverter's
193 // fifo or resampler, so make sure Reset() cleans that all up.
194 AddInput(MakeTestBuffer(48000, CHANNEL_LAYOUT_STEREO, 2, 512));
195 Reset();
196 ConsumeAllOutput();
197 }
198
TEST_F(AudioBufferConverterTest,ResetThenConvert)199 TEST_F(AudioBufferConverterTest, ResetThenConvert) {
200 AddInput(
201 MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512));
202 Reset();
203 // Make sure we can keep using the AudioBufferConverter after we've Reset().
204 AddInput(
205 MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512));
206 ConsumeAllOutput();
207 }
208
TEST_F(AudioBufferConverterTest,DiscreteChannelLayout)209 TEST_F(AudioBufferConverterTest, DiscreteChannelLayout) {
210 output_params_ = AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
211 CHANNEL_LAYOUT_DISCRETE,
212 2,
213 kOutSampleRate,
214 16,
215 512,
216 0);
217 audio_buffer_converter_.reset(new AudioBufferConverter(output_params_));
218 AddInput(MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_STEREO, 2, 512));
219 ConsumeAllOutput();
220 }
221
TEST_F(AudioBufferConverterTest,LargeBuffersResampling)222 TEST_F(AudioBufferConverterTest, LargeBuffersResampling) {
223 output_params_ = AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
224 kOutChannelLayout,
225 kOutSampleRate,
226 16,
227 2048);
228
229 audio_buffer_converter_.reset(new AudioBufferConverter(output_params_));
230 const int kInputSampleRate = 48000;
231 const int kInputFrameSize = 8192;
232 ASSERT_NE(kInputSampleRate, kOutSampleRate);
233
234 const int kInputBuffers = 3;
235 for (int i = 0; i < kInputBuffers; ++i) {
236 AddInput(MakeTestBuffer(kInputSampleRate,
237 kOutChannelLayout,
238 kOutChannelCount,
239 kInputFrameSize));
240 }
241
242 // Do not add an EOS packet here, as it will invoke flushing.
243 while (audio_buffer_converter_->HasNextBuffer())
244 ConsumeOutput();
245
246 // Since the input buffer size is a multiple of the input request size there
247 // should never be any frames remaining at this point.
248 ASSERT_EQ(kInputFrameSize %
249 audio_buffer_converter_->input_buffer_size_for_testing(),
250 0);
251 EXPECT_EQ(0, audio_buffer_converter_->input_frames_left_for_testing());
252 }
253
254 } // namespace media
255