Volume32, StartVol32, and EndVol32 were unsigned int, but
VolumeIncrement32 can be negative (reverse ramping), so
Volume32 += VolumeIncrement32 wraps around instead of going
negative. This breaks the boundary comparison and produces
incorrect volume.

Change them to signed int and add a CLAMP to keep Volume32
within the valid range [0, 0x1fe000].

Reported-by: Pavee Hui <[email protected]>
Signed-off-by: Marc-André Lureau <[email protected]>
---
 hw/audio/gusemu_mixer.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/audio/gusemu_mixer.c b/hw/audio/gusemu_mixer.c
index 56300de77e44..341995cfd19e 100644
--- a/hw/audio/gusemu_mixer.c
+++ b/hw/audio/gusemu_mixer.c
@@ -68,9 +68,10 @@ void gus_mixvoices(GUSEmuState * state, unsigned int 
playback_freq, unsigned int
 
             int             PanningPos = (GUSvoice(wVSRPanning) >> 8) & 0xf;
 
-            unsigned int    Volume32   = 32 * GUSvoice(wVSRCurrVol); /* 32 
times larger than original gus for maintaining precision while ramping */
-            unsigned int    StartVol32 = (GUSvoice(wVSRVolRampStartVol) & 
0xff00) * 32;
-            unsigned int    EndVol32   = (GUSvoice(wVSRVolRampEndVol)   & 
0xff00) * 32;
+            /* 32x original GUS precision for ramping */
+            int Volume32 = 32 * GUSvoice(wVSRCurrVol);
+            int StartVol32 = (GUSvoice(wVSRVolRampStartVol) & 0xff00) * 32;
+            int EndVol32 = (GUSvoice(wVSRVolRampEndVol) & 0xff00) * 32;
             int             VolumeIncrement32 = (32 * 16 * 
(GUSvoice(wVSRVolRampRate) & 0x3f00) >> 8) >> ((((GUSvoice(wVSRVolRampRate) & 
0xc000) >> 8) >> 6) * 3); /* including 1/8/64/512 volume speed divisor */
             VolumeIncrement32 = (((VolumeIncrement32 * 44100 / 2) / 
playback_freq) * 14) / ((GUSregb(NumVoices) & 31) + 1); /* adjust ramping speed 
to playback speed */
 
@@ -82,6 +83,7 @@ void gus_mixvoices(GUSEmuState * state, unsigned int 
playback_freq, unsigned int
             for (sample = 0; sample < numsamples; sample++)
             {
                 int             sample1, sample2, Volume;
+                Volume32 = CLAMP(Volume32, 0, 0x1fe000);
                 if (GUSvoice(wVSRControl) & 0x400)      /* 16bit */
                 {
                     int offset = ((CurrPos >> 9) & 0xc0000) + (((CurrPos >> 9) 
& 0x1ffff) << 1);

-- 
2.56.0.rc0.29.g47ce80527c56


Reply via email to