OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 AudioMixerImpl::Source const* audio_source, | 130 AudioMixerImpl::Source const* audio_source, |
131 AudioMixerImpl::SourceStatusList* audio_source_list) { | 131 AudioMixerImpl::SourceStatusList* audio_source_list) { |
132 return std::find_if(audio_source_list->begin(), audio_source_list->end(), | 132 return std::find_if(audio_source_list->begin(), audio_source_list->end(), |
133 [audio_source](const AudioMixerImpl::SourceStatus& p) { | 133 [audio_source](const AudioMixerImpl::SourceStatus& p) { |
134 return p.audio_source == audio_source; | 134 return p.audio_source == audio_source; |
135 }); | 135 }); |
136 } | 136 } |
137 | 137 |
138 } // namespace | 138 } // namespace |
139 | 139 |
140 std::unique_ptr<AudioMixer> AudioMixer::Create() { | |
141 return AudioMixerImpl::Create(); | |
142 } | |
143 | |
144 AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter) | 140 AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter) |
145 : audio_source_list_(), | 141 : audio_source_list_(), |
146 num_mixed_audio_sources_(0), | |
147 use_limiter_(true), | 142 use_limiter_(true), |
148 time_stamp_(0), | 143 time_stamp_(0), |
149 limiter_(std::move(limiter)) { | 144 limiter_(std::move(limiter)) { |
150 SetOutputFrequency(kDefaultFrequency); | 145 SetOutputFrequency(kDefaultFrequency); |
151 thread_checker_.DetachFromThread(); | 146 thread_checker_.DetachFromThread(); |
152 } | 147 } |
153 | 148 |
154 AudioMixerImpl::~AudioMixerImpl() {} | 149 AudioMixerImpl::~AudioMixerImpl() {} |
155 | 150 |
156 std::unique_ptr<AudioMixerImpl> AudioMixerImpl::Create() { | 151 rtc::scoped_refptr<AudioMixerImpl> AudioMixerImpl::Create() { |
157 Config config; | 152 Config config; |
158 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); | 153 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); |
159 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); | 154 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); |
160 if (!limiter.get()) { | 155 if (!limiter.get()) { |
161 return nullptr; | 156 return nullptr; |
162 } | 157 } |
163 | 158 |
164 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) != | 159 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) != |
165 limiter->kNoError) { | 160 limiter->kNoError) { |
166 return nullptr; | 161 return nullptr; |
(...skipping 12 matching lines...) Expand all Loading... |
179 } | 174 } |
180 | 175 |
181 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) { | 176 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) { |
182 return nullptr; | 177 return nullptr; |
183 } | 178 } |
184 | 179 |
185 if (limiter->gain_control()->Enable(true) != limiter->kNoError) { | 180 if (limiter->gain_control()->Enable(true) != limiter->kNoError) { |
186 return nullptr; | 181 return nullptr; |
187 } | 182 } |
188 | 183 |
189 return std::unique_ptr<AudioMixerImpl>( | 184 return rtc::scoped_refptr<AudioMixerImpl>( |
190 new AudioMixerImpl(std::move(limiter))); | 185 new rtc::RefCountedObject<AudioMixerImpl>(std::move(limiter))); |
191 } | 186 } |
192 | 187 |
193 void AudioMixerImpl::Mix(int sample_rate, | 188 void AudioMixerImpl::Mix(int sample_rate, |
194 size_t number_of_channels, | 189 size_t number_of_channels, |
195 AudioFrame* audio_frame_for_mixing) { | 190 AudioFrame* audio_frame_for_mixing) { |
196 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); | 191 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); |
197 RTC_DCHECK_RUN_ON(&thread_checker_); | 192 RTC_DCHECK_RUN_ON(&thread_checker_); |
198 | 193 |
199 if (OutputFrequency() != sample_rate) { | 194 if (OutputFrequency() != sample_rate) { |
200 SetOutputFrequency(sample_rate); | 195 SetOutputFrequency(sample_rate); |
201 } | 196 } |
202 | 197 |
203 AudioFrameList mix_list; | 198 AudioFrameList mix_list; |
204 size_t num_mixed_audio_sources; | |
205 { | 199 { |
206 rtc::CritScope lock(&crit_); | 200 rtc::CritScope lock(&crit_); |
207 mix_list = GetNonAnonymousAudio(); | 201 mix_list = GetAudioFromSources(); |
208 num_mixed_audio_sources = num_mixed_audio_sources_; | |
209 } | 202 } |
210 | 203 |
211 for (const auto& frame : mix_list) { | 204 for (const auto& frame : mix_list) { |
212 RemixFrame(number_of_channels, frame); | 205 RemixFrame(number_of_channels, frame); |
213 } | 206 } |
214 | 207 |
215 audio_frame_for_mixing->UpdateFrame( | 208 audio_frame_for_mixing->UpdateFrame( |
216 -1, time_stamp_, NULL, 0, OutputFrequency(), AudioFrame::kNormalSpeech, | 209 -1, time_stamp_, NULL, 0, OutputFrequency(), AudioFrame::kNormalSpeech, |
217 AudioFrame::kVadPassive, number_of_channels); | 210 AudioFrame::kVadPassive, number_of_channels); |
218 | 211 |
219 time_stamp_ += static_cast<uint32_t>(sample_size_); | 212 time_stamp_ += static_cast<uint32_t>(sample_size_); |
220 | 213 |
221 use_limiter_ = num_mixed_audio_sources > 1; | 214 use_limiter_ = mix_list.size() > 1; |
222 | 215 |
223 // We only use the limiter if we're actually mixing multiple streams. | 216 // We only use the limiter if we're actually mixing multiple streams. |
224 MixFromList(audio_frame_for_mixing, mix_list, use_limiter_); | 217 MixFromList(audio_frame_for_mixing, mix_list, use_limiter_); |
225 | 218 |
226 if (audio_frame_for_mixing->samples_per_channel_ == 0) { | 219 if (audio_frame_for_mixing->samples_per_channel_ == 0) { |
227 // Nothing was mixed, set the audio samples to silence. | 220 // Nothing was mixed, set the audio samples to silence. |
228 audio_frame_for_mixing->samples_per_channel_ = sample_size_; | 221 audio_frame_for_mixing->samples_per_channel_ = sample_size_; |
229 audio_frame_for_mixing->Mute(); | 222 audio_frame_for_mixing->Mute(); |
230 } else { | 223 } else { |
231 // Only call the limiter if we have something to mix. | 224 // Only call the limiter if we have something to mix. |
232 LimitMixedAudio(audio_frame_for_mixing); | 225 LimitMixedAudio(audio_frame_for_mixing); |
233 } | 226 } |
234 | 227 |
235 return; | 228 return; |
236 } | 229 } |
237 | 230 |
238 void AudioMixerImpl::SetOutputFrequency(int frequency) { | 231 void AudioMixerImpl::SetOutputFrequency(int frequency) { |
239 RTC_DCHECK_RUN_ON(&thread_checker_); | 232 RTC_DCHECK_RUN_ON(&thread_checker_); |
240 output_frequency_ = frequency; | 233 output_frequency_ = frequency; |
241 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000; | 234 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000; |
242 } | 235 } |
243 | 236 |
244 int AudioMixerImpl::OutputFrequency() const { | 237 int AudioMixerImpl::OutputFrequency() const { |
245 RTC_DCHECK_RUN_ON(&thread_checker_); | 238 RTC_DCHECK_RUN_ON(&thread_checker_); |
246 return output_frequency_; | 239 return output_frequency_; |
247 } | 240 } |
248 | 241 |
249 int32_t AudioMixerImpl::SetMixabilityStatus(Source* audio_source, | 242 bool AudioMixerImpl::AddSource(Source* audio_source) { |
250 bool mixable) { | 243 RTC_DCHECK(audio_source); |
251 { | 244 rtc::CritScope lock(&crit_); |
252 rtc::CritScope lock(&crit_); | 245 RTC_DCHECK(FindSourceInList(audio_source, &audio_source_list_) == |
253 const bool is_mixed = FindSourceInList(audio_source, &audio_source_list_) != | 246 audio_source_list_.end()) |
254 audio_source_list_.end(); | 247 << "Source already added to mixer"; |
255 // API must be called with a new state. | 248 audio_source_list_.emplace_back(audio_source, false, 0); |
256 if (!(mixable ^ is_mixed)) { | 249 return true; |
257 return -1; | |
258 } | |
259 bool success = false; | |
260 if (mixable) { | |
261 success = AddAudioSourceToList(audio_source, &audio_source_list_); | |
262 } else { | |
263 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_); | |
264 } | |
265 if (!success) { | |
266 RTC_NOTREACHED(); | |
267 return -1; | |
268 } | |
269 | |
270 size_t num_mixed_non_anonymous = audio_source_list_.size(); | |
271 if (num_mixed_non_anonymous > kMaximumAmountOfMixedAudioSources) { | |
272 num_mixed_non_anonymous = kMaximumAmountOfMixedAudioSources; | |
273 } | |
274 num_mixed_audio_sources_ = num_mixed_non_anonymous; | |
275 } | |
276 return 0; | |
277 } | 250 } |
278 | 251 |
| 252 bool AudioMixerImpl::RemoveSource(Source* audio_source) { |
| 253 RTC_DCHECK(audio_source); |
| 254 rtc::CritScope lock(&crit_); |
| 255 const auto iter = FindSourceInList(audio_source, &audio_source_list_); |
| 256 RTC_DCHECK(iter != audio_source_list_.end()) << "Source not present in mixer"; |
| 257 audio_source_list_.erase(iter); |
| 258 return true; |
| 259 } |
279 | 260 |
280 | 261 AudioFrameList AudioMixerImpl::GetAudioFromSources() { |
281 AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() { | |
282 RTC_DCHECK_RUN_ON(&thread_checker_); | 262 RTC_DCHECK_RUN_ON(&thread_checker_); |
283 AudioFrameList result; | 263 AudioFrameList result; |
284 std::vector<SourceFrame> audio_source_mixing_data_list; | 264 std::vector<SourceFrame> audio_source_mixing_data_list; |
285 std::vector<SourceFrame> ramp_list; | 265 std::vector<SourceFrame> ramp_list; |
286 | 266 |
287 // Get audio source audio and put it in the struct vector. | 267 // Get audio source audio and put it in the struct vector. |
288 for (auto& source_and_status : audio_source_list_) { | 268 for (auto& source_and_status : audio_source_list_) { |
289 auto audio_frame_with_info = | 269 auto audio_frame_with_info = |
290 source_and_status.audio_source->GetAudioFrameWithInfo( | 270 source_and_status.audio_source->GetAudioFrameWithInfo( |
291 static_cast<int>(OutputFrequency())); | 271 static_cast<int>(OutputFrequency())); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 result.push_back(p.audio_frame); | 303 result.push_back(p.audio_frame); |
324 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1); | 304 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1); |
325 is_mixed = true; | 305 is_mixed = true; |
326 } | 306 } |
327 p.source_status->is_mixed = is_mixed; | 307 p.source_status->is_mixed = is_mixed; |
328 } | 308 } |
329 RampAndUpdateGain(ramp_list); | 309 RampAndUpdateGain(ramp_list); |
330 return result; | 310 return result; |
331 } | 311 } |
332 | 312 |
333 bool AudioMixerImpl::AddAudioSourceToList( | |
334 Source* audio_source, | |
335 SourceStatusList* audio_source_list) const { | |
336 audio_source_list->emplace_back(audio_source, false, 0); | |
337 return true; | |
338 } | |
339 | |
340 bool AudioMixerImpl::RemoveAudioSourceFromList( | |
341 Source* audio_source, | |
342 SourceStatusList* audio_source_list) const { | |
343 const auto iter = FindSourceInList(audio_source, audio_source_list); | |
344 if (iter != audio_source_list->end()) { | |
345 audio_source_list->erase(iter); | |
346 return true; | |
347 } else { | |
348 return false; | |
349 } | |
350 } | |
351 | 313 |
352 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { | 314 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { |
353 RTC_DCHECK_RUN_ON(&thread_checker_); | 315 RTC_DCHECK_RUN_ON(&thread_checker_); |
354 if (!use_limiter_) { | 316 if (!use_limiter_) { |
355 return true; | 317 return true; |
356 } | 318 } |
357 | 319 |
358 // Smoothly limit the mixed frame. | 320 // Smoothly limit the mixed frame. |
359 const int error = limiter_->ProcessStream(mixed_audio); | 321 const int error = limiter_->ProcessStream(mixed_audio); |
360 | 322 |
(...skipping 25 matching lines...) Expand all Loading... |
386 const auto non_anonymous_iter = | 348 const auto non_anonymous_iter = |
387 FindSourceInList(audio_source, &audio_source_list_); | 349 FindSourceInList(audio_source, &audio_source_list_); |
388 if (non_anonymous_iter != audio_source_list_.end()) { | 350 if (non_anonymous_iter != audio_source_list_.end()) { |
389 return non_anonymous_iter->is_mixed; | 351 return non_anonymous_iter->is_mixed; |
390 } | 352 } |
391 | 353 |
392 LOG(LS_ERROR) << "Audio source unknown"; | 354 LOG(LS_ERROR) << "Audio source unknown"; |
393 return false; | 355 return false; |
394 } | 356 } |
395 } // namespace webrtc | 357 } // namespace webrtc |
OLD | NEW |