#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;} intDriverUninitSound(it_engine *){ return 0;} static voidkill_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 intupdate_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 intDriverPoll(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 intDriverSetTempo(it_engine *, uint16_t Tempo){ tempo = Tempo; return 0;} static intDriverSetMixVolume(it_engine *ite, uint16_t MixVolume){ USED(ite, MixVolume); return 0;} static intDriverSetStereo(it_engine *ite, uint16_t Stereo){ /* whoops */ USED(ite, Stereo); return 0;} static intDriverReleaseSample(it_engine *, it_sample *){ return 0;} static intDriverMIDIOut(it_engine *, uint8_t){ return 0;} static intDriverGetWaveform(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 voidusage(void){ fprint(2, "usage: %s [-s SECONDS]\n", argv0); exits("usage");} voidmain(int argc, char **argv){ it_engine *ite; char *s; 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); s = (char*)ite->hdr.SongName; if(*s != 0) fprint(2, "%.*s\n", sizeof(ite->hdr.SongName), s); if(pos > 0.0) fprint(2, "time: %g\n", pos); while(ite->PlayMode != 0) Music_Poll(ite);}
#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;
char *s;
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);
s = (char*)ite->hdr.SongName;
if(*s != 0)
fprint(2, "%.*s\n", sizeof(ite->hdr.SongName), s);
if(pos > 0.0)
fprint(2, "time: %g\n", pos);
while(ite->PlayMode != 0)
Music_Poll(ite);
}