📄 mdriver.c
字号:
/* MikMod sound library (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//*============================================================================== $Id: mdriver.c 346 2001-09-11 18:49:18Z slouken $ These routines are used to access the available soundcard drivers.==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef unix#include <pwd.h>#include <sys/stat.h>#endif#include <string.h>#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include "mikmod_internals.h"static MDRIVER *firstdriver=NULL; MDRIVER *md_driver=NULL;extern MODULE *pf; /* modfile being played */ UWORD md_device = 0; UWORD md_mixfreq = 44100; UWORD md_mode = DMODE_STEREO | DMODE_16BITS | DMODE_SURROUND |DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX; UBYTE md_pansep = 128; /* 128 == 100% (full left/right) */ UBYTE md_reverb = 6; /* Reverb */ UBYTE md_volume = 128; /* Global sound volume (0-128) */ UBYTE md_musicvolume = 128; /* volume of song */ UBYTE md_sndfxvolume = 128; /* volume of sound effects */ UWORD 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;/* Previous driver in use */static UWORD idevice;/* 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);}CHAR* MikMod_InfoDriver(void){ int t,len=0; MDRIVER *l; CHAR *list=NULL; MUTEX_LOCK(lists); /* compute size of buffer */ for(l=firstdriver;l;l=l->next) if(l->Version) len+=4+(l->next?1:0)+strlen(l->Version); if(len) if((list=_mm_malloc(len*sizeof(CHAR)))) { list[0]=0; /* list all registered device drivers : */ for(t=1,l=firstdriver;l;l=l->next,t++) if(l->Version) sprintf(list,(l->next)?"%s%2d %s\n":"%s%2d %s", list,t,l->Version); } MUTEX_UNLOCK(lists); return list;}void _mm_registerdriver(struct MDRIVER* drv){ MDRIVER *cruise = firstdriver; if(cruise) { while(cruise->next) cruise=cruise->next; cruise->next=drv; } else firstdriver = drv;}void _mm_unregisterdrivers(void){ MDRIVER *cruise=firstdriver, *drv; while ( cruise ) { drv = cruise; cruise = cruise->next; drv->next = NULL; } firstdriver = NULL;}void MikMod_RegisterDriver(struct MDRIVER* drv){ /* if we try to register an invalid driver, or an already registered driver, ignore this attempt */ if ((!drv)||(drv->next)) return; MUTEX_LOCK(lists); _mm_registerdriver(drv); MUTEX_UNLOCK(lists);}int MikMod_DriverFromAlias(CHAR *alias){ int rank=1; MDRIVER *cruise; MUTEX_LOCK(lists); cruise=firstdriver; while(cruise) { if (cruise->Alias) { if (!(strcasecmp(alias,cruise->Alias))) break; rank++; } cruise=cruise->next; } if(!cruise) rank=0; MUTEX_UNLOCK(lists); return rank;}SWORD MD_SampleLoad(SAMPLOAD* s, int type){ 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); SL_Exit(s); return result;}void MD_SampleUnload(SWORD handle){ md_driver->SampleUnload(handle);}MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t player){ MikMod_player_t result; MUTEX_LOCK(vars); result=md_player; md_player=player; MUTEX_UNLOCK(vars); return result;}void MikMod_Update(void){ MUTEX_LOCK(vars); if(isplaying) { if((!pf)||(!pf->forbid)) md_driver->Update(); else { if (md_driver->Pause) md_driver->Pause(); } } MUTEX_UNLOCK(vars);}void Voice_SetVolume_internal(SBYTE voice,UWORD vol){ ULONG tmp; if((voice<0)||(voice>=md_numchn)) return; /* range checks */ if(md_musicvolume>128) md_musicvolume=128; if(md_sndfxvolume>128) md_sndfxvolume=128; if(md_volume>128) md_volume=128; tmp=(ULONG)vol*(ULONG)md_volume* ((voice<md_sngchn)?(ULONG)md_musicvolume:(ULONG)md_sndfxvolume); md_driver->VoiceSetVolume(voice,tmp/16384UL);}void Voice_SetVolume(SBYTE voice,UWORD vol){ MUTEX_LOCK(vars); Voice_SetVolume_internal(voice,vol); MUTEX_UNLOCK(vars);}UWORD Voice_GetVolume(SBYTE voice){ UWORD result=0; MUTEX_LOCK(vars); if((voice>=0)&&(voice<md_numchn)) result=md_driver->VoiceGetVolume(voice); MUTEX_UNLOCK(vars); return result;}void Voice_SetFrequency_internal(SBYTE voice,ULONG frq){ if((voice<0)||(voice>=md_numchn)) return; if((md_sample[voice])&&(md_sample[voice]->divfactor)) frq/=md_sample[voice]->divfactor; md_driver->VoiceSetFrequency(voice,frq);}void Voice_SetFrequency(SBYTE voice,ULONG frq){ MUTEX_LOCK(vars); Voice_SetFrequency_internal(voice,frq); MUTEX_UNLOCK(vars);}ULONG Voice_GetFrequency(SBYTE voice){ ULONG result=0; MUTEX_LOCK(vars); if((voice>=0)&&(voice<md_numchn)) result=md_driver->VoiceGetFrequency(voice); MUTEX_UNLOCK(vars); return result;}void Voice_SetPanning_internal(SBYTE voice,ULONG pan){ if((voice<0)||(voice>=md_numchn)) return; if(pan!=PAN_SURROUND) { if(md_pansep>128) md_pansep=128; if(md_mode & DMODE_REVERSE) pan=255-pan; pan = (((SWORD)(pan-128)*md_pansep)/128)+128; } md_driver->VoiceSetPanning(voice, pan);}void Voice_SetPanning(SBYTE voice,ULONG pan){#ifdef MIKMOD_DEBUG if((pan!=PAN_SURROUND)&&((pan<0)||(pan>255))) fprintf(stderr,"\rVoice_SetPanning called with pan=%ld\n",(long)pan);#endif MUTEX_LOCK(vars); Voice_SetPanning_internal(voice,pan); MUTEX_UNLOCK(vars);}ULONG Voice_GetPanning(SBYTE voice){ ULONG result=PAN_CENTER; MUTEX_LOCK(vars); if((voice>=0)&&(voice<md_numchn)) result=md_driver->VoiceGetPanning(voice); MUTEX_UNLOCK(vars); return result;}void Voice_Play_internal(SBYTE voice,SAMPLE* s,ULONG start){ ULONG repend; if((voice<0)||(voice>=md_numchn)) return; md_sample[voice]=s; repend=s->loopend; if(s->flags&SF_LOOP) /* repend can't be bigger than size */ if(repend>s->length) repend=s->length; md_driver->VoicePlay(voice,s->handle,start,s->length,s->loopstart,repend,s->flags);}void Voice_Play(SBYTE voice,SAMPLE* s,ULONG start){ if(start>s->length) return; MUTEX_LOCK(vars); Voice_Play_internal(voice,s,start); MUTEX_UNLOCK(vars);}void Voice_Stop_internal(SBYTE 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);}void Voice_Stop(SBYTE voice){ MUTEX_LOCK(vars); Voice_Stop_internal(voice); MUTEX_UNLOCK(vars);}BOOL Voice_Stopped_internal(SBYTE voice){ if((voice<0)||(voice>=md_numchn)) return 0; return(md_driver->VoiceStopped(voice));}BOOL Voice_Stopped(SBYTE voice){ BOOL result; MUTEX_LOCK(vars); result=Voice_Stopped_internal(voice); MUTEX_UNLOCK(vars); return result;}SLONG Voice_GetPosition(SBYTE voice){ SLONG result=0; MUTEX_LOCK(vars); if((voice>=0)&&(voice<md_numchn)) result=(md_driver->VoiceGetPosition(voice)); MUTEX_UNLOCK(vars); return result;}ULONG Voice_RealVolume(SBYTE voice){ ULONG result=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -