@@ -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 );
@@ -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 */
84558483static 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