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, | |
73 int audio_delay_milliseconds) { | 67 int audio_delay_milliseconds) { |
74 current_audio_delay_milliseconds_ = audio_delay_milliseconds; | 68 current_audio_delay_milliseconds_ = audio_delay_milliseconds; |
75 | 69 |
76 if (resampler_.get()) | 70 if (resampler_.get()) |
77 resampler_->Resample(audio_data, number_of_frames); | 71 resampler_->Resample(audio_bus, audio_bus->frames()); |
78 else | 72 else |
79 ProvideInput(audio_data, number_of_frames); | 73 ProvideInput(audio_bus); |
80 | 74 |
81 // Always return the full number of frames requested, ProvideInput() will pad | 75 // Always return the full number of frames requested, ProvideInput() will pad |
82 // with silence if it wasn't able to acquire enough data. | 76 // with silence if it wasn't able to acquire enough data. |
83 return number_of_frames; | 77 return audio_bus->frames(); |
84 } | 78 } |
85 | 79 |
86 void AudioRendererMixer::ProvideInput(const std::vector<float*>& audio_data, | 80 void AudioRendererMixer::ProvideInput(AudioBus* audio_bus) { |
87 int number_of_frames) { | |
88 base::AutoLock auto_lock(mixer_inputs_lock_); | 81 base::AutoLock auto_lock(mixer_inputs_lock_); |
89 | 82 |
90 // Allocate staging area for each mixer input's audio data on first call. We | 83 // 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. | 84 // won't know how much to allocate until here because of resampling. Ensure |
92 if (mixer_input_audio_data_.size() == 0) { | 85 // our intermediate AudioBus is sized exactly as the original. Resize should |
93 mixer_input_audio_data_.reserve(audio_data.size()); | 86 // only happen once due to the way the resampler works. |
94 for (size_t i = 0; i < audio_data.size(); ++i) { | 87 if (!mixer_input_audio_bus_.get() || |
95 // Allocate audio data with a 16-byte alignment for SSE optimizations. | 88 mixer_input_audio_bus_->frames() != audio_bus->frames()) { |
96 mixer_input_audio_data_.push_back(static_cast<float*>( | 89 mixer_input_audio_bus_ = |
97 base::AlignedAlloc(sizeof(float) * number_of_frames, 16))); | 90 AudioBus::Create(audio_bus->channels(), audio_bus->frames()); |
98 } | |
99 mixer_input_audio_data_size_ = number_of_frames; | |
100 } | 91 } |
101 | 92 |
102 // Sanity check our inputs. | 93 // Sanity check our inputs. |
103 DCHECK_LE(number_of_frames, mixer_input_audio_data_size_); | 94 DCHECK_EQ(audio_bus->frames(), mixer_input_audio_bus_->frames()); |
104 DCHECK_EQ(audio_data.size(), mixer_input_audio_data_.size()); | 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->Zero(); |
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(), current_audio_delay_milliseconds_); |
125 current_audio_delay_milliseconds_); | |
126 if (frames_filled == 0) | 115 if (frames_filled == 0) |
127 continue; | 116 continue; |
128 | 117 |
129 // Volume adjust and mix each mixer input into |audio_data| after rendering. | 118 // Volume adjust and mix each mixer input into |audio_bus| after rendering. |
130 for (size_t j = 0; j < audio_data.size(); ++j) { | 119 for (int i = 0; i < audio_bus->channels(); ++i) { |
131 VectorFMAC( | 120 VectorFMAC(mixer_input_audio_bus_->channel(i), volume, frames_filled, |
132 mixer_input_audio_data_[j], volume, frames_filled, audio_data[j]); | 121 audio_bus->channel(i)); |
133 } | 122 } |
134 | 123 |
135 // No need to clamp values as InterleaveFloatToInt() will take care of this | 124 // No need to clamp values as InterleaveFloatToInt() will take care of this |
136 // for us later when data is transferred to the browser process. | 125 // for us later when data is transferred to the browser process. |
137 } | 126 } |
138 } | 127 } |
139 | 128 |
140 void AudioRendererMixer::OnRenderError() { | 129 void AudioRendererMixer::OnRenderError() { |
141 base::AutoLock auto_lock(mixer_inputs_lock_); | 130 base::AutoLock auto_lock(mixer_inputs_lock_); |
142 | 131 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 _mm_mul_ps(_mm_load_ps(src + i), m_scale))); | 172 _mm_mul_ps(_mm_load_ps(src + i), m_scale))); |
184 } | 173 } |
185 | 174 |
186 // Handle any remaining values that wouldn't fit in an SSE pass. | 175 // Handle any remaining values that wouldn't fit in an SSE pass. |
187 if (rem) | 176 if (rem) |
188 VectorFMAC_C(src + len - rem, scale, rem, dest + len - rem); | 177 VectorFMAC_C(src + len - rem, scale, rem, dest + len - rem); |
189 } | 178 } |
190 #endif | 179 #endif |
191 | 180 |
192 } // namespace media | 181 } // namespace media |
OLD | NEW |