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

Side by Side Diff: media/base/audio_renderer_mixer_unittest.cc

Issue 10802005: Add SSE optimizations to AudioRendererMixer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments. Created 8 years, 4 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
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 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/memory/aligned_memory.h"
11 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/scoped_vector.h" 14 #include "base/memory/scoped_vector.h"
15 #include "base/string_number_conversions.h"
13 #include "media/base/audio_renderer_mixer.h" 16 #include "media/base/audio_renderer_mixer.h"
14 #include "media/base/audio_renderer_mixer_input.h" 17 #include "media/base/audio_renderer_mixer_input.h"
15 #include "media/base/fake_audio_render_callback.h" 18 #include "media/base/fake_audio_render_callback.h"
16 #include "media/base/mock_audio_renderer_sink.h" 19 #include "media/base/mock_audio_renderer_sink.h"
17 #include "testing/gmock/include/gmock/gmock.h" 20 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
19 22
20 namespace media { 23 namespace media {
21 24
22 // Parameters which control the many input case tests. 25 // Parameters which control the many input case tests.
23 static const int kMixerInputs = 8; 26 static const int kMixerInputs = 8;
24 static const int kMixerCycles = 3; 27 static const int kMixerCycles = 3;
25 28
26 // Parameters used for testing. 29 // Parameters used for testing.
27 static const int kBitsPerChannel = 16; 30 static const int kBitsPerChannel = 16;
28 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; 31 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
29 static const int kHighLatencyBufferSize = 8192; 32 static const int kHighLatencyBufferSize = 8192;
30 static const int kLowLatencyBufferSize = 256; 33 static const int kLowLatencyBufferSize = 256;
34 static const int kSampleRate = 48000;
31 35
32 // Number of full sine wave cycles for each Render() call. 36 // Number of full sine wave cycles for each Render() call.
33 static const int kSineCycles = 4; 37 static const int kSineCycles = 4;
34 38
39 // Command line switch for runtime adjustment of VectorFMACBenchmark iterations.
40 static const char kVectorFMACIterations[] = "vector-fmac-iterations";
41
42 // Test parameters for VectorFMAC tests.
43 static const float kScale = 0.5;
44 static const float kInputFillValue = 1.0;
45 static const float kOutputFillValue = 3.0;
46
47 // Ensure various optimized VectorFMAC() methods return the same value.
48 TEST(AudioRendererMixerTest, VectorFMAC) {
49 // Initialize a dummy mixer.
50 scoped_refptr<MockAudioRendererSink> sink = new MockAudioRendererSink();
51 EXPECT_CALL(*sink, Start());
52 EXPECT_CALL(*sink, Stop());
53 AudioParameters params(
54 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
55 kBitsPerChannel, kHighLatencyBufferSize);
56 AudioRendererMixer mixer(params, params, sink);
57
58 // Initialize input and output vectors.
59 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> input_vector(
60 static_cast<float*>(
61 base::AlignedAlloc(sizeof(float) * kHighLatencyBufferSize, 16)));
62 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> output_vector(
63 static_cast<float*>(
64 base::AlignedAlloc(sizeof(float) * kHighLatencyBufferSize, 16)));
65
66 // Setup input and output vectors.
67 std::fill(input_vector.get(), input_vector.get() + kHighLatencyBufferSize,
68 kInputFillValue);
69 std::fill(output_vector.get(), output_vector.get() + kHighLatencyBufferSize,
70 kOutputFillValue);
71 mixer.VectorFMAC_C(
72 *input_vector.get(), kScale, kHighLatencyBufferSize, output_vector.get());
73 for(int i = 0; i < kHighLatencyBufferSize; ++i) {
74 ASSERT_FLOAT_EQ(output_vector.get()[i],
75 kInputFillValue * kScale + kOutputFillValue);
76 }
77
78 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__)
79 // Reset vectors, and try with SSE.
80 std::fill(output_vector.get(), output_vector.get() + kHighLatencyBufferSize,
81 kOutputFillValue);
82 mixer.VectorFMAC_SSE(
83 *input_vector.get(), kScale, kHighLatencyBufferSize, output_vector.get());
84 for(int i = 0; i < kHighLatencyBufferSize; ++i) {
85 ASSERT_FLOAT_EQ(output_vector.get()[i],
86 kInputFillValue * kScale + kOutputFillValue);
87 }
88 #endif
89 }
90
91 // Benchmark for the various VectorFMAC() methods. Make sure to build with
92 // branding=Chrome so that DCHECKs are compiled out when benchmarking. Original
93 // benchmarks were run with --vector-fmac-iterations=200000.
94 TEST(AudioRendererMixerTest, VectorFMACBenchmark) {
95 // Initialize a dummy mixer.
96 scoped_refptr<MockAudioRendererSink> sink = new MockAudioRendererSink();
97 EXPECT_CALL(*sink, Start());
98 EXPECT_CALL(*sink, Stop());
99 AudioParameters params(
100 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
101 kBitsPerChannel, kHighLatencyBufferSize);
102 AudioRendererMixer mixer(params, params, sink);
103
104 // Initialize input and output vectors.
105 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> input_vector(
106 static_cast<float*>(
107 base::AlignedAlloc(sizeof(float) * kHighLatencyBufferSize, 16)));
108 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> output_vector(
109 static_cast<float*>(
110 base::AlignedAlloc(sizeof(float) * kHighLatencyBufferSize, 16)));
111
112 // Retrieve benchmark iterations from command line.
113 int vector_fmac_iterations = 10;
114 std::string iterations(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
115 kVectorFMACIterations));
116 if (!iterations.empty())
117 base::StringToInt(iterations, &vector_fmac_iterations);
118
119 printf("Benchmarking %d iterations:\n", vector_fmac_iterations);
120
121 // Benchmark VectorFMAC_C().
122 std::fill(input_vector.get(), input_vector.get() + kHighLatencyBufferSize,
123 kInputFillValue);
124 std::fill(output_vector.get(), output_vector.get() + kHighLatencyBufferSize,
125 kOutputFillValue);
126 base::TimeTicks start = base::TimeTicks::HighResNow();
127 for (int i = 0; i < vector_fmac_iterations; ++i) {
128 mixer.VectorFMAC_C(*input_vector.get(), M_PI, kHighLatencyBufferSize,
129 output_vector.get());
130 }
131 double total_time_c_ms =
132 (base::TimeTicks::HighResNow() - start).InMillisecondsF();
133 printf("VectorFMAC_C took %.2fms.\n", total_time_c_ms);
134
135 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__)
136 // Benchmark VectorFMAC_SSE() with unaligned size; I.e., size % 4 != 0.
137 ASSERT_NE((kHighLatencyBufferSize - 1) % 4, 0);
138 std::fill(output_vector.get(), output_vector.get() + kHighLatencyBufferSize,
139 kOutputFillValue);
140 start = base::TimeTicks::HighResNow();
141 for (int j = 0; j < vector_fmac_iterations; ++j) {
142 mixer.VectorFMAC_SSE(*input_vector.get(), M_PI, kHighLatencyBufferSize - 1,
143 output_vector.get());
144 }
145 double total_time_sse_unaligned_ms =
146 (base::TimeTicks::HighResNow() - start).InMillisecondsF();
147 printf("VectorFMAC_SSE (unaligned size) took %.2fms; which is %.2fx faster"
148 " than VectorFMAC_C.\n", total_time_sse_unaligned_ms,
149 total_time_c_ms / total_time_sse_unaligned_ms);
150
151 // Benchmark VectorFMAC_SSE() with aligned size; I.e., size % 4 == 0.
152 ASSERT_EQ(kHighLatencyBufferSize % 4, 0);
153 std::fill(output_vector.get(), output_vector.get() + kHighLatencyBufferSize,
154 kOutputFillValue);
155 start = base::TimeTicks::HighResNow();
156 for (int j = 0; j < vector_fmac_iterations; ++j) {
157 mixer.VectorFMAC_SSE(*input_vector.get(), M_PI, kHighLatencyBufferSize,
158 output_vector.get());
159 }
160 double total_time_sse_aligned_ms =
161 (base::TimeTicks::HighResNow() - start).InMillisecondsF();
162 printf("VectorFMAC_SSE (aligned size) took %.2fms; which is %.2fx faster than"
163 " VectorFMAC_C and %.2fx faster than VectorFMAC_SSE (unaligned size)."
164 "\n",
165 total_time_sse_aligned_ms, total_time_c_ms / total_time_sse_aligned_ms,
166 total_time_sse_unaligned_ms / total_time_sse_aligned_ms);
167 #endif
168 }
169
35 // Tuple of <input sampling rate, output sampling rate, epsilon>. 170 // Tuple of <input sampling rate, output sampling rate, epsilon>.
36 typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData; 171 typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData;
37 class AudioRendererMixerTest 172 class AudioRendererMixerTest
38 : public testing::TestWithParam<AudioRendererMixerTestData> { 173 : public testing::TestWithParam<AudioRendererMixerTestData> {
39 public: 174 public:
40 AudioRendererMixerTest() 175 AudioRendererMixerTest()
41 : epsilon_(std::tr1::get<2>(GetParam())), 176 : epsilon_(std::tr1::get<2>(GetParam())),
42 half_fill_(false) { 177 half_fill_(false) {
43 // Create input and output parameters based on test parameters. 178 // Create input and output parameters based on test parameters.
44 input_parameters_ = AudioParameters( 179 input_parameters_ = AudioParameters(
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 // No resampling. 547 // No resampling.
413 std::tr1::make_tuple(44100, 44100, 0.00000048), 548 std::tr1::make_tuple(44100, 44100, 0.00000048),
414 549
415 // Upsampling. 550 // Upsampling.
416 std::tr1::make_tuple(44100, 48000, 0.033), 551 std::tr1::make_tuple(44100, 48000, 0.033),
417 552
418 // Downsampling. 553 // Downsampling.
419 std::tr1::make_tuple(48000, 41000, 0.042))); 554 std::tr1::make_tuple(48000, 41000, 0.042)));
420 555
421 } // namespace media 556 } // namespace media
OLDNEW
« media/base/audio_renderer_mixer.h ('K') | « media/base/audio_renderer_mixer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698