12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MSVC++ requires this to be set before any other includes to get M_PI.
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define _USE_MATH_DEFINES
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cmath>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_vector.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/audio_converter.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/fake_audio_render_callback.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace media {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Parameters which control the many input case tests.
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kConvertInputs = 8;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kConvertCycles = 3;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Parameters used for testing.
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kBitsPerChannel = 32;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kHighLatencyBufferSize = 2048;
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kLowLatencyBufferSize = 256;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kSampleRate = 48000;
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Number of full sine wave cycles for each Render() call.
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kSineCycles = 4;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Tuple of <input rate, output rate, output channel layout, epsilon>.
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef std::tr1::tuple<int, int, ChannelLayout, double> AudioConverterTestData;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AudioConverterTest
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public testing::TestWithParam<AudioConverterTestData> {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioConverterTest()
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : epsilon_(std::tr1::get<3>(GetParam())) {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Create input and output parameters based on test parameters.
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    input_parameters_ = AudioParameters(
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::tr1::get<0>(GetParam()), kBitsPerChannel, kHighLatencyBufferSize);
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    output_parameters_ = AudioParameters(
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        AudioParameters::AUDIO_PCM_LOW_LATENCY, std::tr1::get<2>(GetParam()),
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::tr1::get<1>(GetParam()), 16, kLowLatencyBufferSize);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    converter_.reset(new AudioConverter(
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        input_parameters_, output_parameters_, false));
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_bus_ = AudioBus::Create(output_parameters_);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    expected_audio_bus_ = AudioBus::Create(output_parameters_);
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Allocate one callback for generating expected results.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double step = kSineCycles / static_cast<double>(
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        output_parameters_.frames_per_buffer());
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    expected_callback_.reset(new FakeAudioRenderCallback(step));
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Creates |count| input callbacks to be used for conversion testing.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InitializeInputs(int count) {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Setup FakeAudioRenderCallback step to compensate for resampling.
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double scale_factor = input_parameters_.sample_rate() /
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<double>(output_parameters_.sample_rate());
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double step = kSineCycles / (scale_factor *
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<double>(output_parameters_.frames_per_buffer()));
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = 0; i < count; ++i) {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fake_callbacks_.push_back(new FakeAudioRenderCallback(step));
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      converter_->AddInput(fake_callbacks_[i]);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Resets all input callbacks to a pristine state.
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Reset() {
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    converter_->Reset();
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < fake_callbacks_.size(); ++i)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fake_callbacks_[i]->reset();
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    expected_callback_->reset();
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Sets the volume on all input callbacks to |volume|.
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetVolume(float volume) {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < fake_callbacks_.size(); ++i)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fake_callbacks_[i]->set_volume(volume);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Validates audio data between |audio_bus_| and |expected_audio_bus_| from
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |index|..|frames| after |scale| is applied to the expected audio data.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ValidateAudioData(int index, int frames, float scale) {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = 0; i < audio_bus_->channels(); ++i) {
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      for (int j = index; j < frames; ++j) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        double error = fabs(audio_bus_->channel(i)[j] -
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            expected_audio_bus_->channel(i)[j] * scale);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (error > epsilon_) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          EXPECT_NEAR(expected_audio_bus_->channel(i)[j] * scale,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      audio_bus_->channel(i)[j], epsilon_)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              << " i=" << i << ", j=" << j;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return false;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Runs a single Convert() stage, fills |expected_audio_bus_| appropriately,
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // and validates equality with |audio_bus_| after |scale| is applied.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool RenderAndValidateAudioData(float scale) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Render actual audio data.
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    converter_->Convert(audio_bus_.get());
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Render expected audio data.
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    expected_callback_->Render(expected_audio_bus_.get(), 0);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Zero out unused channels in the expected AudioBus just as AudioConverter
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // would during channel mixing.
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (int i = input_parameters_.channels();
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         i < output_parameters_.channels(); ++i) {
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      memset(expected_audio_bus_->channel(i), 0,
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             audio_bus_->frames() * sizeof(*audio_bus_->channel(i)));
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ValidateAudioData(0, audio_bus_->frames(), scale);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Fills |audio_bus_| fully with |value|.
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void FillAudioData(float value) {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = 0; i < audio_bus_->channels(); ++i) {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::fill(audio_bus_->channel(i),
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                audio_bus_->channel(i) + audio_bus_->frames(), value);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Verifies converter output with a |inputs| number of transform inputs.
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RunTest(int inputs) {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InitializeInputs(inputs);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetVolume(0);
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = 0; i < kConvertCycles; ++i)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ASSERT_TRUE(RenderAndValidateAudioData(0));
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Reset();
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Set a different volume for each input and verify the results.
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float total_scale = 0;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < fake_callbacks_.size(); ++i) {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      float volume = static_cast<float>(i) / fake_callbacks_.size();
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      total_scale += volume;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fake_callbacks_[i]->set_volume(volume);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = 0; i < kConvertCycles; ++i)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ASSERT_TRUE(RenderAndValidateAudioData(total_scale));
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Reset();
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Remove every other input.
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 1; i < fake_callbacks_.size(); i += 2)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      converter_->RemoveInput(fake_callbacks_[i]);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetVolume(1);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float scale = inputs > 1 ? inputs / 2.0f : inputs;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = 0; i < kConvertCycles; ++i)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ASSERT_TRUE(RenderAndValidateAudioData(scale));
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~AudioConverterTest() {}
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Converter under test.
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<AudioConverter> converter_;
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Input and output parameters used for AudioConverter construction.
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioParameters input_parameters_;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioParameters output_parameters_;
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Destination AudioBus for AudioConverter output.
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<AudioBus> audio_bus_;
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // AudioBus containing expected results for comparison with |audio_bus_|.
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<AudioBus> expected_audio_bus_;
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Vector of all input callbacks used to drive AudioConverter::Convert().
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedVector<FakeAudioRenderCallback> fake_callbacks_;
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Parallel input callback which generates the expected output.
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<FakeAudioRenderCallback> expected_callback_;
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Epsilon value with which to perform comparisons between |audio_bus_| and
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |expected_audio_bus_|.
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double epsilon_;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AudioConverterTest);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Ensure the buffer delay provided by AudioConverter is accurate.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(AudioConverterTest, AudioDelay) {
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Choose input and output parameters such that the transform must make
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // multiple calls to fill the buffer.
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioParameters input_parameters = AudioParameters(
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kBitsPerChannel, kLowLatencyBufferSize);
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioParameters output_parameters = AudioParameters(
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate * 2,
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kBitsPerChannel, kHighLatencyBufferSize);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioConverter converter(input_parameters, output_parameters, false);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FakeAudioRenderCallback callback(0.2);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<AudioBus> audio_bus = AudioBus::Create(output_parameters);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  converter.AddInput(&callback);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  converter.Convert(audio_bus.get());
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calculate the expected buffer delay for given AudioParameters.
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double input_sample_rate = input_parameters.sample_rate();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fill_count =
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (output_parameters.frames_per_buffer() * input_sample_rate /
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       output_parameters.sample_rate()) / input_parameters.frames_per_buffer();
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta input_frame_duration = base::TimeDelta::FromMicroseconds(
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::kMicrosecondsPerSecond / input_sample_rate);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int expected_last_delay_milliseconds =
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fill_count * input_parameters.frames_per_buffer() *
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      input_frame_duration.InMillisecondsF();
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_last_delay_milliseconds,
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            callback.last_audio_delay_milliseconds());
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)TEST_P(AudioConverterTest, ArbitraryOutputRequestSize) {
23123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Resize output bus to be half of |output_parameters_|'s frames_per_buffer().
23223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  audio_bus_ = AudioBus::Create(output_parameters_.channels(),
23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                output_parameters_.frames_per_buffer() / 2);
23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  RunTest(1);
23523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
23623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_P(AudioConverterTest, NoInputs) {
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FillAudioData(1.0f);
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_P(AudioConverterTest, OneInput) {
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunTest(1);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_P(AudioConverterTest, ManyInputs) {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunTest(kConvertInputs);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)INSTANTIATE_TEST_CASE_P(
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AudioConverterTest, AudioConverterTest, testing::Values(
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // No resampling. No channel mixing.
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        std::tr1::make_tuple(44100, 44100, CHANNEL_LAYOUT_STEREO, 0.00000048),
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Upsampling. Channel upmixing.
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        std::tr1::make_tuple(44100, 48000, CHANNEL_LAYOUT_QUAD, 0.033),
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Downsampling. Channel downmixing.
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        std::tr1::make_tuple(48000, 41000, CHANNEL_LAYOUT_MONO, 0.042)));
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace media
262