Re-ported ft2play from original sources

CQTexperiment
Chris Moeller 2014-04-04 13:40:09 -07:00
parent 0b436c8437
commit 00a014f270
1 changed files with 3926 additions and 3984 deletions

View File

@ -1,36 +1,33 @@
/*
** FT2PLAY v0.42a
** ==============
**
** C port of FastTracker II's replayer, by 8bitbubsy (Olav Sørensen)
** using the original pascal+asm source codes by Mr.H (Fredrik Huss) of Triton
**
** This is by no means a piece of beautiful code, nor is it meant to be...
** It's just an accurate FastTracker II replayer port for people to enjoy.
**
**
** non-FT2 effects:
** - E8x - set panning
**
** (extreme) non-FT2 extensions:
** - Max 127 channels (was 32)
** - Any amount-of-channels number (FT2 supports *even* numbers only)
** - Max 256 instruments (was 128)
** - Max 32 samples per instrument (was 16)
** - Max 1024 rows per pattern (was 256)
** - Stereo samples
**
** These additions shouldn't break FT2 accuracy, unless the XM is malicious.
**
*/
** FT2PLAY v0.42a
** ==============
**
** C port of FastTracker II's replayer, by 8bitbubsy (Olav Sørensen)
** using the original pascal+asm source codes by Mr.H (Fredrik Huss) of Triton
**
** This is by no means a piece of beautiful code, nor is it meant to be...
** It's just an accurate FastTracker II replayer port for people to enjoy.
**
**
** (extreme) non-FT2 extensions:
** - Max 127 channels (was 32)
** - Any amount-of-channels number (FT2 supports *even* numbers only)
** - Max 256 instruments (was 128)
** - Max 32 samples per instrument (was 16)
** - Max 1024 rows per pattern (was 256)
** - Stereo samples
**
** These additions shouldn't break FT2 accuracy, unless the XM is malicious.
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include <math.h>
#include <assert.h>
#include <limits.h>
#include "resampler.h"
@ -42,6 +39,8 @@
#define USE_VOL_RAMP
enum { _soundBufferSize = 512 };
enum
{
IS_Vol = 1,
@ -174,9 +173,9 @@ typedef struct SongTyp_t
uint8_t PosJumpFlag;
uint8_t SongTab[256];
uint16_t Ver;
/*char Name[21];
char Name[21];
char ProgName[21];
char InstrName[256][23];*/
char InstrName[256][23];
uint16_t startOrder;
} SongTyp;
@ -309,11 +308,10 @@ typedef struct TonTyp_t
typedef struct
{
const int8_t *sampleData;
int8_t loopEnabled;
int8_t sixteenBit;
int8_t stereo;
int8_t busy;
const int8_t *sampleData;
int8_t loopBidi;
int8_t loopDir;
int32_t sampleLength;
@ -323,7 +321,6 @@ typedef struct
int8_t interpolating;
float incRate;
float frac;
float volume;
float panningL;
float panningR;
@ -344,12 +341,13 @@ typedef struct
typedef struct
{
uint8_t *_ptr;
uintptr_t _cnt;
size_t _cnt;
uint8_t *_base;
uintptr_t _bufsiz;
size_t _bufsiz;
int32_t _eof;
} MEM;
typedef struct
{
int8_t *VibSineTab;
@ -359,7 +357,7 @@ typedef struct
int16_t *amigaPeriods;
uint32_t *LogTab;
int8_t LinearFrqTab;
int32_t soundBufferSize;
uint32_t soundBufferSize;
uint32_t outputFreq;
TonTyp *NilPatternLine;
@ -387,19 +385,16 @@ typedef struct
// pre-initialized variables
int8_t samplingInterpolation;// = 1;
#ifdef USE_VOL_RAMP
int8_t rampStyle;
#endif
float *masterBufferL;// = NULL;
float *masterBufferR;// = NULL;
int32_t samplesLeft;// = 0; // must be signed
int8_t isMixing;// = 0;
uint32_t samplesPerFrame;// = 882;
// globally accessed
int8_t ModuleLoaded;// = 0;
int8_t Playing;// = 0;
uint8_t numChannels;// = 127;
uint16_t numChannels;// = 127;
uint8_t muted[16];
@ -407,17 +402,14 @@ typedef struct
uint8_t playedOrder[8192];
} PLAYER;
enum { _soundBufferSize = 512 };
// FUNCTION DECLARATIONS
static MEM *mopen(const uint8_t *src, uintptr_t length);
static MEM *mopen(const uint8_t *src, size_t length);
static void mclose(MEM *buf);
//static intptr_t mtell(MEM *buf);
static size_t mread(void *buffer, size_t size, size_t count, MEM *buf);
//static size_t mwrite(const void *buffer, size_t size, size_t count, MEM *buf);
static int32_t meof(MEM *buf);
static void mseek(MEM *buf, intptr_t offset, int32_t whence);
static void mseek(MEM *buf, ssize_t offset, int32_t whence);
static void setSamplesPerFrame(PLAYER *, uint32_t val);
static void voiceSetSource(PLAYER *, uint8_t i, const int8_t *sampleData,
int32_t sampleLength, int32_t sampleLoopLength,
@ -425,14 +417,15 @@ static void voiceSetSource(PLAYER *, uint8_t i, const int8_t *sampleData,
int8_t sixteenbit, int8_t stereo);
static void voiceSetSamplePosition(PLAYER *, uint8_t i, uint16_t value);
static void voiceSetVolume(PLAYER *, uint8_t i, float vol, uint8_t sharp);
void voiceSetPanning(PLAYER *, uint8_t i, uint8_t pan);
static void voiceSetPanning(PLAYER *, uint8_t i, uint8_t pan);
static void voiceSetSamplingFrequency(PLAYER *, uint8_t i, uint32_t samplingFrequency);
static void ft2play_FreeSong(PLAYER *);
// TABLES AND VARIABLES
static const uint16_t AmigaFinePeriod[12 * 8] =
static uint16_t AmigaFinePeriod[12 * 8] =
{
907,900,894,887,881,875,868,862,856,850,844,838,
832,826,820,814,808,802,796,791,785,779,774,768,
@ -445,7 +438,7 @@ static const uint16_t AmigaFinePeriod[12 * 8] =
};
// This table is so small that generating it is almost as big
static const uint8_t VibTab[32] =
static uint8_t VibTab[32] =
{
0, 24, 49, 74, 97,120,141,161,
180,197,212,224,235,244,250,253,
@ -453,8 +446,10 @@ static const uint8_t VibTab[32] =
180,161,141,120, 97, 74, 49, 24
};
// CODE START
static inline void RetrigVolume(StmTyp *ch)
{
ch->RealVol = ch->OldVol;
@ -965,13 +960,19 @@ CheckEffects:
pl->Song.PBreakFlag = 1;
}
}
if (pl->Song.PBreakFlag == 1 && pl->Song.PBreakPos == 0)
{
int32_t offset = pl->Song.SongPos / 8;
int32_t bit = 1 << (pl->Song.SongPos % 8);
pl->playedOrder[offset] &= ~bit;
}
}
}
// E7x - set tremolo waveform
else if ((ch->Eff & 0xF0) == 0x70) ch->WaveCtrl = ((ch->Eff & 0x0F) << 4) | (ch->WaveCtrl & 0x0F);
// E8x - set panning - *non-FT2*
// E8x - set panning *non-FT2*
else if ((ch->Eff & 0xF0) == 0x80)
{
ch->OutPan = (ch->Eff & 0x0F) << 4;
@ -1884,9 +1885,7 @@ static inline void DoEffects(PLAYER *p, StmTyp *ch)
{
StartTone(p, ch->TonTyp & 0x00FF, 0, 0, ch);
if (ch->TonTyp & 0xFF00)
RetrigVolume(ch);
if (ch->TonTyp & 0xFF00) RetrigVolume(ch);
RetrigEnvelopeVibrato(ch);
if ((ch->VolKolVol >= 0x10) && (ch->VolKolVol <= 0x50))
@ -2075,11 +2074,10 @@ static void MainPlayer(PLAYER *p) // periodically called from mixer
resampler_dup_inplace(p->resampler[ch->Nr + 127 + 254], p->resampler[ch->Nr + 254]);
}
#endif
s = ch->InstrOfs;
voiceSetSamplePosition(p, ch->Nr, ch->SmpStartPos);
voiceSetSource(p, ch->Nr, s.Pek, s.Len, s.RepL, s.RepS + s.RepL, s.Typ & 3, s.Typ & 16, s.Typ & 32);
voiceSetSamplePosition(p, ch->Nr, ch->SmpStartPos);
}
ch->Status = 0;
@ -2094,20 +2092,21 @@ static void StopVoices(PLAYER *p)
for (a = 0; a < 127; ++a)
{
p->Stm[a].Nr = a;
p->Stm[a].TonTyp = 0;
p->Stm[a].RelTonNr = 0;
p->Stm[a].InstrNr = 0;
p->Stm[a].InstrSeg = *p->Instr[0];
p->Stm[a].Status = IS_Vol;
p->Stm[a].RealVol = 0;
p->Stm[a].OutVol = 0;
p->Stm[a].OldVol = 0;
p->Stm[a].FinalVol = 0.0f;
p->Stm[a].OldPan = 128;
p->Stm[a].OutPan = 128;
p->Stm[a].FinalPan = 128;
p->Stm[a].VibDepth = 0;
StmTyp *ch = &p->Stm[a];
ch->Nr = a;
ch->TonTyp = 0;
ch->RelTonNr = 0;
ch->InstrNr = 0;
ch->InstrSeg = *p->Instr[0];
ch->Status = IS_Vol;
ch->RealVol = 0;
ch->OutVol = 0;
ch->OldVol = 0;
ch->FinalVol = 0.0f;
ch->OldPan = 128;
ch->OutPan = 128;
ch->FinalPan = 128;
ch->VibDepth = 0;
voiceSetPanning(p, a, 128);
}
@ -2264,6 +2263,39 @@ static void Delta2Samp(int8_t *p, uint32_t len, uint8_t typ)
}
}
static inline int8_t GetAdpcmSample(const int8_t *sampleDictionary, const uint8_t *sampleData, int32_t samplePosition, int8_t *lastDelta)
{
uint8_t byte = sampleData[samplePosition / 2];
byte = (samplePosition & 1) ? byte >> 4 : byte & 15;
return *lastDelta += sampleDictionary[byte];
}
static void Adpcm2Samp(uint8_t * sample, uint32_t length)
{
const int8_t *sampleDictionary;
const uint8_t *sampleData;
uint32_t samplePosition;
int8_t lastDelta;
uint8_t * sampleDataOut = (uint8_t *) malloc(length);
if (!sampleDataOut)
return;
sampleDictionary = (const int8_t *)sample;
sampleData = (uint8_t*)sampleDictionary + 16;
samplePosition = 0;
lastDelta = 0;
while (samplePosition < length)
{
sampleDataOut[samplePosition] = GetAdpcmSample(sampleDictionary, sampleData, samplePosition, &lastDelta);
samplePosition++;
}
memcpy(sample, sampleDataOut, length);
}
static void FreeAllInstr(PLAYER *p)
{
@ -2273,9 +2305,10 @@ static void FreeAllInstr(PLAYER *p)
static int8_t AllocateInstr(PLAYER *pl, uint16_t i)
{
InstrTyp *p;
uint8_t j;
InstrTyp *p;
if (pl->Instr[i] == NULL)
{
p = (InstrTyp *)(calloc(1, sizeof (InstrTyp)));
@ -2329,75 +2362,43 @@ static int8_t LoadInstrHeader(PLAYER *p, MEM *f, uint16_t i)
return (1);
}
static inline int8_t get_adpcm_sample(const int8_t *sampleDictionary, const uint8_t *sampleData, int32_t samplePosition, int8_t *lastDelta)
{
uint8_t byte = sampleData[samplePosition / 2];
byte = (samplePosition & 1) ? byte >> 4 : byte & 15;
return *lastDelta += sampleDictionary[byte];
}
static void Adpcm2Samp(uint8_t * sample, uint32_t length)
{
const int8_t *sampleDictionary;
const uint8_t *sampleData;
uint32_t samplePosition;
int8_t lastDelta;
uint8_t * sampleDataOut = (uint8_t *) malloc(length);
if (!sampleDataOut)
return;
sampleDictionary = (const int8_t *)sample;
sampleData = (uint8_t*)sampleDictionary + 16;
samplePosition = 0;
lastDelta = 0;
while (samplePosition < length)
{
sampleDataOut[samplePosition] = get_adpcm_sample(sampleDictionary, sampleData, samplePosition, &lastDelta);
samplePosition++;
}
memcpy(sample, sampleDataOut, length);
}
static int8_t LoadInstrSample(PLAYER *p, MEM *f, uint16_t i)
{
uint16_t j;
int32_t l;
InstrTyp *Instr;
SampleTyp *s;
if (p->Instr[i] != NULL)
{
for (j = 1; j <= p->Instr[i]->AntSamp; ++j)
Instr = p->Instr[i];
for (j = 1; j <= Instr->AntSamp; ++j)
{
int adpcm = 0;
p->Instr[i]->Samp[j - 1].Pek = NULL;
s = &Instr->Samp[j - 1];
s->Pek = NULL;
l = p->Instr[i]->Samp[j - 1].Len;
if (p->Instr[i]->Samp[j - 1].skrap == 0xAD &&
!(p->Instr[i]->Samp[j - 1].Typ & (16|32)))
adpcm = (((l + 1) / 2) + 16);
l = s->Len;
if (s->skrap == 0xAD &&
!(s->Typ & (16|32)))
adpcm = ((l + 1) / 2) + 16;
if (l > 0)
{
p->Instr[i]->Samp[j - 1].Pek = (int8_t *)(malloc(l));
if (p->Instr[i]->Samp[j - 1].Pek == NULL)
s->Pek = (int8_t *)(malloc(l));
if (s->Pek == NULL)
{
for (j = i; j <= p->Song.AntInstrs; ++j) FreeInstr(p, j);
return (0);
}
mread(p->Instr[i]->Samp[j - 1].Pek, adpcm ? adpcm : l, 1, f);
mread(s->Pek, adpcm ? adpcm : l, 1, f);
if (!adpcm)
Delta2Samp(p->Instr[i]->Samp[j - 1].Pek, l, p->Instr[i]->Samp[j - 1].Typ);
Delta2Samp(s->Pek, l, s->Typ);
else
Adpcm2Samp((uint8_t *)p->Instr[i]->Samp[j - 1].Pek, l);
Adpcm2Samp((uint8_t *)s->Pek, l);
}
s = &p->Instr[i]->Samp[j - 1];
if (s->Pek == NULL)
{
s->Len = 0;
@ -2459,7 +2460,7 @@ static void UnpackPatt(PLAYER *p, TonTyp *patdata, uint16_t length, uint16_t pac
}
}
static int8_t PatternEmpty(PLAYER *p, uint16_t nr)
static inline int8_t PatternEmpty(PLAYER *p, uint16_t nr)
{
uint32_t patofs;
uint16_t i;
@ -2491,12 +2492,12 @@ static int8_t PatternEmpty(PLAYER *p, uint16_t nr)
static int8_t LoadPatterns(PLAYER *p, MEM *f)
{
PatternHeaderTyp ph;
uint8_t *patttmp;
uint16_t i;
uint8_t tmpLen;
PatternHeaderTyp ph;
for (i = 0; i < p->Song.AntPtn; ++i)
{
mread(&ph.PatternHeaderSize, 4, 1, f);
@ -2522,6 +2523,7 @@ static int8_t LoadPatterns(PLAYER *p, MEM *f)
if (meof(f))
{
mclose(f);
return (0);
}
@ -2531,12 +2533,14 @@ static int8_t LoadPatterns(PLAYER *p, MEM *f)
p->Patt[i] = (TonTyp *)(calloc(sizeof (TonTyp), ph.PattLen * 127));
if (p->Patt[i] == NULL)
{
mclose(f);
return (0);
}
patttmp = (uint8_t *)(malloc(ph.DataLen));
if (patttmp == NULL)
{
mclose(f);
return (0);
}
@ -2547,9 +2551,12 @@ static int8_t LoadPatterns(PLAYER *p, MEM *f)
if (PatternEmpty(p, i))
{
if (p->Patt[i]) free(p->Patt[i]);
if (p->Patt[i] != NULL)
{
free(p->Patt[i]);
p->Patt[i] = NULL;
}
p->PattLens[i] = 64;
}
}
@ -2557,10 +2564,8 @@ static int8_t LoadPatterns(PLAYER *p, MEM *f)
return (1);
}
static void ft2play_FreeSong(void *_p)
static void ft2play_FreeSong(PLAYER *p)
{
PLAYER * p = (PLAYER *)_p;
p->Playing = 0;
memset(p->voice, 0, sizeof (p->voice));
@ -2584,8 +2589,10 @@ int8_t ft2play_LoadModule(void *_p, const uint8_t *buffer, size_t size)
p->ModuleLoaded = 0;
AllocateInstr(p, 0); // instr0 = placeholder for invalid ins
p->Instr[0]->Samp[0].Vol = 0; // mute invalid instruments
// instr 0 is a placeholder for invalid instruments
AllocateInstr(p, 0);
p->Instr[0]->Samp[0].Vol = 0;
// ------------------------------------------------
FreeMusic(p);
p->LinearFrqTab = 0;
@ -2594,16 +2601,17 @@ int8_t ft2play_LoadModule(void *_p, const uint8_t *buffer, size_t size)
if (f == NULL) return (0);
// start loading
mread(&h, sizeof (h), 1, f);
mread(&h, sizeof(h), 1, f);
if ((memcmp(h.Sig, "Extended Module: ", 17) != 0) || (h.Ver < 0x0102) || (h.Ver > 0x0104))
if ((memcmp(h.Sig, "Extended Module: ", 17) != 0) || (h.Ver < 0x0102) || (h.Ver > 0x104))
{
mclose(f);
return (0);
}
if ((h.AntChn < 1) || (h.AntChn > 127) || (h.AntPtn > 256))
{
mclose(f);
return (0);
}
@ -2614,16 +2622,16 @@ int8_t ft2play_LoadModule(void *_p, const uint8_t *buffer, size_t size)
return (0);
}
/*memcpy(p->Song.Name, h.Name, 20);
memcpy(p->Song.ProgName, h.ProggName, 20);*/
memcpy(p->Song.Name, h.Name, 20);
memcpy(p->Song.ProgName, h.ProggName, 20);
p->Song.Len = h.Len;
p->Song.RepS = h.RepS;
p->Song.AntChn = (uint8_t)(h.AntChn);
p->Song.InitSpeed = h.DefSpeed ? h.DefSpeed : 125;
p->Song.Speed = p->Song.InitSpeed;
p->Song.InitTempo = h.DefTempo ? h.DefTempo : 6;
p->Song.Tempo = p->Song.InitTempo;
p->Song.Speed = h.DefSpeed ? h.DefSpeed : 125;
p->Song.Tempo = h.DefTempo ? h.DefTempo : 6;
p->Song.InitSpeed = p->Song.Speed;
p->Song.InitTempo = p->Song.Tempo;
p->Song.AntInstrs = h.AntInstrs;
p->Song.AntPtn = h.AntPtn;
p->Song.Ver = h.Ver;
@ -2672,7 +2680,7 @@ int8_t ft2play_LoadModule(void *_p, const uint8_t *buffer, size_t size)
{
if (LoadInstrHeader(p, f, i) == 0)
{
FreeInstr(p, i);
FreeInstr(p, (uint8_t)(i));
mclose(f);
f = NULL;
break;
@ -2704,7 +2712,22 @@ int8_t ft2play_LoadModule(void *_p, const uint8_t *buffer, size_t size)
return (1);
}
void voiceSetSource(PLAYER *p, uint8_t i, const int8_t *sampleData,
static void setSamplesPerFrame(PLAYER *p, uint32_t val)
{
p->samplesPerFrame = val;
#ifdef USE_VOL_RAMP
p->f_samplesPerFrame = 1.0f / ((float)(val) / 4.0f);
p->f_samplesPerFrameSharp = 1.0f / (p->f_outputFreq / 1000.0f); // 1ms
#endif
}
static void setSamplingInterpolation(PLAYER *p, int8_t value)
{
p->samplingInterpolation = value;
}
static void voiceSetSource(PLAYER *p, uint8_t i, const int8_t *sampleData,
int32_t sampleLength, int32_t sampleLoopLength,
int32_t sampleLoopEnd, int8_t loopEnabled,
int8_t sixteenbit, int8_t stereo)
@ -2733,9 +2756,6 @@ void voiceSetSource(PLAYER *p, uint8_t i, const int8_t *sampleData,
p->voice[i].loopDir = 0;
p->voice[i].stereo = stereo;
p->voice[i].interpolating = 1;
#ifdef USE_VOL_RAMP
p->voice[i].rampTerminates = 0;
#endif
resampler_clear(p->resampler[i]);
#ifdef USE_VOL_RAMP
@ -2745,7 +2765,7 @@ void voiceSetSource(PLAYER *p, uint8_t i, const int8_t *sampleData,
#endif
}
void voiceSetSamplePosition(PLAYER *p, uint8_t i, uint16_t value)
static void voiceSetSamplePosition(PLAYER *p, uint8_t i, uint16_t value)
{
p->voice[i].samplePosition = value;
if (p->voice[i].samplePosition >= p->voice[i].sampleLength)
@ -2764,7 +2784,7 @@ void voiceSetSamplePosition(PLAYER *p, uint8_t i, uint16_t value)
#endif
}
void voiceSetVolume(PLAYER *p, uint8_t i, float vol, uint8_t sharp)
static void voiceSetVolume(PLAYER *p, uint8_t i, float vol, uint8_t sharp)
{
#ifdef USE_VOL_RAMP
if (p->rampStyle > 0 && !sharp)
@ -2778,15 +2798,13 @@ void voiceSetVolume(PLAYER *p, uint8_t i, float vol, uint8_t sharp)
if (sharp)
{
if (vol)
{
p->voice[i].volume = 0.0f;
}
p->voice[i].volume = 0;
else if (sharp != 3)
p->voice[i].rampTerminates = 1;
}
p->voice[i].targetVol = vol;
p->voice[i].volDelta = (p->voice[i].targetVol - p->voice[i].volume) * rampRate;
p->voice[i].volDelta = rampRate * (p->voice[i].targetVol - p->voice[i].volume);
}
else
{
@ -2795,11 +2813,11 @@ void voiceSetVolume(PLAYER *p, uint8_t i, float vol, uint8_t sharp)
p->voice[i].volDelta = 0;
}
#else
p->voice[i].volume = vol;
voice[i].volume = vol;
#endif
}
void voiceSetPanning(PLAYER *p, uint8_t i, uint8_t pan)
static void voiceSetPanning(PLAYER *p, uint8_t i, uint8_t pan)
{
#ifdef USE_VOL_RAMP
if (p->rampStyle > 1)
@ -2820,12 +2838,12 @@ void voiceSetPanning(PLAYER *p, uint8_t i, uint8_t pan)
p->voice[i].panDeltaR = 0;
}
#else
voice[i].panningL = p->PanningTab[256 - pan];
voice[i].panningR = p->PanningTab[ pan];
voice[i].panningL = PanningTab[256 - pan];
voice[i].panningR = PanningTab[ pan];
#endif
}
void voiceSetSamplingFrequency(PLAYER *p, uint8_t i, uint32_t samplingFrequency)
static void voiceSetSamplingFrequency(PLAYER *p, uint8_t i, uint32_t samplingFrequency)
{
p->voice[i].incRate = (float)(samplingFrequency) / p->f_outputFreq;
}
@ -2871,11 +2889,10 @@ static inline void mix8b(PLAYER *p, uint32_t ch, uint32_t samples)
resampler = p->resampler[ch];
resampler_set_rate(resampler, p->voice[ch].incRate );
resampler_set_rate(resampler, p->voice[ch].incRate);
for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j)
{
p->voice[ch].busy = 1;
samplePosition = p->voice[ch].samplePosition;
while (interpolating && resampler_get_free_count(resampler))
@ -2928,17 +2945,16 @@ static inline void mix8b(PLAYER *p, uint32_t ch, uint32_t samples)
if ( !resampler_ready(resampler) )
{
p->voice[ch].sampleData = NULL;
p->voice[ch].busy = 0;
break;
}
sample = resampler_get_sample(resampler);
resampler_remove_sample(resampler);
sample = (sample * p->voice[ch].volume);
sample *= p->voice[ch].volume;
sampleL = (sample * p->voice[ch].panningL);
sampleR = (sample * p->voice[ch].panningR);
sampleL = sample * p->voice[ch].panningL;
sampleR = sample * p->voice[ch].panningR;
#ifdef USE_VOL_RAMP
if (rampStyle > 0)
@ -2982,11 +2998,7 @@ static inline void mix8b(PLAYER *p, uint32_t ch, uint32_t samples)
}
if (p->voice[ch].rampTerminates && !p->voice[ch].volume)
{
p->voice[ch].sampleData = NULL;
p->voice[ch].samplePosition = 0;
p->voice[ch].busy = 0;
}
}
#endif
@ -3040,12 +3052,11 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
resampler[1] = p->resampler[ch+127];
#endif
resampler_set_rate(resampler[0], p->voice[ch].incRate );
resampler_set_rate(resampler[1], p->voice[ch].incRate );
resampler_set_rate(resampler[0], p->voice[ch].incRate);
resampler_set_rate(resampler[1], p->voice[ch].incRate);
for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j)
{
p->voice[ch].busy = 1;
samplePosition = p->voice[ch].samplePosition;
while (interpolating && resampler_get_free_count(resampler[0]))
@ -3099,7 +3110,6 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
if ( !resampler_ready(resampler[0]) )
{
p->voice[ch].sampleData = NULL;
p->voice[ch].busy = 0;
break;
}
@ -3108,11 +3118,11 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
resampler_remove_sample(resampler[0]);
resampler_remove_sample(resampler[1]);
sampleL = (sampleL * p->voice[ch].volume);
sampleR = (sampleR * p->voice[ch].volume);
sampleL *= p->voice[ch].volume;
sampleR *= p->voice[ch].volume;
sampleL = (sampleL * p->voice[ch].panningL);
sampleR = (sampleR * p->voice[ch].panningR);
sampleL *= p->voice[ch].panningL;
sampleR *= p->voice[ch].panningR;
#ifdef USE_VOL_RAMP
if (rampStyle > 0)
@ -3156,11 +3166,7 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
}
if (p->voice[ch].rampTerminates && !p->voice[ch].volume)
{
p->voice[ch].sampleData = NULL;
p->voice[ch].samplePosition = 0;
p->voice[ch].busy = 0;
}
}
#endif
@ -3206,15 +3212,14 @@ static inline void mix16b(PLAYER *p, uint32_t ch, uint32_t samples)
loopDir = p->voice[ch].loopDir;
interpolating = p->voice[ch].interpolating;
sampleData = (const int16_t *)(p->voice[ch].sampleData);
sampleData = (const int16_t *) p->voice[ch].sampleData;
resampler = p->resampler[ch];
resampler_set_rate(resampler, p->voice[ch].incRate );
resampler_set_rate(resampler, p->voice[ch].incRate);
for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j)
{
p->voice[ch].busy = 1;
samplePosition = p->voice[ch].samplePosition;
while (interpolating && resampler_get_free_count(resampler))
@ -3267,17 +3272,16 @@ static inline void mix16b(PLAYER *p, uint32_t ch, uint32_t samples)
if ( !resampler_ready(resampler) )
{
p->voice[ch].sampleData = NULL;
p->voice[ch].busy = 0;
break;
}
sample = resampler_get_sample(resampler);
resampler_remove_sample(resampler);
sample = (sample * p->voice[ch].volume);
sample *= p->voice[ch].volume;
sampleL = (sample * p->voice[ch].panningL);
sampleR = (sample * p->voice[ch].panningR);
sampleL = sample * p->voice[ch].panningL;
sampleR = sample * p->voice[ch].panningR;
#ifdef USE_VOL_RAMP
if (rampStyle > 0)
@ -3321,11 +3325,7 @@ static inline void mix16b(PLAYER *p, uint32_t ch, uint32_t samples)
}
if (p->voice[ch].rampTerminates && !p->voice[ch].volume)
{
p->voice[ch].sampleData = NULL;
p->voice[ch].samplePosition = 0;
p->voice[ch].busy = 0;
}
}
#endif
@ -3370,7 +3370,7 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
loopDir = p->voice[ch].loopDir;
interpolating = p->voice[ch].interpolating;
sampleData = (const int16_t *)(p->voice[ch].sampleData);
sampleData = (const int16_t *) p->voice[ch].sampleData;
resampler[0] = p->resampler[ch];
#ifdef USE_VOL_RAMP
@ -3379,12 +3379,11 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
resampler[1] = p->resampler[ch+127];
#endif
resampler_set_rate(resampler[0], p->voice[ch].incRate );
resampler_set_rate(resampler[1], p->voice[ch].incRate );
resampler_set_rate(resampler[0], p->voice[ch].incRate);
resampler_set_rate(resampler[1], p->voice[ch].incRate);
for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j)
{
p->voice[ch].busy = 1;
samplePosition = p->voice[ch].samplePosition;
while (interpolating && resampler_get_free_count(resampler[0]))
@ -3438,7 +3437,6 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
if ( !resampler_ready(resampler[0]) )
{
p->voice[ch].sampleData = NULL;
p->voice[ch].busy = 0;
break;
}
@ -3447,11 +3445,11 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
resampler_remove_sample(resampler[0]);
resampler_remove_sample(resampler[1]);
sampleL = (sampleL * p->voice[ch].volume);
sampleR = (sampleR * p->voice[ch].volume);
sampleL *= p->voice[ch].volume;
sampleR *= p->voice[ch].volume;
sampleL = (sampleL * p->voice[ch].panningL);
sampleR = (sampleR * p->voice[ch].panningR);
sampleL *= p->voice[ch].panningL;
sampleR *= p->voice[ch].panningR;
#ifdef USE_VOL_RAMP
if (rampStyle > 0)
@ -3495,11 +3493,7 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
}
if (p->voice[ch].rampTerminates && !p->voice[ch].volume)
{
p->voice[ch].sampleData = NULL;
p->voice[ch].samplePosition = 0;
p->voice[ch].busy = 0;
}
}
#endif
@ -3569,7 +3563,7 @@ void ft2play_RenderFloat(void *_p, float *buffer, int32_t count)
int32_t samplesTodo;
float * outputStream;
if (p->isMixing)
if (p->Playing)
{
outputStream = buffer;
@ -3664,13 +3658,13 @@ void * ft2play_Alloc(uint32_t _samplingFrequency, int8_t interpolation, int8_t r
if ( !p->masterBufferL || !p->masterBufferR )
goto error;
p->samplingInterpolation = interpolation;
setSamplingInterpolation(p, interpolation);
#ifdef USE_VOL_RAMP
p->rampStyle = ramp_style;
#endif
resampler_init();
#ifdef USE_VOL_RAMP
for ( i = 0; i < 127 * 2 * 2; ++i )
#else
@ -3753,10 +3747,8 @@ void ft2play_Free(void *_p)
PLAYER * p = (PLAYER *)_p;
if (p->isMixing)
if (p->Playing)
{
p->isMixing = 0;
if (p->masterBufferL) free(p->masterBufferL); p->masterBufferL = NULL;
if (p->masterBufferR) free(p->masterBufferR); p->masterBufferR = NULL;
}
@ -3799,7 +3791,6 @@ void ft2play_PlaySong(void *_p, int32_t startOrder)
p->Playing = 1;
setSamplesPerFrame(p, ((p->outputFreq * 5UL) / 2 / p->Song.Speed));
p->isMixing = 1;
SetPos(p, (int16_t)startOrder, 0);
@ -3810,7 +3801,7 @@ void ft2play_PlaySong(void *_p, int32_t startOrder)
p->playedOrder[startOrder / 8] = 1 << (startOrder % 8);
}
static MEM *mopen(const uint8_t *src, uintptr_t length)
static MEM *mopen(const uint8_t *src, size_t length)
{
MEM *b;
@ -3831,23 +3822,13 @@ static MEM *mopen(const uint8_t *src, uintptr_t length)
static void mclose(MEM *buf)
{
if (buf != NULL)
{
free(buf);
buf = NULL;
}
}
#if 0
static intptr_t mtell(MEM *buf)
{
return (buf->_bufsiz - buf->_cnt);
}
#endif
static size_t mread(void *buffer, size_t size, size_t count, MEM *buf)
{
size_t wrcnt;
intptr_t pcnt;
ssize_t pcnt;
if (buf == NULL) return (0);
if (buf->_ptr == NULL) return (0);
@ -3855,7 +3836,7 @@ static size_t mread(void *buffer, size_t size, size_t count, MEM *buf)
wrcnt = size * count;
if ((size == 0) || buf->_eof) return (0);
pcnt = ((uint32_t)(buf->_cnt) > wrcnt) ? wrcnt : buf->_cnt;
pcnt = (buf->_cnt > wrcnt) ? wrcnt : buf->_cnt;
memcpy(buffer, buf->_ptr, pcnt);
buf->_cnt -= pcnt;
@ -3871,35 +3852,6 @@ static size_t mread(void *buffer, size_t size, size_t count, MEM *buf)
return (pcnt / size);
}
#if 0
static size_t mwrite(const void *buffer, size_t size, size_t count, MEM *buf)
{
size_t wrcnt;
intptr_t pcnt;
if (buf == NULL) return (0);
if (buf->_ptr == NULL) return (0);
wrcnt = size * count;
if ((size == 0) || buf->_eof) return (0);
pcnt = ((uint32_t)(buf->_cnt) > wrcnt) ? wrcnt : buf->_cnt;
memcpy(buf->_ptr, buffer, pcnt);
buf->_cnt -= pcnt;
buf->_ptr += pcnt;
if (buf->_cnt <= 0)
{
buf->_ptr = buf->_base + buf->_bufsiz;
buf->_cnt = 0;
buf->_eof = 1;
}
return (pcnt / size);
}
#endif
static int32_t meof(MEM *buf)
{
if (buf == NULL) return (1); // XXX: Should return a different value?
@ -3907,7 +3859,7 @@ static int32_t meof(MEM *buf)
return (buf->_eof);
}
static void mseek(MEM *buf, intptr_t offset, int32_t whence)
static void mseek(MEM *buf, ssize_t offset, int32_t whence)
{
if (buf == NULL) return;
@ -3932,16 +3884,6 @@ static void mseek(MEM *buf, intptr_t offset, int32_t whence)
}
}
static void setSamplesPerFrame(PLAYER *p, uint32_t val)
{
p->samplesPerFrame = val;
#ifdef USE_VOL_RAMP
p->f_samplesPerFrame = 1.0f / ((float)(val) / 4.0f);
p->f_samplesPerFrameSharp = 1.0f / (p->f_outputFreq / 1000.0f); // 1ms
#endif
}
void ft2play_Mute(void *_p, int8_t channel, int8_t mute)
{
PLAYER * p = (PLAYER *)_p;
@ -3970,11 +3912,11 @@ void ft2play_GetInfo(void *_p, ft2_info *info)
info->speed = p->Song.Tempo; // Hurr
info->tempo = p->Song.Speed;
channels_playing = 0;
if (p->isMixing)
if (p->Playing)
{
for (i = 0; i < p->Song.AntChn; ++i)
{
if (p->voice[i].busy)
if (p->voice[i].sampleData)
++channels_playing;
}
}