ref: 9e6e95166ac606b05631c0ebacd81e93038f073e
parent: 4cb9cdc4475ea90ba9eb591cf00628ec60230f74
author: Olav Sørensen <olav.sorensen@live.no>
date: Mon Apr 6 17:53:03 EDT 2020
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)
--- 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 @@
{
if (ch->finalPeriod != oldPeriod) // this value will very often be the same as before
{
+ oldPeriod = ch->finalPeriod;
+
oldSFrq = getFrequenceValue(ch->finalPeriod);
oldSFrqRev = 0xFFFFFFFF;
--- a/src/ft2_audio.h
+++ b/src/ft2_audio.h
@@ -33,7 +33,7 @@
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 @@
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;
--- a/src/ft2_diskop.c
+++ b/src/ft2_diskop.c
@@ -1478,6 +1478,9 @@
}
#endif
+ if (searchRec->filesize < -1)
+ searchRec->filesize = -1;
+
if (handleEntrySkip(searchRec->nameU, searchRec->isDir))
{
// skip file
@@ -1557,6 +1560,9 @@
}
}
#endif
+
+ if (searchRec->filesize < -1)
+ searchRec->filesize = -1;
if (handleEntrySkip(searchRec->nameU, searchRec->isDir))
{
--- 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...
--- a/src/ft2_main.c
+++ b/src/ft2_main.c
@@ -119,7 +119,8 @@
/* 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 @@
/* 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__
--- a/src/ft2_mix.c
+++ b/src/ft2_mix.c
@@ -38,8 +38,8 @@
{
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 @@
}
GET_MIXER_VARS
- GET_DELTA
SET_BASE8
CDA_BytesLeft = numSamples;
@@ -102,8 +101,8 @@
{
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 @@
}
GET_MIXER_VARS
- GET_DELTA
SET_BASE8
CDA_BytesLeft = numSamples;
@@ -166,8 +164,8 @@
{
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 @@
{
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 @@
}
GET_MIXER_VARS
- GET_DELTA
SET_BASE8
CDA_BytesLeft = numSamples;
@@ -297,8 +294,8 @@
{
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 @@
}
GET_MIXER_VARS
- GET_DELTA
SET_BASE8
CDA_BytesLeft = numSamples;
@@ -364,8 +360,8 @@
{
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 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 @@
}
GET_MIXER_VARS_RAMP
- GET_DELTA
SET_BASE8
CDA_BytesLeft = numSamples;
@@ -502,9 +497,9 @@
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 @@
}
GET_MIXER_VARS_RAMP
- GET_DELTA
SET_BASE8
CDA_BytesLeft = numSamples;
@@ -573,9 +567,9 @@
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 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 @@
}
GET_MIXER_VARS_RAMP
- GET_DELTA
SET_BASE8
CDA_BytesLeft = numSamples;
@@ -719,9 +712,9 @@
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 @@
}
GET_MIXER_VARS_RAMP
- GET_DELTA
SET_BASE8
CDA_BytesLeft = numSamples;
@@ -793,9 +785,9 @@
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 @@
{
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 @@
}
GET_MIXER_VARS
- GET_DELTA
SET_BASE16
CDA_BytesLeft = numSamples;
@@ -938,8 +929,8 @@
{
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 @@
}
GET_MIXER_VARS
- GET_DELTA
SET_BASE16
CDA_BytesLeft = numSamples;
@@ -1002,8 +992,8 @@
{
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 @@
{
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 @@
}
GET_MIXER_VARS
- GET_DELTA
SET_BASE16
CDA_BytesLeft = numSamples;
@@ -1134,8 +1123,8 @@
{
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 @@
}
GET_MIXER_VARS
- GET_DELTA
SET_BASE16
CDA_BytesLeft = numSamples;
@@ -1201,8 +1189,8 @@
{
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 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 @@
}
GET_MIXER_VARS_RAMP
- GET_DELTA
SET_BASE16
CDA_BytesLeft = numSamples;
@@ -1339,9 +1326,9 @@
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 @@
}
GET_MIXER_VARS_RAMP
- GET_DELTA
SET_BASE16
CDA_BytesLeft = numSamples;
@@ -1410,9 +1396,9 @@
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 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 @@
}
GET_MIXER_VARS_RAMP
- GET_DELTA
SET_BASE16
CDA_BytesLeft = numSamples;
@@ -1556,9 +1541,9 @@
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 @@
}
GET_MIXER_VARS_RAMP
- GET_DELTA
SET_BASE16
CDA_BytesLeft = numSamples;
@@ -1630,9 +1614,9 @@
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
--- 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; \
} \
@@ -304,31 +325,6 @@
realPos = (int32_t)(smpPtr - CDA_LinearAdr); \
} \
\
-
-/* ----------------------------------------------------------------------- */
-/* 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 */
--- 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 @@
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.
}
--- 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; \
--- 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 @@
} 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 @@
void resetCachedScopeVars(void)
{
- oldVoiceDelta = 0xFFFFFFFF;
+ oldPeriod = -1;
oldSFrq = 0;
}
@@ -405,8 +410,8 @@
// 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 @@
// 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;
--- 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 @@
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
--- 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 @@
{
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 @@
}
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 @@
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 @@
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);
--- a/src/ft2_video.c
+++ b/src/ft2_video.c
@@ -162,8 +162,6 @@
void flipFrame(void)
{
- uint32_t windowFlags = SDL_GetWindowFlags(video.window);
-
renderSprites();
if (video.showFPSCounter)
@@ -181,6 +179,8 @@
}
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.
*/