@@ -124,7 +124,12 @@ AudioConferenceMixerImpl::AudioConferenceMixerImpl(int id)
124
124
use_limiter_(true ),
125
125
_timeStamp(0 ),
126
126
_timeScheduler(kProcessPeriodicityInMs ),
127
- _processCalls(0 ) {}
127
+ _processCalls(0 ),
128
+ _vadEnabled(false ),
129
+ _vadReceiver(NULL ),
130
+ _amountOf10MsBetweenVadCallbacks(0 ),
131
+ _amountOf10MsUntilNextVadCallback(0 ),
132
+ _vadStatisticsAmount(0 ) {}
128
133
129
134
bool AudioConferenceMixerImpl::Init () {
130
135
Config config;
@@ -255,66 +260,133 @@ void AudioConferenceMixerImpl::Process() {
255
260
UpdateMixedStatus (mixedParticipantsMap);
256
261
}
257
262
258
- // Get an AudioFrame for mixing from the memory pool.
259
- AudioFrame* mixedAudio = NULL ;
260
- if (_audioFramePool->PopMemory (mixedAudio) == -1 ) {
263
+ AudioFrame* generalFrame = NULL ;
264
+ if (_audioFramePool->PopMemory (generalFrame) == -1 ) {
261
265
WEBRTC_TRACE (kTraceMemory , kTraceAudioMixerServer , _id,
262
266
" failed PopMemory() call" );
263
267
assert (false );
264
268
return ;
265
269
}
266
270
271
+ AudioFrame* uniqueFrames[kMaximumAmountOfMixedParticipants ];
272
+ for (size_t i = 0 ; i < mixList.size (); ++i) {
273
+ if (_audioFramePool->PopMemory (uniqueFrames[i]) == -1 ) {
274
+ WEBRTC_TRACE (kTraceMemory , kTraceAudioMixerServer , _id,
275
+ " failed PopMemory() call" );
276
+ assert (false );
277
+ return ;
278
+ }
279
+ }
280
+
267
281
{
268
282
rtc::CritScope cs (&_crit);
269
283
284
+ // woogeen vad
285
+ _vadStatisticsAmount = 0 ;
286
+ if (_vadEnabled && _amountOf10MsUntilNextVadCallback-- == 0 ) {
287
+ _amountOf10MsUntilNextVadCallback = _amountOf10MsBetweenVadCallbacks;
288
+
289
+ if (mixList.size () + additionalFramesList.size () <= kMaximumVadParticipants ) {
290
+ AudioFrameList vadParticipantList;
291
+
292
+ if (mixList.size () > 0 )
293
+ vadParticipantList.insert (vadParticipantList.end (), mixList.begin (), mixList.end ());
294
+
295
+ if (additionalFramesList.size () > 0 )
296
+ vadParticipantList.insert (vadParticipantList.end (), additionalFramesList.begin (), additionalFramesList.end ());
297
+
298
+ UpdateVadStatistics (&vadParticipantList);
299
+ } else {
300
+ WEBRTC_TRACE (kTraceWarning , kTraceAudioMixerServer , _id,
301
+ " vad participants exceeded MaximumAmount(%d)" , kMaximumVadParticipants );
302
+ }
303
+ }
304
+
270
305
// TODO(henrike): it might be better to decide the number of channels
271
306
// with an API instead of dynamically.
272
307
273
308
// Find the max channels over all mixing lists.
274
- const size_t num_mixed_channels = std::max (MaxNumChannels (&mixList),
309
+ size_t num_mixed_channels;
310
+
311
+ // force dual channels for 48000hz output
312
+ if (_outputFrequency < 48000 )
313
+ num_mixed_channels = std::max (MaxNumChannels (&mixList),
275
314
std::max (MaxNumChannels (&additionalFramesList),
276
315
MaxNumChannels (&rampOutList)));
277
-
278
- mixedAudio->UpdateFrame (-1 , _timeStamp, NULL , 0 , _outputFrequency,
279
- AudioFrame::kNormalSpeech ,
280
- AudioFrame::kVadPassive , num_mixed_channels);
281
-
282
- _timeStamp += static_cast <uint32_t >(_sampleSize);
316
+ else
317
+ num_mixed_channels = 2 ;
283
318
284
319
// We only use the limiter if it supports the output sample rate and
285
320
// we're actually mixing multiple streams.
286
- use_limiter_ =
321
+ use_limiter_ = false && // disable limiter
287
322
_numMixedParticipants > 1 &&
288
323
_outputFrequency <= AudioProcessing::kMaxNativeSampleRateHz ;
289
324
290
- MixFromList (mixedAudio, mixList);
291
- MixAnonomouslyFromList (mixedAudio, additionalFramesList);
292
- MixAnonomouslyFromList (mixedAudio, rampOutList);
325
+ // 1. mix AnonomouslyFromList
326
+ generalFrame->UpdateFrame (-1 , _timeStamp, NULL , 0 , _outputFrequency,
327
+ AudioFrame::kNormalSpeech ,
328
+ AudioFrame::kVadPassive , num_mixed_channels);
293
329
294
- if (mixedAudio->samples_per_channel_ == 0 ) {
295
- // Nothing was mixed, set the audio samples to silence.
296
- mixedAudio->samples_per_channel_ = _sampleSize;
297
- AudioFrameOperations::Mute (mixedAudio);
298
- } else {
299
- // Only call the limiter if we have something to mix.
300
- LimitMixedAudio (mixedAudio);
330
+ MixAnonomouslyFromList (generalFrame, additionalFramesList);
331
+ MixAnonomouslyFromList (generalFrame, rampOutList);
332
+
333
+ // 2. mix workList and anonomouslyMixerdFrame
334
+ for (size_t i = 0 ; i <= mixList.size (); ++i) {
335
+ AudioFrameList workList = mixList;
336
+ int id = -1 ;
337
+ AudioFrame* mixedAudio = NULL ;
338
+
339
+ if (i == mixList.size ()) {
340
+ mixedAudio = generalFrame;
341
+ } else {
342
+ mixedAudio = uniqueFrames[i];
343
+ AudioFrameList::iterator it = workList.begin ();
344
+ advance (it, i);
345
+ id = (*it).frame ->id_ ;
346
+ workList.erase (it);
347
+
348
+ mixedAudio->CopyFrom (*generalFrame);
349
+ }
350
+
351
+ MixFromList (mixedAudio, workList);
352
+
353
+ if (mixedAudio->samples_per_channel_ == 0 ) {
354
+ // Nothing was mixed, set the audio samples to silence.
355
+ mixedAudio->samples_per_channel_ = _sampleSize;
356
+ AudioFrameOperations::Mute (mixedAudio);
357
+ } else {
358
+ // Only call the limiter if we have something to mix.
359
+ LimitMixedAudio (mixedAudio);
360
+ }
361
+
362
+ mixedAudio->id_ = id;
363
+ mixedAudio->timestamp_ = _timeStamp;
364
+ _timeStamp += static_cast <uint32_t >(_sampleSize);
301
365
}
302
366
}
303
367
304
368
{
305
369
rtc::CritScope cs (&_cbCrit);
306
370
if (_mixReceiver != NULL ) {
307
- const AudioFrame** dummy = NULL ;
308
371
_mixReceiver->NewMixedAudio (
309
372
_id,
310
- *mixedAudio,
311
- dummy,
312
- 0 );
373
+ *generalFrame,
374
+ const_cast <const AudioFrame**>(uniqueFrames),
375
+ mixList.size ());
376
+ }
377
+
378
+ if ((_vadReceiver != NULL ) && _vadStatisticsAmount > 0 ) {
379
+ _vadReceiver->VadParticipants (
380
+ _vadStatistics,
381
+ _vadStatisticsAmount);
313
382
}
314
383
}
315
384
316
385
// Reclaim all outstanding memory.
317
- _audioFramePool->PushMemory (mixedAudio);
386
+ _audioFramePool->PushMemory (generalFrame);
387
+ for (size_t i = 0 ; i < mixList.size (); ++i) {
388
+ _audioFramePool->PushMemory (uniqueFrames[i]);
389
+ }
318
390
ClearAudioFrameList (&mixList);
319
391
ClearAudioFrameList (&rampOutList);
320
392
ClearAudioFrameList (&additionalFramesList);
@@ -466,7 +538,7 @@ int32_t AudioConferenceMixerImpl::SetMinimumMixingFrequency(
466
538
freq = kSwbInHz ;
467
539
}
468
540
469
- if ((freq == kNbInHz ) || (freq == kWbInHz ) || (freq == kSwbInHz ) ||
541
+ if ((freq == kNbInHz ) || (freq == kWbInHz ) || (freq == kSwbInHz ) || (freq == kFbInHz ) ||
470
542
(freq == kLowestPossible )) {
471
543
_minimumMixingFreq=freq;
472
544
return 0 ;
@@ -922,4 +994,65 @@ bool AudioConferenceMixerImpl::LimitMixedAudio(AudioFrame* mixedAudio) const {
922
994
}
923
995
return true ;
924
996
}
997
+
998
+ // woogeen vad
999
+ int32_t AudioConferenceMixerImpl::RegisterMixerVadCallback (
1000
+ AudioMixerVadReceiver *vadReceiver,
1001
+ const uint32_t amountOf10MsBetweenCallbacks) {
1002
+ if (amountOf10MsBetweenCallbacks == 0 ) {
1003
+ WEBRTC_TRACE (
1004
+ kTraceWarning ,
1005
+ kTraceAudioMixerServer ,
1006
+ _id,
1007
+ " amountOf10MsBetweenCallbacks(%d) needs to be larger than 0" ,
1008
+ amountOf10MsBetweenCallbacks
1009
+ );
1010
+ return -1 ;
1011
+ }
1012
+ {
1013
+ rtc::CritScope cs (&_cbCrit);
1014
+ if (_vadReceiver != NULL ) {
1015
+ WEBRTC_TRACE (kTraceWarning , kTraceAudioMixerServer , _id,
1016
+ " Mixer vad callback already registered" );
1017
+ return -1 ;
1018
+ }
1019
+ _vadReceiver = vadReceiver;
1020
+ }
1021
+ {
1022
+ rtc::CritScope cs (&_crit);
1023
+ _amountOf10MsBetweenVadCallbacks = amountOf10MsBetweenCallbacks;
1024
+ _vadEnabled = true ;
1025
+ }
1026
+ return 0 ;
1027
+ }
1028
+
1029
+ int32_t AudioConferenceMixerImpl::UnRegisterMixerVadCallback () {
1030
+ {
1031
+ rtc::CritScope cs (&_crit);
1032
+ if (!_vadEnabled)
1033
+ return -1 ;
1034
+
1035
+ _vadEnabled = false ;
1036
+ _amountOf10MsBetweenVadCallbacks = 0 ;
1037
+ }
1038
+ {
1039
+ rtc::CritScope cs (&_cbCrit);
1040
+ _vadReceiver = NULL ;
1041
+ }
1042
+ return 0 ;
1043
+ }
1044
+
1045
+ void AudioConferenceMixerImpl::UpdateVadStatistics (AudioFrameList* mixList) {
1046
+ _vadStatisticsAmount = 0 ;
1047
+ for (AudioFrameList::iterator iter = mixList->begin ();
1048
+ iter != mixList->end ();
1049
+ ++iter) {
1050
+ if ((*iter).frame ->vad_activity_ == AudioFrame::kVadActive ) {
1051
+ _vadStatistics[_vadStatisticsAmount].id = (*iter).frame ->id_ ;
1052
+ _vadStatistics[_vadStatisticsAmount].energy = CalculateEnergy (*(*iter).frame );
1053
+ _vadStatisticsAmount++;
1054
+ }
1055
+ }
1056
+ }
1057
+
925
1058
} // namespace webrtc
0 commit comments