Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
| OLD | NEW |