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 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: 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 49 void Reset() { 50 audio_buffer_converter_->Reset(); 51 output_frames_ = expected_output_frames_ = input_frames_ = 0; 52 } 53 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 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 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 95 TEST_F(AudioBufferConverterTest, PassThrough) { 96 scoped_refptr<AudioBuffer> in = 97 MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512); 98 AddInput(in); 99 ConsumeAllOutput(); 100 } 101 102 TEST_F(AudioBufferConverterTest, Downsample) { 103 scoped_refptr<AudioBuffer> in = 104 MakeTestBuffer(48000, kOutChannelLayout, kOutChannelCount, 512); 105 AddInput(in); 106 ConsumeAllOutput(); 107 } 108 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. 117 TEST_F(AudioBufferConverterTest, Resample_TinyBuffer) { 118 AddInput(MakeTestBuffer( 119 48000, CHANNEL_LAYOUT_STEREO, 2, SincResampler::kKernelSize - 1)); 120 ConsumeAllOutput(); 121 } 122 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 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 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 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 159 TEST_F(AudioBufferConverterTest, ConfigChange_SampleRate) { 160 AddInput(MakeTestBuffer(48000, kOutChannelLayout, kOutChannelCount, 512)); 161 AddInput(MakeTestBuffer(44100, kOutChannelLayout, kOutChannelCount, 512)); 162 ConsumeAllOutput(); 163 } 164 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 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 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 185 TEST_F(AudioBufferConverterTest, Reset) { 186 AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512)); 187 Reset(); 188 ConsumeAllOutput(); 189 } 190 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 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 209 TEST_F(AudioBufferConverterTest, DiscreteChannelLayout) { 210 output_params_ = AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, 211 CHANNEL_LAYOUT_DISCRETE, 212 2, 213 0, 214 kOutSampleRate, 215 16, 216 512, 217 0); 218 audio_buffer_converter_.reset(new AudioBufferConverter(output_params_)); 219 AddInput(MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_STEREO, 2, 512)); 220 ConsumeAllOutput(); 221 } 222 223 TEST_F(AudioBufferConverterTest, LargeBuffersResampling) { 224 output_params_ = AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, 225 kOutChannelLayout, 226 kOutSampleRate, 227 16, 228 2048); 229 230 audio_buffer_converter_.reset(new AudioBufferConverter(output_params_)); 231 const int kInputSampleRate = 48000; 232 const int kInputFrameSize = 8192; 233 ASSERT_NE(kInputSampleRate, kOutSampleRate); 234 235 const int kInputBuffers = 3; 236 for (int i = 0; i < kInputBuffers; ++i) { 237 AddInput(MakeTestBuffer(kInputSampleRate, 238 kOutChannelLayout, 239 kOutChannelCount, 240 kInputFrameSize)); 241 } 242 243 // Do not add an EOS packet here, as it will invoke flushing. 244 while (audio_buffer_converter_->HasNextBuffer()) 245 ConsumeOutput(); 246 247 // Since the input buffer size is a multiple of the input request size there 248 // should never be any frames remaining at this point. 249 ASSERT_EQ(kInputFrameSize % 250 audio_buffer_converter_->input_buffer_size_for_testing(), 251 0); 252 EXPECT_EQ(0, audio_buffer_converter_->input_frames_left_for_testing()); 253 } 254 255 } // namespace media 256