⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mdriver.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	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 SUNOS
extern int fprintf(FILE *, const char *, ...);
#endif

static	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 + -