#include #include #include #include "mtypes.h" #include "mdriver.h" DRIVER *firstdriver=NULL,*md_driver; void (*md_tickhandler)(void)=NULL; UWORD md_device =0; UWORD md_mixfreq =44100; UWORD md_mode =0; UWORD md_dmabufsize =8192; UBYTE md_bpm =125; UBYTE md_numchn =0; static FILE *sl_fp; static WORD sl_old; static UWORD sl_infmt; static UWORD sl_outfmt; GHOLD ghld[32]; void SL_Init(FILE *fp,UWORD infmt,UWORD outfmt) { sl_old=0; sl_fp=fp; sl_infmt=infmt; sl_outfmt=outfmt; } int SL_GetSample(void) { WORD s; if(sl_infmt & SF_16BITS){ fread(&s,2,1,sl_fp); } else{ s=fgetc(sl_fp)<<8; } if(sl_infmt & SF_DELTA){ s+=sl_old; sl_old=s; } if((sl_infmt^sl_outfmt) & SF_SIGNED) s^=0x8000; return s; } void SL_Load(void *buffer,ULONG length) { if(sl_outfmt & SF_16BITS){ WORD *p=buffer; length>>=1; while(length--) *(p++)=SL_GetSample(); } else{ BYTE *p=buffer; while(length--) *(p++)=SL_GetSample()>>8; } } ULONG tcount; UWORD tspeed; void SetBPM(UBYTE BPM) { tspeed=(1193181UL*125)/(50U*BPM); outportb(0x43,0x34); outportb(0x40,tspeed&0xff); outportb(0x40,tspeed>>8); } void MD_InfoDriver(void) { int t; DRIVER *l; /* list all registered devicedrivers: */ for(t=1,l=firstdriver; l!=NULL; l=l->next, t++){ printf("%d. %s\n",t,l->Version); } } void MD_RegisterDriver(DRIVER *drv) { if(firstdriver==NULL){ firstdriver=drv; drv->next=NULL; } else{ drv->next=firstdriver; firstdriver=drv; } } WORD MD_SampleLoad(FILE *fp,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { return(md_driver->SampleLoad(fp,size,reppos,repend,flags)); } void MD_SampleUnLoad(WORD handle) { md_driver->SampleUnLoad(handle); } BOOL MD_Init(void) { UWORD t; // if md_device==0, try to find a device number if(md_device==0){ for(t=1,md_driver=firstdriver; md_driver!=NULL; md_driver=md_driver->next, t++){ if(md_driver->IsPresent()) break; } if(md_driver==NULL){ myerr="You don't have any of the supported sound-devices"; return 0; } md_device=t; } // if n>0 use that driver for(t=1,md_driver=firstdriver; md_driver!=NULL && t!=md_device; md_driver=md_driver->next, t++); if(md_driver==NULL){ myerr="Device number out of range"; return 0; } return(md_driver->Init()); } void MD_Exit(void) { md_driver->Exit(); } static int isfirst; void (interrupt far *oldclocktick)(void); void interrupt timerhandler(void) { SetBPM(md_bpm); if(md_tickhandler!=NULL){ /* do not call the tickhandler if this is the very first interrupt generated by the timer.. this prevents getting getting wierd noises on the first tick when the dma buffer played an uncertain amount of samples. */ if(isfirst) isfirst=0; else md_tickhandler(); } md_driver->Update(); tcount+=tspeed; if(tcount>=0x10000){ tcount-=0x10000; oldclocktick(); } else outportb(0x20,0x20); } void MD_PlayStart(void) { UWORD t; for(t=0;tPlayStart(); oldclocktick=_dos_getvect(0x8); _dos_setvect(0x8,timerhandler); tcount=0; SetBPM(md_bpm); } void MD_PlayStop(void) { _dos_setvect(0x8,oldclocktick); outportb(0x43,0x34); outportb(0x40,0); outportb(0x40,0); md_driver->PlayStop(); } void MD_VoiceSetVolume(UBYTE voice,UBYTE vol) { ghld[voice].vol=vol; } void MD_VoiceSetFrequency(UBYTE voice,ULONG frq) { ghld[voice].frq=frq; } void MD_VoiceSetPanning(UBYTE voice,ULONG pan) { ghld[voice].pan=pan; } void MD_VoicePlay(UBYTE voice,WORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { if(start>=size) return; if(flags&SF_LOOP){ if(repend>size) repend=size; // repend can't be bigger than size } ghld[voice].flags=flags; ghld[voice].handle=handle; ghld[voice].start=start; ghld[voice].size=size; ghld[voice].reppos=reppos; ghld[voice].repend=repend; ghld[voice].kick=1; } void MD_RegisterTickHandler(void (*tickhandler)(void)) { md_tickhandler=tickhandler; }