| 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__) | 7 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__) |
| 8 #include <xmmintrin.h> | 8 #include <xmmintrin.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 } | 39 } |
| 40 | 40 |
| 41 audio_sink_->Initialize(output_params, this); | 41 audio_sink_->Initialize(output_params, this); |
| 42 audio_sink_->Start(); | 42 audio_sink_->Start(); |
| 43 } | 43 } |
| 44 | 44 |
| 45 AudioRendererMixer::~AudioRendererMixer() { | 45 AudioRendererMixer::~AudioRendererMixer() { |
| 46 // AudioRendererSinks must be stopped before being destructed. | 46 // AudioRendererSinks must be stopped before being destructed. |
| 47 audio_sink_->Stop(); | 47 audio_sink_->Stop(); |
| 48 | 48 |
| 49 // Clean up |mixer_input_audio_data_|. | |
| 50 for (size_t i = 0; i < mixer_input_audio_data_.size(); ++i) | |
| 51 base::AlignedFree(mixer_input_audio_data_[i]); | |
| 52 mixer_input_audio_data_.clear(); | |
| 53 | |
| 54 // Ensures that all mixer inputs have stopped themselves prior to destruction | 49 // Ensures that all mixer inputs have stopped themselves prior to destruction |
| 55 // and have called RemoveMixerInput(). | 50 // and have called RemoveMixerInput(). |
| 56 DCHECK_EQ(mixer_inputs_.size(), 0U); | 51 DCHECK_EQ(mixer_inputs_.size(), 0U); |
| 57 } | 52 } |
| 58 | 53 |
| 59 void AudioRendererMixer::AddMixerInput( | 54 void AudioRendererMixer::AddMixerInput( |
| 60 const scoped_refptr<AudioRendererMixerInput>& input) { | 55 const scoped_refptr<AudioRendererMixerInput>& input) { |
| 61 base::AutoLock auto_lock(mixer_inputs_lock_); | 56 base::AutoLock auto_lock(mixer_inputs_lock_); |
| 62 mixer_inputs_.insert(input); | 57 mixer_inputs_.insert(input); |
| 63 } | 58 } |
| 64 | 59 |
| 65 void AudioRendererMixer::RemoveMixerInput( | 60 void AudioRendererMixer::RemoveMixerInput( |
| 66 const scoped_refptr<AudioRendererMixerInput>& input) { | 61 const scoped_refptr<AudioRendererMixerInput>& input) { |
| 67 base::AutoLock auto_lock(mixer_inputs_lock_); | 62 base::AutoLock auto_lock(mixer_inputs_lock_); |
| 68 mixer_inputs_.erase(input); | 63 mixer_inputs_.erase(input); |
| 69 } | 64 } |
| 70 | 65 |
| 71 int AudioRendererMixer::Render(const std::vector<float*>& audio_data, | 66 int AudioRendererMixer::Render(AudioBus* audio_bus, |
| 72 int number_of_frames, | 67 int number_of_frames, |
| 73 int audio_delay_milliseconds) { | 68 int audio_delay_milliseconds) { |
| 74 current_audio_delay_milliseconds_ = audio_delay_milliseconds; | 69 current_audio_delay_milliseconds_ = audio_delay_milliseconds; |
| 75 | 70 |
| 76 if (resampler_.get()) | 71 if (resampler_.get()) |
| 77 resampler_->Resample(audio_data, number_of_frames); | 72 resampler_->Resample(audio_bus, number_of_frames); |
| 78 else | 73 else |
| 79 ProvideInput(audio_data, number_of_frames); | 74 ProvideInput(audio_bus, number_of_frames); |
| 80 | 75 |
| 81 // Always return the full number of frames requested, ProvideInput() will pad | 76 // Always return the full number of frames requested, ProvideInput() will pad |
| 82 // with silence if it wasn't able to acquire enough data. | 77 // with silence if it wasn't able to acquire enough data. |
| 83 return number_of_frames; | 78 return number_of_frames; |
| 84 } | 79 } |
| 85 | 80 |
| 86 void AudioRendererMixer::ProvideInput(const std::vector<float*>& audio_data, | 81 void AudioRendererMixer::ProvideInput(AudioBus* audio_bus, |
| 87 int number_of_frames) { | 82 int number_of_frames) { |
| 88 base::AutoLock auto_lock(mixer_inputs_lock_); | 83 base::AutoLock auto_lock(mixer_inputs_lock_); |
| 89 | 84 |
| 90 // Allocate staging area for each mixer input's audio data on first call. We | 85 // Allocate staging area for each mixer input's audio data on first call. We |
| 91 // won't know how much to allocate until here because of resampling. | 86 // won't know how much to allocate until here because of resampling. |
| 92 if (mixer_input_audio_data_.size() == 0) { | 87 if (!mixer_input_audio_bus_.get()) { |
| 93 mixer_input_audio_data_.reserve(audio_data.size()); | 88 mixer_input_audio_bus_ = |
| 94 for (size_t i = 0; i < audio_data.size(); ++i) { | 89 AudioBus::Create(audio_bus->channels(), number_of_frames); |
| 95 // Allocate audio data with a 16-byte alignment for SSE optimizations. | |
| 96 mixer_input_audio_data_.push_back(static_cast<float*>( | |
| 97 base::AlignedAlloc(sizeof(float) * number_of_frames, 16))); | |
| 98 } | |
| 99 mixer_input_audio_data_size_ = number_of_frames; | |
| 100 } | 90 } |
| 101 | 91 |
| 102 // Sanity check our inputs. | 92 // Sanity check our inputs. |
| 103 DCHECK_LE(number_of_frames, mixer_input_audio_data_size_); | 93 DCHECK_LE(number_of_frames, audio_bus->frames()); |
| 104 DCHECK_EQ(audio_data.size(), mixer_input_audio_data_.size()); | 94 DCHECK_LE(number_of_frames, mixer_input_audio_bus_->frames()); |
| 95 DCHECK_EQ(audio_bus->channels(), mixer_input_audio_bus_->channels()); |
| 105 | 96 |
| 106 // Zero |audio_data| so we're mixing into a clean buffer and return silence if | 97 // Zero |audio_bus| so we're mixing into a clean buffer and return silence if |
| 107 // we couldn't get enough data from our inputs. | 98 // we couldn't get enough data from our inputs. |
| 108 for (size_t i = 0; i < audio_data.size(); ++i) | 99 audio_bus->ZeroFrames(number_of_frames); |
| 109 memset(audio_data[i], 0, number_of_frames * sizeof(*audio_data[i])); | |
| 110 | 100 |
| 111 // Have each mixer render its data into an output buffer then mix the result. | 101 // Have each mixer render its data into an output buffer then mix the result. |
| 112 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin(); | 102 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin(); |
| 113 it != mixer_inputs_.end(); ++it) { | 103 it != mixer_inputs_.end(); ++it) { |
| 114 const scoped_refptr<AudioRendererMixerInput>& input = *it; | 104 const scoped_refptr<AudioRendererMixerInput>& input = *it; |
| 115 | 105 |
| 116 double volume; | 106 double volume; |
| 117 input->GetVolume(&volume); | 107 input->GetVolume(&volume); |
| 118 | 108 |
| 119 // Nothing to do if the input isn't playing. | 109 // Nothing to do if the input isn't playing. |
| 120 if (!input->playing()) | 110 if (!input->playing()) |
| 121 continue; | 111 continue; |
| 122 | 112 |
| 123 int frames_filled = input->callback()->Render( | 113 int frames_filled = input->callback()->Render( |
| 124 mixer_input_audio_data_, number_of_frames, | 114 mixer_input_audio_bus_.get(), number_of_frames, |
| 125 current_audio_delay_milliseconds_); | 115 current_audio_delay_milliseconds_); |
| 126 if (frames_filled == 0) | 116 if (frames_filled == 0) |
| 127 continue; | 117 continue; |
| 128 | 118 |
| 129 // Volume adjust and mix each mixer input into |audio_data| after rendering. | 119 // Volume adjust and mix each mixer input into |audio_bus| after rendering. |
| 130 for (size_t j = 0; j < audio_data.size(); ++j) { | 120 for (int i = 0; i < audio_bus->channels(); ++i) { |
| 131 VectorFMAC( | 121 VectorFMAC(mixer_input_audio_bus_->channel(i), volume, frames_filled, |
| 132 mixer_input_audio_data_[j], volume, frames_filled, audio_data[j]); | 122 audio_bus->channel(i)); |
| 133 } | 123 } |
| 134 | 124 |
| 135 // No need to clamp values as InterleaveFloatToInt() will take care of this | 125 // No need to clamp values as InterleaveFloatToInt() will take care of this |
| 136 // for us later when data is transferred to the browser process. | 126 // for us later when data is transferred to the browser process. |
| 137 } | 127 } |
| 138 } | 128 } |
| 139 | 129 |
| 140 void AudioRendererMixer::OnRenderError() { | 130 void AudioRendererMixer::OnRenderError() { |
| 141 base::AutoLock auto_lock(mixer_inputs_lock_); | 131 base::AutoLock auto_lock(mixer_inputs_lock_); |
| 142 | 132 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 _mm_mul_ps(_mm_load_ps(src + i), m_scale))); | 173 _mm_mul_ps(_mm_load_ps(src + i), m_scale))); |
| 184 } | 174 } |
| 185 | 175 |
| 186 // Handle any remaining values that wouldn't fit in an SSE pass. | 176 // Handle any remaining values that wouldn't fit in an SSE pass. |
| 187 if (rem) | 177 if (rem) |
| 188 VectorFMAC_C(src + len - rem, scale, rem, dest + len - rem); | 178 VectorFMAC_C(src + len - rem, scale, rem, dest + len - rem); |
| 189 } | 179 } |
| 190 #endif | 180 #endif |
| 191 | 181 |
| 192 } // namespace media | 182 } // namespace media |
| OLD | NEW |