1 // Copyright (c) 2012 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.
8 #include "base/bind_helpers.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "media/base/audio_bus.h"
12 #include "media/base/multi_channel_resampler.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 // Just test a basic resampling case. The SincResampler unit test will take
18 // care of accuracy testing; we just need to check that multichannel works as
19 // expected within some tolerance.
20 static const float kScaleFactor
= 192000.0f
/ 44100.0f
;
22 // Simulate large and small sample requests used by the different audio paths.
23 static const int kHighLatencySize
= 8192;
24 // Low latency buffers show a larger error than high latency ones. Which makes
25 // sense since each error represents a larger portion of the total request.
26 static const int kLowLatencySize
= 128;
29 static const float kFillValue
= 0.1f
;
31 // Chosen arbitrarily based on what each resampler reported during testing.
32 static const double kLowLatencyMaxRMSError
= 0.0036;
33 static const double kLowLatencyMaxError
= 0.04;
34 static const double kHighLatencyMaxRMSError
= 0.0036;
35 static const double kHighLatencyMaxError
= 0.04;
37 class MultiChannelResamplerTest
38 : public testing::TestWithParam
<int> {
40 MultiChannelResamplerTest()
41 : last_frame_delay_(-1) {
43 virtual ~MultiChannelResamplerTest() {}
45 void InitializeAudioData(int channels
, int frames
) {
47 audio_bus_
= AudioBus::Create(channels
, frames
);
50 // MultiChannelResampler::MultiChannelAudioSourceProvider implementation, just
51 // fills the provided audio_data with |kFillValue|.
52 virtual void ProvideInput(int frame_delay
, AudioBus
* audio_bus
) {
53 EXPECT_GE(frame_delay
, last_frame_delay_
);
54 last_frame_delay_
= frame_delay
;
56 float fill_value
= fill_junk_values_
? (1 / kFillValue
) : kFillValue
;
57 EXPECT_EQ(audio_bus
->channels(), audio_bus_
->channels());
58 for (int i
= 0; i
< audio_bus
->channels(); ++i
)
59 for (int j
= 0; j
< audio_bus
->frames(); ++j
)
60 audio_bus
->channel(i
)[j
] = fill_value
;
63 void MultiChannelTest(int channels
, int frames
, double expected_max_rms_error
,
64 double expected_max_error
) {
65 InitializeAudioData(channels
, frames
);
66 MultiChannelResampler
resampler(
67 channels
, kScaleFactor
, SincResampler::kDefaultRequestSize
, base::Bind(
68 &MultiChannelResamplerTest::ProvideInput
, base::Unretained(this)));
70 // First prime the resampler with some junk data, so we can verify Flush().
71 fill_junk_values_
= true;
72 resampler
.Resample(1, audio_bus_
.get());
74 fill_junk_values_
= false;
76 // The last frame delay should be strictly less than the total frame count.
77 EXPECT_LT(last_frame_delay_
, audio_bus_
->frames());
78 last_frame_delay_
= -1;
80 // If Flush() didn't work, the rest of the tests will fail.
81 resampler
.Resample(frames
, audio_bus_
.get());
82 TestValues(expected_max_rms_error
, expected_max_error
);
85 void HighLatencyTest(int channels
) {
86 MultiChannelTest(channels
, kHighLatencySize
, kHighLatencyMaxRMSError
,
87 kHighLatencyMaxError
);
90 void LowLatencyTest(int channels
) {
91 MultiChannelTest(channels
, kLowLatencySize
, kLowLatencyMaxRMSError
,
95 void TestValues(double expected_max_rms_error
, double expected_max_error
) {
96 // Calculate Root-Mean-Square-Error for the resampling.
97 double max_error
= 0.0;
98 double sum_of_squares
= 0.0;
99 for (int i
= 0; i
< audio_bus_
->channels(); ++i
) {
100 for (int j
= 0; j
< frames_
; ++j
) {
101 // Ensure all values are accounted for.
102 ASSERT_NE(audio_bus_
->channel(i
)[j
], 0);
104 double error
= fabs(audio_bus_
->channel(i
)[j
] - kFillValue
);
105 max_error
= std::max(max_error
, error
);
106 sum_of_squares
+= error
* error
;
110 double rms_error
= sqrt(
111 sum_of_squares
/ (frames_
* audio_bus_
->channels()));
113 EXPECT_LE(rms_error
, expected_max_rms_error
);
114 EXPECT_LE(max_error
, expected_max_error
);
119 bool fill_junk_values_
;
120 scoped_ptr
<AudioBus
> audio_bus_
;
121 int last_frame_delay_
;
123 DISALLOW_COPY_AND_ASSIGN(MultiChannelResamplerTest
);
126 TEST_P(MultiChannelResamplerTest
, HighLatency
) {
127 HighLatencyTest(GetParam());
130 TEST_P(MultiChannelResamplerTest
, LowLatency
) {
131 LowLatencyTest(GetParam());
134 // Test common channel layouts: mono, stereo, 5.1, 7.1.
135 INSTANTIATE_TEST_CASE_P(
136 MultiChannelResamplerTest
, MultiChannelResamplerTest
,
137 testing::Values(1, 2, 6, 8));