audio_converter_unittest.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
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