Skip to content

Commit ab93ea0

Browse files
committed
Smoothen AudioBridge mix instead of clamping/truncating (see #3593 and #3601)
1 parent fcfd0c5 commit ab93ea0

File tree

1 file changed

+33
-13
lines changed

1 file changed

+33
-13
lines changed

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);
@@ -8451,6 +8455,30 @@ static void janus_audiobridge_update_wav_header(janus_audiobridge_room *audiobri
84518455
}
84528456
}
84538457

8458+
/* Helper to limit/clamp mixed audio */
8459+
static inline void janus_audiobridge_limit_mix(opus_int32 *sumBuffer, opus_int16 *outBuffer, int samples) {
8460+
/* Find the loudest sample first, if there's one */
8461+
opus_int32 loudest = 0, sample = 0;
8462+
int i = 0;
8463+
for(i=0; i<samples; i++) {
8464+
sample = abs(sumBuffer[i]);
8465+
if(sample > JANUS_AUDIOBRIDGE_SHRT_MAX_TUNED && sample > loudest)
8466+
loudest = sample;
8467+
}
8468+
int gain = 100;
8469+
if(loudest > JANUS_AUDIOBRIDGE_SHRT_MAX_TUNED) {
8470+
/* We need to apply a negative gain to contain the mix */
8471+
float gainF = (float)JANUS_AUDIOBRIDGE_SHRT_MAX_TUNED / (float)loudest;
8472+
gainF *= 100;
8473+
gain = gainF;
8474+
}
8475+
/* Transform to 16-bit samples, limiting if necessary */
8476+
for(i=0; i<samples; i++) {
8477+
sample = (gain == 100) ? sumBuffer[i] : ((sumBuffer[i]*gain)/100);
8478+
outBuffer[i] = sample;
8479+
}
8480+
}
8481+
84548482
/* Thread to mix the contributions from all participants */
84558483
static void *janus_audiobridge_mixer_thread(void *data) {
84568484
JANUS_LOG(LOG_VERB, "Audio bridge thread starting...\n");
@@ -8834,10 +8862,7 @@ static void *janus_audiobridge_mixer_thread(void *data) {
88348862
}
88358863
/* Are we recording the mix? (only do it if there's someone in, though...) */
88368864
if(audiobridge->recording != NULL && g_list_length(participants_list) > 0) {
8837-
for(i=0; i<samples; i++) {
8838-
/* FIXME Smoothen/Normalize instead of truncating? */
8839-
outBuffer[i] = buffer[i];
8840-
}
8865+
janus_audiobridge_limit_mix(buffer, outBuffer, samples);
88418866
fwrite(outBuffer, sizeof(opus_int16), samples, audiobridge->recording);
88428867
/* Every 5 seconds we update the wav header */
88438868
gint64 now = janus_get_monotonic_time();
@@ -8905,9 +8930,7 @@ static void *janus_audiobridge_mixer_thread(void *data) {
89058930
}
89068931
}
89078932
}
8908-
for(i=0; i<samples; i++)
8909-
/* FIXME Smoothen/Normalize instead of truncating? */
8910-
outBuffer[i] = sumBuffer[i];
8933+
janus_audiobridge_limit_mix(sumBuffer, outBuffer, samples);
89118934
/* Enqueue this mixed frame for encoding in the participant thread */
89128935
janus_audiobridge_rtp_relay_packet *mixedpkt = g_malloc(sizeof(janus_audiobridge_rtp_relay_packet));
89138936
mixedpkt->data = g_malloc(samples*2);
@@ -8965,8 +8988,7 @@ static void *janus_audiobridge_mixer_thread(void *data) {
89658988
if(go_on) {
89668989
/* By default, let's send the mixed frame to everybody */
89678990
if(groups_num == 0) {
8968-
for(i=0; i<samples; i++)
8969-
outBuffer[i] = buffer[i];
8991+
janus_audiobridge_limit_mix(buffer, outBuffer, samples);
89708992
have_opus[0] = FALSE;
89718993
have_alaw[0] = FALSE;
89728994
have_ulaw[0] = FALSE;
@@ -8990,13 +9012,11 @@ static void *janus_audiobridge_mixer_thread(void *data) {
89909012
if(groups_num > 0) {
89919013
if(rfm->group == 0) {
89929014
/* We're forwarding the main mix */
8993-
for(i=0; i<samples; i++)
8994-
outBuffer[i] = buffer[i];
9015+
janus_audiobridge_limit_mix(buffer, outBuffer, samples);
89959016
} else {
89969017
/* We're forwarding a group mix */
89979018
index = rfm->group-1;
8998-
for(i=0; i<samples; i++)
8999-
outBuffer[i] = *(groupBuffers + index*samples + i);
9019+
janus_audiobridge_limit_mix(groupBuffers + index*samples, outBuffer, samples);
90009020
}
90019021
}
90029022
if(rfm->codec == JANUS_AUDIOCODEC_OPUS) {

0 commit comments

Comments
 (0)