ft2-clone

Fasttracker 2 clone
Log | Files | Refs | README | LICENSE

commit 9e6e95166ac606b05631c0ebacd81e93038f073e
parent 4cb9cdc4475ea90ba9eb591cf00628ec60230f74
Author: Olav Sørensen <olav.sorensen@live.no>
Date:   Mon,  6 Apr 2020 21:52:36 +0200

Pushed v1.18 code

- Windows: Fixed files >2GB displaying bogus filesizes in Disk Op.
- Fixed a potential crash in the audio mixer on quirky modules (when a
  channel's sampling rate is somehow set to 0).
- Fixed a bug with vertical scrollbars that have a very small thumb (v1.16)

Diffstat:
Msrc/ft2_audio.c | 6++++--
Msrc/ft2_audio.h | 9++++-----
Msrc/ft2_diskop.c | 6++++++
Msrc/ft2_header.h | 2+-
Msrc/ft2_main.c | 6++++--
Msrc/ft2_mix.c | 136+++++++++++++++++++++++++++++++++++--------------------------------------------
Msrc/ft2_mix_macros.h | 72++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/ft2_replayer.c | 26++++++++------------------
Msrc/ft2_scopedraw.c | 4++--
Msrc/ft2_scopes.c | 21+++++++++++++--------
Msrc/ft2_scopes.h | 8+++++++-
Msrc/ft2_scrollbars.c | 12+++++++-----
Msrc/ft2_video.c | 4++--
13 files changed, 152 insertions(+), 160 deletions(-)

diff --git a/src/ft2_audio.c b/src/ft2_audio.c @@ -20,8 +20,8 @@ static int8_t pmpCountDiv, pmpChannels = 2; static uint16_t smpBuffSize; static int32_t masterVol, oldAudioFreq, speedVal, pmpLeft, randSeed = INITIAL_DITHER_SEED; -static int32_t prngStateL, prngStateR, oldPeriod, oldSFrq, oldSFrqRev; -static uint32_t tickTimeLen, tickTimeLenFrac; +static int32_t prngStateL, prngStateR, oldPeriod; +static uint32_t tickTimeLen, tickTimeLenFrac, oldSFrq, oldSFrqRev; static float fAudioAmpMul; static voice_t voice[MAX_VOICES * 2]; static void (*sendAudSamplesFunc)(uint8_t *, uint32_t, uint8_t); // "send mixed samples" routines @@ -372,6 +372,8 @@ void mix_UpdateChannelVolPanFrq(void) { if (ch->finalPeriod != oldPeriod) // this value will very often be the same as before { + oldPeriod = ch->finalPeriod; + oldSFrq = getFrequenceValue(ch->finalPeriod); oldSFrqRev = 0xFFFFFFFF; diff --git a/src/ft2_audio.h b/src/ft2_audio.h @@ -33,7 +33,7 @@ struct audio_t uint32_t freq; uint32_t audLatencyPerfValInt, audLatencyPerfValFrac; uint64_t tickTime64, tickTime64Frac; - double dAudioLatencyMs, dSpeedValMul, dScopeFreqMul, dPianoDeltaMul; + double dAudioLatencyMs, dSpeedValMul, dPianoDeltaMul; SDL_AudioDeviceID dev; uint32_t wantFreq, haveFreq, wantSamples, haveSamples, wantChannels, haveChannels; } audio; @@ -45,10 +45,9 @@ typedef struct bool backwards, isFadeOutVoice; uint8_t SPan; uint16_t SVol; - int32_t SLVol1, SRVol1, SLVol2, SRVol2, SLVolIP, SRVolIP, SVolIPLen; - int32_t SPos, SLen, SRepS, SRepL, SFrq, SFrqRev; - uint32_t SPosDec; - + int32_t SLVol1, SRVol1, SLVol2, SRVol2, SLVolIP, SRVolIP; + int32_t SPos, SLen, SRepS, SRepL; + uint32_t SVolIPLen, SPosDec, SFrq, SFrqRev; void (*mixRoutine)(void *, int32_t); // function pointer to mix routine } voice_t; diff --git a/src/ft2_diskop.c b/src/ft2_diskop.c @@ -1478,6 +1478,9 @@ static int8_t findFirst(DirRec *searchRec) } #endif + if (searchRec->filesize < -1) + searchRec->filesize = -1; + if (handleEntrySkip(searchRec->nameU, searchRec->isDir)) { // skip file @@ -1558,6 +1561,9 @@ static int8_t findNext(DirRec *searchRec) } #endif + if (searchRec->filesize < -1) + searchRec->filesize = -1; + if (handleEntrySkip(searchRec->nameU, searchRec->isDir)) { // skip file diff --git a/src/ft2_header.h b/src/ft2_header.h @@ -12,7 +12,7 @@ #endif #include "ft2_replayer.h" -#define PROG_VER_STR "1.17" +#define PROG_VER_STR "1.18" // do NOT change these! It will only mess things up... diff --git a/src/ft2_main.c b/src/ft2_main.c @@ -119,7 +119,8 @@ int main(int argc, char *argv[]) /* SDL 2.0.9 for Windows has a serious bug where you need to initialize the joystick subsystem ** (even if you don't use it) or else weird things happen like random stutters, keyboard (rarely) being ** reinitialized in Windows and what not. - ** Ref.: https://bugzilla.libsdl.org/show_bug.cgi?id=4391 */ + ** Ref.: https://bugzilla.libsdl.org/show_bug.cgi?id=4391 + */ #if defined _WIN32 && SDL_PATCHLEVEL == 9 if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0) #else @@ -133,7 +134,8 @@ int main(int argc, char *argv[]) /* Text input is started by default in SDL2, turn it off to remove ~2ms spikes per key press. ** We manuallay start it again when a text edit box is activated, and stop it when done. - ** Ref.: https://bugzilla.libsdl.org/show_bug.cgi?id=4166 */ + ** Ref.: https://bugzilla.libsdl.org/show_bug.cgi?id=4166 + */ SDL_StopTextInput(); #ifdef __APPLE__ diff --git a/src/ft2_mix.c b/src/ft2_mix.c @@ -38,8 +38,8 @@ static void mix8bNoLoop(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *smpPtr; int32_t realPos, sample, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; GET_VOL @@ -50,7 +50,6 @@ static void mix8bNoLoop(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS - GET_DELTA SET_BASE8 CDA_BytesLeft = numSamples; @@ -102,8 +101,8 @@ static void mix8bLoop(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *smpPtr;; int32_t realPos, sample, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; GET_VOL @@ -114,7 +113,6 @@ static void mix8bLoop(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS - GET_DELTA SET_BASE8 CDA_BytesLeft = numSamples; @@ -166,8 +164,8 @@ static void mix8bBidiLoop(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr; int32_t realPos, sample, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos, delta; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft; GET_VOL @@ -230,8 +228,8 @@ static void mix8bNoLoopIntrp(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *smpPtr; int32_t realPos, sample, sample2, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -245,7 +243,6 @@ static void mix8bNoLoopIntrp(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS - GET_DELTA SET_BASE8 CDA_BytesLeft = numSamples; @@ -297,8 +294,8 @@ static void mix8bLoopIntrp(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *smpPtr; int32_t realPos, sample, sample2, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -312,7 +309,6 @@ static void mix8bLoopIntrp(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS - GET_DELTA SET_BASE8 CDA_BytesLeft = numSamples; @@ -364,8 +360,8 @@ static void mix8bBidiLoopIntrp(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr; int32_t realPos, sample, sample2, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos, delta; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -431,9 +427,9 @@ static void mix8bBidiLoopIntrp(voice_t *v, uint32_t numSamples) static void mix8bRampNoLoop(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *smpPtr; - int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t realPos, sample, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0) { @@ -442,7 +438,6 @@ static void mix8bRampNoLoop(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS_RAMP - GET_DELTA SET_BASE8 CDA_BytesLeft = numSamples; @@ -502,9 +497,9 @@ static void mix8bRampNoLoop(voice_t *v, uint32_t numSamples) static void mix8bRampLoop(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *smpPtr;; - int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t realPos, sample, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0) { @@ -513,7 +508,6 @@ static void mix8bRampLoop(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS_RAMP - GET_DELTA SET_BASE8 CDA_BytesLeft = numSamples; @@ -573,9 +567,9 @@ static void mix8bRampLoop(voice_t *v, uint32_t numSamples) static void mix8bRampBidiLoop(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr; - int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos, delta; + int32_t realPos, sample, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft; if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0) { @@ -645,9 +639,9 @@ static void mix8bRampBidiLoop(voice_t *v, uint32_t numSamples) static void mix8bRampNoLoopIntrp(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *smpPtr; - int32_t realPos, sample, sample2, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t realPos, sample, sample2, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -659,7 +653,6 @@ static void mix8bRampNoLoopIntrp(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS_RAMP - GET_DELTA SET_BASE8 CDA_BytesLeft = numSamples; @@ -719,9 +712,9 @@ static void mix8bRampNoLoopIntrp(voice_t *v, uint32_t numSamples) static void mix8bRampLoopIntrp(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *smpPtr; - int32_t realPos, sample, sample2, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t realPos, sample, sample2, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -733,7 +726,6 @@ static void mix8bRampLoopIntrp(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS_RAMP - GET_DELTA SET_BASE8 CDA_BytesLeft = numSamples; @@ -793,9 +785,9 @@ static void mix8bRampLoopIntrp(voice_t *v, uint32_t numSamples) static void mix8bRampBidiLoopIntrp(voice_t *v, uint32_t numSamples) { const int8_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr; - int32_t realPos, sample, sample2, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos, delta; + int32_t realPos, sample, sample2, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -874,8 +866,8 @@ static void mix16bNoLoop(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *smpPtr; int32_t realPos, sample, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; GET_VOL @@ -886,7 +878,6 @@ static void mix16bNoLoop(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS - GET_DELTA SET_BASE16 CDA_BytesLeft = numSamples; @@ -938,8 +929,8 @@ static void mix16bLoop(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *smpPtr; int32_t realPos, sample, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; GET_VOL @@ -950,7 +941,6 @@ static void mix16bLoop(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS - GET_DELTA SET_BASE16 CDA_BytesLeft = numSamples; @@ -1002,8 +992,8 @@ static void mix16bBidiLoop(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr; int32_t realPos, sample, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos, delta; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft; GET_VOL @@ -1067,8 +1057,8 @@ static void mix16bNoLoopIntrp(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *smpPtr; int32_t realPos, sample, sample2, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -1082,7 +1072,6 @@ static void mix16bNoLoopIntrp(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS - GET_DELTA SET_BASE16 CDA_BytesLeft = numSamples; @@ -1134,8 +1123,8 @@ static void mix16bLoopIntrp(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *smpPtr; int32_t realPos, sample, sample2, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -1149,7 +1138,6 @@ static void mix16bLoopIntrp(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS - GET_DELTA SET_BASE16 CDA_BytesLeft = numSamples; @@ -1201,8 +1189,8 @@ static void mix16bBidiLoopIntrp(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr; int32_t realPos, sample, sample2, *audioMixL, *audioMixR; - int32_t CDA_BytesLeft, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos, delta; + int32_t CDA_LVol, CDA_RVol; + uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -1268,9 +1256,9 @@ static void mix16bBidiLoopIntrp(voice_t *v, uint32_t numSamples) static void mix16bRampNoLoop(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *smpPtr; - int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t realPos, sample, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0) { @@ -1279,7 +1267,6 @@ static void mix16bRampNoLoop(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS_RAMP - GET_DELTA SET_BASE16 CDA_BytesLeft = numSamples; @@ -1339,9 +1326,9 @@ static void mix16bRampNoLoop(voice_t *v, uint32_t numSamples) static void mix16bRampLoop(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *smpPtr; - int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t realPos, sample, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0) { @@ -1350,7 +1337,6 @@ static void mix16bRampLoop(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS_RAMP - GET_DELTA SET_BASE16 CDA_BytesLeft = numSamples; @@ -1410,9 +1396,9 @@ static void mix16bRampLoop(voice_t *v, uint32_t numSamples) static void mix16bRampBidiLoop(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr; - int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos, delta; + int32_t realPos, sample, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft; if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0) { @@ -1482,9 +1468,9 @@ static void mix16bRampBidiLoop(voice_t *v, uint32_t numSamples) static void mix16bRampNoLoopIntrp(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *smpPtr; - int32_t realPos, sample, sample2, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t realPos, sample, sample2, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -1496,7 +1482,6 @@ static void mix16bRampNoLoopIntrp(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS_RAMP - GET_DELTA SET_BASE16 CDA_BytesLeft = numSamples; @@ -1556,9 +1541,9 @@ static void mix16bRampNoLoopIntrp(voice_t *v, uint32_t numSamples) static void mix16bRampLoopIntrp(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *smpPtr; - int32_t realPos, sample, sample2, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos; + int32_t realPos, sample, sample2, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif @@ -1570,7 +1555,6 @@ static void mix16bRampLoopIntrp(voice_t *v, uint32_t numSamples) } GET_MIXER_VARS_RAMP - GET_DELTA SET_BASE16 CDA_BytesLeft = numSamples; @@ -1630,9 +1614,9 @@ static void mix16bRampLoopIntrp(voice_t *v, uint32_t numSamples) static void mix16bRampBidiLoopIntrp(voice_t *v, uint32_t numSamples) { const int16_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr; - int32_t realPos, sample, sample2, *audioMixL, *audioMixR, CDA_BytesLeft; - int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol, i, samplesToMix; - uint32_t pos, delta; + int32_t realPos, sample, sample2, *audioMixL, *audioMixR; + int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol; + uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft; #ifndef LERPMIX int32_t sample3, sample4; #endif diff --git a/src/ft2_mix_macros.h b/src/ft2_mix_macros.h @@ -14,11 +14,9 @@ v->SLVol2 = CDA_LVol; \ v->SRVol2 = CDA_RVol; \ -#define GET_DELTA \ - const uint32_t delta = v->SFrq; - #define GET_MIXER_VARS \ - const int32_t SFrqRev = v->SFrqRev; \ + const uint32_t SFrq = v->SFrq; \ + const uint32_t SFrqRev = v->SFrqRev; \ audioMixL = audio.mixBufferL; \ audioMixR = audio.mixBufferR; \ const bool mixInMono = (CDA_LVol == CDA_RVol); \ @@ -26,7 +24,8 @@ pos = v->SPosDec; \ #define GET_MIXER_VARS_RAMP \ - const int32_t SFrqRev = v->SFrqRev; \ + const uint32_t SFrq = v->SFrq; \ + const uint32_t SFrqRev = v->SFrqRev; \ audioMixL = audio.mixBufferL; \ audioMixR = audio.mixBufferR; \ CDA_LVolIP = v->SLVolIP; \ @@ -52,7 +51,7 @@ CDA_LinAdrRev = v->SRevBase16; \ #define INC_POS \ - pos += delta; \ + pos += SFrq; \ smpPtr += pos >> 16; \ pos &= 0xFFFF; \ @@ -243,17 +242,18 @@ /* ----------------------------------------------------------------------- */ #define LIMIT_MIX_NUM \ - samplesToMix = (v->SLen - 1) - realPos; \ - if (samplesToMix > 65535) \ - samplesToMix = 65535; \ + i = (v->SLen - 1) - realPos; \ + if (i > 65535) \ + i = 65535; \ \ - samplesToMix = (samplesToMix << 16) | (pos ^ 0xFFFF); \ - samplesToMix = ((int64_t)samplesToMix * SFrqRev) >> 32; \ + i = (i << 16) | (pos ^ 0xFFFF); \ + samplesToMix = ((int64_t)i * SFrqRev) >> 32; \ samplesToMix++; \ \ if (samplesToMix > CDA_BytesLeft) \ samplesToMix = CDA_BytesLeft; \ + #define LIMIT_MIX_NUM_RAMP \ if (v->SVolIPLen == 0) \ { \ @@ -274,10 +274,31 @@ v->SVolIPLen -= samplesToMix; \ } \ +#define HANDLE_SAMPLE_END \ + realPos = (int32_t)(smpPtr - CDA_LinearAdr); \ + if (realPos >= v->SLen) \ + { \ + v->mixRoutine = NULL; \ + return; \ + } \ + +#define WRAP_LOOP \ + realPos = (int32_t)(smpPtr - CDA_LinearAdr); \ + while (realPos >= v->SLen) \ + realPos -= v->SRepL; \ + smpPtr = CDA_LinearAdr + realPos; \ + +#define WRAP_BIDI_LOOP \ + while (realPos >= v->SLen) \ + { \ + realPos -= v->SRepL; \ + v->backwards ^= 1; \ + } \ + #define START_BIDI \ if (v->backwards) \ { \ - delta = 0 - v->SFrq; \ + delta = 0 - SFrq; \ assert(realPos >= v->SRepS && realPos < v->SLen); \ realPos = ~realPos; \ smpPtr = CDA_LinAdrRev + realPos; \ @@ -285,7 +306,7 @@ } \ else \ { \ - delta = v->SFrq; \ + delta = SFrq; \ assert(realPos >= 0 && realPos < v->SLen); \ smpPtr = CDA_LinearAdr + realPos; \ } \ @@ -306,31 +327,6 @@ \ /* ----------------------------------------------------------------------- */ -/* SAMPLE END/LOOP WRAPPING MACROS */ -/* ----------------------------------------------------------------------- */ - -#define HANDLE_SAMPLE_END \ - realPos = (int32_t)(smpPtr - CDA_LinearAdr); \ - if (realPos >= v->SLen) \ - { \ - v->mixRoutine = NULL; \ - return; \ - } \ - -#define WRAP_LOOP \ - realPos = (int32_t)(smpPtr - CDA_LinearAdr); \ - while (realPos >= v->SLen) \ - realPos -= v->SRepL; \ - smpPtr = CDA_LinearAdr + realPos; \ - -#define WRAP_BIDI_LOOP \ - while (realPos >= v->SLen) \ - { \ - realPos -= v->SRepL; \ - v->backwards ^= 1; \ - } \ - -/* ----------------------------------------------------------------------- */ /* VOLUME=0 OPTIMIZATION MACROS */ /* ----------------------------------------------------------------------- */ diff --git a/src/ft2_replayer.c b/src/ft2_replayer.c @@ -26,7 +26,8 @@ */ static bool bxxOverflow; -static int32_t oldPeriod, oldRate, frequenceDivFactor, frequenceMulFactor; +static int32_t oldPeriod, oldRate; +static uint32_t frequenceDivFactor, frequenceMulFactor; static tonTyp nilPatternLine; // globally accessed @@ -324,27 +325,16 @@ void calcReplayRate(int32_t rate) // 100% FT2-accurate routine, do not touch! if (rate == 0) return; - // for voice delta calculation - - double dVal, dMul = 1.0 / rate; - - dVal = dMul * (65536.0 * 1712.0 * 8363.0); - frequenceDivFactor = (int32_t)(dVal + 0.5); - - dVal = dMul * (256.0 * 65536.0 * 8363.0); - frequenceMulFactor = (int32_t)(dVal + 0.5); - - audio.dScopeFreqMul = rate / SCOPE_HZ; - - // for volume ramping (FT2 doesn't round here) + // the following calculations are 100% accurate to FT2, do not touch! + frequenceDivFactor = (int32_t)round(65536.0 * 1712.0 / rate * 8363.0); + frequenceMulFactor = (int32_t)round(256.0 * 65536.0 / rate * 8363.0); audio.quickVolSizeVal = rate / 200; + // the following are non-FT2 calculations audio.rampQuickVolMul = (int32_t)round((UINT32_MAX + 1.0) / audio.quickVolSizeVal); + audio.dSpeedValMul = editor.dPerfFreq / rate; // for audio/video sync - // for audio/video sync - audio.dSpeedValMul = (1.0 / rate) * editor.dPerfFreq; - - uint32_t deltaBase = frequenceDivFactor / (1712 * 16); // exact 16.16 delta base for this audio rate + const uint32_t deltaBase = frequenceDivFactor / (1712 * 16); // exact 16.16 delta base audio.dPianoDeltaMul = 1.0 / deltaBase; // for piano in Instr. Ed. } diff --git a/src/ft2_scopedraw.c b/src/ft2_scopedraw.c @@ -60,12 +60,12 @@ } \ #define SCOPE_UPDATE_DRAWPOS \ - scopeDrawFrac += s->SFrq >> 6; \ + scopeDrawFrac += (uint32_t)(s->SFrq >> (SCOPE_FRAC_BITS - 10)); \ scopeDrawPos += scopeDrawFrac >> 16; \ scopeDrawFrac &= 0xFFFF; \ #define SCOPE_UPDATE_DRAWPOS_PINGPONG \ - scopeDrawFrac += s->SFrq >> 6; \ + scopeDrawFrac += (uint32_t)(s->SFrq >> (SCOPE_FRAC_BITS - 10)); \ scopeDrawPos += (scopeDrawFrac >> 16) * drawPosDir; \ scopeDrawFrac &= 0xFFFF; \ diff --git a/src/ft2_scopes.c b/src/ft2_scopes.c @@ -22,6 +22,10 @@ #include "ft2_scopedraw.h" #include "ft2_tables.h" +#if SCOPE_HZ != 64 +#error The SCOPE_HZ definition in ft2_header.h must be 2^n! +#endif + enum { LOOP_NONE = 0, @@ -40,8 +44,9 @@ typedef struct scopeState_t } scopeState_t; static volatile bool scopesUpdatingFlag, scopesDisplayingFlag; -static uint32_t oldVoiceDelta, oldSFrq, scopeTimeLen, scopeTimeLenFrac; -static uint64_t timeNext64, timeNext64Frac; +static int32_t oldPeriod; +static uint32_t scopeTimeLen, scopeTimeLenFrac; +static uint64_t timeNext64, timeNext64Frac, oldSFrq; static volatile scope_t scope[MAX_VOICES]; static SDL_Thread *scopeThread; static uint8_t *scopeMuteBMP_Ptrs[16]; @@ -50,7 +55,7 @@ lastChInstr_t lastChInstr[MAX_VOICES]; // global void resetCachedScopeVars(void) { - oldVoiceDelta = 0xFFFFFFFF; + oldPeriod = -1; oldSFrq = 0; } @@ -405,8 +410,8 @@ static void updateScopes(void) // scope position update tempState.SPosDec += tempState.SFrq; - tempState.SPos += ((tempState.SPosDec >> 16) * tempState.SPosDir); - tempState.SPosDec &= 0xFFFF; + tempState.SPos += ((int32_t)(tempState.SPosDec >> SCOPE_FRAC_BITS) * tempState.SPosDir); + tempState.SPosDec &= SCOPE_FRAC_MASK; // handle loop wrapping or sample end @@ -558,10 +563,10 @@ void handleScopesFromChQueue(chSyncData_t *chSyncData, uint8_t *scopeUpdateStatu // set scope frequency if (status & IS_Period) { - if (ch->voiceDelta != oldVoiceDelta) + if (ch->finalPeriod != oldPeriod) { - oldVoiceDelta = ch->voiceDelta; - oldSFrq = (int32_t)(((int32_t)oldVoiceDelta * audio.dScopeFreqMul) + 0.5); // rounded + oldPeriod = ch->finalPeriod; + oldSFrq = (uint64_t)ch->voiceDelta * audio.freq; // this can very well be higher than 2^32 } sc->SFrq = oldSFrq; diff --git a/src/ft2_scopes.h b/src/ft2_scopes.h @@ -4,6 +4,12 @@ #include <stdbool.h> #include "ft2_header.h" +// log2(65536 / SCOPE_HZ) where SCOPE_HZ is 2^n +#define SCOPE_FRAC_BITS 22 + +#define SCOPE_FRAC_SCALE (1UL << SCOPE_FRAC_BITS) +#define SCOPE_FRAC_MASK (SCOPE_FRAC_SCALE-1) + void resetCachedScopeVars(void); int32_t getSamplePosition(uint8_t ch); void stopAllScopes(void); @@ -23,7 +29,7 @@ typedef struct scope_t bool wasCleared, sample16Bit; uint8_t loopType; int32_t SPosDir, SRepS, SRepL, SLen, SPos; - uint32_t SFrq, SPosDec; + uint64_t SFrq, SPosDec; } scope_t; typedef struct lastChInstr_t diff --git a/src/ft2_scrollbars.c b/src/ft2_scrollbars.c @@ -24,7 +24,7 @@ ** it's difficult to use them. In units of pixels. ** Shouldn't be higher than 9! */ -#define MIN_THUMB_LENGTH 9 +#define MIN_THUMB_LENGTH 5 scrollBar_t scrollBars[NUM_SCROLLBARS] = { @@ -271,7 +271,7 @@ static void setScrollBarThumbCoords(uint16_t scrollBarID) { dTmp = (scrollBar->h / (double)scrollBar->end) * scrollBar->page; tmp32 = (int32_t)(dTmp + 0.5); - realThumbLength = (int16_t)CLAMP(tmp32, MIN_THUMB_LENGTH, scrollBar->h); + realThumbLength = (int16_t)CLAMP(tmp32, 1, scrollBar->h); } else { @@ -279,8 +279,8 @@ static void setScrollBarThumbCoords(uint16_t scrollBarID) } thumbH = realThumbLength; - if (thumbW < MIN_THUMB_LENGTH) - thumbW = MIN_THUMB_LENGTH; + if (thumbH < MIN_THUMB_LENGTH) + thumbH = MIN_THUMB_LENGTH; if (scrollBar->end > scrollBar->page) { @@ -578,7 +578,7 @@ bool testScrollBarMouseDown(void) assert(scrollBar->h > 0); scrollPos = CLAMP(scrollPos, 0, scrollBar->h); - length = scrollBar->h + (scrollBar->realThumbLength - scrollBar->thumbW); + length = scrollBar->h + (scrollBar->realThumbLength - scrollBar->thumbH); if (length < 1) length = 1; @@ -669,6 +669,8 @@ void handleScrollBarsWhileMouseDown(void) mouse.lastScrollY = mouse.y; scrollY = mouse.lastScrollY - mouse.saveMouseY - scrollBar->y; + + assert(scrollBar->h > 0); scrollY = CLAMP(scrollY, 0, scrollBar->h); length = scrollBar->h + (scrollBar->realThumbLength - scrollBar->thumbH); diff --git a/src/ft2_video.c b/src/ft2_video.c @@ -162,8 +162,6 @@ void endFPSCounter(void) void flipFrame(void) { - uint32_t windowFlags = SDL_GetWindowFlags(video.window); - renderSprites(); if (video.showFPSCounter) @@ -181,6 +179,8 @@ void flipFrame(void) } else { + uint32_t windowFlags = SDL_GetWindowFlags(video.window); + /* We have VSync, but it can unexpectedly get inactive in certain scenarios. ** We have to force thread sleeping (to ~60Hz) if so. */