Updated playptmod to fix some bugs with glissando slides

CQTexperiment
Chris Moeller 2015-02-05 16:37:21 -08:00
parent 8c6f1fa152
commit dab47057a3
1 changed files with 116 additions and 64 deletions

View File

@ -1,7 +1,11 @@
/* /*
** - playptmod v1.16 - 23rd of January 2015 - ** - playptmod v1.2 - 3rd of February 2015 -
** This is the foobar2000 version, with added code by kode54 ** This is the foobar2000 version, with added code by kode54
** **
** Changelog from 1.16:
** - The sample swap quirk had a bug (discovered by Wasp of PowerLine)
** - 3xx/5xy was still wrong in PT mode (fixes "MOD.lite teknalogy" by tEiS)
**
** Changelog from 1.15b: ** Changelog from 1.15b:
** - Glissando (3xx/5xy) should not continue after its slide was done, ** - Glissando (3xx/5xy) should not continue after its slide was done,
** but this only applies to MODs playing in ProTracker mode. ** but this only applies to MODs playing in ProTracker mode.
@ -44,7 +48,7 @@
#define HI_NYBBLE(x) ((x) >> 4) #define HI_NYBBLE(x) ((x) >> 4)
#define LO_NYBBLE(x) ((x) & 0x0F) #define LO_NYBBLE(x) ((x) & 0x0F)
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#define DENORMAL_OFFSET 1E-10f #define DENORMAL_OFFSET 1e-10f
#define PT_MIN_PERIOD 78 #define PT_MIN_PERIOD 78
#define PT_MAX_PERIOD 937 #define PT_MAX_PERIOD 937
#define MAX_CHANNELS 32 #define MAX_CHANNELS 32
@ -135,9 +139,10 @@ typedef struct
unsigned char invertLoopDelay; unsigned char invertLoopDelay;
unsigned char invertLoopSpeed; unsigned char invertLoopSpeed;
unsigned char chanIndex; unsigned char chanIndex;
unsigned char doGlissando; unsigned char toneportdirec;
short period; short period;
short tempPeriod; short tempPeriod;
short wantedperiod;
int noNote; int noNote;
int invertLoopOffset; int invertLoopOffset;
int offset; int offset;
@ -431,7 +436,7 @@ static void mixerSwapChSource(player *p, int ch, const signed char *src, int len
// sample will play through first (either // sample will play through first (either
// >len or >loop_len), then when that is // >len or >loop_len), then when that is
// reached you change to the new sample you // reached you change to the new sample you
// put earlier. // put earlier (if new sample is looped)
v = &p->v[ch]; v = &p->v[ch];
@ -444,8 +449,9 @@ static void mixerSwapChSource(player *p, int ch, const signed char *src, int len
v->newStep = step; v->newStep = step;
v->interpolating = 1; v->interpolating = 1;
// if the mixer was already shut down because of a short non-loop sample, force swap // if the mixer was already shut down earlier after a non-loop swap,
if (v->data == NULL) // force swap again, but only if the new sample has loop enabled (ONLY!)
if ((v->data == NULL) && v->newLoopFlag)
{ {
v->loopBegin = v->newLoopBegin; v->loopBegin = v->newLoopBegin;
v->loopEnd = v->newLoopEnd; v->loopEnd = v->newLoopEnd;
@ -454,9 +460,9 @@ static void mixerSwapChSource(player *p, int ch, const signed char *src, int len
v->length = v->newLength; v->length = v->newLength;
v->step = v->newStep; v->step = v->newStep;
// for safety, shut down voice if the sample position is overriding the length // we need to wrap here for safety reasons
if (v->index >= v->length) while (v->index >= v->loopEnd)
v->data = NULL; v->index = v->loopBegin + (v->index - v->loopEnd);
} }
} }
@ -1859,72 +1865,126 @@ static void efxInvertLoop(player *p, mod_channel *ch)
} }
} }
// -- this is only for PT mode ----------------------------
static void setupGlissando(mod_channel *ch, short period)
{
unsigned char i;
const short *tablePointer;
tablePointer = &rawAmigaPeriods[37 * ch->fineTune];
i = 0;
while (true)
{
if (period >= tablePointer[i])
break;
if (++i >= 37)
{
i = 35;
break;
}
}
if ((ch->fineTune & 8) && i) i--; // yes, PT does this
ch->wantedperiod = tablePointer[i];
ch->toneportdirec = 0;
if (ch->period == ch->wantedperiod)
ch->wantedperiod = 0; // don't do any more slides
else if (ch->period > ch->wantedperiod)
ch->toneportdirec = 1;
}
// --------------------------------------------------------
static void handleGlissando(player *p, mod_channel *ch) static void handleGlissando(player *p, mod_channel *ch)
{ {
unsigned char i;
char l; char l;
char m; char m;
char h; char h;
short *tablePointer; const short *tablePointer;
// quirk for glissando in PT mode // different routine for PT mode
if ((p->minPeriod == PT_MIN_PERIOD) && !ch->doGlissando) if (p->minPeriod == PT_MIN_PERIOD)
return; {
if (ch->wantedperiod != 0)
{
if (ch->toneportdirec == 0)
{
// downwards
ch->period += ch->glissandoSpeed;
if (ch->period >= ch->wantedperiod)
{
ch->period = ch->wantedperiod;
ch->wantedperiod = 0;
}
}
else
{
// upwards
ch->period -= ch->glissandoSpeed;
if (ch->period <= ch->wantedperiod)
{
ch->period = ch->wantedperiod;
ch->wantedperiod = 0;
}
}
if (ch->glissandoControl == 0)
{
p->tempPeriod = ch->period;
}
else
{
tablePointer = &rawAmigaPeriods[37 * ch->fineTune];
i = 0;
while (true)
{
if (ch->period >= tablePointer[i])
break;
if (++i >= 37)
{
i = 35;
break;
}
}
p->tempPeriod = tablePointer[i];
}
}
}
else
{
if (p->tempPeriod > 0) if (p->tempPeriod > 0)
{ {
if (ch->period < ch->tempPeriod) if (ch->period < ch->tempPeriod)
{ {
ch->period += ch->glissandoSpeed; ch->period += ch->glissandoSpeed;
if (ch->period >= ch->tempPeriod) if (ch->period > ch->tempPeriod)
{
ch->period = ch->tempPeriod; ch->period = ch->tempPeriod;
ch->doGlissando = false;
}
} }
else else
{ {
ch->period -= ch->glissandoSpeed; ch->period -= ch->glissandoSpeed;
if (ch->period <= ch->tempPeriod) if (ch->period < ch->tempPeriod)
{
ch->period = ch->tempPeriod; ch->period = ch->tempPeriod;
ch->doGlissando = false;
}
} }
if (ch->glissandoControl != 0) if (ch->glissandoControl == 0)
{ {
if (p->minPeriod == PT_MIN_PERIOD) p->tempPeriod = ch->period;
{
l = 0;
h = 35;
tablePointer = (short *)&rawAmigaPeriods[ch->fineTune * 37];
while (h >= l)
{
m = (h + l) / 2;
if (tablePointer[m] == ch->period)
{
p->tempPeriod = tablePointer[m];
break;
}
else if (tablePointer[m] > ch->period)
{
l = m + 1;
}
else
{
h = m - 1;
}
}
} }
else else
{ {
l = 0; l = 0;
h = 83; h = 83;
tablePointer = (short *)&extendedRawPeriods[ch->fineTune * 85]; tablePointer = (short *)&extendedRawPeriods[85 * ch->fineTune];
while (h >= l) while (h >= l)
{ {
m = (h + l) / 2; m = (h + l) / 2;
@ -1945,10 +2005,6 @@ static void handleGlissando(player *p, mod_channel *ch)
} }
} }
} }
else
{
p->tempPeriod = ch->period;
}
} }
} }
@ -2502,15 +2558,11 @@ static void fetchPatternData(player *p, mod_channel *ch)
ch->flags |= FLAG_NOTE; ch->flags |= FLAG_NOTE;
} }
// 3xx/5xy quirk for PT MODs // do a slightly different path for 3xx/5xy in PT mode
if (p->minPeriod == PT_MIN_PERIOD) if (p->minPeriod == PT_MIN_PERIOD)
{ {
if ((ch->command == 0x03) || (ch->command == 0x05)) if ((ch->command == 0x03) || (ch->command == 0x05))
{ setupGlissando(ch, note->period);
ch->doGlissando = true;
if (!ch->period || (ch->period == ch->tempPeriod))
ch->doGlissando = false;
}
} }
} }
else else