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 13namespace media { 14 15// Important: Use an odd buffer size here so SIMD issues are caught. 16const int kOutFrameSize = 441; 17const int kOutSampleRate = 44100; 18const ChannelLayout kOutChannelLayout = CHANNEL_LAYOUT_STEREO; 19const int kOutChannelCount = 2; 20 21static 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 35class 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 95TEST_F(AudioBufferConverterTest, PassThrough) { 96 scoped_refptr<AudioBuffer> in = 97 MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512); 98 AddInput(in); 99 ConsumeAllOutput(); 100} 101 102TEST_F(AudioBufferConverterTest, Downsample) { 103 scoped_refptr<AudioBuffer> in = 104 MakeTestBuffer(48000, kOutChannelLayout, kOutChannelCount, 512); 105 AddInput(in); 106 ConsumeAllOutput(); 107} 108 109TEST_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. 117TEST_F(AudioBufferConverterTest, Resample_TinyBuffer) { 118 AddInput(MakeTestBuffer( 119 48000, CHANNEL_LAYOUT_STEREO, 2, SincResampler::kKernelSize - 1)); 120 ConsumeAllOutput(); 121} 122 123TEST_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 138TEST_F(AudioBufferConverterTest, ChannelDownmix) { 139 scoped_refptr<AudioBuffer> in = 140 MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_MONO, 1, 512); 141 AddInput(in); 142 ConsumeAllOutput(); 143} 144 145TEST_F(AudioBufferConverterTest, ChannelUpmix) { 146 scoped_refptr<AudioBuffer> in = 147 MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_5_1, 6, 512); 148 AddInput(in); 149 ConsumeAllOutput(); 150} 151 152TEST_F(AudioBufferConverterTest, ResampleAndRemix) { 153 scoped_refptr<AudioBuffer> in = 154 MakeTestBuffer(48000, CHANNEL_LAYOUT_5_1, 6, 512); 155 AddInput(in); 156 ConsumeAllOutput(); 157} 158 159TEST_F(AudioBufferConverterTest, ConfigChange_SampleRate) { 160 AddInput(MakeTestBuffer(48000, kOutChannelLayout, kOutChannelCount, 512)); 161 AddInput(MakeTestBuffer(44100, kOutChannelLayout, kOutChannelCount, 512)); 162 ConsumeAllOutput(); 163} 164 165TEST_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 171TEST_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 177TEST_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 185TEST_F(AudioBufferConverterTest, Reset) { 186 AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512)); 187 Reset(); 188 ConsumeAllOutput(); 189} 190 191TEST_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 199TEST_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 209TEST_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 222TEST_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