OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // MSVC++ requires this to be set before any other includes to get M_PI. | 5 // MSVC++ requires this to be set before any other includes to get M_PI. |
6 #define _USE_MATH_DEFINES | 6 #define _USE_MATH_DEFINES |
7 | 7 |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/command_line.h" | |
13 #include "base/cpu.h" | 12 #include "base/cpu.h" |
14 #include "base/logging.h" | |
15 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
16 #include "base/strings/stringize_macros.h" | |
17 #include "base/time/time.h" | 14 #include "base/time/time.h" |
18 #include "build/build_config.h" | 15 #include "build/build_config.h" |
19 #include "media/base/sinc_resampler.h" | 16 #include "media/base/sinc_resampler.h" |
20 #include "testing/gmock/include/gmock/gmock.h" | 17 #include "testing/gmock/include/gmock/gmock.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
22 | 19 |
23 using testing::_; | 20 using testing::_; |
24 | 21 |
25 namespace media { | 22 namespace media { |
26 | 23 |
27 static const double kSampleRateRatio = 192000.0 / 44100.0; | 24 static const double kSampleRateRatio = 192000.0 / 44100.0; |
28 static const double kKernelInterpolationFactor = 0.5; | 25 static const double kKernelInterpolationFactor = 0.5; |
29 | 26 |
30 // Command line switch for runtime adjustment of ConvolveBenchmark iterations. | |
31 static const char kConvolveIterations[] = "convolve-iterations"; | |
32 | |
33 // Helper class to ensure ChunkedResample() functions properly. | 27 // Helper class to ensure ChunkedResample() functions properly. |
34 class MockSource { | 28 class MockSource { |
35 public: | 29 public: |
36 MOCK_METHOD2(ProvideInput, void(int frames, float* destination)); | 30 MOCK_METHOD2(ProvideInput, void(int frames, float* destination)); |
37 }; | 31 }; |
38 | 32 |
39 ACTION(ClearBuffer) { | 33 ACTION(ClearBuffer) { |
40 memset(arg1, 0, arg0 * sizeof(float)); | 34 memset(arg1, 0, arg0 * sizeof(float)); |
41 } | 35 } |
42 | 36 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 result = resampler.Convolve_C( | 148 result = resampler.Convolve_C( |
155 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), | 149 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), |
156 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | 150 resampler.kernel_storage_.get(), kKernelInterpolationFactor); |
157 result2 = resampler.CONVOLVE_FUNC( | 151 result2 = resampler.CONVOLVE_FUNC( |
158 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), | 152 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), |
159 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | 153 resampler.kernel_storage_.get(), kKernelInterpolationFactor); |
160 EXPECT_NEAR(result2, result, kEpsilon); | 154 EXPECT_NEAR(result2, result, kEpsilon); |
161 } | 155 } |
162 #endif | 156 #endif |
163 | 157 |
164 // Benchmark for the various Convolve() methods. Make sure to build with | |
165 // branding=Chrome so that DCHECKs are compiled out when benchmarking. Original | |
166 // benchmarks were run with --convolve-iterations=50000000. | |
167 TEST(SincResamplerTest, ConvolveBenchmark) { | |
168 // Initialize a dummy resampler. | |
169 MockSource mock_source; | |
170 SincResampler resampler( | |
171 kSampleRateRatio, SincResampler::kDefaultRequestSize, | |
172 base::Bind(&MockSource::ProvideInput, base::Unretained(&mock_source))); | |
173 | |
174 // Retrieve benchmark iterations from command line. | |
175 int convolve_iterations = 10; | |
176 std::string iterations(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
177 kConvolveIterations)); | |
178 if (!iterations.empty()) | |
179 base::StringToInt(iterations, &convolve_iterations); | |
180 | |
181 printf("Benchmarking %d iterations:\n", convolve_iterations); | |
182 | |
183 // Benchmark Convolve_C(). | |
184 base::TimeTicks start = base::TimeTicks::HighResNow(); | |
185 for (int i = 0; i < convolve_iterations; ++i) { | |
186 resampler.Convolve_C( | |
187 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), | |
188 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | |
189 } | |
190 double total_time_c_ms = | |
191 (base::TimeTicks::HighResNow() - start).InMillisecondsF(); | |
192 printf("Convolve_C took %.2fms.\n", total_time_c_ms); | |
193 | |
194 #if defined(CONVOLVE_FUNC) | |
195 #if defined(ARCH_CPU_X86_FAMILY) | |
196 ASSERT_TRUE(base::CPU().has_sse()); | |
197 #endif | |
198 | |
199 // Benchmark with unaligned input pointer. | |
200 start = base::TimeTicks::HighResNow(); | |
201 for (int j = 0; j < convolve_iterations; ++j) { | |
202 resampler.CONVOLVE_FUNC( | |
203 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), | |
204 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | |
205 } | |
206 double total_time_optimized_unaligned_ms = | |
207 (base::TimeTicks::HighResNow() - start).InMillisecondsF(); | |
208 printf(STRINGIZE(CONVOLVE_FUNC) " (unaligned) took %.2fms; which is %.2fx " | |
209 "faster than Convolve_C.\n", total_time_optimized_unaligned_ms, | |
210 total_time_c_ms / total_time_optimized_unaligned_ms); | |
211 | |
212 // Benchmark with aligned input pointer. | |
213 start = base::TimeTicks::HighResNow(); | |
214 for (int j = 0; j < convolve_iterations; ++j) { | |
215 resampler.CONVOLVE_FUNC( | |
216 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), | |
217 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | |
218 } | |
219 double total_time_optimized_aligned_ms = | |
220 (base::TimeTicks::HighResNow() - start).InMillisecondsF(); | |
221 printf(STRINGIZE(CONVOLVE_FUNC) " (aligned) took %.2fms; which is %.2fx " | |
222 "faster than Convolve_C and %.2fx faster than " | |
223 STRINGIZE(CONVOLVE_FUNC) " (unaligned).\n", | |
224 total_time_optimized_aligned_ms, | |
225 total_time_c_ms / total_time_optimized_aligned_ms, | |
226 total_time_optimized_unaligned_ms / total_time_optimized_aligned_ms); | |
227 #endif | |
228 } | |
229 | |
230 #undef CONVOLVE_FUNC | |
231 | |
232 // Fake audio source for testing the resampler. Generates a sinusoidal linear | 158 // Fake audio source for testing the resampler. Generates a sinusoidal linear |
233 // chirp (http://en.wikipedia.org/wiki/Chirp) which can be tuned to stress the | 159 // chirp (http://en.wikipedia.org/wiki/Chirp) which can be tuned to stress the |
234 // resampler for the specific sample rate conversion being used. | 160 // resampler for the specific sample rate conversion being used. |
235 class SinusoidalLinearChirpSource { | 161 class SinusoidalLinearChirpSource { |
236 public: | 162 public: |
237 SinusoidalLinearChirpSource(int sample_rate, | 163 SinusoidalLinearChirpSource(int sample_rate, |
238 int samples, | 164 int samples, |
239 double max_frequency) | 165 double max_frequency) |
240 : sample_rate_(sample_rate), | 166 : sample_rate_(sample_rate), |
241 total_samples_(samples), | 167 total_samples_(samples), |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 std::tr1::make_tuple(11025, 192000, kResamplingRMSError, -62.61), | 361 std::tr1::make_tuple(11025, 192000, kResamplingRMSError, -62.61), |
436 std::tr1::make_tuple(16000, 192000, kResamplingRMSError, -63.14), | 362 std::tr1::make_tuple(16000, 192000, kResamplingRMSError, -63.14), |
437 std::tr1::make_tuple(22050, 192000, kResamplingRMSError, -62.42), | 363 std::tr1::make_tuple(22050, 192000, kResamplingRMSError, -62.42), |
438 std::tr1::make_tuple(32000, 192000, kResamplingRMSError, -63.38), | 364 std::tr1::make_tuple(32000, 192000, kResamplingRMSError, -63.38), |
439 std::tr1::make_tuple(44100, 192000, kResamplingRMSError, -62.63), | 365 std::tr1::make_tuple(44100, 192000, kResamplingRMSError, -62.63), |
440 std::tr1::make_tuple(48000, 192000, kResamplingRMSError, -73.44), | 366 std::tr1::make_tuple(48000, 192000, kResamplingRMSError, -73.44), |
441 std::tr1::make_tuple(96000, 192000, kResamplingRMSError, -73.52), | 367 std::tr1::make_tuple(96000, 192000, kResamplingRMSError, -73.52), |
442 std::tr1::make_tuple(192000, 192000, kResamplingRMSError, -73.52))); | 368 std::tr1::make_tuple(192000, 192000, kResamplingRMSError, -73.52))); |
443 | 369 |
444 } // namespace media | 370 } // namespace media |
OLD | NEW |