Updated playptmod to version 1.31.

CQTexperiment
Christopher Snowhill 2016-12-22 20:43:29 -08:00
parent 68f8979bbe
commit bcff934561
2 changed files with 127 additions and 52 deletions

View File

@ -1,8 +1,17 @@
/*
** PLAYPTMOD v1.27 - 8th of October 2015 - http://16-bits.org
** ==========================================================
** PLAYPTMOD v1.31 - 23rd of December 2016 - http://16-bits.org
** ==============================================================
** This is the foobar2000 version, with added code by kode54
**
** Changelog from 1.3:
** - Fixed an unchecked memcpy when testing for ADPCM samples in possible STK files
**
** Changelog from 1.27:
** - Added support for FEST modules (.MOD with "FEST" tag instead of "M.K.")
** - Added the one-shot loop quirk for PT MODs
** - When setting mixSource, check loopLen>2 *or* loopStart>0 (yes, like PT)
** - Using 9xx on a >64kB sample should result in killing the voice (PT only)
**
** Changelog from 1.26:
** - Only loop module if speed is zero after fully processing an entire row
**
@ -215,6 +224,7 @@ typedef struct voice_data
int newLoopBegin;
int newLoopEnd;
int index;
int loopQuirk;
int vol;
int panL;
int panR;
@ -449,7 +459,7 @@ static inline int periodToNote(player *p, char finetune, short period)
break;
}
return i;
return (i);
}
static void mixerSwapChSource(player *p, int ch, const signed char *src, int length, int loopStart, int loopLength, int step)
@ -465,29 +475,30 @@ static void mixerSwapChSource(player *p, int ch, const signed char *src, int len
v = &p->v[ch];
v->swapSampleFlag = true;
v->newData = src;
v->newLoopFlag = loopLength > (2 * step);
v->newLength = length;
v->newLoopBegin = loopStart;
v->newLoopEnd = loopStart + loopLength;
v->newStep = step;
v->interpolating = 1;
v->loopQuirk = false;
v->swapSampleFlag = true;
v->newData = src;
v->newLoopFlag = (loopStart + loopLength) > (2 * step);
v->newLength = length;
v->newLoopBegin = loopStart;
v->newLoopEnd = loopStart + loopLength;
v->newStep = step;
v->interpolating = 1;
// if the mixer was already shut down earlier after a non-loop swap,
// force swap again, but only if the new sample has loop enabled (ONLY!)
if ((v->data == NULL) && v->newLoopFlag)
{
v->loopBegin = v->newLoopBegin;
v->loopEnd = v->newLoopEnd;
v->loopFlag = v->newLoopFlag;
v->data = v->newData;
v->length = v->newLength;
v->step = v->newStep;
v->loopBegin = v->newLoopBegin;
v->loopEnd = v->newLoopEnd;
v->loopFlag = v->newLoopFlag;
v->data = v->newData;
v->length = v->newLength;
v->step = v->newStep;
/* we need to wrap here for safety reasons */
while (v->index >= v->loopEnd)
v->index = v->loopBegin + (v->index - v->loopEnd);
v->index = v->loopBegin + (v->index - v->loopEnd);
}
}
@ -497,11 +508,12 @@ static void mixerSetChSource(player *p, int ch, const signed char *src, int leng
v = &p->v[ch];
v->loopQuirk = false;
v->swapSampleFlag = false;
v->data = src;
v->index = offset;
v->length = length;
v->loopFlag = loopLength > (2 * step);
v->loopFlag = (loopStart + loopLength) > (2 * step);
v->loopBegin = loopStart;
v->loopEnd = loopStart + loopLength;
v->step = step;
@ -521,6 +533,24 @@ static void mixerSetChSource(player *p, int ch, const signed char *src, int leng
if (offset >= v->length)
v->data = NULL;
}
/* PT specific quirks */
if (p->minPeriod == PT_MIN_PERIOD)
{
/* One-shot loops */
if ((loopLength > 2) && (loopStart == 0))
{
v->loopQuirk = v->loopEnd;
v->loopEnd = v->length;
}
/* 9xx on >64kB samples = kill voice */
if ((length > 65534) && (offset > 0))
{
v->loopQuirk = false;
v->data = NULL;
}
}
}
// adejr: these sin/cos approximations both use a 0..1
@ -593,7 +623,7 @@ static void outputAudio(player *p, int *target, int numSamples)
int *out;
int step;
int tempVolume;
/*int delta;*/
int delta;
int interpolating;
unsigned int i;
unsigned int j;
@ -656,18 +686,24 @@ static void outputAudio(player *p, int *target, int numSamples)
break;
}
v->loopBegin = v->newLoopBegin;
v->loopEnd = v->newLoopEnd;
v->loopFlag = v->newLoopFlag;
v->data = v->newData;
v->length = v->newLength;
v->step = v->newStep;
v->loopBegin = v->newLoopBegin;
v->loopEnd = v->newLoopEnd;
v->loopFlag = v->newLoopFlag;
v->data = v->newData;
v->length = v->newLength;
v->step = v->newStep;
v->index = v->loopBegin;
}
else
{
v->index = v->loopBegin;
if (v->loopQuirk)
{
v->loopEnd = v->loopQuirk;
v->loopQuirk = false;
}
}
}
}
@ -683,12 +719,12 @@ static void outputAudio(player *p, int *target, int numSamples)
break;
}
v->loopBegin = v->newLoopBegin;
v->loopEnd = v->newLoopEnd;
v->loopFlag = v->newLoopFlag;
v->data = v->newData;
v->length = v->newLength;
v->step = v->newStep;
v->loopBegin = v->newLoopBegin;
v->loopEnd = v->newLoopEnd;
v->loopFlag = v->newLoopFlag;
v->data = v->newData;
v->length = v->newLength;
v->step = v->newStep;
v->index = v->loopBegin;
}
@ -1075,7 +1111,17 @@ static void checkModType(MODULE_HEADER *h, player *p, const char *buf)
p->maxPeriod = PT_MAX_PERIOD;
return;
}
else if (!strncmp(buf, "FEST", 4))
{
h->format = FORMAT_FEST; /* NoiseTracker 1.0, special ones (from music disk?) */
p->numChans = h->channelCount = 4;
/* Normal period range */
p->minPeriod = PT_MIN_PERIOD;
p->maxPeriod = PT_MAX_PERIOD;
return;
}
h->format = FORMAT_UNKNOWN; /* May be The Ultimate SoundTracker, 15 samples */
p->numChans = h->channelCount = 4;
@ -1137,7 +1183,7 @@ int playptmod_LoadMem(void *_p, const unsigned char *buf, unsigned long bufLengt
{
i = playptmod_LoadMTM(p, fmodule);
bufclose(fmodule);
return i;
return (i);
}
bufseek(fmodule, 0x0438, SEEK_SET);
@ -1165,8 +1211,12 @@ int playptmod_LoadMem(void *_p, const unsigned char *buf, unsigned long bufLengt
if (s->length > 9999)
lateVerSTKFlag = true; /* Only used if mightBeSTK is set */
bufread(&s->fineTune, 1, 1, fmodule);
s->fineTune = s->fineTune & 0x0F;
tmp = 0;
bufread(&tmp, 1, 1, fmodule); /* xxx: is this big-endian safe? */
if (p->source->head.format == FORMAT_FEST)
s->fineTune = (-tmp & 0x1F) / 2; /* One more bit of precision, + inverted */
else
s->fineTune = tmp & 0x0F;
bufread(&s->volume, 1, 1, fmodule);
if (s->volume > 64)
@ -1381,8 +1431,14 @@ int playptmod_LoadMem(void *_p, const unsigned char *buf, unsigned long bufLengt
if ((note->param > 0x8F) && (note->param != 0xA4))
extendedPanning = true;
}
if (mightBeSTK)
if (p->source->head.format == FORMAT_FEST)
{
/* Any Dxx == D00 in FEST modules */
if (note->command == 0x0D)
note->param = 0x00;
}
else if (mightBeSTK)
{
// Convert STK effects to PT effects
// TODO: Add tracker checking, as there
@ -1446,6 +1502,24 @@ int playptmod_LoadMem(void *_p, const unsigned char *buf, unsigned long bufLengt
if (j > s->length)
j = s->length;
if (j < 0 || j > 131072)
{
bufclose(fmodule);
for (pattern = 0; pattern < 256; ++i)
{
if (p->source->patterns[pattern] != NULL)
{
free(p->source->patterns[pattern]);
p->source->patterns[pattern] = NULL;
}
}
free(p->source);
return (false);
}
bufread(tempSample, 1, j, fmodule);
smpDat8 = tempSample;
@ -1584,7 +1658,7 @@ int playptmod_Load(void *_p, const char *filename)
free(buffer);
return i;
return (i);
}
return (false);
@ -2262,7 +2336,7 @@ static void fxArpeggio(player *p, mod_channel *ch)
static void fxPortamentoSlideUp(player *p, mod_channel *ch)
{
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) // all ticks while EDx (weird)
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) /* all ticks while EDx (weird) */
{
if (p->tempPeriod > 0)
{
@ -2286,7 +2360,7 @@ static void fxPortamentoSlideUp(player *p, mod_channel *ch)
static void fxPortamentoSlideDown(player *p, mod_channel *ch)
{
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) // all ticks while EDx (weird)
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) /* all ticks while EDx (weird) */
{
if (p->tempPeriod > 0)
{
@ -2310,7 +2384,7 @@ static void fxPortamentoSlideDown(player *p, mod_channel *ch)
static void fxGlissando(player *p, mod_channel *ch)
{
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) // all ticks while EDx (weird)
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) /* all ticks while EDx (weird) */
{
if (ch->param != 0)
{
@ -2344,7 +2418,7 @@ static void fxVibrato(player *p, mod_channel *ch)
static void fxGlissandoVolumeSlide(player *p, mod_channel *ch)
{
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) // all ticks while EDx (weird)
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) /* all ticks while EDx (weird) */
{
processGlissando(p, ch);
fxVolumeSlide(p, ch);
@ -2353,7 +2427,7 @@ static void fxGlissandoVolumeSlide(player *p, mod_channel *ch)
static void fxVibratoVolumeSlide(player *p, mod_channel *ch)
{
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) // all ticks while EDx (weird)
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) /* all ticks while EDx (weird) */
{
processVibrato(p, ch);
fxVolumeSlide(p, ch);
@ -2416,7 +2490,7 @@ static void fxVolumeSlide(player *p, mod_channel *ch)
unsigned char hiNybble;
unsigned char loNybble;
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) // all ticks while EDx (weird)
if ((p->modTick > 0) || (p->PattDelayTime2 > 0)) /* all ticks while EDx (weird) */
{
hiNybble = ch->param >> 4;
loNybble = ch->param & 0x0F;
@ -2470,7 +2544,7 @@ static void fxPatternBreak(player *p, mod_channel *ch)
if (p->modTick == 0)
{
pos = (((ch->param >> 4) * 10) + (ch->param & 0x0F));
pos = ((ch->param >> 4) * 10) + (ch->param & 0x0F);
if (pos > 63)
p->PBreakPosition = 0;
@ -2517,8 +2591,8 @@ static void fxSetTempo(player *p, mod_channel *ch)
static void processEffects(player *p, mod_channel *ch)
{
if (p->modTick > 0)
processInvertLoop(p, ch);
if (p->modTick > 0)
processInvertLoop(p, ch);
if ((!ch->command && !ch->param) == 0)
{
@ -2696,7 +2770,7 @@ static void processChannel(player *p, mod_channel *ch)
{
ch->flags &= ~FLAG_NEWSAMPLE;
// sample swapping (PT only)
/* sample swapping (PT only) */
if ((ch->sample > 0) && (p->minPeriod == PT_MIN_PERIOD))
{
s = &p->source->samples[ch->sample - 1];
@ -2821,7 +2895,6 @@ static void processTick(player *p)
p->PosJumpAssert = true;
}
p->modTick++;
if (p->modTick >= p->modSpeed)
{
@ -2877,6 +2950,7 @@ void playptmod_Render(void *_p, int *target, int length)
outputAudio(p, target, tempSamples);
target += tempSamples * 2;
}
p->sampleCounter -= tempSamples;
length -= tempSamples;
}
@ -2936,12 +3010,12 @@ void *playptmod_Create(int samplingFrequency)
for (i = 14; i <= 1712; ++i) /* 0..13 will never be looked up, junk is OK */
p->extendedFrequencyTable[i] = (float)samplingFrequency / (3546895.0f / (float)i);
// generate extended period table
/* generate extended period table */
for (j = 0; j < 16; ++j)
for (i = 0; i < ((12 * 7) + 1); ++i)
extendedRawPeriods[(j * ((12 * 7) + 1)) + i] = (i == (12 * 7)) ? 0 : (npertab[i] * 8363 / finetune[j]);
// add padding (zeroes)
/* add padding (zeroes) */
for (i = 0; i < 14; ++i)
extendedRawPeriods[(16 * ((12 * 7) + 1)) + i] = 0;
@ -2965,7 +3039,7 @@ void *playptmod_Create(int samplingFrequency)
mixerCutChannels(p);
return p;
return (p);
}
void playptmod_Config(void *_p, int option, int value)

View File

@ -17,6 +17,7 @@ enum
FORMAT_32CN, // FastTracker II (32 channel MODs)
FORMAT_STK, // The Ultimate SoundTracker (15 samples)
FORMAT_NT, // NoiseTracker 1.0
FORMAT_FEST, // NoiseTracker (special ones)
FORMAT_MTM, // MultiTracker