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
