Home | History | Annotate | Download | only in base
      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