| 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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 } | 138 } |
| 139 | 139 |
| 140 } // namespace | 140 } // namespace |
| 141 | 141 |
| 142 AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter) | 142 AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter) |
| 143 : audio_source_list_(), | 143 : audio_source_list_(), |
| 144 use_limiter_(true), | 144 use_limiter_(true), |
| 145 time_stamp_(0), | 145 time_stamp_(0), |
| 146 limiter_(std::move(limiter)) { | 146 limiter_(std::move(limiter)) { |
| 147 SetOutputFrequency(kDefaultFrequency); | 147 SetOutputFrequency(kDefaultFrequency); |
| 148 thread_checker_.DetachFromThread(); | |
| 149 } | 148 } |
| 150 | 149 |
| 151 AudioMixerImpl::~AudioMixerImpl() {} | 150 AudioMixerImpl::~AudioMixerImpl() {} |
| 152 | 151 |
| 153 rtc::scoped_refptr<AudioMixerImpl> AudioMixerImpl::Create() { | 152 rtc::scoped_refptr<AudioMixerImpl> AudioMixerImpl::Create() { |
| 154 Config config; | 153 Config config; |
| 155 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); | 154 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); |
| 156 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); | 155 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); |
| 157 if (!limiter.get()) { | 156 if (!limiter.get()) { |
| 158 return nullptr; | 157 return nullptr; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 184 } | 183 } |
| 185 | 184 |
| 186 return rtc::scoped_refptr<AudioMixerImpl>( | 185 return rtc::scoped_refptr<AudioMixerImpl>( |
| 187 new rtc::RefCountedObject<AudioMixerImpl>(std::move(limiter))); | 186 new rtc::RefCountedObject<AudioMixerImpl>(std::move(limiter))); |
| 188 } | 187 } |
| 189 | 188 |
| 190 void AudioMixerImpl::Mix(int sample_rate, | 189 void AudioMixerImpl::Mix(int sample_rate, |
| 191 size_t number_of_channels, | 190 size_t number_of_channels, |
| 192 AudioFrame* audio_frame_for_mixing) { | 191 AudioFrame* audio_frame_for_mixing) { |
| 193 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); | 192 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); |
| 194 RTC_DCHECK_RUN_ON(&thread_checker_); | 193 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); |
| 195 | 194 |
| 196 if (OutputFrequency() != sample_rate) { | 195 if (OutputFrequency() != sample_rate) { |
| 197 SetOutputFrequency(sample_rate); | 196 SetOutputFrequency(sample_rate); |
| 198 } | 197 } |
| 199 | 198 |
| 200 AudioFrameList mix_list; | 199 AudioFrameList mix_list; |
| 201 { | 200 { |
| 202 rtc::CritScope lock(&crit_); | 201 rtc::CritScope lock(&crit_); |
| 203 mix_list = GetAudioFromSources(); | 202 mix_list = GetAudioFromSources(); |
| 204 } | 203 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 224 audio_frame_for_mixing->Mute(); | 223 audio_frame_for_mixing->Mute(); |
| 225 } else { | 224 } else { |
| 226 // Only call the limiter if we have something to mix. | 225 // Only call the limiter if we have something to mix. |
| 227 LimitMixedAudio(audio_frame_for_mixing); | 226 LimitMixedAudio(audio_frame_for_mixing); |
| 228 } | 227 } |
| 229 | 228 |
| 230 return; | 229 return; |
| 231 } | 230 } |
| 232 | 231 |
| 233 void AudioMixerImpl::SetOutputFrequency(int frequency) { | 232 void AudioMixerImpl::SetOutputFrequency(int frequency) { |
| 234 RTC_DCHECK_RUN_ON(&thread_checker_); | 233 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); |
| 235 output_frequency_ = frequency; | 234 output_frequency_ = frequency; |
| 236 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000; | 235 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000; |
| 237 } | 236 } |
| 238 | 237 |
| 239 int AudioMixerImpl::OutputFrequency() const { | 238 int AudioMixerImpl::OutputFrequency() const { |
| 240 RTC_DCHECK_RUN_ON(&thread_checker_); | 239 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); |
| 241 return output_frequency_; | 240 return output_frequency_; |
| 242 } | 241 } |
| 243 | 242 |
| 244 bool AudioMixerImpl::AddSource(Source* audio_source) { | 243 bool AudioMixerImpl::AddSource(Source* audio_source) { |
| 245 RTC_DCHECK(audio_source); | 244 RTC_DCHECK(audio_source); |
| 246 rtc::CritScope lock(&crit_); | 245 rtc::CritScope lock(&crit_); |
| 247 RTC_DCHECK(FindSourceInList(audio_source, &audio_source_list_) == | 246 RTC_DCHECK(FindSourceInList(audio_source, &audio_source_list_) == |
| 248 audio_source_list_.end()) | 247 audio_source_list_.end()) |
| 249 << "Source already added to mixer"; | 248 << "Source already added to mixer"; |
| 250 audio_source_list_.emplace_back(new SourceStatus(audio_source, false, 0)); | 249 audio_source_list_.emplace_back(new SourceStatus(audio_source, false, 0)); |
| 251 return true; | 250 return true; |
| 252 } | 251 } |
| 253 | 252 |
| 254 bool AudioMixerImpl::RemoveSource(Source* audio_source) { | 253 bool AudioMixerImpl::RemoveSource(Source* audio_source) { |
| 255 RTC_DCHECK(audio_source); | 254 RTC_DCHECK(audio_source); |
| 256 rtc::CritScope lock(&crit_); | 255 rtc::CritScope lock(&crit_); |
| 257 const auto iter = FindSourceInList(audio_source, &audio_source_list_); | 256 const auto iter = FindSourceInList(audio_source, &audio_source_list_); |
| 258 RTC_DCHECK(iter != audio_source_list_.end()) << "Source not present in mixer"; | 257 RTC_DCHECK(iter != audio_source_list_.end()) << "Source not present in mixer"; |
| 259 audio_source_list_.erase(iter); | 258 audio_source_list_.erase(iter); |
| 260 return true; | 259 return true; |
| 261 } | 260 } |
| 262 | 261 |
| 263 AudioFrameList AudioMixerImpl::GetAudioFromSources() { | 262 AudioFrameList AudioMixerImpl::GetAudioFromSources() { |
| 264 RTC_DCHECK_RUN_ON(&thread_checker_); | 263 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); |
| 265 AudioFrameList result; | 264 AudioFrameList result; |
| 266 std::vector<SourceFrame> audio_source_mixing_data_list; | 265 std::vector<SourceFrame> audio_source_mixing_data_list; |
| 267 std::vector<SourceFrame> ramp_list; | 266 std::vector<SourceFrame> ramp_list; |
| 268 | 267 |
| 269 // Get audio from the audio sources and put it in the SourceFrame vector. | 268 // Get audio from the audio sources and put it in the SourceFrame vector. |
| 270 for (auto& source_and_status : audio_source_list_) { | 269 for (auto& source_and_status : audio_source_list_) { |
| 271 const auto audio_frame_info = | 270 const auto audio_frame_info = |
| 272 source_and_status->audio_source->GetAudioFrameWithInfo( | 271 source_and_status->audio_source->GetAudioFrameWithInfo( |
| 273 OutputFrequency(), &source_and_status->audio_frame); | 272 OutputFrequency(), &source_and_status->audio_frame); |
| 274 | 273 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 304 is_mixed = true; | 303 is_mixed = true; |
| 305 } | 304 } |
| 306 p.source_status->is_mixed = is_mixed; | 305 p.source_status->is_mixed = is_mixed; |
| 307 } | 306 } |
| 308 RampAndUpdateGain(ramp_list); | 307 RampAndUpdateGain(ramp_list); |
| 309 return result; | 308 return result; |
| 310 } | 309 } |
| 311 | 310 |
| 312 | 311 |
| 313 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { | 312 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { |
| 314 RTC_DCHECK_RUN_ON(&thread_checker_); | 313 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); |
| 315 if (!use_limiter_) { | 314 if (!use_limiter_) { |
| 316 return true; | 315 return true; |
| 317 } | 316 } |
| 318 | 317 |
| 319 // Smoothly limit the mixed frame. | 318 // Smoothly limit the mixed frame. |
| 320 const int error = limiter_->ProcessStream(mixed_audio); | 319 const int error = limiter_->ProcessStream(mixed_audio); |
| 321 | 320 |
| 322 // And now we can safely restore the level. This procedure results in | 321 // And now we can safely restore the level. This procedure results in |
| 323 // some loss of resolution, deemed acceptable. | 322 // some loss of resolution, deemed acceptable. |
| 324 // | 323 // |
| 325 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS | 324 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS |
| 326 // and compression gain of 6 dB). However, in the transition frame when this | 325 // and compression gain of 6 dB). However, in the transition frame when this |
| 327 // is enabled (moving from one to two audio sources) it has the potential to | 326 // is enabled (moving from one to two audio sources) it has the potential to |
| 328 // create discontinuities in the mixed frame. | 327 // create discontinuities in the mixed frame. |
| 329 // | 328 // |
| 330 // Instead we double the frame (with addition since left-shifting a | 329 // Instead we double the frame (with addition since left-shifting a |
| 331 // negative value is undefined). | 330 // negative value is undefined). |
| 332 *mixed_audio += *mixed_audio; | 331 *mixed_audio += *mixed_audio; |
| 333 | 332 |
| 334 if (error != limiter_->kNoError) { | 333 if (error != limiter_->kNoError) { |
| 335 LOG_F(LS_ERROR) << "Error from AudioProcessing: " << error; | 334 LOG_F(LS_ERROR) << "Error from AudioProcessing: " << error; |
| 336 RTC_NOTREACHED(); | 335 RTC_NOTREACHED(); |
| 337 return false; | 336 return false; |
| 338 } | 337 } |
| 339 return true; | 338 return true; |
| 340 } | 339 } |
| 341 | 340 |
| 342 bool AudioMixerImpl::GetAudioSourceMixabilityStatusForTest( | 341 bool AudioMixerImpl::GetAudioSourceMixabilityStatusForTest( |
| 343 AudioMixerImpl::Source* audio_source) const { | 342 AudioMixerImpl::Source* audio_source) const { |
| 344 RTC_DCHECK_RUN_ON(&thread_checker_); | 343 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); |
| 345 rtc::CritScope lock(&crit_); | 344 rtc::CritScope lock(&crit_); |
| 346 | 345 |
| 347 const auto iter = FindSourceInList(audio_source, &audio_source_list_); | 346 const auto iter = FindSourceInList(audio_source, &audio_source_list_); |
| 348 if (iter != audio_source_list_.end()) { | 347 if (iter != audio_source_list_.end()) { |
| 349 return (*iter)->is_mixed; | 348 return (*iter)->is_mixed; |
| 350 } | 349 } |
| 351 | 350 |
| 352 LOG(LS_ERROR) << "Audio source unknown"; | 351 LOG(LS_ERROR) << "Audio source unknown"; |
| 353 return false; | 352 return false; |
| 354 } | 353 } |
| 355 } // namespace webrtc | 354 } // namespace webrtc |
| OLD | NEW |