📄 drv_ultra.c
字号:
/* 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 + -