Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1053)

Side by Side Diff: media/base/sinc_resampler_unittest.cc

Issue 10702050: Add SincResampler ported from WebKit. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments! Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4 // MSVC++ requires this to be set before any other includes to get M_PI.
5 #define _USE_MATH_DEFINES
6
7 #include <cmath>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/stringprintf.h"
14 #include "media/base/sinc_resampler.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace media {
18
19 class SweptSineSource {
Ami GONE FROM CHROMIUM 2012/07/03 20:54:42 How about some commentary?
DaleCurtis 2012/07/10 01:00:25 Done.
20 public:
21 SweptSineSource(int sample_rate, int output_samples, double max_frequency)
22 : sample_rate_(sample_rate),
23 total_output_samples_(output_samples),
24 min_frequency_(kMinFrequency),
25 max_frequency_(max_frequency),
26 frequency_(min_frequency_),
27 phase_(0) {
28 }
29
30 virtual ~SweptSineSource() {}
31
32 void ProvideInput(float* destination, int frames) {
33 for (int i = 0; i < frames; ++i) {
34 // Filter out frequencies higher than Nyquist.
35 if (frequency_ > 0.5 * sample_rate_) {
Ami GONE FROM CHROMIUM 2012/07/03 20:54:42 is this not always max_frequency_?
DaleCurtis 2012/07/10 01:00:25 No, per Chris max_frequency is the nyquist limit o
36 destination[i] = 0;
37 } else {
38 destination[i] = sin(phase_);
39 phase_ += 2 * M_PI * frequency_ / sample_rate_;
40 frequency_ += (max_frequency_ - min_frequency_) / total_output_samples_;
Ami GONE FROM CHROMIUM 2012/07/03 20:54:42 FWIW, ISTM the RHS here is a ctor-time constant, s
DaleCurtis 2012/07/10 01:00:25 Cleaned this up a bit using Chris's new method.
41 }
42 }
43 }
44
45 private:
46 static const int kMinFrequency = 5;
Ami GONE FROM CHROMIUM 2012/07/03 20:54:42 enum
DaleCurtis 2012/07/10 01:00:25 Done.
47
48 double sample_rate_;
49 int total_output_samples_;
50 double min_frequency_;
51 double max_frequency_;
52 double frequency_;
53 double phase_;
54
55 DISALLOW_COPY_AND_ASSIGN(SweptSineSource);
56 };
57
58 typedef std::tr1::tuple<int, int, double, double, double> SincResamplerTestData;
Ami GONE FROM CHROMIUM 2012/07/03 20:54:42 Chromium's Tuple class is slightly less ugly to wo
DaleCurtis 2012/07/10 01:00:25 I thought of that, but I think this ends up being
59 class SincResamplerTestCase
60 : public testing::TestWithParam<SincResamplerTestData> {
61 public:
62 SincResamplerTestCase()
63 : input_rate_(std::tr1::get<0>(GetParam())),
Ami GONE FROM CHROMIUM 2012/07/03 20:54:42 using?
DaleCurtis 2012/07/10 01:00:25 Clearer this way I think.
64 output_rate_(std::tr1::get<1>(GetParam())),
65 rms_error_(std::tr1::get<2>(GetParam())),
66 low_freq_error_(std::tr1::get<3>(GetParam())),
67 high_freq_error_(std::tr1::get<4>(GetParam())) {
68 }
69
70 virtual ~SincResamplerTestCase() {}
71
72 protected:
73 int input_rate_;
74 int output_rate_;
75 double rms_error_;
76 double low_freq_error_;
77 double high_freq_error_;
78 };
79
80 // Tests resampling using a given input and output sample rate.
81 TEST_P(SincResamplerTestCase, Resample) {
82 // Make comparisons using one second of data.
83 static const int kTestDurationSecs = 1;
84 int input_samples = kTestDurationSecs * input_rate_;
85 int output_samples = kTestDurationSecs * output_rate_;
86
87 // Nyquist frequency for the input sampling rate.
88 double input_nyquist_freq = 0.5 * input_rate_;
89
90 // Source for data to be resampled.
91 SweptSineSource resampler_source(
92 input_rate_, input_samples, input_nyquist_freq);
93
94 SincResampler resampler(
95 base::Bind(
96 &SweptSineSource::ProvideInput, base::Unretained(&resampler_source)),
97 input_rate_ / static_cast<double>(output_rate_));
98
99 // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to
100 // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes.
101 scoped_array<float> resampled_destination(new float[output_samples]);
102 scoped_array<float> pure_destination(new float[output_samples]);
103
104 // Generate resampled signal.
105 resampler.Resample(resampled_destination.get(), output_samples);
106
107 // Generate pure signal.
108 SweptSineSource pure_source(
109 output_rate_, output_samples, input_nyquist_freq);
110 pure_source.ProvideInput(pure_destination.get(), output_samples);
111
112 // TODO(dalecurtis): Figure out what we need to do here w/ crogers.
113 // // Calculate Root-Mean-Square-Error for the resampling.
114 // double sum_of_squares = 0;
115 // double max_error = 0;
116 // for (int i = 0; i < output_samples; ++i) {
117 // double error = fabs(resampled_destination[i] - pure_destination[i]);
118 // max_error = std::max(error, max_error);
119 // sum_of_squares += error * error;
120 // }
121
122 // double rms_error = sqrt(sum_of_squares / output_samples);
123
124 // EXPECT_LT(rms_error, rms_error_);
125 // EXPECT_LT(max_error, low_freq_error_);
126 // EXPECT_LT(max_error, high_freq_error_);
127 }
128
129 INSTANTIATE_TEST_CASE_P(
130 SincResamplerTest, SincResamplerTestCase, testing::Values(
131 // To 44.1kHz
132 std::tr1::make_tuple(8000, 44100, 0, 0, 0),
Ami GONE FROM CHROMIUM 2012/07/03 20:54:42 I guess these 0,0,0's are placeholders that won't
DaleCurtis 2012/07/10 01:00:25 Correct.
133 std::tr1::make_tuple(11025, 44100, 0, 0, 0),
134 std::tr1::make_tuple(16000, 44100, 0, 0, 0),
135 std::tr1::make_tuple(22050, 44100, 0, 0, 0),
136 std::tr1::make_tuple(32000, 44100, 0, 0, 0),
137 std::tr1::make_tuple(44100, 44100, 0, 0, 0),
138 std::tr1::make_tuple(48000, 44100, 0, 0, 0),
139 std::tr1::make_tuple(96000, 44100, 0, 0, 0),
140 std::tr1::make_tuple(192000, 44100, 0, 0, 0),
141
142 // To 48kHz
143 std::tr1::make_tuple(8000, 48000, 0, 0, 0),
144 std::tr1::make_tuple(11025, 48000, 0, 0, 0),
145 std::tr1::make_tuple(16000, 48000, 0, 0, 0),
146 std::tr1::make_tuple(22050, 48000, 0, 0, 0),
147 std::tr1::make_tuple(32000, 48000, 0, 0, 0),
148 std::tr1::make_tuple(44100, 48000, 0, 0, 0),
149 std::tr1::make_tuple(48000, 48000, 0, 0, 0),
150 std::tr1::make_tuple(96000, 48000, 0, 0, 0),
151 std::tr1::make_tuple(192000, 48000, 0, 0, 0),
152
153 // To 96kHz
154 std::tr1::make_tuple(8000, 96000, 0, 0, 0),
155 std::tr1::make_tuple(11025, 96000, 0, 0, 0),
156 std::tr1::make_tuple(16000, 96000, 0, 0, 0),
157 std::tr1::make_tuple(22050, 96000, 0, 0, 0),
158 std::tr1::make_tuple(32000, 96000, 0, 0, 0),
159 std::tr1::make_tuple(44100, 96000, 0, 0, 0),
160 std::tr1::make_tuple(48000, 96000, 0, 0, 0),
161 std::tr1::make_tuple(96000, 96000, 0, 0, 0),
162 std::tr1::make_tuple(192000, 96000, 0, 0, 0),
163
164 // To 192kHz
165 std::tr1::make_tuple(8000, 192000, 0, 0, 0),
166 std::tr1::make_tuple(11025, 192000, 0, 0, 0),
167 std::tr1::make_tuple(16000, 192000, 0, 0, 0),
168 std::tr1::make_tuple(22050, 192000, 0, 0, 0),
169 std::tr1::make_tuple(32000, 192000, 0, 0, 0),
170 std::tr1::make_tuple(44100, 192000, 0, 0, 0),
171 std::tr1::make_tuple(48000, 192000, 0, 0, 0),
172 std::tr1::make_tuple(96000, 192000, 0, 0, 0),
173 std::tr1::make_tuple(192000, 192000, 0, 0, 0)));
174
175 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698