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

📄 drv_ultra.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 2 页
字号:

	/* We support only 16-bit stereo with 44K mixing frequency. On UltraSound
	   Classic mixing frequency depends on number of channels, on Interwave it
	   is always 44KHz. */
	md_mode |= DMODE_16BITS | DMODE_STEREO;
	md_mixfreq = info.mixing_freq;

#ifdef MIKMOD_DEBUG
	switch (info.version) {
	  case 0x24:
		fputs("GUS 2.4", stderr);
		break;
	  case 0x35:
		fputs("GUS 3.7 (flipped)", stderr);
		break;
	  case 0x37:
		fputs("GUS 3.7", stderr);
		break;
	  case 0x90:
		fputs("GUS ACE", stderr);
		break;
	  case 0xa0:
		fputs("GUS MAX 10", stderr);
		break;
	  case 0xa1:
		fputs("GUS MAX 11", stderr);
		break;
	  case 0x100:
		fputs("Interwave/GUS PnP", stderr);
		break;
	  default:
		fprintf(stderr, "Unknown GUS type %x", info.version);
		break;
	}
	fprintf(stderr, " with %dKb RAM on board\n", info.memory_size >> 10);
#endif

	/* Zero the voice states and sample handles */
	memset (&voices, 0, sizeof (voices));
	memset (&samples, 0, sizeof (samples));

	return 0;
}

static BOOL Ultra_Init(void)
{
#ifdef MIKMOD_DYNAMIC
	if (Ultra_Link()) {
		_mm_errno = MMERR_DYNAMIC_LINKING;
		return 1;
	}
#endif
	return Ultra_Init_internal();
}

/* Closes the driver */
static void Ultra_Exit_internal(void)
{
	if (ultra_handle >= 0) {
		ultra_handle = -1;
		libgus_close(ultra_dev);
	}
	ultra_fd = -1;
}

static void Ultra_Exit(void)
{
	Ultra_Exit_internal();
#ifdef MIKMOD_DYNAMIC
	Ultra_Unlink();
#endif
}

/* Poor man's reset function */
static BOOL Ultra_Reset(void)
{
	Ultra_Exit_internal();
	return Ultra_Init_internal();
}

static BOOL Ultra_SetNumVoices(void)
{
	return 0;
}

/* Module player tick function */
static void UltraPlayer(void)
{
	int channel, panning;
	struct GUS_VOICE *voice;
	static BOOL ultra_pause = 1;	/* paused status */

	md_player();

	if (ultra_pause != Player_Paused())
		if ((ultra_pause = Player_Paused()))
			for (channel = 0, voice = voices; channel < md_numchn;
			     channel++, voice++) {
				libgus_do_voice_volume (channel, 0);
				voices->changes |= (CH_VOL | CH_FREQ | CH_PAN);
			}

	if (ultra_pause)
		return;

	for (channel = 0, voice = voices; channel < md_numchn; channel++, voice++) {
		panning = (voice->pan == PAN_SURROUND) ?
			       ULTRA_PAN_MIDDLE : (voice->pan << 6);

		if (voice->kick) {
			voice->kick = 0;
			voice->decvol = voice->vol;
			if (voice->start > 0)
				libgus_do_voice_start_position(channel, voice->handle,
				      voice->frq, voice->vol << 6, panning, voice->start << 4);
			else
				libgus_do_voice_start(channel, voice->handle, voice->frq,
			                                 voice->vol << 6, voice->pan << 6);
		} else {
			if (voice->changes & CH_FREQ)
				libgus_do_voice_frequency(channel, voice->frq);
			if (voice->changes & CH_VOL)
				libgus_do_voice_volume(channel, voice->vol << 6);
			if (voice->changes & CH_PAN)
				libgus_do_voice_pan(channel, panning);
			if (voice->decvol)
				voice->decvol -= 4;
		}
		voice->changes = 0;
	}
}

/* Play sound */
#if defined (__DJGPP__) || defined (__EMX__)

static void Ultra_Callback(void)
{
	UltraPlayer();
	libgus_do_flush();
}

static void Ultra_Update(void)
{
	static UWORD ultra_bpm = 0;		/* current GUS tempo */

	/* All real work is done during GF1 timer 1 interrupt */
	if (ultra_bpm != md_bpm) {
		libgus_do_tempo((md_bpm * 50) / 125);
		ultra_bpm = md_bpm;
	}
}

#else

static void Ultra_Update(void)
{
	fd_set write_fds;
	int need_write;
	static UWORD ultra_bpm = 0;		/* current GUS tempo */

	if (ultra_bpm != md_bpm) {
		libgus_do_tempo((md_bpm * 50) / 125);
		ultra_bpm = md_bpm;
	}

	UltraPlayer();

	do {
		need_write = libgus_do_flush();

		FD_ZERO(&write_fds);
		do {
			FD_SET(ultra_fd, &write_fds);

			select(ultra_fd + 1, NULL, &write_fds, NULL, NULL);
		} while (!FD_ISSET(ultra_fd, &write_fds));
	} while(need_write > 0);

	/* Wait so that all voice commands gets executed */
	libgus_do_wait (1);
}

#endif

/* Start playback */
static BOOL Ultra_PlayStart(void)
{
	int t;
	gus_info_t info;

	for (t = 0; t < md_numchn; t++) {
		voices[t].flags = 0;
		voices[t].handle = 0;
		voices[t].size = 0;
		voices[t].start = 0;
		voices[t].reppos = 0;
		voices[t].repend = 0;
		voices[t].changes = 0;
		voices[t].kick = 0;
		voices[t].frq = 10000;
		voices[t].vol = 0;
		voices[t].pan = ULTRA_PAN_MIDDLE;
		voices[t].active = 0;
	}

	libgus_select(ultra_handle);
	if (libgus_reset(md_numchn, 0) < 0) {
		_mm_errno = MMERR_GUS_RESET;
		return 1;
	}

	/* Query mixing frequency */
	libgus_info(&info, 0);
	md_mixfreq = info.mixing_freq;

	libgus_queue_write_set_size(1024);
	libgus_queue_read_set_size(128);

	if (libgus_timer_start() < 0) {
		_mm_errno = MMERR_GUS_TIMER;
		return 1;
	}

#if defined (__DJGPP__) || defined (__EMX__)
	gus_timer_callback(Ultra_Callback);
#endif

	libgus_timer_tempo(50);

	for (t = 0; t < md_numchn; t++) {
		libgus_do_voice_pan(t, ULTRA_PAN_MIDDLE);
		libgus_do_voice_volume(t, 0 << 8);
	}

	libgus_do_flush();

	return 0;
}

/* Stop playback */
static void Ultra_PlayStop(void)
{
	int voice;

	libgus_queue_flush();
	libgus_timer_stop();
	libgus_queue_write_set_size(0);
	libgus_queue_read_set_size(0);
	for(voice = 0; voice < md_numchn; voice++)
		libgus_do_voice_stop(voice, 0);

#if defined (__DJGPP__) || defined (__EMX__)
	gus_timer_callback(NULL);
#endif

	libgus_do_flush();
}

/* Set the volume for the given voice */
static void Ultra_VoiceSetVolume(UBYTE voice, UWORD vol)
{
	if (voice < md_numchn)
		if (vol != voices[voice].vol) {
			voices[voice].decvol =
			voices[voice].vol = vol;
			voices[voice].changes |= CH_VOL;
		}
}

/* Returns the volume of the given voice */
static UWORD Ultra_VoiceGetVolume(UBYTE voice)
{
	return (voice < md_numchn) ? voices[voice].vol : 0;
}

/* Set the pitch for the given voice */
static void Ultra_VoiceSetFrequency(UBYTE voice, ULONG frq)
{
	if (voice < md_numchn)
		if (frq != voices[voice].frq) {
			voices[voice].frq = frq;
			voices[voice].changes |= CH_FREQ;
		}
}

/* Returns the frequency of the given voice */
static ULONG Ultra_VoiceGetFrequency(UBYTE voice)
{
	return (voice < md_numchn) ? voices[voice].frq : 0;
}

/* Set the panning position for the given voice */
static void Ultra_VoiceSetPanning(UBYTE voice, ULONG pan)
{
	if (voice < md_numchn)
		if (pan != voices[voice].pan) {
			voices[voice].pan = pan;
			voices[voice].changes |= CH_PAN;
		}
}

/* Returns the panning of the given voice */
static ULONG Ultra_VoiceGetPanning(UBYTE voice)
{
	return (voice < md_numchn) ? voices[voice].pan : 0;
}

/* Start a new sample on a voice */
static void Ultra_VoicePlay(UBYTE voice, SWORD handle, ULONG start,
							ULONG size, ULONG reppos, ULONG repend,
							UWORD flags)
{
	if ((voice >= md_numchn) || (start >= size))
		return;

	if (flags & SF_LOOP)
		if (repend > size)
			repend = size;

	voices[voice].flags = flags;
	voices[voice].handle = handle;
	voices[voice].start = start;
	voices[voice].size = size;
	voices[voice].reppos = reppos;
	voices[voice].repend = repend;
	voices[voice].kick = 1;
	voices[voice].active = 1;
#ifndef HAVE_VOICE_STATUS
	voices[voice].started = time(NULL);
#endif
}

/* Stops a voice */
static void Ultra_VoiceStop(UBYTE voice)
{
	if (voice < md_numchn)
		voices[voice].active = 0;
}

/* Returns whether a voice is stopped */
static BOOL Ultra_VoiceStopped(UBYTE voice)
{
	if (voice >= md_numchn)
		return 1;

#ifdef HAVE_VOICE_STATUS
	if (voices[voice].active)
		return gus_get_voice_status(voice) ? 0 : 1;
	else
		return 1;
#else
	if (voices[voice].active) {
		/* is sample looping ? */
		if (voices[voice].flags & (SF_LOOP | SF_BIDI))
			return 0;
		else
		  if (time(NULL) - voices[voice].started >=
			  ((voices[voice].size - voices[voice].start + md_mixfreq -1)
			  / md_mixfreq)) {
			voices[voice].active = 0;
			return 1;
		}
		return 0;
	} else
		return 1;
#endif
}

/* Returns current voice position */
static SLONG Ultra_VoiceGetPosition(UBYTE voice)
{
	/* NOTE This information can not be determined. */
	return -1;
}

/* Returns voice real volume */
static ULONG Ultra_VoiceRealVolume(UBYTE voice)
{
	int retval = 0;
	if (!Ultra_VoiceStopped (voice)) {
		/* NOTE This information can not be accurately determined. */
		retval = (voices [voice].decvol) << 8;
		if (retval > 0xffff) retval = 0xffff;
	}
	return retval;
}

MDRIVER drv_ultra = {
	NULL,
	"Gravis Ultrasound native mode",
	"Gravis Ultrasound native mode driver v1.2",
	0, (GUS_CHANNELS)-1,
	"ultra",
#ifdef __DJGPP__
        "dma:b:1:Use DMA for transferring samples into GUS DRAM\n"
#endif
	"card:r:0,8,0:Soundcard number\n",

	Ultra_CommandLine,
	Ultra_IsThere,
	Ultra_SampleLoad,
	Ultra_SampleUnload,
	Ultra_SampleSpace,
	Ultra_SampleLength,
	Ultra_Init,
	Ultra_Exit,
	Ultra_Reset,
	Ultra_SetNumVoices,
	Ultra_PlayStart,
	Ultra_PlayStop,
	Ultra_Update,
	NULL,
	Ultra_VoiceSetVolume,
	Ultra_VoiceGetVolume,
	Ultra_VoiceSetFrequency,
	Ultra_VoiceGetFrequency,
	Ultra_VoiceSetPanning,
	Ultra_VoiceGetPanning,
	Ultra_VoicePlay,
	Ultra_VoiceStop,
	Ultra_VoiceStopped,
	Ultra_VoiceGetPosition,
	Ultra_VoiceRealVolume
};
#else

MISSING(drv_ultra);

#endif // DRV_ULTRA

/* ex:set ts=4: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -