Updated playptmod to version 1.31.
parent
68f8979bbe
commit
bcff934561
|
@ -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
|
** 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:
|
** Changelog from 1.26:
|
||||||
** - Only loop module if speed is zero after fully processing an entire row
|
** - Only loop module if speed is zero after fully processing an entire row
|
||||||
**
|
**
|
||||||
|
@ -215,6 +224,7 @@ typedef struct voice_data
|
||||||
int newLoopBegin;
|
int newLoopBegin;
|
||||||
int newLoopEnd;
|
int newLoopEnd;
|
||||||
int index;
|
int index;
|
||||||
|
int loopQuirk;
|
||||||
int vol;
|
int vol;
|
||||||
int panL;
|
int panL;
|
||||||
int panR;
|
int panR;
|
||||||
|
@ -449,7 +459,7 @@ static inline int periodToNote(player *p, char finetune, short period)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return (i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mixerSwapChSource(player *p, int ch, const signed char *src, int length, int loopStart, int loopLength, int step)
|
static void mixerSwapChSource(player *p, int ch, const signed char *src, int length, int loopStart, int loopLength, int step)
|
||||||
|
@ -465,9 +475,10 @@ static void mixerSwapChSource(player *p, int ch, const signed char *src, int len
|
||||||
|
|
||||||
v = &p->v[ch];
|
v = &p->v[ch];
|
||||||
|
|
||||||
|
v->loopQuirk = false;
|
||||||
v->swapSampleFlag = true;
|
v->swapSampleFlag = true;
|
||||||
v->newData = src;
|
v->newData = src;
|
||||||
v->newLoopFlag = loopLength > (2 * step);
|
v->newLoopFlag = (loopStart + loopLength) > (2 * step);
|
||||||
v->newLength = length;
|
v->newLength = length;
|
||||||
v->newLoopBegin = loopStart;
|
v->newLoopBegin = loopStart;
|
||||||
v->newLoopEnd = loopStart + loopLength;
|
v->newLoopEnd = loopStart + loopLength;
|
||||||
|
@ -497,11 +508,12 @@ static void mixerSetChSource(player *p, int ch, const signed char *src, int leng
|
||||||
|
|
||||||
v = &p->v[ch];
|
v = &p->v[ch];
|
||||||
|
|
||||||
|
v->loopQuirk = false;
|
||||||
v->swapSampleFlag = false;
|
v->swapSampleFlag = false;
|
||||||
v->data = src;
|
v->data = src;
|
||||||
v->index = offset;
|
v->index = offset;
|
||||||
v->length = length;
|
v->length = length;
|
||||||
v->loopFlag = loopLength > (2 * step);
|
v->loopFlag = (loopStart + loopLength) > (2 * step);
|
||||||
v->loopBegin = loopStart;
|
v->loopBegin = loopStart;
|
||||||
v->loopEnd = loopStart + loopLength;
|
v->loopEnd = loopStart + loopLength;
|
||||||
v->step = step;
|
v->step = step;
|
||||||
|
@ -521,6 +533,24 @@ static void mixerSetChSource(player *p, int ch, const signed char *src, int leng
|
||||||
if (offset >= v->length)
|
if (offset >= v->length)
|
||||||
v->data = NULL;
|
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
|
// 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 *out;
|
||||||
int step;
|
int step;
|
||||||
int tempVolume;
|
int tempVolume;
|
||||||
/*int delta;*/
|
int delta;
|
||||||
int interpolating;
|
int interpolating;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
@ -668,6 +698,12 @@ static void outputAudio(player *p, int *target, int numSamples)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v->index = v->loopBegin;
|
v->index = v->loopBegin;
|
||||||
|
|
||||||
|
if (v->loopQuirk)
|
||||||
|
{
|
||||||
|
v->loopEnd = v->loopQuirk;
|
||||||
|
v->loopQuirk = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1075,6 +1111,16 @@ static void checkModType(MODULE_HEADER *h, player *p, const char *buf)
|
||||||
p->maxPeriod = PT_MAX_PERIOD;
|
p->maxPeriod = PT_MAX_PERIOD;
|
||||||
return;
|
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 */
|
h->format = FORMAT_UNKNOWN; /* May be The Ultimate SoundTracker, 15 samples */
|
||||||
p->numChans = h->channelCount = 4;
|
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);
|
i = playptmod_LoadMTM(p, fmodule);
|
||||||
bufclose(fmodule);
|
bufclose(fmodule);
|
||||||
return i;
|
return (i);
|
||||||
}
|
}
|
||||||
|
|
||||||
bufseek(fmodule, 0x0438, SEEK_SET);
|
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)
|
if (s->length > 9999)
|
||||||
lateVerSTKFlag = true; /* Only used if mightBeSTK is set */
|
lateVerSTKFlag = true; /* Only used if mightBeSTK is set */
|
||||||
|
|
||||||
bufread(&s->fineTune, 1, 1, fmodule);
|
tmp = 0;
|
||||||
s->fineTune = s->fineTune & 0x0F;
|
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);
|
bufread(&s->volume, 1, 1, fmodule);
|
||||||
if (s->volume > 64)
|
if (s->volume > 64)
|
||||||
|
@ -1382,7 +1432,13 @@ int playptmod_LoadMem(void *_p, const unsigned char *buf, unsigned long bufLengt
|
||||||
extendedPanning = true;
|
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
|
// Convert STK effects to PT effects
|
||||||
// TODO: Add tracker checking, as there
|
// 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)
|
if (j > s->length)
|
||||||
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);
|
bufread(tempSample, 1, j, fmodule);
|
||||||
smpDat8 = tempSample;
|
smpDat8 = tempSample;
|
||||||
|
|
||||||
|
@ -1584,7 +1658,7 @@ int playptmod_Load(void *_p, const char *filename)
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
return i;
|
return (i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (false);
|
return (false);
|
||||||
|
@ -2262,7 +2336,7 @@ static void fxArpeggio(player *p, mod_channel *ch)
|
||||||
|
|
||||||
static void fxPortamentoSlideUp(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)
|
if (p->tempPeriod > 0)
|
||||||
{
|
{
|
||||||
|
@ -2286,7 +2360,7 @@ static void fxPortamentoSlideUp(player *p, mod_channel *ch)
|
||||||
|
|
||||||
static void fxPortamentoSlideDown(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)
|
if (p->tempPeriod > 0)
|
||||||
{
|
{
|
||||||
|
@ -2310,7 +2384,7 @@ static void fxPortamentoSlideDown(player *p, mod_channel *ch)
|
||||||
|
|
||||||
static void fxGlissando(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)
|
if (ch->param != 0)
|
||||||
{
|
{
|
||||||
|
@ -2344,7 +2418,7 @@ static void fxVibrato(player *p, mod_channel *ch)
|
||||||
|
|
||||||
static void fxGlissandoVolumeSlide(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);
|
processGlissando(p, ch);
|
||||||
fxVolumeSlide(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)
|
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);
|
processVibrato(p, ch);
|
||||||
fxVolumeSlide(p, ch);
|
fxVolumeSlide(p, ch);
|
||||||
|
@ -2416,7 +2490,7 @@ static void fxVolumeSlide(player *p, mod_channel *ch)
|
||||||
unsigned char hiNybble;
|
unsigned char hiNybble;
|
||||||
unsigned char loNybble;
|
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;
|
hiNybble = ch->param >> 4;
|
||||||
loNybble = ch->param & 0x0F;
|
loNybble = ch->param & 0x0F;
|
||||||
|
@ -2470,7 +2544,7 @@ static void fxPatternBreak(player *p, mod_channel *ch)
|
||||||
|
|
||||||
if (p->modTick == 0)
|
if (p->modTick == 0)
|
||||||
{
|
{
|
||||||
pos = (((ch->param >> 4) * 10) + (ch->param & 0x0F));
|
pos = ((ch->param >> 4) * 10) + (ch->param & 0x0F);
|
||||||
|
|
||||||
if (pos > 63)
|
if (pos > 63)
|
||||||
p->PBreakPosition = 0;
|
p->PBreakPosition = 0;
|
||||||
|
@ -2696,7 +2770,7 @@ static void processChannel(player *p, mod_channel *ch)
|
||||||
{
|
{
|
||||||
ch->flags &= ~FLAG_NEWSAMPLE;
|
ch->flags &= ~FLAG_NEWSAMPLE;
|
||||||
|
|
||||||
// sample swapping (PT only)
|
/* sample swapping (PT only) */
|
||||||
if ((ch->sample > 0) && (p->minPeriod == PT_MIN_PERIOD))
|
if ((ch->sample > 0) && (p->minPeriod == PT_MIN_PERIOD))
|
||||||
{
|
{
|
||||||
s = &p->source->samples[ch->sample - 1];
|
s = &p->source->samples[ch->sample - 1];
|
||||||
|
@ -2821,7 +2895,6 @@ static void processTick(player *p)
|
||||||
p->PosJumpAssert = true;
|
p->PosJumpAssert = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
p->modTick++;
|
p->modTick++;
|
||||||
if (p->modTick >= p->modSpeed)
|
if (p->modTick >= p->modSpeed)
|
||||||
{
|
{
|
||||||
|
@ -2877,6 +2950,7 @@ void playptmod_Render(void *_p, int *target, int length)
|
||||||
outputAudio(p, target, tempSamples);
|
outputAudio(p, target, tempSamples);
|
||||||
target += tempSamples * 2;
|
target += tempSamples * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->sampleCounter -= tempSamples;
|
p->sampleCounter -= tempSamples;
|
||||||
length -= 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 */
|
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);
|
p->extendedFrequencyTable[i] = (float)samplingFrequency / (3546895.0f / (float)i);
|
||||||
|
|
||||||
// generate extended period table
|
/* generate extended period table */
|
||||||
for (j = 0; j < 16; ++j)
|
for (j = 0; j < 16; ++j)
|
||||||
for (i = 0; i < ((12 * 7) + 1); ++i)
|
for (i = 0; i < ((12 * 7) + 1); ++i)
|
||||||
extendedRawPeriods[(j * ((12 * 7) + 1)) + i] = (i == (12 * 7)) ? 0 : (npertab[i] * 8363 / finetune[j]);
|
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)
|
for (i = 0; i < 14; ++i)
|
||||||
extendedRawPeriods[(16 * ((12 * 7) + 1)) + i] = 0;
|
extendedRawPeriods[(16 * ((12 * 7) + 1)) + i] = 0;
|
||||||
|
|
||||||
|
@ -2965,7 +3039,7 @@ void *playptmod_Create(int samplingFrequency)
|
||||||
|
|
||||||
mixerCutChannels(p);
|
mixerCutChannels(p);
|
||||||
|
|
||||||
return p;
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void playptmod_Config(void *_p, int option, int value)
|
void playptmod_Config(void *_p, int option, int value)
|
||||||
|
|
|
@ -17,6 +17,7 @@ enum
|
||||||
FORMAT_32CN, // FastTracker II (32 channel MODs)
|
FORMAT_32CN, // FastTracker II (32 channel MODs)
|
||||||
FORMAT_STK, // The Ultimate SoundTracker (15 samples)
|
FORMAT_STK, // The Ultimate SoundTracker (15 samples)
|
||||||
FORMAT_NT, // NoiseTracker 1.0
|
FORMAT_NT, // NoiseTracker 1.0
|
||||||
|
FORMAT_FEST, // NoiseTracker (special ones)
|
||||||
|
|
||||||
FORMAT_MTM, // MultiTracker
|
FORMAT_MTM, // MultiTracker
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue