@@ -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 */
12581262janus_plugin * create (void );
12591263int 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 */
84708498static 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