| 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 #include "media/base/audio_renderer_mixer.h" | 5 #include "media/base/audio_renderer_mixer.h" |
| 6 | 6 |
| 7 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__) | |
| 8 #include <xmmintrin.h> | |
| 9 #endif | |
| 10 | |
| 11 #include "base/bind.h" | 7 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 13 #include "base/cpu.h" | |
| 14 #include "base/logging.h" | 9 #include "base/logging.h" |
| 15 #include "base/memory/aligned_memory.h" | |
| 16 #include "media/audio/audio_util.h" | 10 #include "media/audio/audio_util.h" |
| 17 #include "media/base/limits.h" | 11 #include "media/base/limits.h" |
| 12 #include "media/base/vector_math.h" |
| 18 | 13 |
| 19 namespace media { | 14 namespace media { |
| 20 | 15 |
| 21 AudioRendererMixer::AudioRendererMixer( | 16 AudioRendererMixer::AudioRendererMixer( |
| 22 const AudioParameters& input_params, const AudioParameters& output_params, | 17 const AudioParameters& input_params, const AudioParameters& output_params, |
| 23 const scoped_refptr<AudioRendererSink>& sink) | 18 const scoped_refptr<AudioRendererSink>& sink) |
| 24 : audio_sink_(sink), | 19 : audio_sink_(sink), |
| 25 current_audio_delay_milliseconds_(0) { | 20 current_audio_delay_milliseconds_(0) { |
| 26 // Sanity check sample rates. | 21 // Sanity check sample rates. |
| 27 DCHECK_LE(input_params.sample_rate(), limits::kMaxSampleRate); | 22 DCHECK_LE(input_params.sample_rate(), limits::kMaxSampleRate); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 if (!input->playing()) | 105 if (!input->playing()) |
| 111 continue; | 106 continue; |
| 112 | 107 |
| 113 int frames_filled = input->callback()->Render( | 108 int frames_filled = input->callback()->Render( |
| 114 mixer_input_audio_bus_.get(), current_audio_delay_milliseconds_); | 109 mixer_input_audio_bus_.get(), current_audio_delay_milliseconds_); |
| 115 if (frames_filled == 0) | 110 if (frames_filled == 0) |
| 116 continue; | 111 continue; |
| 117 | 112 |
| 118 // Volume adjust and mix each mixer input into |audio_bus| after rendering. | 113 // Volume adjust and mix each mixer input into |audio_bus| after rendering. |
| 119 for (int i = 0; i < audio_bus->channels(); ++i) { | 114 for (int i = 0; i < audio_bus->channels(); ++i) { |
| 120 VectorFMAC(mixer_input_audio_bus_->channel(i), volume, frames_filled, | 115 vector_math::FMAC( |
| 121 audio_bus->channel(i)); | 116 mixer_input_audio_bus_->channel(i), volume, frames_filled, |
| 117 audio_bus->channel(i)); |
| 122 } | 118 } |
| 123 } | 119 } |
| 124 } | 120 } |
| 125 | 121 |
| 126 void AudioRendererMixer::OnRenderError() { | 122 void AudioRendererMixer::OnRenderError() { |
| 127 base::AutoLock auto_lock(mixer_inputs_lock_); | 123 base::AutoLock auto_lock(mixer_inputs_lock_); |
| 128 | 124 |
| 129 // Call each mixer input and signal an error. | 125 // Call each mixer input and signal an error. |
| 130 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin(); | 126 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin(); |
| 131 it != mixer_inputs_.end(); ++it) { | 127 it != mixer_inputs_.end(); ++it) { |
| 132 (*it)->callback()->OnRenderError(); | 128 (*it)->callback()->OnRenderError(); |
| 133 } | 129 } |
| 134 } | 130 } |
| 135 | 131 |
| 136 void AudioRendererMixer::VectorFMAC(const float src[], float scale, int len, | |
| 137 float dest[]) { | |
| 138 // Rely on function level static initialization to keep VectorFMACProc | |
| 139 // selection thread safe. | |
| 140 typedef void (*VectorFMACProc)(const float src[], float scale, int len, | |
| 141 float dest[]); | |
| 142 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__) | |
| 143 static const VectorFMACProc kVectorFMACProc = | |
| 144 base::CPU().has_sse() ? VectorFMAC_SSE : VectorFMAC_C; | |
| 145 #else | |
| 146 static const VectorFMACProc kVectorFMACProc = VectorFMAC_C; | |
| 147 #endif | |
| 148 | |
| 149 return kVectorFMACProc(src, scale, len, dest); | |
| 150 } | |
| 151 | |
| 152 void AudioRendererMixer::VectorFMAC_C(const float src[], float scale, int len, | |
| 153 float dest[]) { | |
| 154 for (int i = 0; i < len; ++i) | |
| 155 dest[i] += src[i] * scale; | |
| 156 } | |
| 157 | |
| 158 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__) | |
| 159 void AudioRendererMixer::VectorFMAC_SSE(const float src[], float scale, int len, | |
| 160 float dest[]) { | |
| 161 // Ensure |src| and |dest| are 16-byte aligned. | |
| 162 DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(src) & 0x0F); | |
| 163 DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(dest) & 0x0F); | |
| 164 | |
| 165 __m128 m_scale = _mm_set_ps1(scale); | |
| 166 int rem = len % 4; | |
| 167 for (int i = 0; i < len - rem; i += 4) { | |
| 168 _mm_store_ps(dest + i, _mm_add_ps(_mm_load_ps(dest + i), | |
| 169 _mm_mul_ps(_mm_load_ps(src + i), m_scale))); | |
| 170 } | |
| 171 | |
| 172 // Handle any remaining values that wouldn't fit in an SSE pass. | |
| 173 if (rem) | |
| 174 VectorFMAC_C(src + len - rem, scale, rem, dest + len - rem); | |
| 175 } | |
| 176 #endif | |
| 177 | |
| 178 } // namespace media | 132 } // namespace media |
| OLD | NEW |