Mercurial > ~darius > hgwebdir.cgi > mikmod
diff playercode/mdriver.c @ 12:437e8455d862
General tidy up..
Rename makefile.gcc to Makefile
author | darius |
---|---|
date | Thu, 23 Apr 1998 07:20:13 +0000 |
parents | 42e11dc15457 |
children | 80fa6dd10e14 |
line wrap: on
line diff
--- a/playercode/mdriver.c Fri Jan 23 16:05:11 1998 +0000 +++ b/playercode/mdriver.c Thu Apr 23 07:20:13 1998 +0000 @@ -1,556 +1,626 @@ -/* - -Name: MDRIVER.C - -Description: -These routines are used to access the available soundcard drivers. - -Portability: -All systems - all compilers - -*/ - -#include "mikmod.h" - -MDRIVER *firstdriver = NULL, *md_driver = &drv_nos; - -UWORD md_device = 0; -UWORD md_mixfreq = 44100; -UWORD md_mode = DMODE_STEREO | DMODE_16BITS | DMODE_SURROUND; -UWORD md_dmabufsize = 50; -UBYTE md_pansep = 128; // 128 == 100% (full left/right) - -UBYTE md_reverb = 6; // Reverb - -UBYTE md_volume = 96; // Global sound volume (0-128) -UBYTE md_musicvolume = 128; // volume of song -UBYTE md_sndfxvolume = 128; // volume of sound effects - -UBYTE md_bpm = 125; - - -// Do not modify the numchn variables yourself! use MD_SetVoices() - -UBYTE md_numchn = 0, md_sngchn = 0, md_sfxchn = 0; -UBYTE md_hardchn = 0, md_softchn = 0; - - -void (*md_player)(void) = Player_HandleTick; -static BOOL isplaying = 0, initialized = 0; -static UBYTE *sfxinfo; -static int sfxpool; - -static SAMPLE **md_sample = NULL; - -// Backup variables. This way, the end programmer can fiddle with the -// main globals without mikmod blowing up. - -static UWORD idevice, imixfreq, imode, idmabufsize; - - -static void LimitHardVoices(int limit) - -// Limits the number of hardware voices to the specified amount. -// This function should only be used by the low-level drivers. - -{ - int t = 0; - - if(!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > limit)) md_sfxchn = limit; - if(!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > limit)) md_sngchn = limit; - - if(!(md_mode & DMODE_SOFT_SNDFX)) - md_hardchn = md_sfxchn; - else - md_hardchn = 0; - - if(!(md_mode & DMODE_SOFT_MUSIC)) - md_hardchn += md_sngchn; - - while(md_hardchn > limit) - { - if(++t & 1) - if(!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > 4)) md_sfxchn--; - else - if(!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > 8)) md_sngchn--; - - if(!(md_mode & DMODE_SOFT_SNDFX)) - md_hardchn = md_sfxchn; - else - md_hardchn = 0; - - if(!(md_mode & DMODE_SOFT_MUSIC)) - md_hardchn += md_sngchn; - } - - md_numchn = md_hardchn + md_softchn; -} - - -static void LimitSoftVoices(int limit) - -// Limits the number of hardware voices to the specified amount. -// This function should only be used by the low-level drivers. - -{ - int t = 0; - - if((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > limit)) md_sfxchn = limit; - if((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > limit)) md_sngchn = limit; - - if(md_mode & DMODE_SOFT_SNDFX) - md_softchn = md_sfxchn; - else - md_softchn = 0; - - if(md_mode & DMODE_SOFT_MUSIC) - md_softchn += md_sngchn; - - while(md_softchn > limit) - { - if(++t & 1) - if((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > 4)) md_sfxchn--; - else - if((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > 8)) md_sngchn--; - - if(!(md_mode & DMODE_SOFT_SNDFX)) - md_softchn = md_sfxchn; - else - md_softchn = 0; - - if(!(md_mode & DMODE_SOFT_MUSIC)) - md_softchn += md_sngchn; - } - - md_numchn = md_hardchn + md_softchn; -} - - -// Note: 'type' indicates whether the returned value should be for music -// or for sound effects. - -ULONG MD_SampleSpace(int type) -{ - if(type==MD_MUSIC) - type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE; - else if(type==MD_SNDFX) - type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE; - - return md_driver->FreeSampleSpace(type); -} - - -ULONG MD_SampleLength(int type, SAMPLE *s) -{ - if(type==MD_MUSIC) - type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE; - else if(type==MD_SNDFX) - type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE; - - return md_driver->RealSampleLength(type, s); -} - - -UWORD MD_SetDMA(int secs) - -// Converts the given number of 1/10th seconds into the number of bytes of -// audio that a sample # 1/10th seconds long would require at the current md_* -// settings. - -{ - ULONG result; - - result = (md_mixfreq * ((md_mode & DMODE_STEREO) ? 2 : 1) * - ((md_mode & DMODE_16BITS) ? 2 : 1) * secs) * 10; - - if(result > 32000) result = 32000; - return(md_dmabufsize = (result & ~3)); // round it off to an 8 byte boundry -} - - -void MD_InfoDriver(void) -{ - int t; - MDRIVER *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(MDRIVER *drv) -{ - MDRIVER *cruise = firstdriver; - - if(cruise!=NULL) - { while(cruise->next!=NULL) cruise = cruise->next; - cruise->next = drv; - } else - firstdriver = drv; -} - - -SWORD MD_SampleLoad(SAMPLOAD *s, int type, FILE *fp) -// type - sample type .. MD_MUSIC or MD_SNDFX -{ - SWORD result; - - if(type==MD_MUSIC) - type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE; - else if(type==MD_SNDFX) - type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE; - - SL_Init(s); - result = md_driver->SampleLoad(s, type, fp); - SL_Exit(s); - - return result; -} - - -void MD_SampleUnLoad(SWORD handle) -{ - md_driver->SampleUnLoad(handle); -} - - -void MD_SetBPM(UBYTE bpm) -{ - md_bpm = bpm; -} - - -void MikMod_RegisterPlayer(void (*player)(void)) -{ - md_player = player; -} - - -void MikMod_Update(void) -{ - if(isplaying) md_driver->Update(); -} - - -void Voice_SetVolume(int voice, UWORD vol) -{ - ULONG tmp; - - if((voice<0) || (voice>=md_numchn)) return; - tmp = (ULONG)vol * (ULONG)md_volume * ((voice < md_sngchn) ? (ULONG)md_musicvolume : (ULONG)md_sndfxvolume); - md_driver->VoiceSetVolume(voice,tmp/16384UL); -} - - -void Voice_SetFrequency(int voice, ULONG frq) -{ - if((voice < 0) || (voice >= md_numchn)) return; - if(md_sample[voice]!=NULL && md_sample[voice]->divfactor!=0) frq/=md_sample[voice]->divfactor; - md_driver->VoiceSetFrequency(voice, frq); -} - - -void Voice_SetPanning(int voice, ULONG pan) -{ - if((voice < 0) || (voice >= md_numchn)) return; - if(pan!=PAN_SURROUND) - { if(md_mode & DMODE_REVERSE) pan = 255-pan; - pan = (((SWORD)(pan-128)*md_pansep) / 128)+128; - } - md_driver->VoiceSetPanning(voice, pan); -} - - -void Voice_Play(int voice, SAMPLE *s, ULONG start) -{ - ULONG repend; - - if((voice < 0) || (voice >= md_numchn) || (start >= s->length)) return; - - md_sample[voice] = s; - repend = s->loopend; - - if(s->flags&SF_LOOP) - if(repend > s->length) repend = s->length; // repend can't be bigger than size - - md_driver->VoicePlay(voice,s->handle,start,s->length,s->loopstart,repend,s->flags); -} - - -void Voice_Stop(int voice) -{ - if((voice < 0) || (voice >= md_numchn)) return; - if(voice >= md_sngchn) - { // It is a sound effects channel, so flag the voice as non-critical! - sfxinfo[voice-md_sngchn] = 0; - } - - md_driver->VoiceStop(voice); -} - - -BOOL Voice_Stopped(int voice) -{ - if((voice < 0) || (voice >= md_numchn)) return 0; - return(md_driver->VoiceStopped(voice)); -} - - -SLONG Voice_GetPosition(int voice) -{ - if((voice < 0) || (voice >= md_numchn)) return 0; - return(md_driver->VoiceGetPosition(voice)); -} - - -ULONG Voice_RealVolume(int voice) -{ - if((voice < 0) || (voice >= md_numchn)) return 0; - return(md_driver->VoiceRealVolume(voice)); -} - - -// ================================ -// Functions prefixed with MikMod -// ================================ - -BOOL MikMod_Init(void) -{ - UWORD t; - - _mm_critical = 1; - - // 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) - { _mm_errno = MMERR_DETECTING_DEVICE; - if(_mm_errorhandler!=NULL) _mm_errorhandler(); - md_driver = &drv_nos; - return 1; - } - - md_device = t; - } else - { // 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) - { _mm_errno = MMERR_INVALID_DEVICE; - if(_mm_errorhandler!=NULL) _mm_errorhandler(); - md_driver = &drv_nos; - return 1; - } - - if(!md_driver->IsPresent()) - { _mm_errno = MMERR_DETECTING_DEVICE; - if(_mm_errorhandler!=NULL) _mm_errorhandler(); - md_driver = &drv_nos; - return 1; - } - } - - if(md_driver->Init()) - { MikMod_Exit(); - if(_mm_errorhandler!=NULL) _mm_errorhandler(); - return 1; - } - - idevice = md_device; imode = md_mode; - imixfreq = md_mixfreq; idmabufsize = md_dmabufsize; - initialized = 1; - _mm_critical = 0; - - return 0; -} - - -void MikMod_Exit(void) -{ - MikMod_DisableOutput(); - md_driver->Exit(); - md_numchn = md_sfxchn = md_sngchn = 0; - md_driver = &drv_nos; - initialized = 0; -} - - -BOOL MikMod_Reset(void) - -// Reset the driver using the new global variable settings. -// If the driver has not been initialized, it will be now. - -{ - if(!initialized) return MikMod_Init(); - if((md_driver->Reset == NULL) || (md_device != idevice)) - { // md_driver->Reset was NULL, or md_device was changed, - // so do a full reset of the driver. - - if(isplaying) md_driver->PlayStop(); - md_driver->Exit(); - if(MikMod_Init()) - { MikMod_Exit(); - if(_mm_errorhandler!=NULL) _mm_errorhandler(); - return 1; - } - if(isplaying) md_driver->PlayStart(); - } else - { if(md_driver->Reset()) - { MikMod_Exit(); - if(_mm_errorhandler!=NULL) _mm_errorhandler(); - return 1; - } - } - - return 0; -} - - -BOOL MikMod_SetNumVoices(int music, int sfx) - -// If either parameter is -1, the current set value will be retained. - -{ - BOOL resume = 0; - int t, oldchn = 0; - - if((music==0) && (sfx==0)) return 0; - - _mm_critical = 1; - - if(isplaying) - { MikMod_DisableOutput(); - oldchn = md_numchn; - resume = 1; - } - - if(sfxinfo!=NULL) free(sfxinfo); - if(md_sample!=NULL) free(md_sample); - md_sample = NULL; - sfxinfo = NULL; - - /*md_softchn = md_hardchn = 0; - - if(md_mode & DMODE_SOFT_SNDFX) - md_softchn = sfx; else md_hardchn = sfx; - - if(md_mode & DMODE_SOFT_MUSIC) - md_softchn += music; else md_hardchn += music; - */ - - if(music != -1) md_sngchn = music; - if(sfx != -1) md_sfxchn = sfx; - - md_numchn = md_sngchn + md_sfxchn; - - LimitHardVoices(md_driver->HardVoiceLimit); - LimitSoftVoices(md_driver->SoftVoiceLimit); - - if(md_driver->SetNumVoices()) - { MikMod_Exit(); - md_numchn = md_softchn = md_hardchn = md_sfxchn = md_sngchn = 0; - if(_mm_errorhandler!=NULL) _mm_errorhandler(); - return 1; - } - - if(md_sngchn || md_sfxchn) - md_sample = (SAMPLE **)_mm_calloc(md_sngchn+md_sfxchn, sizeof(SAMPLE *)); - if(md_sfxchn) - sfxinfo = (UBYTE *)_mm_calloc(md_sfxchn, sizeof(UBYTE)); - - // make sure the player doesn't start with garbage - for(t=oldchn; t<md_numchn; t++) Voice_Stop(t); - - sfxpool = 0; - - if(resume) MikMod_EnableOutput(); - _mm_critical = 0; - - return 0; -} - - -BOOL MikMod_EnableOutput(void) -{ - // safety valve, prevents entering - // playstart twice: - - _mm_critical = 1; - if(!isplaying) - { if(md_driver->PlayStart()) return 1; - isplaying = 1; - } - _mm_critical = 0; - return 0; -} - - -void MikMod_DisableOutput(void) -{ - // safety valve, prevents calling playStop when playstart - // hasn't been called: - - if(isplaying && md_driver!=NULL) - { isplaying = 0; - md_driver->PlayStop(); - } -} - - -BOOL MikMod_Active(void) -{ - return isplaying; -} - - -int MikMod_PlaySample(SAMPLE *s, ULONG start, UBYTE flags) - -// Plays a sound effects sample. Picks a voice from the number of voices -// allocated for use as sound effects (loops through voices, skipping all -// active criticals). -// -// Returns the voice that the sound is being played on. - -{ - int orig = sfxpool; // for cases where all channels are critical - int c; - - if(md_sfxchn==0) return -1; - if(s->volume > 64) s->volume = 64; - - // check the first location after sfxpool - do - { if(sfxinfo[sfxpool] & SFX_CRITICAL) - { if(md_driver->VoiceStopped(c=sfxpool+md_sngchn)) - { sfxinfo[sfxpool] = flags; - Voice_Play(c, s, start); - md_driver->VoiceSetVolume(c,s->volume<<2); - md_driver->VoiceSetPanning(c,s->panning); - md_driver->VoiceSetFrequency(c,s->speed); - sfxpool++; - if(sfxpool >= md_sfxchn) sfxpool = 0; - return c; - } - } else - { sfxinfo[sfxpool] = flags; - Voice_Play(c=sfxpool+md_sngchn, s, start); - md_driver->VoiceSetVolume(c,s->volume<<2); - md_driver->VoiceSetPanning(c,s->panning); - md_driver->VoiceSetFrequency(c,s->speed); - sfxpool++; - if(sfxpool >= md_sfxchn) sfxpool = 0; - return c; - } - - sfxpool++; - if(sfxpool >= md_sfxchn) sfxpool = 0; - } while(sfxpool!=orig); - - return -1; -} - +/* + * Name: MDRIVER.C + * + * Description: These routines are used to access the available soundcard + * drivers. + * + * Portability: All systems - all compilers + * + */ + +#include "mikmod.h" + +MDRIVER *firstdriver = NULL, *md_driver = &drv_nos; + +UWORD md_device = 0; +UWORD md_mixfreq = 44100; +UWORD md_mode = DMODE_STEREO | DMODE_16BITS | DMODE_SURROUND; +UWORD md_dmabufsize = 50; +UBYTE md_pansep = 128; /* 128 == 100% (full left/right) */ + +UBYTE md_reverb = 6; /* Reverb */ + +UBYTE md_volume = 96; /* Global sound volume (0-128) */ +UBYTE md_musicvolume = 128; /* volume of song */ +UBYTE md_sndfxvolume = 128; /* volume of sound effects */ + +UBYTE md_bpm = 125; + + +/* Do not modify the numchn variables yourself! use MD_SetVoices() */ + +UBYTE md_numchn = 0, md_sngchn = 0, md_sfxchn = 0; +UBYTE md_hardchn = 0, md_softchn = 0; + + +void (*md_player) (void) = Player_HandleTick; +static BOOL isplaying = 0, initialized = 0; +static UBYTE *sfxinfo; +static int sfxpool; + +static SAMPLE **md_sample = NULL; + +/* + * Backup variables. This way, the end programmer can fiddle with the main + * globals without mikmod blowing up. + */ + +static UWORD idevice, imixfreq, imode, idmabufsize; + +/* + * Limits the number of hardware voices to the specified amount. This + * function should only be used by the low-level drivers. + */ +static void +LimitHardVoices(int limit) +{ + int t = 0; + + if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > limit)) + md_sfxchn = limit; + if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > limit)) + md_sngchn = limit; + + if (!(md_mode & DMODE_SOFT_SNDFX)) + md_hardchn = md_sfxchn; + else + md_hardchn = 0; + + if (!(md_mode & DMODE_SOFT_MUSIC)) + md_hardchn += md_sngchn; + + while (md_hardchn > limit) { + if (++t & 1) + if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > 4)) + md_sfxchn--; + else if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > 8)) + md_sngchn--; + + if (!(md_mode & DMODE_SOFT_SNDFX)) + md_hardchn = md_sfxchn; + else + md_hardchn = 0; + + if (!(md_mode & DMODE_SOFT_MUSIC)) + md_hardchn += md_sngchn; + } + + md_numchn = md_hardchn + md_softchn; +} + +/* + * Limits the number of hardware voices to the specified amount. This + * function should only be used by the low-level drivers. + */ +static void +LimitSoftVoices(int limit) +{ + int t = 0; + + if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > limit)) + md_sfxchn = limit; + if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > limit)) + md_sngchn = limit; + + if (md_mode & DMODE_SOFT_SNDFX) + md_softchn = md_sfxchn; + else + md_softchn = 0; + + if (md_mode & DMODE_SOFT_MUSIC) + md_softchn += md_sngchn; + + while (md_softchn > limit) { + if (++t & 1) + if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > 4)) + md_sfxchn--; + else if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > 8)) + md_sngchn--; + + if (!(md_mode & DMODE_SOFT_SNDFX)) + md_softchn = md_sfxchn; + else + md_softchn = 0; + + if (!(md_mode & DMODE_SOFT_MUSIC)) + md_softchn += md_sngchn; + } + + md_numchn = md_hardchn + md_softchn; +} + + +/* + * Note: 'type' indicates whether the returned value should be for music or + * for sound effects. + */ +ULONG +MD_SampleSpace(int type) +{ + if (type == MD_MUSIC) + type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE; + else if (type == MD_SNDFX) + type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE; + + return md_driver->FreeSampleSpace(type); +} + + +ULONG +MD_SampleLength(int type, SAMPLE * s) +{ + if (type == MD_MUSIC) + type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE; + else if (type == MD_SNDFX) + type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE; + + return md_driver->RealSampleLength(type, s); +} + + +/* + * Converts the given number of 1/10th seconds into the number of bytes of + * audio that a sample # 1/10th seconds long would require at the current md_* + * settings. + */ +UWORD +MD_SetDMA(int secs) +{ + ULONG result; + + result = (md_mixfreq * ((md_mode & DMODE_STEREO) ? 2 : 1) * + ((md_mode & DMODE_16BITS) ? 2 : 1) * secs) * 10; + + if (result > 32000) + result = 32000; + return (md_dmabufsize = (result & ~3)); /* round it off to an 8 byte + * boundry */ +} + + +void +MD_InfoDriver(void) +{ + int t; + MDRIVER *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(MDRIVER * drv) +{ + MDRIVER *cruise = firstdriver; + + if (cruise != NULL) { + while (cruise->next != NULL) + cruise = cruise->next; + cruise->next = drv; + } else + firstdriver = drv; +} + + +/* type - sample type .. MD_MUSIC or MD_SNDFX */ +SWORD +MD_SampleLoad(SAMPLOAD * s, int type, FILE * fp) +{ + SWORD result; + + if (type == MD_MUSIC) + type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE; + else if (type == MD_SNDFX) + type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE; + + SL_Init(s); + result = md_driver->SampleLoad(s, type, fp); + SL_Exit(s); + + return result; +} + + +void +MD_SampleUnLoad(SWORD handle) +{ + md_driver->SampleUnLoad(handle); +} + + +void +MD_SetBPM(UBYTE bpm) +{ + md_bpm = bpm; +} + + +void +MikMod_RegisterPlayer(void (*player) (void)) +{ + md_player = player; +} + + +void +MikMod_Update(void) +{ + if (isplaying) + md_driver->Update(); +} + + +void +Voice_SetVolume(int voice, UWORD vol) +{ + ULONG tmp; + + if ((voice < 0) || (voice >= md_numchn)) + return; + tmp = (ULONG) vol *(ULONG) md_volume * + ((voice < md_sngchn) ? (ULONG) md_musicvolume : (ULONG) md_sndfxvolume); + md_driver->VoiceSetVolume(voice, tmp / 16384 UL); +} + + +void +Voice_SetFrequency(int voice, ULONG frq) +{ + if ((voice < 0) || (voice >= md_numchn)) + return; + if (md_sample[voice] != NULL && md_sample[voice]->divfactor != 0) + frq /= md_sample[voice]->divfactor; + md_driver->VoiceSetFrequency(voice, frq); +} + + +void +Voice_SetPanning(int voice, ULONG pan) +{ + if ((voice < 0) || (voice >= md_numchn)) + return; + if (pan != PAN_SURROUND) { + if (md_mode & DMODE_REVERSE) + pan = 255 - pan; + pan = (((SWORD) (pan - 128) * md_pansep) / 128) + 128; + } + md_driver->VoiceSetPanning(voice, pan); +} + + +void +Voice_Play(int voice, SAMPLE * s, ULONG start) +{ + ULONG repend; + + if ((voice < 0) || (voice >= md_numchn) || (start >= s->length)) + return; + + md_sample[voice] = s; + repend = s->loopend; + + if (s->flags & SF_LOOP) + if (repend > s->length) + repend = s->length; /* repend can't be bigger than size */ + + md_driver->VoicePlay(voice, s->handle, start, s->length, s->loopstart, repend, s->flags); +} + + +void +Voice_Stop(int voice) +{ + if ((voice < 0) || (voice >= md_numchn)) + return; + if (voice >= md_sngchn) { /* It is a sound effects channel, so flag the + * voice as non-critical! */ + sfxinfo[voice - md_sngchn] = 0; + } + md_driver->VoiceStop(voice); +} + + +BOOL +Voice_Stopped(int voice) +{ + if ((voice < 0) || (voice >= md_numchn)) + return 0; + return (md_driver->VoiceStopped(voice)); +} + + +SLONG +Voice_GetPosition(int voice) +{ + if ((voice < 0) || (voice >= md_numchn)) + return 0; + return (md_driver->VoiceGetPosition(voice)); +} + + +ULONG +Voice_RealVolume(int voice) +{ + if ((voice < 0) || (voice >= md_numchn)) + return 0; + return (md_driver->VoiceRealVolume(voice)); +} + + +/* + * Functions prefixed with MikMod + */ +BOOL +MikMod_Init(void) +{ + UWORD t; + + _mm_critical = 1; + + /* 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) { + _mm_errno = MMERR_DETECTING_DEVICE; + if (_mm_errorhandler != NULL) + _mm_errorhandler(); + md_driver = &drv_nos; + return 1; + } + md_device = t; + } else { /* if n>0 use that driver */ + for (t = 1, md_driver = firstdriver; + (md_driver != NULL) && (t != md_device); + md_driver = md_driver->next, t++) + ; /* Nothing */ + + if (md_driver == NULL) { + _mm_errno = MMERR_INVALID_DEVICE; + if (_mm_errorhandler != NULL) + _mm_errorhandler(); + md_driver = &drv_nos; + return 1; + } + if (!md_driver->IsPresent()) { + _mm_errno = MMERR_DETECTING_DEVICE; + if (_mm_errorhandler != NULL) + _mm_errorhandler(); + md_driver = &drv_nos; + return 1; + } + } + + if (md_driver->Init()) { + MikMod_Exit(); + if (_mm_errorhandler != NULL) + _mm_errorhandler(); + return 1; + } + idevice = md_device; + imode = md_mode; + imixfreq = md_mixfreq; + idmabufsize = md_dmabufsize; + initialized = 1; + _mm_critical = 0; + + return 0; +} + + +void +MikMod_Exit(void) +{ + MikMod_DisableOutput(); + md_driver->Exit(); + md_numchn = md_sfxchn = md_sngchn = 0; + md_driver = &drv_nos; + initialized = 0; +} + + +/* + * Reset the driver using the new global variable settings. If the driver has + * not been initialized, it will be now. + */ +BOOL +MikMod_Reset(void) +{ + if (!initialized) + return MikMod_Init(); + if ((md_driver->Reset == NULL) || + (md_device != idevice)) { /* md_driver->Reset was + * NULL, or md_device + * was changed, so do a + * full reset of the + * driver. */ + if (isplaying) + md_driver->PlayStop(); + md_driver->Exit(); + if (MikMod_Init()) { + MikMod_Exit(); + if (_mm_errorhandler != NULL) + _mm_errorhandler(); + return 1; + } + if (isplaying) + md_driver->PlayStart(); + } else { + if (md_driver->Reset()) { + MikMod_Exit(); + if (_mm_errorhandler != NULL) + _mm_errorhandler(); + return 1; + } + } + + return 0; +} + + +/* If either parameter is -1, the current set value will be retained. */ +BOOL +MikMod_SetNumVoices(int music, int sfx) +{ + BOOL resume = 0; + int t, oldchn = 0; + + if ((music == 0) && (sfx == 0)) + return 0; + + _mm_critical = 1; + + if (isplaying) { + MikMod_DisableOutput(); + oldchn = md_numchn; + resume = 1; + } + if (sfxinfo != NULL) + free(sfxinfo); + if (md_sample != NULL) + free(md_sample); + md_sample = NULL; + sfxinfo = NULL; + + /* + * md_softchn = md_hardchn = 0; + * + * if(md_mode & DMODE_SOFT_SNDFX) md_softchn = sfx; else md_hardchn = sfx; + * + * if(md_mode & DMODE_SOFT_MUSIC) md_softchn += music; else md_hardchn += + * music; + */ + + if (music != -1) + md_sngchn = music; + if (sfx != -1) + md_sfxchn = sfx; + + md_numchn = md_sngchn + md_sfxchn; + + LimitHardVoices(md_driver->HardVoiceLimit); + LimitSoftVoices(md_driver->SoftVoiceLimit); + + if (md_driver->SetNumVoices()) { + MikMod_Exit(); + md_numchn = md_softchn = md_hardchn = md_sfxchn = md_sngchn = 0; + if (_mm_errorhandler != NULL) + _mm_errorhandler(); + return 1; + } + if (md_sngchn || md_sfxchn) + md_sample = (SAMPLE **) _mm_calloc(md_sngchn + md_sfxchn, sizeof(SAMPLE *)); + if (md_sfxchn) + sfxinfo = (UBYTE *) _mm_calloc(md_sfxchn, sizeof(UBYTE)); + + /* make sure the player doesn't start with garbage */ + for (t = oldchn; t < md_numchn; t++) + Voice_Stop(t); + + sfxpool = 0; + + if (resume) + MikMod_EnableOutput(); + _mm_critical = 0; + + return 0; +} + + +BOOL +MikMod_EnableOutput(void) +{ + /* + * safety valve, prevents entering playstart twice: + */ + _mm_critical = 1; + if (!isplaying) { + if (md_driver->PlayStart()) + return 1; + isplaying = 1; + } + _mm_critical = 0; + return 0; +} + + +void +MikMod_DisableOutput(void) +{ + /* + * safety valve, prevents calling playStop when playstart hasn't been + * called: + */ + + if (isplaying && md_driver != NULL) { + isplaying = 0; + md_driver->PlayStop(); + } +} + + +BOOL +MikMod_Active(void) +{ + return isplaying; +} + + +/* + * Plays a sound effects sample. Picks a voice from the number of voices + * allocated for use as sound effects (loops through voices, skipping all + * active criticals). + * + * Returns the voice that the sound is being played on. + */ +int +MikMod_PlaySample(SAMPLE * s, ULONG start, UBYTE flags) +{ + int orig = sfxpool; /* for cases where all channels are + * critical */ + int c; + + if (md_sfxchn == 0) + return -1; + if (s->volume > 64) + s->volume = 64; + + /* check the first location after sfxpool */ + do { + if (sfxinfo[sfxpool] & SFX_CRITICAL) { + if (md_driver->VoiceStopped(c = sfxpool + md_sngchn)) { + sfxinfo[sfxpool] = flags; + Voice_Play(c, s, start); + md_driver->VoiceSetVolume(c, s->volume << 2); + md_driver->VoiceSetPanning(c, s->panning); + md_driver->VoiceSetFrequency(c, s->speed); + sfxpool++; + if (sfxpool >= md_sfxchn) + sfxpool = 0; + return c; + } + } else { + sfxinfo[sfxpool] = flags; + Voice_Play(c = sfxpool + md_sngchn, s, start); + md_driver->VoiceSetVolume(c, s->volume << 2); + md_driver->VoiceSetPanning(c, s->panning); + md_driver->VoiceSetFrequency(c, s->speed); + sfxpool++; + if (sfxpool >= md_sfxchn) + sfxpool = 0; + return c; + } + + sfxpool++; + if (sfxpool >= md_sfxchn) + sfxpool = 0; + } while (sfxpool != orig); + + return -1; +}