Chromium Code Reviews| 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" |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 88 EXPECT_CALL(mock_source, ProvideInput(_, _)) | 88 EXPECT_CALL(mock_source, ProvideInput(_, _)) |
| 89 .Times(1).WillOnce(ClearBuffer()); | 89 .Times(1).WillOnce(ClearBuffer()); |
| 90 resampler.Resample(resampled_destination.get(), resampler.ChunkSize() / 2); | 90 resampler.Resample(resampled_destination.get(), resampler.ChunkSize() / 2); |
| 91 for (int i = 0; i < resampler.ChunkSize() / 2; ++i) | 91 for (int i = 0; i < resampler.ChunkSize() / 2; ++i) |
| 92 ASSERT_EQ(resampled_destination[i], 0); | 92 ASSERT_EQ(resampled_destination[i], 0); |
| 93 } | 93 } |
| 94 | 94 |
| 95 // Ensure various optimized Convolve() methods return the same value. Only run | 95 // Ensure various optimized Convolve() methods return the same value. Only run |
| 96 // this test if other optimized methods exist, otherwise the default Convolve() | 96 // this test if other optimized methods exist, otherwise the default Convolve() |
| 97 // will be tested by the parameterized SincResampler tests below. | 97 // will be tested by the parameterized SincResampler tests below. |
| 98 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__) | |
| 99 TEST(SincResamplerTest, Convolve) { | 98 TEST(SincResamplerTest, Convolve) { |
| 100 // Initialize a dummy resampler. | 99 // Initialize a dummy resampler. |
| 101 MockSource mock_source; | 100 MockSource mock_source; |
| 102 SincResampler resampler( | 101 SincResampler resampler( |
| 103 kSampleRateRatio, | 102 kSampleRateRatio, |
| 104 base::Bind(&MockSource::ProvideInput, base::Unretained(&mock_source))); | 103 base::Bind(&MockSource::ProvideInput, base::Unretained(&mock_source))); |
| 105 | 104 |
| 106 // Convolve_SSE() is slightly more precise than Convolve_C(), so comparison | 105 // Convolve_SSE() is slightly more precise than Convolve_C(), so comparison |
| 107 // must be done using an epsilon. | 106 // must be done using an epsilon. |
| 108 static const double kEpsilon = 0.00000005; | 107 static const double kEpsilon = 0.00000005; |
| 109 | 108 |
| 110 // Use a kernel from SincResampler as input and kernel data, this has the | 109 // Use a kernel from SincResampler as input and kernel data, this has the |
| 111 // benefit of already being properly sized and aligned for Convolve_SSE(). | 110 // benefit of already being properly sized and aligned for Convolve_SSE(). |
| 112 double result = resampler.Convolve_C( | 111 double result = resampler.Convolve_C( |
| 113 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), | 112 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), |
| 114 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | 113 resampler.kernel_storage_.get(), kKernelInterpolationFactor); |
| 115 double result2 = resampler.Convolve_SSE( | 114 |
| 115 double result2 = result; | |
|
Ami GONE FROM CHROMIUM
2012/09/21 04:41:41
I don't like this b/c it'll make the test claim to
DaleCurtis
2012/09/24 19:54:37
Done.
| |
| 116 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__) | |
| 117 result2 = resampler.Convolve_SSE( | |
| 116 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), | 118 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), |
| 117 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | 119 resampler.kernel_storage_.get(), kKernelInterpolationFactor); |
| 120 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(__ARM_NEON__) && defined(USE_NEON) | |
|
Ami GONE FROM CHROMIUM
2012/09/21 04:41:41
Here and elsewhere, I think __ARM_NEON__ is unnece
DaleCurtis
2012/09/24 19:54:37
Done.
| |
| 121 result2 = resampler.Convolve_NEON( | |
| 122 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), | |
| 123 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | |
| 124 #endif | |
| 118 EXPECT_NEAR(result2, result, kEpsilon); | 125 EXPECT_NEAR(result2, result, kEpsilon); |
| 119 | 126 |
| 120 // Test Convolve_SSE() w/ unaligned input pointer. | 127 // Test Convolve() w/ unaligned input pointer. |
| 121 result = resampler.Convolve_C( | 128 result = resampler.Convolve_C( |
| 122 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), | 129 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), |
| 123 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | 130 resampler.kernel_storage_.get(), kKernelInterpolationFactor); |
| 131 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__) | |
| 124 result2 = resampler.Convolve_SSE( | 132 result2 = resampler.Convolve_SSE( |
| 125 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), | 133 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), |
| 126 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | 134 resampler.kernel_storage_.get(), kKernelInterpolationFactor); |
| 135 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(__ARM_NEON__) && defined(USE_NEON) | |
| 136 result2 = resampler.Convolve_NEON( | |
| 137 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), | |
| 138 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | |
| 139 #endif | |
| 127 EXPECT_NEAR(result2, result, kEpsilon); | 140 EXPECT_NEAR(result2, result, kEpsilon); |
| 128 } | 141 } |
| 129 #endif | |
| 130 | 142 |
| 131 // Benchmark for the various Convolve() methods. Make sure to build with | 143 // Benchmark for the various Convolve() methods. Make sure to build with |
| 132 // branding=Chrome so that DCHECKs are compiled out when benchmarking. Original | 144 // branding=Chrome so that DCHECKs are compiled out when benchmarking. Original |
| 133 // benchmarks were run with --convolve-iterations=50000000. | 145 // benchmarks were run with --convolve-iterations=50000000. |
| 134 TEST(SincResamplerTest, ConvolveBenchmark) { | 146 TEST(SincResamplerTest, ConvolveBenchmark) { |
| 135 // Initialize a dummy resampler. | 147 // Initialize a dummy resampler. |
| 136 MockSource mock_source; | 148 MockSource mock_source; |
| 137 SincResampler resampler( | 149 SincResampler resampler( |
| 138 kSampleRateRatio, | 150 kSampleRateRatio, |
| 139 base::Bind(&MockSource::ProvideInput, base::Unretained(&mock_source))); | 151 base::Bind(&MockSource::ProvideInput, base::Unretained(&mock_source))); |
| 140 | 152 |
| 141 // Retrieve benchmark iterations from command line. | 153 // Retrieve benchmark iterations from command line. |
| 142 int convolve_iterations = 10; | 154 int convolve_iterations = 50000000; |
|
Ami GONE FROM CHROMIUM
2012/09/21 04:41:41
what now?
DaleCurtis
2012/09/24 19:54:37
Was just for benchmarking on the try bot, but sadl
| |
| 143 std::string iterations(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 155 std::string iterations(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 144 kConvolveIterations)); | 156 kConvolveIterations)); |
| 145 if (!iterations.empty()) | 157 if (!iterations.empty()) |
| 146 base::StringToInt(iterations, &convolve_iterations); | 158 base::StringToInt(iterations, &convolve_iterations); |
| 147 | 159 |
| 148 printf("Benchmarking %d iterations:\n", convolve_iterations); | 160 printf("Benchmarking %d iterations:\n", convolve_iterations); |
| 149 | 161 |
| 150 // Benchmark Convolve_C(). | 162 // Benchmark Convolve_C(). |
| 151 base::TimeTicks start = base::TimeTicks::HighResNow(); | 163 base::TimeTicks start = base::TimeTicks::HighResNow(); |
| 152 for (int i = 0; i < convolve_iterations; ++i) { | 164 for (int i = 0; i < convolve_iterations; ++i) { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 178 resampler.Convolve_SSE( | 190 resampler.Convolve_SSE( |
| 179 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), | 191 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), |
| 180 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | 192 resampler.kernel_storage_.get(), kKernelInterpolationFactor); |
| 181 } | 193 } |
| 182 double total_time_sse_aligned_ms = | 194 double total_time_sse_aligned_ms = |
| 183 (base::TimeTicks::HighResNow() - start).InMillisecondsF(); | 195 (base::TimeTicks::HighResNow() - start).InMillisecondsF(); |
| 184 printf("Convolve_SSE (aligned) took %.2fms; which is %.2fx faster than" | 196 printf("Convolve_SSE (aligned) took %.2fms; which is %.2fx faster than" |
| 185 " Convolve_C and %.2fx faster than Convolve_SSE (unaligned).\n", | 197 " Convolve_C and %.2fx faster than Convolve_SSE (unaligned).\n", |
| 186 total_time_sse_aligned_ms, total_time_c_ms / total_time_sse_aligned_ms, | 198 total_time_sse_aligned_ms, total_time_c_ms / total_time_sse_aligned_ms, |
| 187 total_time_sse_unaligned_ms / total_time_sse_aligned_ms); | 199 total_time_sse_unaligned_ms / total_time_sse_aligned_ms); |
| 200 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(__ARM_NEON__) && defined(USE_NEON) | |
|
Ami GONE FROM CHROMIUM
2012/09/21 04:41:41
Like with the original SSE CL, IWBN to include ben
DaleCurtis
2012/09/24 19:54:37
Done.
| |
| 201 // Benchmark Convolve_NEON() with unaligned input pointer. | |
| 202 start = base::TimeTicks::HighResNow(); | |
| 203 for (int j = 0; j < convolve_iterations; ++j) { | |
| 204 resampler.Convolve_NEON( | |
| 205 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), | |
| 206 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | |
| 207 } | |
| 208 double total_time_sse_unaligned_ms = | |
|
Ami GONE FROM CHROMIUM
2012/09/22 02:38:27
there are a bunch of variables here and below that
DaleCurtis
2012/09/24 19:54:37
Done.
| |
| 209 (base::TimeTicks::HighResNow() - start).InMillisecondsF(); | |
| 210 printf("Convolve_NEON (unaligned) took %.2fms; which is %.2fx faster than" | |
| 211 " Convolve_C.\n", total_time_sse_unaligned_ms, | |
| 212 total_time_c_ms / total_time_sse_unaligned_ms); | |
| 213 | |
| 214 // Benchmark Convolve_NEON() with aligned input pointer. | |
| 215 start = base::TimeTicks::HighResNow(); | |
| 216 for (int j = 0; j < convolve_iterations; ++j) { | |
| 217 resampler.Convolve_NEON( | |
| 218 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), | |
| 219 resampler.kernel_storage_.get(), kKernelInterpolationFactor); | |
| 220 } | |
| 221 double total_time_sse_aligned_ms = | |
| 222 (base::TimeTicks::HighResNow() - start).InMillisecondsF(); | |
| 223 printf("Convolve_NEON (aligned) took %.2fms; which is %.2fx faster than" | |
| 224 " Convolve_C and %.2fx faster than Convolve_SSE (unaligned).\n", | |
|
Ami GONE FROM CHROMIUM
2012/09/22 02:38:27
s/SSE/NEON/, I think :)
DaleCurtis
2012/09/24 19:54:37
Done.
| |
| 225 total_time_sse_aligned_ms, total_time_c_ms / total_time_sse_aligned_ms, | |
| 226 total_time_sse_unaligned_ms / total_time_sse_aligned_ms); | |
| 188 #endif | 227 #endif |
| 189 } | 228 } |
| 190 | 229 |
| 191 // Fake audio source for testing the resampler. Generates a sinusoidal linear | 230 // Fake audio source for testing the resampler. Generates a sinusoidal linear |
| 192 // chirp (http://en.wikipedia.org/wiki/Chirp) which can be tuned to stress the | 231 // chirp (http://en.wikipedia.org/wiki/Chirp) which can be tuned to stress the |
| 193 // resampler for the specific sample rate conversion being used. | 232 // resampler for the specific sample rate conversion being used. |
| 194 class SinusoidalLinearChirpSource { | 233 class SinusoidalLinearChirpSource { |
| 195 public: | 234 public: |
| 196 SinusoidalLinearChirpSource(int sample_rate, int samples, | 235 SinusoidalLinearChirpSource(int sample_rate, int samples, |
| 197 double max_frequency) | 236 double max_frequency) |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 380 std::tr1::make_tuple(11025, 192000, kResamplingRMSError, -62.61), | 419 std::tr1::make_tuple(11025, 192000, kResamplingRMSError, -62.61), |
| 381 std::tr1::make_tuple(16000, 192000, kResamplingRMSError, -63.14), | 420 std::tr1::make_tuple(16000, 192000, kResamplingRMSError, -63.14), |
| 382 std::tr1::make_tuple(22050, 192000, kResamplingRMSError, -62.42), | 421 std::tr1::make_tuple(22050, 192000, kResamplingRMSError, -62.42), |
| 383 std::tr1::make_tuple(32000, 192000, kResamplingRMSError, -63.38), | 422 std::tr1::make_tuple(32000, 192000, kResamplingRMSError, -63.38), |
| 384 std::tr1::make_tuple(44100, 192000, kResamplingRMSError, -62.63), | 423 std::tr1::make_tuple(44100, 192000, kResamplingRMSError, -62.63), |
| 385 std::tr1::make_tuple(48000, 192000, kResamplingRMSError, -73.44), | 424 std::tr1::make_tuple(48000, 192000, kResamplingRMSError, -73.44), |
| 386 std::tr1::make_tuple(96000, 192000, kResamplingRMSError, -73.52), | 425 std::tr1::make_tuple(96000, 192000, kResamplingRMSError, -73.52), |
| 387 std::tr1::make_tuple(192000, 192000, kResamplingRMSError, -73.52))); | 426 std::tr1::make_tuple(192000, 192000, kResamplingRMSError, -73.52))); |
| 388 | 427 |
| 389 } // namespace media | 428 } // namespace media |
| OLD | NEW |