Skip to content

Commit 6736cae

Browse files
committed
Fix overflow mixing
1 parent 701fb37 commit 6736cae

File tree

1 file changed

+37
-25
lines changed

1 file changed

+37
-25
lines changed

src/plugins/janus_audiobridge.c

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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 */
12581270
janus_plugin *create(void);
12591271
int 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

Comments
 (0)