ref: 3e8dbce97cd4b03b43f226aaf406b8809dba998b
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; 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); }