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/source/new_audio_conference_mixer_impl.h" | 11 #include "webrtc/modules/audio_mixer/source/new_audio_conference_mixer_impl.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <functional> | 14 #include <functional> |
15 | 15 |
16 #include "webrtc/modules/audio_conference_mixer/source/audio_frame_manipulator.h " | 16 #include "webrtc/modules/audio_conference_mixer/source/audio_frame_manipulator.h " |
17 #include "webrtc/modules/audio_mixer/include/audio_mixer_defines.h" | 17 #include "webrtc/modules/audio_mixer/include/audio_mixer_defines.h" |
18 #include "webrtc/modules/audio_processing/include/audio_processing.h" | 18 #include "webrtc/modules/audio_processing/include/audio_processing.h" |
19 #include "webrtc/modules/utility/include/audio_frame_operations.h" | 19 #include "webrtc/modules/utility/include/audio_frame_operations.h" |
20 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | 20 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" |
21 #include "webrtc/system_wrappers/include/trace.h" | 21 #include "webrtc/system_wrappers/include/trace.h" |
22 #include "webrtc/voice_engine/utility.h" | |
22 | 23 |
23 namespace webrtc { | 24 namespace webrtc { |
24 namespace { | 25 namespace { |
25 | 26 |
26 class SourceFrame { | 27 class SourceFrame { |
27 public: | 28 public: |
28 SourceFrame(MixerAudioSource* p, AudioFrame* a, bool m, bool was_mixed_before) | 29 SourceFrame(MixerAudioSource* p, AudioFrame* a, bool m, bool was_mixed_before) |
29 : audio_source_(p), | 30 : audio_source_(p), |
30 audio_frame_(a), | 31 audio_frame_(a), |
31 muted_(m), | 32 muted_(m), |
(...skipping 19 matching lines...) Expand all Loading... | |
51 return energy_ > other.energy_; | 52 return energy_ > other.energy_; |
52 } | 53 } |
53 | 54 |
54 MixerAudioSource* audio_source_; | 55 MixerAudioSource* audio_source_; |
55 AudioFrame* audio_frame_; | 56 AudioFrame* audio_frame_; |
56 bool muted_; | 57 bool muted_; |
57 uint32_t energy_; | 58 uint32_t energy_; |
58 bool was_mixed_before_; | 59 bool was_mixed_before_; |
59 }; | 60 }; |
60 | 61 |
62 // Remixes a frame between stereo and mono. | |
aleloi2
2016/08/06 10:13:50
I couldn't find any function that does this in Web
| |
63 void RemixFrame(AudioFrame* frame, size_t number_of_channels) { | |
64 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); | |
65 if (frame->num_channels_ == 1 && number_of_channels == 2) { | |
66 AudioFrameOperations::MonoToStereo(frame); | |
67 } else if (frame->num_channels_ == 2 && number_of_channels == 1) { | |
68 AudioFrameOperations::StereoToMono(frame); | |
69 } | |
70 } | |
71 | |
61 // Mix |frame| into |mixed_frame|, with saturation protection and upmixing. | 72 // Mix |frame| into |mixed_frame|, with saturation protection and upmixing. |
62 // These effects are applied to |frame| itself prior to mixing. Assumes that | 73 // These effects are applied to |frame| itself prior to mixing. Assumes that |
63 // |mixed_frame| always has at least as many channels as |frame|. Supports | 74 // |mixed_frame| always has at least as many channels as |frame|. Supports |
64 // stereo at most. | 75 // stereo at most. |
65 // | 76 // |
66 // TODO(andrew): consider not modifying |frame| here. | 77 // TODO(andrew): consider not modifying |frame| here. |
67 void MixFrames(AudioFrame* mixed_frame, AudioFrame* frame, bool use_limiter) { | 78 void MixFrames(AudioFrame* mixed_frame, AudioFrame* frame, bool use_limiter) { |
68 RTC_DCHECK_GE(mixed_frame->num_channels_, frame->num_channels_); | 79 RTC_DCHECK_GE(mixed_frame->num_channels_, frame->num_channels_); |
69 if (use_limiter) { | 80 if (use_limiter) { |
70 // Divide by two to avoid saturation in the mixing. | 81 // Divide by two to avoid saturation in the mixing. |
71 // This is only meaningful if the limiter will be used. | 82 // This is only meaningful if the limiter will be used. |
72 *frame >>= 1; | 83 *frame >>= 1; |
73 } | 84 } |
74 if (mixed_frame->num_channels_ > frame->num_channels_) { | 85 RTC_DCHECK_EQ(frame->num_channels_, mixed_frame->num_channels_); |
75 // We only support mono-to-stereo. | |
76 RTC_DCHECK_EQ(mixed_frame->num_channels_, static_cast<size_t>(2)); | |
77 RTC_DCHECK_EQ(frame->num_channels_, static_cast<size_t>(1)); | |
78 AudioFrameOperations::MonoToStereo(frame); | |
79 } | |
80 | |
81 *mixed_frame += *frame; | 86 *mixed_frame += *frame; |
82 } | 87 } |
83 | 88 |
84 // Return the max number of channels from a |list| composed of AudioFrames. | |
85 size_t MaxNumChannels(const AudioFrameList* list) { | |
86 size_t max_num_channels = 1; | |
87 for (AudioFrameList::const_iterator iter = list->begin(); iter != list->end(); | |
88 ++iter) { | |
89 max_num_channels = std::max(max_num_channels, (*iter).frame->num_channels_); | |
90 } | |
91 return max_num_channels; | |
92 } | |
93 | |
94 } // namespace | 89 } // namespace |
95 | 90 |
96 MixerAudioSource::MixerAudioSource() : _mixHistory(new NewMixHistory()) {} | 91 MixerAudioSource::MixerAudioSource() : _mixHistory(new NewMixHistory()) {} |
97 | 92 |
98 MixerAudioSource::~MixerAudioSource() { | 93 MixerAudioSource::~MixerAudioSource() { |
99 delete _mixHistory; | 94 delete _mixHistory; |
100 } | 95 } |
101 | 96 |
102 bool MixerAudioSource::IsMixed() const { | 97 bool MixerAudioSource::IsMixed() const { |
103 return _mixHistory->IsMixed(); | 98 return _mixHistory->IsMixed(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 | 177 |
183 if (_limiter->gain_control()->enable_limiter(true) != _limiter->kNoError) | 178 if (_limiter->gain_control()->enable_limiter(true) != _limiter->kNoError) |
184 return false; | 179 return false; |
185 | 180 |
186 if (_limiter->gain_control()->Enable(true) != _limiter->kNoError) | 181 if (_limiter->gain_control()->Enable(true) != _limiter->kNoError) |
187 return false; | 182 return false; |
188 | 183 |
189 return true; | 184 return true; |
190 } | 185 } |
191 | 186 |
192 void NewAudioConferenceMixerImpl::Mix(AudioFrame* audio_frame_for_mixing) { | 187 void NewAudioConferenceMixerImpl::Mix(int sample_rate, |
188 size_t number_of_channels, | |
189 AudioFrame* audio_frame_for_mixing) { | |
190 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); | |
193 size_t remainingAudioSourcesAllowedToMix = kMaximumAmountOfMixedAudioSources; | 191 size_t remainingAudioSourcesAllowedToMix = kMaximumAmountOfMixedAudioSources; |
194 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 192 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
195 AudioFrameList mixList; | 193 AudioFrameList mixList; |
196 AudioFrameList additionalFramesList; | 194 AudioFrameList additionalFramesList; |
197 std::map<int, MixerAudioSource*> mixedAudioSourcesMap; | 195 std::map<int, MixerAudioSource*> mixedAudioSourcesMap; |
198 { | 196 { |
199 CriticalSectionScoped cs(_cbCrit.get()); | 197 CriticalSectionScoped cs(_cbCrit.get()); |
198 Frequency mixing_frequency; | |
200 | 199 |
201 int32_t lowFreq = GetLowestMixingFrequency(); | 200 switch (sample_rate) { |
202 // SILK can run in 12 kHz and 24 kHz. These frequencies are not | 201 case 8000: |
203 // supported so use the closest higher frequency to not lose any | 202 mixing_frequency = kNbInHz; |
204 // information. | 203 break; |
205 // TODO(aleloi): this is probably more appropriate to do in | 204 case 16000: |
206 // GetLowestMixingFrequency(). | 205 mixing_frequency = kWbInHz; |
207 if (lowFreq == 12000) { | 206 break; |
208 lowFreq = 16000; | 207 case 32000: |
209 } else if (lowFreq == 24000) { | 208 mixing_frequency = kSwbInHz; |
210 lowFreq = 32000; | 209 break; |
210 case 48000: | |
211 mixing_frequency = kFbInHz; | |
212 break; | |
213 default: | |
214 RTC_NOTREACHED(); | |
211 } | 215 } |
212 if (lowFreq <= 0) { | 216 |
213 return; | 217 if (OutputFrequency() != mixing_frequency) { |
214 } else { | 218 SetOutputFrequency(mixing_frequency); |
215 switch (lowFreq) { | |
216 case 8000: | |
217 if (OutputFrequency() != kNbInHz) { | |
218 SetOutputFrequency(kNbInHz); | |
219 } | |
220 break; | |
221 case 16000: | |
222 if (OutputFrequency() != kWbInHz) { | |
223 SetOutputFrequency(kWbInHz); | |
224 } | |
225 break; | |
226 case 32000: | |
227 if (OutputFrequency() != kSwbInHz) { | |
228 SetOutputFrequency(kSwbInHz); | |
229 } | |
230 break; | |
231 case 48000: | |
232 if (OutputFrequency() != kFbInHz) { | |
233 SetOutputFrequency(kFbInHz); | |
234 } | |
235 break; | |
236 default: | |
237 RTC_NOTREACHED(); | |
238 return; | |
239 } | |
240 } | 219 } |
241 | 220 |
242 mixList = UpdateToMix(remainingAudioSourcesAllowedToMix); | 221 mixList = UpdateToMix(remainingAudioSourcesAllowedToMix); |
243 remainingAudioSourcesAllowedToMix -= mixList.size(); | 222 remainingAudioSourcesAllowedToMix -= mixList.size(); |
244 GetAdditionalAudio(&additionalFramesList); | 223 GetAdditionalAudio(&additionalFramesList); |
245 } | 224 } |
246 | 225 |
247 // TODO(aleloi): it might be better to decide the number of channels | 226 for (FrameAndMuteInfo& frame_and_mute : mixList) { |
aleloi2
2016/08/06 10:13:50
Previously, all frames were up-mixed if a single o
| |
248 // with an API instead of dynamically. | 227 RemixFrame(frame_and_mute.frame, number_of_channels); |
249 | 228 } |
250 // Find the max channels over all mixing lists. | 229 for (FrameAndMuteInfo& frame_and_mute : additionalFramesList) { |
251 const size_t num_mixed_channels = | 230 RemixFrame(frame_and_mute.frame, number_of_channels); |
252 std::max(MaxNumChannels(&mixList), MaxNumChannels(&additionalFramesList)); | 231 } |
253 | 232 |
254 audio_frame_for_mixing->UpdateFrame( | 233 audio_frame_for_mixing->UpdateFrame( |
255 -1, _timeStamp, NULL, 0, _outputFrequency, AudioFrame::kNormalSpeech, | 234 -1, _timeStamp, NULL, 0, _outputFrequency, AudioFrame::kNormalSpeech, |
256 AudioFrame::kVadPassive, num_mixed_channels); | 235 AudioFrame::kVadPassive, number_of_channels); |
257 | 236 |
258 _timeStamp += static_cast<uint32_t>(_sampleSize); | 237 _timeStamp += static_cast<uint32_t>(_sampleSize); |
259 | 238 |
260 use_limiter_ = num_mixed_audio_sources_ > 1 && | 239 use_limiter_ = num_mixed_audio_sources_ > 1 && |
261 _outputFrequency <= AudioProcessing::kMaxNativeSampleRateHz; | 240 _outputFrequency <= AudioProcessing::kMaxNativeSampleRateHz; |
262 | 241 |
263 // We only use the limiter if it supports the output sample rate and | 242 // We only use the limiter if it supports the output sample rate and |
264 // we're actually mixing multiple streams. | 243 // we're actually mixing multiple streams. |
265 MixFromList(audio_frame_for_mixing, mixList, _id, use_limiter_); | 244 MixFromList(audio_frame_for_mixing, mixList, _id, use_limiter_); |
266 | 245 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
404 _minimumMixingFreq = freq; | 383 _minimumMixingFreq = freq; |
405 return 0; | 384 return 0; |
406 } else { | 385 } else { |
407 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, | 386 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, |
408 "SetMinimumMixingFrequency incorrect frequency: %i", freq); | 387 "SetMinimumMixingFrequency incorrect frequency: %i", freq); |
409 RTC_NOTREACHED(); | 388 RTC_NOTREACHED(); |
410 return -1; | 389 return -1; |
411 } | 390 } |
412 } | 391 } |
413 | 392 |
414 // Check all AudioFrames that are to be mixed. The highest sampling frequency | |
415 // found is the lowest that can be used without losing information. | |
416 int32_t NewAudioConferenceMixerImpl::GetLowestMixingFrequency() const { | |
417 const int audioSourceListFrequency = | |
418 GetLowestMixingFrequencyFromList(audio_source_list_); | |
419 const int anonymousListFrequency = | |
420 GetLowestMixingFrequencyFromList(additional_audio_source_list_); | |
421 const int highestFreq = (audioSourceListFrequency > anonymousListFrequency) | |
422 ? audioSourceListFrequency | |
423 : anonymousListFrequency; | |
424 // Check if the user specified a lowest mixing frequency. | |
425 if (_minimumMixingFreq != kLowestPossible) { | |
426 if (_minimumMixingFreq > highestFreq) { | |
427 return _minimumMixingFreq; | |
428 } | |
429 } | |
430 return highestFreq; | |
431 } | |
432 | |
433 int32_t NewAudioConferenceMixerImpl::GetLowestMixingFrequencyFromList( | |
434 const MixerAudioSourceList& mixList) const { | |
435 int32_t highestFreq = 8000; | |
436 for (MixerAudioSourceList::const_iterator iter = mixList.begin(); | |
437 iter != mixList.end(); ++iter) { | |
438 const int32_t neededFrequency = (*iter)->NeededFrequency(_id); | |
439 if (neededFrequency > highestFreq) { | |
440 highestFreq = neededFrequency; | |
441 } | |
442 } | |
443 return highestFreq; | |
444 } | |
445 | |
446 AudioFrameList NewAudioConferenceMixerImpl::UpdateToMix( | 393 AudioFrameList NewAudioConferenceMixerImpl::UpdateToMix( |
447 size_t maxAudioFrameCounter) const { | 394 size_t maxAudioFrameCounter) const { |
448 AudioFrameList result; | 395 AudioFrameList result; |
449 std::vector<SourceFrame> audioSourceMixingDataList; | 396 std::vector<SourceFrame> audioSourceMixingDataList; |
450 | 397 |
451 // Get audio source audio and put it in the struct vector. | 398 // Get audio source audio and put it in the struct vector. |
452 for (MixerAudioSource* audio_source : audio_source_list_) { | 399 for (MixerAudioSource* audio_source : audio_source_list_) { |
453 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted( | 400 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted( |
454 _id, static_cast<int>(_outputFrequency)); | 401 _id, static_cast<int>(_outputFrequency)); |
455 | 402 |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
663 | 610 |
664 if (error != _limiter->kNoError) { | 611 if (error != _limiter->kNoError) { |
665 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, | 612 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, |
666 "Error from AudioProcessing: %d", error); | 613 "Error from AudioProcessing: %d", error); |
667 RTC_NOTREACHED(); | 614 RTC_NOTREACHED(); |
668 return false; | 615 return false; |
669 } | 616 } |
670 return true; | 617 return true; |
671 } | 618 } |
672 } // namespace webrtc | 619 } // namespace webrtc |
OLD | NEW |