Skip to content

Commit ba04656

Browse files
lminierospscream
authored andcommitted
Smoothen AudioBridge mix instead of clamping/truncating (see meetecho#3593 and meetecho#3601)
1 parent e5a7c24 commit ba04656

1 file changed

Lines changed: 33 additions & 13 deletions

File tree

src/plugins/janus_audiobridge.c

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,10 @@ room-<unique room ID>: {
12541254

12551255
#define JANUS_AUDIOBRIDGE_MAX_GROUPS 5
12561256

1257+
/* Audio mixing with overflow protection - tuned to 0.9 of MAX/MIN to prevent clipping */
1258+
#define JANUS_AUDIOBRIDGE_SHRT_MAX_TUNED 29491
1259+
#define JANUS_AUDIOBRIDGE_SHRT_MIN_TUNED -29491
1260+
12571261
/* Plugin methods */
12581262
janus_plugin *create(void);
12591263
int janus_audiobridge_init(janus_callbacks *callback, const char *config_path);
@@ -8466,6 +8470,30 @@ static void janus_audiobridge_update_wav_header(janus_audiobridge_room *audiobri
84668470
}
84678471
}
84688472

8473+
/* Helper to limit/clamp mixed audio */
8474+
static inline void janus_audiobridge_limit_mix(opus_int32 *sumBuffer, opus_int16 *outBuffer, int samples) {
8475+
/* Find the loudest sample first, if there's one */
8476+
opus_int32 loudest = 0, sample = 0;
8477+
int i = 0;
8478+
for(i=0; i<samples; i++) {
8479+
sample = abs(sumBuffer[i]);
8480+
if(sample > JANUS_AUDIOBRIDGE_SHRT_MAX_TUNED && sample > loudest)
8481+
loudest = sample;
8482+
}
8483+
int gain = 100;
8484+
if(loudest > JANUS_AUDIOBRIDGE_SHRT_MAX_TUNED) {
8485+
/* We need to apply a negative gain to contain the mix */
8486+
float gainF = (float)JANUS_AUDIOBRIDGE_SHRT_MAX_TUNED / (float)loudest;
8487+
gainF *= 100;
8488+
gain = gainF;
8489+
}
8490+
/* Transform to 16-bit samples, limiting if necessary */
8491+
for(i=0; i<samples; i++) {
8492+
sample = (gain == 100) ? sumBuffer[i] : ((sumBuffer[i]*gain)/100);
8493+
outBuffer[i] = sample;
8494+
}
8495+
}
8496+
84698497
/* Thread to mix the contributions from all participants */
84708498
static void *janus_audiobridge_mixer_thread(void *data) {
84718499
JANUS_LOG(LOG_VERB, "Audio bridge thread starting...\n");
@@ -8849,10 +8877,7 @@ static void *janus_audiobridge_mixer_thread(void *data) {
88498877
}
88508878
/* Are we recording the mix? (only do it if there's someone in, though...) */
88518879
if(audiobridge->recording != NULL && g_list_length(participants_list) > 0) {
8852-
for(i=0; i<samples; i++) {
8853-
/* FIXME Smoothen/Normalize instead of truncating? */
8854-
outBuffer[i] = buffer[i];
8855-
}
8880+
janus_audiobridge_limit_mix(buffer, outBuffer, samples);
88568881
fwrite(outBuffer, sizeof(opus_int16), samples, audiobridge->recording);
88578882
/* Every 5 seconds we update the wav header */
88588883
gint64 now = janus_get_monotonic_time();
@@ -8920,9 +8945,7 @@ static void *janus_audiobridge_mixer_thread(void *data) {
89208945
}
89218946
}
89228947
}
8923-
for(i=0; i<samples; i++)
8924-
/* FIXME Smoothen/Normalize instead of truncating? */
8925-
outBuffer[i] = sumBuffer[i];
8948+
janus_audiobridge_limit_mix(sumBuffer, outBuffer, samples);
89268949
/* Enqueue this mixed frame for encoding in the participant thread */
89278950
janus_audiobridge_rtp_relay_packet *mixedpkt = g_malloc(sizeof(janus_audiobridge_rtp_relay_packet));
89288951
mixedpkt->data = g_malloc(samples*2);
@@ -8980,8 +9003,7 @@ static void *janus_audiobridge_mixer_thread(void *data) {
89809003
if(go_on) {
89819004
/* By default, let's send the mixed frame to everybody */
89829005
if(groups_num == 0) {
8983-
for(i=0; i<samples; i++)
8984-
outBuffer[i] = buffer[i];
9006+
janus_audiobridge_limit_mix(buffer, outBuffer, samples);
89859007
have_opus[0] = FALSE;
89869008
have_alaw[0] = FALSE;
89879009
have_ulaw[0] = FALSE;
@@ -9005,13 +9027,11 @@ static void *janus_audiobridge_mixer_thread(void *data) {
90059027
if(groups_num > 0) {
90069028
if(rfm->group == 0) {
90079029
/* We're forwarding the main mix */
9008-
for(i=0; i<samples; i++)
9009-
outBuffer[i] = buffer[i];
9030+
janus_audiobridge_limit_mix(buffer, outBuffer, samples);
90109031
} else {
90119032
/* We're forwarding a group mix */
90129033
index = rfm->group-1;
9013-
for(i=0; i<samples; i++)
9014-
outBuffer[i] = *(groupBuffers + index*samples + i);
9034+
janus_audiobridge_limit_mix(groupBuffers + index*samples, outBuffer, samples);
90159035
}
90169036
}
90179037
if(rfm->codec == JANUS_AUDIOCODEC_OPUS) {

0 commit comments

Comments
 (0)