@@ -1254,6 +1254,18 @@ 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 SHRT_MAX_TUNED 29491
1259+ #define SHRT_MIN_TUNED -29491
1260+
1261+ /* Optimized inline function to add two 16-bit audio samples with overflow protection */
1262+ static inline opus_int16 add_with_overflow_check (opus_int16 a , opus_int16 b ) {
1263+ int sum = (int )a + (int )b ;
1264+ sum = sum > SHRT_MAX_TUNED ? SHRT_MAX_TUNED : sum ;
1265+ sum = sum < SHRT_MIN_TUNED ? SHRT_MIN_TUNED : sum ;
1266+ return (opus_int16 )sum ;
1267+ }
1268+
12571269/* Plugin methods */
12581270janus_plugin * create (void );
12591271int janus_audiobridge_init (janus_callbacks * callback , const char * config_path );
@@ -8636,9 +8648,9 @@ static void *janus_audiobridge_mixer_thread(void *data) {
86368648 if (!p -> stereo ) {
86378649 for (i = 0 ; i < samples ; i ++ ) {
86388650 if (p -> volume_gain == 100 ) {
8639- buffer [i ] += curBuffer [i ];
8651+ buffer [i ] = add_with_overflow_check ( buffer [ i ], curBuffer [i ]) ;
86408652 } else {
8641- buffer [i ] += ( curBuffer [i ]* p -> volume_gain )/100 ;
8653+ buffer [i ] = add_with_overflow_check ( buffer [ i ], ( curBuffer [i ]* p -> volume_gain )/100 ) ;
86428654 }
86438655 }
86448656 } else {
@@ -8649,29 +8661,29 @@ static void *janus_audiobridge_mixer_thread(void *data) {
86498661 if (i %2 == 0 ) {
86508662 if (lgain == 100 ) {
86518663 if (p -> volume_gain == 100 ) {
8652- buffer [i ] += curBuffer [i ];
8664+ buffer [i ] = add_with_overflow_check ( buffer [ i ], curBuffer [i ]) ;
86538665 } else {
8654- buffer [i ] += ( curBuffer [i ]* p -> volume_gain )/100 ;
8666+ buffer [i ] = add_with_overflow_check ( buffer [ i ], ( curBuffer [i ]* p -> volume_gain )/100 ) ;
86558667 }
86568668 } else {
86578669 if (p -> volume_gain == 100 ) {
8658- buffer [i ] += ( curBuffer [i ]* lgain )/100 ;
8670+ buffer [i ] = add_with_overflow_check ( buffer [ i ], ( curBuffer [i ]* lgain )/100 ) ;
86598671 } else {
8660- buffer [i ] += ((( curBuffer [i ]* lgain )/100 )* p -> volume_gain )/100 ;
8672+ buffer [i ] = add_with_overflow_check ( buffer [ i ], ((( curBuffer [i ]* lgain )/100 )* p -> volume_gain )/100 ) ;
86618673 }
86628674 }
86638675 } else {
86648676 if (rgain == 100 ) {
86658677 if (p -> volume_gain == 100 ) {
8666- buffer [i ] += curBuffer [i ];
8678+ buffer [i ] = add_with_overflow_check ( buffer [ i ], curBuffer [i ]) ;
86678679 } else {
8668- buffer [i ] += ( curBuffer [i ]* p -> volume_gain )/100 ;
8680+ buffer [i ] = add_with_overflow_check ( buffer [ i ], ( curBuffer [i ]* p -> volume_gain )/100 ) ;
86698681 }
86708682 } else {
86718683 if (p -> volume_gain == 100 ) {
8672- buffer [i ] += ( curBuffer [i ]* rgain )/100 ;
8684+ buffer [i ] = add_with_overflow_check ( buffer [ i ], ( curBuffer [i ]* rgain )/100 ) ;
86738685 } else {
8674- buffer [i ] += ((( curBuffer [i ]* rgain )/100 )* p -> volume_gain )/100 ;
8686+ buffer [i ] = add_with_overflow_check ( buffer [ i ], ((( curBuffer [i ]* rgain )/100 )* p -> volume_gain )/100 ) ;
86758687 }
86768688 }
86778689 }
@@ -8683,9 +8695,9 @@ static void *janus_audiobridge_mixer_thread(void *data) {
86838695 if (!p -> stereo ) {
86848696 for (i = 0 ; i < samples ; i ++ ) {
86858697 if (p -> volume_gain == 100 ) {
8686- * (groupBuffers + index * samples + i ) += curBuffer [i ];
8698+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), curBuffer [i ]) ;
86878699 } else {
8688- * (groupBuffers + index * samples + i ) += ( curBuffer [i ]* p -> volume_gain )/100 ;
8700+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), ( curBuffer [i ]* p -> volume_gain )/100 ) ;
86898701 }
86908702 }
86918703 } else {
@@ -8696,29 +8708,29 @@ static void *janus_audiobridge_mixer_thread(void *data) {
86968708 if (i %2 == 0 ) {
86978709 if (lgain == 100 ) {
86988710 if (p -> volume_gain == 100 ) {
8699- * (groupBuffers + index * samples + i ) += curBuffer [i ];
8711+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), curBuffer [i ]) ;
87008712 } else {
8701- * (groupBuffers + index * samples + i ) += ( curBuffer [i ]* p -> volume_gain )/100 ;
8713+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), ( curBuffer [i ]* p -> volume_gain )/100 ) ;
87028714 }
87038715 } else {
87048716 if (p -> volume_gain == 100 ) {
8705- * (groupBuffers + index * samples + i ) += ( curBuffer [i ]* lgain )/100 ;
8717+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), ( curBuffer [i ]* lgain )/100 ) ;
87068718 } else {
8707- * (groupBuffers + index * samples + i ) += ((( curBuffer [i ]* lgain )/100 )* p -> volume_gain )/100 ;
8719+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), ((( curBuffer [i ]* lgain )/100 )* p -> volume_gain )/100 ) ;
87088720 }
87098721 }
87108722 } else {
87118723 if (rgain == 100 ) {
87128724 if (p -> volume_gain == 100 ) {
8713- * (groupBuffers + index * samples + i ) += curBuffer [i ];
8725+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), curBuffer [i ]) ;
87148726 } else {
8715- * (groupBuffers + index * samples + i ) += ( curBuffer [i ]* p -> volume_gain )/100 ;
8727+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), ( curBuffer [i ]* p -> volume_gain )/100 ) ;
87168728 }
87178729 } else {
87188730 if (p -> volume_gain == 100 ) {
8719- * (groupBuffers + index * samples + i ) += ( curBuffer [i ]* rgain )/100 ;
8731+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), ( curBuffer [i ]* rgain )/100 ) ;
87208732 } else {
8721- * (groupBuffers + index * samples + i ) += ((( curBuffer [i ]* rgain )/100 )* p -> volume_gain )/100 ;
8733+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), ((( curBuffer [i ]* rgain )/100 )* p -> volume_gain )/100 ) ;
87228734 }
87238735 }
87248736 }
@@ -8796,19 +8808,19 @@ static void *janus_audiobridge_mixer_thread(void *data) {
87968808 /* Add to the main mix */
87978809 for (i = 0 ; i < samples ; i ++ ) {
87988810 if (p -> volume_gain == 100 ) {
8799- buffer [i ] += resampled [i ];
8811+ buffer [i ] = add_with_overflow_check ( buffer [ i ], resampled [i ]) ;
88008812 } else {
8801- buffer [i ] += ( resampled [i ]* p -> volume_gain )/100 ;
8813+ buffer [i ] = add_with_overflow_check ( buffer [ i ], ( resampled [i ]* p -> volume_gain )/100 ) ;
88028814 }
88038815 }
88048816 } else {
88058817 /* Add to the group submix */
88068818 index = p -> group - 1 ;
88078819 for (i = 0 ; i < samples ; i ++ ) {
88088820 if (p -> volume_gain == 100 ) {
8809- * (groupBuffers + index * samples + i ) += resampled [i ];
8821+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), resampled [i ]) ;
88108822 } else {
8811- * (groupBuffers + index * samples + i ) += ( resampled [i ]* p -> volume_gain )/100 ;
8823+ * (groupBuffers + index * samples + i ) = add_with_overflow_check ( * ( groupBuffers + index * samples + i ), ( resampled [i ]* p -> volume_gain )/100 ) ;
88128824 }
88138825 }
88148826 }
@@ -8822,7 +8834,7 @@ static void *janus_audiobridge_mixer_thread(void *data) {
88228834 /* Mix all submixes */
88238835 for (index = 0 ; index < groups_num ; index ++ ) {
88248836 for (i = 0 ; i < samples ; i ++ )
8825- buffer [i ] += * (groupBuffers + index * samples + i );
8837+ buffer [i ] = add_with_overflow_check ( buffer [ i ], * (groupBuffers + index * samples + i ) );
88268838 }
88278839 }
88288840 /* Are we recording the mix? (only do it if there's someone in, though...) */
0 commit comments