📄 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; }}#elsestatic 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};#elseMISSING(drv_ultra);#endif // DRV_ULTRA/* ex:set ts=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -