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 |
11 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h" | 11 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <functional> | 14 #include <functional> |
| 15 #include <iterator> |
15 #include <utility> | 16 #include <utility> |
16 | 17 |
17 #include "webrtc/audio/utility/audio_frame_operations.h" | 18 #include "webrtc/audio/utility/audio_frame_operations.h" |
18 #include "webrtc/base/logging.h" | 19 #include "webrtc/base/logging.h" |
19 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h" | 20 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h" |
| 21 #include "webrtc/modules/audio_mixer/default_output_rate_calculator.h" |
20 | 22 |
21 namespace webrtc { | 23 namespace webrtc { |
22 namespace { | 24 namespace { |
23 | 25 |
24 struct SourceFrame { | 26 struct SourceFrame { |
25 SourceFrame(AudioMixerImpl::SourceStatus* source_status, | 27 SourceFrame(AudioMixerImpl::SourceStatus* source_status, |
26 AudioFrame* audio_frame, | 28 AudioFrame* audio_frame, |
27 bool muted) | 29 bool muted) |
28 : source_status(source_status), audio_frame(audio_frame), muted(muted) { | 30 : source_status(source_status), audio_frame(audio_frame), muted(muted) { |
29 RTC_DCHECK(source_status); | 31 RTC_DCHECK(source_status); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 AudioMixerImpl::SourceStatusList::iterator FindSourceInList( | 132 AudioMixerImpl::SourceStatusList::iterator FindSourceInList( |
131 AudioMixerImpl::Source const* audio_source, | 133 AudioMixerImpl::Source const* audio_source, |
132 AudioMixerImpl::SourceStatusList* audio_source_list) { | 134 AudioMixerImpl::SourceStatusList* audio_source_list) { |
133 return std::find_if( | 135 return std::find_if( |
134 audio_source_list->begin(), audio_source_list->end(), | 136 audio_source_list->begin(), audio_source_list->end(), |
135 [audio_source](const std::unique_ptr<AudioMixerImpl::SourceStatus>& p) { | 137 [audio_source](const std::unique_ptr<AudioMixerImpl::SourceStatus>& p) { |
136 return p->audio_source == audio_source; | 138 return p->audio_source == audio_source; |
137 }); | 139 }); |
138 } | 140 } |
139 | 141 |
140 // Rounds the maximal audio source frequency up to an APM-native | 142 std::unique_ptr<AudioProcessing> CreateLimiter() { |
141 // frequency. | |
142 int CalculateMixingFrequency( | |
143 const AudioMixerImpl::SourceStatusList& audio_source_list) { | |
144 if (audio_source_list.empty()) { | |
145 return AudioMixerImpl::kDefaultFrequency; | |
146 } | |
147 using NativeRate = AudioProcessing::NativeRate; | |
148 int maximal_frequency = 0; | |
149 for (const auto& source_status : audio_source_list) { | |
150 const int source_needed_frequency = | |
151 source_status->audio_source->PreferredSampleRate(); | |
152 RTC_DCHECK_LE(NativeRate::kSampleRate8kHz, source_needed_frequency); | |
153 RTC_DCHECK_LE(source_needed_frequency, NativeRate::kSampleRate48kHz); | |
154 maximal_frequency = std::max(maximal_frequency, source_needed_frequency); | |
155 } | |
156 | |
157 static constexpr NativeRate native_rates[] = { | |
158 NativeRate::kSampleRate8kHz, NativeRate::kSampleRate16kHz, | |
159 NativeRate::kSampleRate32kHz, NativeRate::kSampleRate48kHz}; | |
160 const auto rounded_up_index = std::lower_bound( | |
161 std::begin(native_rates), std::end(native_rates), maximal_frequency); | |
162 RTC_DCHECK(rounded_up_index != std::end(native_rates)); | |
163 return *rounded_up_index; | |
164 } | |
165 | |
166 } // namespace | |
167 | |
168 AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter) | |
169 : audio_source_list_(), | |
170 use_limiter_(true), | |
171 time_stamp_(0), | |
172 limiter_(std::move(limiter)) { | |
173 SetOutputFrequency(kDefaultFrequency); | |
174 } | |
175 | |
176 AudioMixerImpl::~AudioMixerImpl() {} | |
177 | |
178 rtc::scoped_refptr<AudioMixerImpl> AudioMixerImpl::Create() { | |
179 Config config; | 143 Config config; |
180 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); | 144 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); |
181 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); | 145 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); |
182 if (!limiter.get()) { | 146 if (!limiter.get()) { |
183 return nullptr; | 147 return nullptr; |
184 } | 148 } |
185 | 149 |
186 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) != | 150 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) != |
187 limiter->kNoError) { | 151 limiter->kNoError) { |
188 return nullptr; | 152 return nullptr; |
(...skipping 11 matching lines...) Expand all Loading... |
200 return nullptr; | 164 return nullptr; |
201 } | 165 } |
202 | 166 |
203 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) { | 167 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) { |
204 return nullptr; | 168 return nullptr; |
205 } | 169 } |
206 | 170 |
207 if (limiter->gain_control()->Enable(true) != limiter->kNoError) { | 171 if (limiter->gain_control()->Enable(true) != limiter->kNoError) { |
208 return nullptr; | 172 return nullptr; |
209 } | 173 } |
| 174 return limiter; |
| 175 } |
210 | 176 |
| 177 } // namespace |
| 178 |
| 179 AudioMixerImpl::AudioMixerImpl( |
| 180 std::unique_ptr<AudioProcessing> limiter, |
| 181 std::unique_ptr<OutputRateCalculator> output_rate_calculator) |
| 182 : output_rate_calculator_(std::move(output_rate_calculator)), |
| 183 output_frequency_(0), |
| 184 sample_size_(0), |
| 185 audio_source_list_(), |
| 186 use_limiter_(true), |
| 187 time_stamp_(0), |
| 188 limiter_(std::move(limiter)) {} |
| 189 |
| 190 AudioMixerImpl::~AudioMixerImpl() {} |
| 191 |
| 192 rtc::scoped_refptr<AudioMixerImpl> AudioMixerImpl::Create() { |
| 193 return CreateWithOutputRateCalculator( |
| 194 std::unique_ptr<DefaultOutputRateCalculator>( |
| 195 new DefaultOutputRateCalculator())); |
| 196 } |
| 197 |
| 198 rtc::scoped_refptr<AudioMixerImpl> |
| 199 AudioMixerImpl::CreateWithOutputRateCalculator( |
| 200 std::unique_ptr<OutputRateCalculator> output_rate_calculator) { |
211 return rtc::scoped_refptr<AudioMixerImpl>( | 201 return rtc::scoped_refptr<AudioMixerImpl>( |
212 new rtc::RefCountedObject<AudioMixerImpl>(std::move(limiter))); | 202 new rtc::RefCountedObject<AudioMixerImpl>( |
| 203 CreateLimiter(), std::move(output_rate_calculator))); |
213 } | 204 } |
214 | 205 |
215 void AudioMixerImpl::Mix(size_t number_of_channels, | 206 void AudioMixerImpl::Mix(size_t number_of_channels, |
216 AudioFrame* audio_frame_for_mixing) { | 207 AudioFrame* audio_frame_for_mixing) { |
217 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); | 208 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); |
218 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); | 209 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); |
219 | 210 |
220 const int sample_rate = [&]() { | 211 CalculateOutputFrequency(); |
221 rtc::CritScope lock(&crit_); | |
222 return CalculateMixingFrequency(audio_source_list_); | |
223 }(); | |
224 | |
225 if (OutputFrequency() != sample_rate) { | |
226 SetOutputFrequency(sample_rate); | |
227 } | |
228 | 212 |
229 AudioFrameList mix_list; | 213 AudioFrameList mix_list; |
230 { | 214 { |
231 rtc::CritScope lock(&crit_); | 215 rtc::CritScope lock(&crit_); |
232 mix_list = GetAudioFromSources(); | 216 mix_list = GetAudioFromSources(); |
233 | 217 |
234 for (const auto& frame : mix_list) { | 218 for (const auto& frame : mix_list) { |
235 RemixFrame(number_of_channels, frame); | 219 RemixFrame(number_of_channels, frame); |
236 } | 220 } |
237 | 221 |
(...skipping 14 matching lines...) Expand all Loading... |
252 audio_frame_for_mixing->samples_per_channel_ = sample_size_; | 236 audio_frame_for_mixing->samples_per_channel_ = sample_size_; |
253 AudioFrameOperations::Mute(audio_frame_for_mixing); | 237 AudioFrameOperations::Mute(audio_frame_for_mixing); |
254 } else { | 238 } else { |
255 // Only call the limiter if we have something to mix. | 239 // Only call the limiter if we have something to mix. |
256 LimitMixedAudio(audio_frame_for_mixing); | 240 LimitMixedAudio(audio_frame_for_mixing); |
257 } | 241 } |
258 | 242 |
259 return; | 243 return; |
260 } | 244 } |
261 | 245 |
262 void AudioMixerImpl::SetOutputFrequency(int frequency) { | 246 void AudioMixerImpl::CalculateOutputFrequency() { |
263 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); | 247 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); |
264 output_frequency_ = frequency; | 248 rtc::CritScope lock(&crit_); |
| 249 |
| 250 std::vector<int> preferred_rates; |
| 251 std::transform(audio_source_list_.begin(), audio_source_list_.end(), |
| 252 std::back_inserter(preferred_rates), |
| 253 [&](std::unique_ptr<SourceStatus>& a) { |
| 254 return a->audio_source->PreferredSampleRate(); |
| 255 }); |
| 256 |
| 257 output_frequency_ = |
| 258 output_rate_calculator_->CalculateOutputRate(preferred_rates); |
265 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000; | 259 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000; |
266 } | 260 } |
267 | 261 |
268 int AudioMixerImpl::OutputFrequency() const { | 262 int AudioMixerImpl::OutputFrequency() const { |
269 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); | 263 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); |
270 return output_frequency_; | 264 return output_frequency_; |
271 } | 265 } |
272 | 266 |
273 bool AudioMixerImpl::AddSource(Source* audio_source) { | 267 bool AudioMixerImpl::AddSource(Source* audio_source) { |
274 RTC_DCHECK(audio_source); | 268 RTC_DCHECK(audio_source); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 | 368 |
375 const auto iter = FindSourceInList(audio_source, &audio_source_list_); | 369 const auto iter = FindSourceInList(audio_source, &audio_source_list_); |
376 if (iter != audio_source_list_.end()) { | 370 if (iter != audio_source_list_.end()) { |
377 return (*iter)->is_mixed; | 371 return (*iter)->is_mixed; |
378 } | 372 } |
379 | 373 |
380 LOG(LS_ERROR) << "Audio source unknown"; | 374 LOG(LS_ERROR) << "Audio source unknown"; |
381 return false; | 375 return false; |
382 } | 376 } |
383 } // namespace webrtc | 377 } // namespace webrtc |
OLD | NEW |