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

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

Issue 10802005: Add SSE optimizations to AudioRendererMixer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include "media/base/audio_renderer_mixer.h" 5 #include "media/base/audio_renderer_mixer.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/cpu.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "media/audio/audio_util.h" 11 #include "media/audio/audio_util.h"
11 #include "media/base/limits.h" 12 #include "media/base/limits.h"
12 13
14 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__)
15 #include <xmmintrin.h>
16 #endif
17
13 namespace media { 18 namespace media {
14 19
20 static void VectorFMAC_C(float* src, float* dest, float scale, int len) {
21 for (int i = 0; i < len; ++i)
22 dest[i] += src[i] * scale;
23 }
24
25 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__)
26 static const int kFloatsPerPass = sizeof(__m128) / sizeof(float);
27 static void VectorFMAC_SSE(float* src, float* dest, float scale, int len) {
28 // Ensure |src| and |dest| are aligned properly.
29 DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(src) & (sizeof(__m128) - 1));
30 DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(dest) & (sizeof(__m128) - 1));
31
32 __m128 m_scale = _mm_set_ps1(scale);
33 int rem = len % kFloatsPerPass;
34 for (int i = 0; i < len - rem; i += kFloatsPerPass) {
35 _mm_store_ps(dest + i, _mm_add_ps(_mm_load_ps(dest + i),
36 _mm_mul_ps(_mm_load_ps(src + i), m_scale)));
37 }
38
39 // Handle any remaining values that wouldn't fit in an SSE pass.
40 if (rem)
41 VectorFMAC_C(src + len - rem, dest + len - rem, scale, rem);
42 }
43 #endif
44
45 typedef void (*VectorFMACProc)(float* src, float* dest, float scale, int len);
46 static VectorFMACProc vector_fmac_proc = NULL;
47
15 AudioRendererMixer::AudioRendererMixer( 48 AudioRendererMixer::AudioRendererMixer(
16 const AudioParameters& input_params, const AudioParameters& output_params, 49 const AudioParameters& input_params, const AudioParameters& output_params,
17 const scoped_refptr<AudioRendererSink>& sink) 50 const scoped_refptr<AudioRendererSink>& sink)
18 : audio_sink_(sink), 51 : audio_sink_(sink),
19 current_audio_delay_milliseconds_(0) { 52 current_audio_delay_milliseconds_(0) {
53 if (!vector_fmac_proc) {
54 vector_fmac_proc = VectorFMAC_C;
55 base::CPU cpu;
56 if (cpu.has_sse())
57 vector_fmac_proc = VectorFMAC_SSE;
58 }
59
20 // Sanity check sample rates. 60 // Sanity check sample rates.
21 DCHECK_LE(input_params.sample_rate(), limits::kMaxSampleRate); 61 DCHECK_LE(input_params.sample_rate(), limits::kMaxSampleRate);
22 DCHECK_GE(input_params.sample_rate(), limits::kMinSampleRate); 62 DCHECK_GE(input_params.sample_rate(), limits::kMinSampleRate);
23 DCHECK_LE(output_params.sample_rate(), limits::kMaxSampleRate); 63 DCHECK_LE(output_params.sample_rate(), limits::kMaxSampleRate);
24 DCHECK_GE(output_params.sample_rate(), limits::kMinSampleRate); 64 DCHECK_GE(output_params.sample_rate(), limits::kMinSampleRate);
25 65
26 // Only resample if necessary since it's expensive. 66 // Only resample if necessary since it's expensive.
27 if (input_params.sample_rate() != output_params.sample_rate()) { 67 if (input_params.sample_rate() != output_params.sample_rate()) {
28 resampler_.reset(new MultiChannelResampler( 68 resampler_.reset(new MultiChannelResampler(
29 output_params.channels(), 69 output_params.channels(),
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 if (!input->playing()) 153 if (!input->playing())
114 continue; 154 continue;
115 155
116 int frames_filled = input->callback()->Render( 156 int frames_filled = input->callback()->Render(
117 mixer_input_audio_data_, number_of_frames, 157 mixer_input_audio_data_, number_of_frames,
118 current_audio_delay_milliseconds_); 158 current_audio_delay_milliseconds_);
119 if (frames_filled == 0) 159 if (frames_filled == 0)
120 continue; 160 continue;
121 161
122 // Volume adjust and mix each mixer input into |audio_data| after rendering. 162 // Volume adjust and mix each mixer input into |audio_data| after rendering.
123 // TODO(dalecurtis): Optimize with NEON/SSE/AVX vector_fmac from FFmpeg.
124 for (size_t j = 0; j < audio_data.size(); ++j) { 163 for (size_t j = 0; j < audio_data.size(); ++j) {
125 float* dest = audio_data[j]; 164 vector_fmac_proc(
126 float* source = mixer_input_audio_data_[j]; 165 mixer_input_audio_data_[j], audio_data[j], volume, frames_filled);
127 for (int k = 0; k < frames_filled; ++k)
128 dest[k] += source[k] * static_cast<float>(volume);
129 } 166 }
130 167
131 // No need to clamp values as InterleaveFloatToInt() will take care of this 168 // No need to clamp values as InterleaveFloatToInt() will take care of this
132 // for us later when data is transferred to the browser process. 169 // for us later when data is transferred to the browser process.
133 } 170 }
134 } 171 }
135 172
136 void AudioRendererMixer::OnRenderError() { 173 void AudioRendererMixer::OnRenderError() {
137 base::AutoLock auto_lock(mixer_inputs_lock_); 174 base::AutoLock auto_lock(mixer_inputs_lock_);
138 175
139 // Call each mixer input and signal an error. 176 // Call each mixer input and signal an error.
140 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin(); 177 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin();
141 it != mixer_inputs_.end(); ++it) { 178 it != mixer_inputs_.end(); ++it) {
142 (*it)->callback()->OnRenderError(); 179 (*it)->callback()->OnRenderError();
143 } 180 }
144 } 181 }
145 182
146 } // namespace media 183 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698