ref: 69b97132c75dc22b44c78db1061ea6828a1cb211
dir: /itdec.c/
#include "it_struc.h"
#define MIN(a,b) ((a)<(b)?(a):(b))
static int tempo = 125;
static double pos;
static s32int mixbuf[44100*2];
static s16int outbuf[44100*2];
static const char *
DriverDetectCard(it_engine *, const char *, uint16_t, uint16_t)
{
return nil;
}
static const char *
DriverInitSound(it_engine *)
{
return nil;
}
int
DriverUninitSound(it_engine *)
{
return 0;
}
static void
kill_channel(it_engine *ite, it_slave *slave)
{
slave->Flags = 0x0200;
slave->LpD = 0;
if((slave->HCN & 0x80) == 0)
ite->chn[slave->HCN].Flags &= ~4;
}
static int
update_offs(it_engine *ite, it_slave *slave, int32_t *offs, int32_t *oferr, int32_t *nfreq, const int32_t lpbeg, const int32_t lpend)
{
*oferr += *nfreq;
*offs += *oferr>>16;
*oferr &= 0xFFFF;
if((slave->LpM & 24) == 24 && slave->LpD != 0 && (*offs < lpbeg)){
*offs = lpbeg - *offs;
if(lpend <= lpbeg){
kill_channel(ite, slave);
return 1;
}
*offs %= (lpend-lpbeg)*2;
if(*offs < (lpend-lpbeg)){
slave->LpD = 0;
if(*nfreq < 0) *nfreq = -*nfreq;
*offs += lpbeg;
}else{
*offs = (lpend - lpbeg) - *offs;
*offs += lpend - 1;
}
}
if(*offs < 0){
if((slave->LpM & 24) != 24){
kill_channel(ite, slave);
slave->LpD = 0;
return 1;
}
*offs = 0;
if(*nfreq < 0) *nfreq = -*nfreq;
slave->LpD = 0;
}
if(*offs >= lpend){
if((slave->LpM & 8) == 0){
kill_channel(ite, slave);
return 1;
}
if((slave->LpM & 24) == 24){
if(lpend <= lpbeg){
kill_channel(ite, slave);
return 1;
}
*offs -= lpend;
*offs %= (lpend-lpbeg)*2;
if(*offs >= (lpend-lpbeg)){
*offs -= (lpend - lpbeg);
*offs += lpbeg;
}else{
slave->LpD = 1;
*offs = lpend - *offs - 1;
if(*nfreq > 0)
*nfreq = -*nfreq;
}
}else{
if(lpend <= lpbeg){
kill_channel(ite, slave);
return 1;
}
*offs -= lpend;
*offs %= (lpend-lpbeg);
*offs += lpbeg;
}
}
if(*offs < 0 || *offs >= lpend){
kill_channel(ite, slave);
return 1;
}
return 0;
}
static int
DriverPoll(it_engine *ite, uint16_t PlayMode, uint16_t CurrentPattern)
{
it_slave *slave;
u16int ax, cx;
it_slave *si;
int i, j;
USED(PlayMode, CurrentPattern);
Update(ite, &cx, &si, &ax);
int tper = (44100*10)/(tempo*4);
memset(mixbuf, 0, tper*2*4);
memset(outbuf, 0, tper*2*2);
for(i = 0; i < ite->NumChannels; i++){
slave = &ite->slave[i];
if((slave->Flags & 1) != 0 && (slave->Flags & 0x0200) == 0){
int offs = slave->Sample_Offset;
int oferr = slave->SmpErr;
int lpbeg = slave->Loop_Beginning;
int lpend = slave->Loop_End;
int nfreq = slave->Frequency;
int32_t vol = slave->_16bVol;
vol *= ite->hdr.MV;
vol >>= 8;
int lvol = vol, rvol = vol;
if(slave->FPP == 100)
rvol = -rvol;
else if(slave->FPP < 32)
rvol = (rvol * slave->FPP) >> 5;
else
lvol = (lvol * (64 - slave->FPP)) >> 5;
nfreq = (((s64int)nfreq) << 16) / 44100ULL;
if(slave->LpD == 1) nfreq = -nfreq;
if(ite->SamplePointer[slave->Smp] == nil){
kill_channel(ite, slave);
break;
}else if(slave->Bit != 0){
s16int *data = (s16int*)ite->SamplePointer[slave->Smp];
for(j = 0; j < tper*2; j+=2){
if(update_offs(ite, slave, &offs, &oferr, &nfreq, lpbeg, lpend) != 0)
break;
mixbuf[j+0] -= (lvol*(int32_t)data[offs])>>14;
mixbuf[j+1] -= (rvol*(int32_t)data[offs])>>14;
}
}else{
s8int *data = (s8int*)ite->SamplePointer[slave->Smp];
for(j = 0; j < tper*2; j+=2){
if(update_offs(ite, slave, &offs, &oferr, &nfreq, lpbeg, lpend) != 0)
break;
mixbuf[j+0] -= (lvol*(int32_t)data[offs])>>(14-8);
mixbuf[j+1] -= (rvol*(int32_t)data[offs])>>(14-8);
}
}
slave->Sample_Offset = offs;
slave->SmpErr = oferr;
}
slave->Flags &= 0x788D;
}
for(i = 0; i < tper*2; i++){
int32_t v = mixbuf[i];
if(v > 0x7FFF)
v = 0x7FFF;
else if(v < -0x7FFF)
v = -0x7FFF;
outbuf[i] = v;
}
int got = tper*2*2;
int skip = 0;
if(pos > 0.001){
double n = MIN(pos, (double)got / 44100.0);
int skip = (int)(n * 44100)*2*2;
pos -= n;
if(skip >= got)
return 0;
}
write(1, outbuf+skip, got-skip);
return 0;
}
static int
DriverSetTempo(it_engine *, uint16_t Tempo)
{
tempo = Tempo;
return 0;
}
static int
DriverSetMixVolume(it_engine *ite, uint16_t MixVolume)
{
USED(ite, MixVolume);
return 0;
}
static int
DriverSetStereo(it_engine *ite, uint16_t Stereo)
{
/* whoops */
USED(ite, Stereo);
return 0;
}
static int
DriverReleaseSample(it_engine *, it_sample *)
{
return 0;
}
static int
DriverMIDIOut(it_engine *, uint8_t)
{
return 0;
}
static int
DriverGetWaveform(it_engine *)
{
return 0;
}
it_drvdata *
drv_oss_init(it_engine *)
{
static it_drvdata d = {
.BasePort = 0xFFFF,
.IRQ = 0xFFFF,
.DMA = 0xFFFF,
.CmdLineMixSpeed = 0,
.CmdLineDMASize = 1024,
.ReverseChannels = 0,
.DriverMaxChannels = 256,
.StopEndOfPlaySection = 1,
.DefaultChannels = 256,
.DriverFlags = 0,
.DriverDetectCard = DriverDetectCard,
.DriverInitSound = DriverInitSound,
.DriverUninitSound = DriverUninitSound,
.DriverPoll = DriverPoll,
.DriverSetTempo = DriverSetTempo,
.DriverSetMixVolume = DriverSetMixVolume,
.DriverSetStereo = DriverSetStereo,
.DriverReleaseSample = DriverReleaseSample,
.DriverMIDIOut = DriverMIDIOut,
.DriverGetWaveform = DriverGetWaveform,
};
return &d;
}
it_drvdata *
drv_sdl_init(it_engine *)
{
return nil;
}
static void
usage(void)
{
fprint(2, "usage: %s [-s SECONDS]\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
it_engine *ite;
ARGBEGIN{
case 's':
pos = atof(EARGF(usage()));
assert(pos >= 0.0);
break;
default:
usage();
}ARGEND
ite = ITEngineNew();
Music_InitMusic(ite);
Music_AutoDetectSoundCard(ite);
D_LoadIT(ite, 0);
Music_PlaySong(ite, 0);
if(pos > 0.0)
fprint(2, "time: %g\n", pos);
while(ite->PlayMode != 0)
Music_Poll(ite);
}