• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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