📄 mdriver.c
字号:
/* MikMod sound library (c) 1998, 1999, 2000, 2001 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,v 1.3 2004/02/18 13:29:19 raph Exp $ 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#if defined unix || (defined __APPLE__ && defined __MACH__)#include <pwd.h>#include <sys/stat.h>#endif#include <string.h>#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include "mikmod_internals.h"#ifdef SUNOSextern int fprintf(FILE *, const char *, ...);#endifstatic MDRIVER *firstdriver=NULL;MIKMODAPI MDRIVER *md_driver=NULL;extern MODULE *pf; /* modfile being played *//* Initial global settings */MIKMODAPI UWORD md_device = 0; /* autodetect */MIKMODAPI UWORD md_mixfreq = 44100;MIKMODAPI UWORD md_mode = DMODE_STEREO | DMODE_16BITS | DMODE_SURROUND |DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX;MIKMODAPI UBYTE md_pansep = 128; /* 128 == 100% (full left/right) */MIKMODAPI UBYTE md_reverb = 0; /* no reverb */MIKMODAPI UBYTE md_volume = 128; /* global sound volume (0-128) */MIKMODAPI UBYTE md_musicvolume = 128; /* volume of song */MIKMODAPI UBYTE md_sndfxvolume = 128; /* volume of sound effects */ UWORD md_bpm = 125; /* tempo *//* 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 SWORD olddevice = -1;/* 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);}MIKMODAPI 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) 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++) 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; /* don't register a MISSING() driver */ if ((drv->Name) && (drv->Version)) { if (cruise) { while (cruise->next) cruise = cruise->next; cruise->next = drv; } else firstdriver = drv; }}MIKMODAPI 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)||(!drv->Name)) return; MUTEX_LOCK(lists); _mm_registerdriver(drv); MUTEX_UNLOCK(lists);}MIKMODAPI 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;}MIKMODAPI MDRIVER *MikMod_DriverByOrdinal(int ordinal){ MDRIVER *cruise; /* Allow only driver ordinals > 0 */ if (!ordinal) return 0; MUTEX_LOCK(lists); cruise = firstdriver; while (cruise && --ordinal) cruise = cruise->next; MUTEX_UNLOCK(lists); return cruise;}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);}MIKMODAPI 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;}MIKMODAPI 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);}MIKMODAPI void Voice_SetVolume(SBYTE voice,UWORD vol){ MUTEX_LOCK(vars); Voice_SetVolume_internal(voice,vol); MUTEX_UNLOCK(vars);}MIKMODAPI 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);}MIKMODAPI void Voice_SetFrequency(SBYTE voice,ULONG frq){ MUTEX_LOCK(vars); Voice_SetFrequency_internal(voice,frq); MUTEX_UNLOCK(vars);}MIKMODAPI 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);}MIKMODAPI 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);}MIKMODAPI 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);}MIKMODAPI 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);}MIKMODAPI 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));}MIKMODAPI BOOL Voice_Stopped(SBYTE voice){ BOOL result; MUTEX_LOCK(vars); result=Voice_Stopped_internal(voice); MUTEX_UNLOCK(vars); return result;}MIKMODAPI SLONG Voice_GetPosition(SBYTE voice){ SLONG result=0; MUTEX_LOCK(vars); if((voice>=0)&&(voice<md_numchn)) { if (md_driver->VoiceGetPosition) result=(md_driver->VoiceGetPosition(voice)); else result=-1; } MUTEX_UNLOCK(vars); return result;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -