| 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 |