Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit 0c0f03f

Browse files
daijhDuan, Xiande
authored andcommitted
Enable multiple audioMixer outputs and enable vad
Signed-off-by: jdai12 <[email protected]> Change-Id: I7fb75697da97a33baf330d72a1f83a2eb502ff40 Reviewed-on: https://git-ccr-1.devtools.intel.com/gerrit/56180 Reviewed-by: Duan, Xiande <[email protected]> Tested-by: Duan, Xiande <[email protected]>
1 parent 769f22f commit 0c0f03f

File tree

4 files changed

+205
-29
lines changed

4 files changed

+205
-29
lines changed

webrtc/modules/audio_conference_mixer/include/audio_conference_mixer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ class AudioConferenceMixer : public Module
6969
// downsampling of audio contributing to the mixed audio.
7070
virtual int32_t SetMinimumMixingFrequency(Frequency freq) = 0;
7171

72+
// woogeen vad
73+
virtual int32_t RegisterMixerVadCallback(AudioMixerVadReceiver *vadReceiver,
74+
const uint32_t amountOf10MsBetweenCallbacks) = 0;
75+
virtual int32_t UnRegisterMixerVadCallback() = 0;
76+
7277
protected:
7378
AudioConferenceMixer() {}
7479
};

webrtc/modules/audio_conference_mixer/include/audio_conference_mixer_defines.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class MixerParticipant
6565
MixHistory* _mixHistory;
6666
protected:
6767
MixerParticipant();
68-
virtual ~MixerParticipant();
68+
virtual ~MixerParticipant() = 0;
6969
};
7070

7171
class AudioMixerOutputReceiver
@@ -82,6 +82,26 @@ class AudioMixerOutputReceiver
8282
AudioMixerOutputReceiver() {}
8383
virtual ~AudioMixerOutputReceiver() {}
8484
};
85+
86+
// woogeen vad
87+
struct ParticipantVadStatistics
88+
{
89+
int32_t id;
90+
uint32_t energy;
91+
};
92+
93+
class AudioMixerVadReceiver
94+
{
95+
public:
96+
virtual void VadParticipants(
97+
const ParticipantVadStatistics *statistics,
98+
const uint32_t size) = 0;
99+
100+
protected:
101+
AudioMixerVadReceiver() {}
102+
virtual ~AudioMixerVadReceiver() {}
103+
};
104+
85105
} // namespace webrtc
86106

87107
#endif // WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_INCLUDE_AUDIO_CONFERENCE_MIXER_DEFINES_H_

webrtc/modules/audio_conference_mixer/source/audio_conference_mixer_impl.cc

Lines changed: 161 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,12 @@ AudioConferenceMixerImpl::AudioConferenceMixerImpl(int id)
124124
use_limiter_(true),
125125
_timeStamp(0),
126126
_timeScheduler(kProcessPeriodicityInMs),
127-
_processCalls(0) {}
127+
_processCalls(0),
128+
_vadEnabled(false),
129+
_vadReceiver(NULL),
130+
_amountOf10MsBetweenVadCallbacks(0),
131+
_amountOf10MsUntilNextVadCallback(0),
132+
_vadStatisticsAmount(0) {}
128133

129134
bool AudioConferenceMixerImpl::Init() {
130135
Config config;
@@ -255,66 +260,133 @@ void AudioConferenceMixerImpl::Process() {
255260
UpdateMixedStatus(mixedParticipantsMap);
256261
}
257262

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) {
261265
WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id,
262266
"failed PopMemory() call");
263267
assert(false);
264268
return;
265269
}
266270

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+
267281
{
268282
rtc::CritScope cs(&_crit);
269283

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+
270305
// TODO(henrike): it might be better to decide the number of channels
271306
// with an API instead of dynamically.
272307

273308
// 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),
275314
std::max(MaxNumChannels(&additionalFramesList),
276315
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;
283318

284319
// We only use the limiter if it supports the output sample rate and
285320
// we're actually mixing multiple streams.
286-
use_limiter_ =
321+
use_limiter_ = false && // disable limiter
287322
_numMixedParticipants > 1 &&
288323
_outputFrequency <= AudioProcessing::kMaxNativeSampleRateHz;
289324

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);
293329

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);
301365
}
302366
}
303367

304368
{
305369
rtc::CritScope cs(&_cbCrit);
306370
if(_mixReceiver != NULL) {
307-
const AudioFrame** dummy = NULL;
308371
_mixReceiver->NewMixedAudio(
309372
_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);
313382
}
314383
}
315384

316385
// 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+
}
318390
ClearAudioFrameList(&mixList);
319391
ClearAudioFrameList(&rampOutList);
320392
ClearAudioFrameList(&additionalFramesList);
@@ -466,7 +538,7 @@ int32_t AudioConferenceMixerImpl::SetMinimumMixingFrequency(
466538
freq = kSwbInHz;
467539
}
468540

469-
if((freq == kNbInHz) || (freq == kWbInHz) || (freq == kSwbInHz) ||
541+
if((freq == kNbInHz) || (freq == kWbInHz) || (freq == kSwbInHz) || (freq == kFbInHz ) ||
470542
(freq == kLowestPossible)) {
471543
_minimumMixingFreq=freq;
472544
return 0;
@@ -922,4 +994,65 @@ bool AudioConferenceMixerImpl::LimitMixedAudio(AudioFrame* mixedAudio) const {
922994
}
923995
return true;
924996
}
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+
9251058
} // namespace webrtc

webrtc/modules/audio_conference_mixer/source/audio_conference_mixer_impl.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ class AudioConferenceMixerImpl : public AudioConferenceMixer
8585
bool AnonymousMixabilityStatus(
8686
const MixerParticipant& participant) const override;
8787

88+
// woogeen vad
89+
int32_t RegisterMixerVadCallback(AudioMixerVadReceiver *vadReceiver,
90+
const uint32_t amountOf10MsBetweenCallbacks) override;
91+
int32_t UnRegisterMixerVadCallback() override;
92+
8893
private:
8994
enum{DEFAULT_AUDIO_FRAME_POOLSIZE = 50};
9095

@@ -186,6 +191,19 @@ class AudioConferenceMixerImpl : public AudioConferenceMixer
186191

187192
// Used for inhibiting saturation in mixing.
188193
std::unique_ptr<AudioProcessing> _limiter;
194+
195+
// woogeen vad
196+
enum {kMaximumVadParticipants = 128};
197+
198+
void UpdateVadStatistics(AudioFrameList* mixList);
199+
200+
bool _vadEnabled;
201+
AudioMixerVadReceiver* _vadReceiver;
202+
uint32_t _amountOf10MsBetweenVadCallbacks;
203+
204+
uint32_t _amountOf10MsUntilNextVadCallback;
205+
size_t _vadStatisticsAmount;
206+
ParticipantVadStatistics _vadStatistics[kMaximumVadParticipants];
189207
};
190208
} // namespace webrtc
191209

0 commit comments

Comments
 (0)