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

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: Zero-Initialize Arrays + Check Max Error. 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/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/stringprintf.h"
12 #include "media/base/sinc_resampler.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace media {
16
17 // Chosen arbitrarily on what each resampler reported during testing.
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 s/on/based on/
DaleCurtis 2012/07/03 00:36:34 Done.
18 static const double kMaxRMSError = 0.0002;
Chris Rogers 2012/07/02 20:38:14 I'm not sure if the RMS error will be useful, but
DaleCurtis 2012/07/03 00:36:34 Happy to drop it, but I figured there would be cas
19 static const double kMaxError = 0.00022;
Chris Rogers 2012/07/02 20:38:14 I'd represent this in decibels (actually dbFS) - s
20
21 // Generate a swept sine wave with the given hertz over [0, kCycles * 2 * PI].
22 class SweptSineSourceProvider : public SincResampler::AudioSourceProvider {
23 public:
24 // Maximum sine wave cycles.
25 static const int kCycles = 6;
Chris Rogers 2012/07/02 20:38:14 As we discussed in chat, I think we should define
DaleCurtis 2012/07/03 00:36:34 Done.
26
27 // Hz/sec value for the swept sine wave.
28 // TODO(dalecurtis): Should we use a more complex pattern here?
29 static const int kHertzPerSecond = 1;
Chris Rogers 2012/07/02 20:38:14 I don't think we'll need this constant.
DaleCurtis 2012/07/03 00:36:34 Done.
30
31 explicit SweptSineSourceProvider(int max) {
Chris Rogers 2012/07/02 20:38:14 "max"? how about "sample_rate" Then I'd simply g
DaleCurtis 2012/07/03 00:36:34 Done.
32 ResetTimeState(max);
33 }
34
35 virtual ~SweptSineSourceProvider() {}
36
37 virtual void ProvideInput(float* destination, int number_of_frames) OVERRIDE {
38 for (int i = 0; i < number_of_frames; ++i) {
39 destination[i] = sin(kHertzPerSecond * time_state_ * time_state_);
40 time_state_ += time_increment_;
41 }
42 }
43
44 void ResetTimeState(int max) {
45 time_state_ = 0.0;
46 time_increment_ = kCycles * 2 * M_PI / max;
47 }
48
49 protected:
50 double hertz_;
51 double time_increment_;
52 double time_state_;
53
54 DISALLOW_COPY_AND_ASSIGN(SweptSineSourceProvider);
55 };
56
57 // Used for tests which just need to run without crashing or tooling errors, but
58 // which may have undefined behavior for hashing, etc.
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 wat?
DaleCurtis 2012/07/01 23:31:30 Copy paste fail! (from ffmpeg_regression_tests)
DaleCurtis 2012/07/03 00:36:34 Done.
59 struct SincResamplerTestData {
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 Isn't this kind of overkill for a std::pair<int, i
DaleCurtis 2012/07/01 23:31:30 Good point, I completely forgot about pair.
DaleCurtis 2012/07/03 00:36:34 Switched to using tr1::tuple since gtest uses that
60 SincResamplerTestData(int input_rate, int output_rate)
61 : input_rate(input_rate),
62 output_rate(output_rate) {
63 }
64
65 std::string DebugString() const {
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 FWIW, since this doesn't touch private data (there
DaleCurtis 2012/07/03 00:36:34 Removed with tuple().
66 return base::StringPrintf(
67 "Resampling test from %dHz to %dHz.", input_rate, output_rate);
68 }
69
70 const int input_rate;
71 const int output_rate;
72 };
73
74 class SincResamplerTestCase
75 : public testing::TestWithParam<SincResamplerTestData> {
76 };
77
78 // Define ostream << operator so GTest will print nice error messages instead of
79 // "[...], where GetParam() = 8-byte object <44-AC 00-00 00-77 01-00>"
80 ::std::ostream& operator<<(::std::ostream& os,
81 const SincResamplerTestData& data) {
82 return os << data.DebugString();
83 }
84
85 INSTANTIATE_TEST_CASE_P(
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 Traditionally this goes *after* the test case it i
DaleCurtis 2012/07/03 00:36:34 Done.
86 SincResamplerTest, SincResamplerTestCase, testing::Values(
87 // To 44.1kHz
88 SincResamplerTestData(8000, 44100),
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 Replace the explicit lists (which are prone to acc
DaleCurtis 2012/07/01 23:31:30 Neat! I was looking for that.
DaleCurtis 2012/07/03 00:36:34 Don't think we'll be able to use this since after
89 SincResamplerTestData(11025, 44100),
90 SincResamplerTestData(16000, 44100),
91 SincResamplerTestData(22050, 44100),
92 SincResamplerTestData(32000, 44100),
93 SincResamplerTestData(48000, 44100),
94 SincResamplerTestData(96000, 44100),
95 SincResamplerTestData(192000, 44100),
96
97 // To 48kHz
98 SincResamplerTestData(8000, 48000),
99 SincResamplerTestData(11025, 48000),
100 SincResamplerTestData(16000, 48000),
101 SincResamplerTestData(22050, 48000),
102 SincResamplerTestData(32000, 48000),
103 SincResamplerTestData(44100, 48000),
104 SincResamplerTestData(96000, 48000),
105 SincResamplerTestData(192000, 48000),
106
107 // To 96kHz
108 SincResamplerTestData(8000, 96000),
109 SincResamplerTestData(11025, 96000),
110 SincResamplerTestData(16000, 96000),
111 SincResamplerTestData(22050, 96000),
112 SincResamplerTestData(32000, 96000),
113 SincResamplerTestData(44100, 96000),
114 SincResamplerTestData(48000, 96000),
115 SincResamplerTestData(192000, 96000),
116
117 // To 192kHz
118 SincResamplerTestData(8000, 192000),
119 SincResamplerTestData(11025, 192000),
120 SincResamplerTestData(16000, 192000),
121 SincResamplerTestData(22050, 192000),
122 SincResamplerTestData(32000, 192000),
123 SincResamplerTestData(44100, 192000),
124 SincResamplerTestData(48000, 192000),
125 SincResamplerTestData(96000, 192000)));
126
127 // Test callback() works as expected.
128 TEST_P(SincResamplerTestCase, Resample) {
129 int input_rate = GetParam().input_rate;
130 int output_rate = GetParam().output_rate;
131
132 scoped_ptr<SweptSineSourceProvider> provider(
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 hopefully you won't need this post-migration-to-CB
DaleCurtis 2012/07/03 00:36:34 Done.
133 new SweptSineSourceProvider(input_rate));
134 scoped_ptr<SincResampler> resampler(new SincResampler(
135 provider.get(), static_cast<double>(input_rate) / output_rate));
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 you could avoid this cast by making the input & ou
DaleCurtis 2012/07/03 00:36:34 Then I need two casts for constructing the arrays.
136
137 // TODO(dalecurtis): These will need SSE appropriate allocations.
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 Do you mean padding/alignment? why not fix now?
DaleCurtis 2012/07/01 23:31:30 Yes, but it's more than just here that needs to be
138 scoped_array<float> resampled_destination(new float[output_rate]);
139 scoped_array<float> pure_destination(new float[output_rate]);
140
141 // Generate resampled signal.
142 resampler->Resample(resampled_destination.get(), output_rate);
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 It's confusing that output_rate is used for number
DaleCurtis 2012/07/03 00:36:34 Done.
143
144 // Generate pure signal.
145 provider->ResetTimeState(output_rate);
Chris Rogers 2012/07/02 20:38:14 Instead of re-using the existing object and exposi
DaleCurtis 2012/07/03 00:36:34 Done.
146 provider->ProvideInput(pure_destination.get(), output_rate);
147
148 // Calculate Root-Mean-Square-Error for the resampling.
149 double sum_of_squares = 0.0;
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 .0 here and below unnecessary
DaleCurtis 2012/07/03 00:36:34 Done.
150 double max_error = 0.0;
151 for (int i = 0; i < output_rate; ++i) {
152 double error = fabs(resampled_destination[i] - pure_destination[i]);
153 max_error = std::max(max_error, error);
154 sum_of_squares += error * error;
155 }
156
157 double rms_error = sqrt(sum_of_squares / output_rate);
158
159 // TODO(dalecurtis): Should this be different for each (in, out) pair?
Ami GONE FROM CHROMIUM 2012/06/30 20:29:30 how wide is the spread?
DaleCurtis 2012/07/03 00:36:34 rms error is about 0.17 -> 0.55, max: 0.86 -> 1.86
160 EXPECT_LT(rms_error, kMaxRMSError);
161 EXPECT_LT(max_error, kMaxError);
162 }
163
164 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698