📄 dosgus.c
字号:
__gus_mem_clear(); gus.t1_callback = __gus_timer_update; gus.wt_callback = __gus_wavetable_update; gus.vl_callback = __gus_volume_update; gus_do_tempo(60); /* Default is 60 Hz */ return 0;}int gus_close(int card){ __dpmi_meminfo struct_info; if (!gus.open || card != 0) return -1; /* First reset the card: disable any operation it can currently perform */ __gus_reset(0); gus.open--; /* Stop the timer */ gus_timer_stop(); /* Free DMA buffer if used */ if (gus.dma_buff) dma_free(gus.dma_buff); /* And unhook the GF1 interrupt */ irq_unhook(gus.gf1_irq); gus.gf1_irq = NULL; /* Unlock the gus structure */ struct_info.address = __djgpp_base_address + (unsigned long)&gus; struct_info.size = sizeof(gus); __dpmi_unlock_linear_region(&struct_info); __gus_mem_clear(); __gus_instruments_clear(); return 0;}int gus_select(int card){ if (!gus.open || (card != 0)) return -1; return 0;}/* return value: same as gus_reset function note: this command doesn't change number of active voices and doesn't do hardware reset */int gus_reset_engine_only(){ gus.timer_base = 100; return 0;}int gus_reset(int voices, unsigned int channel_voices){ static unsigned short freq_table[32 - 14 + 1] = { 44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400, 28063, 26843, 25725, 24696, 23746, 22866, 22050, 21289, 20580, 19916, 19293 }; int voice; int timer; /* No support for dynamically allocated voices for now */ gus.dynmask = channel_voices; if (voices < 14) voices = 14; if (voices > 32) voices = 32; /* Stop the timer so that GUS IRQ won't clobber registers */ timer = (gus.timer_ctl_reg & GF1M_TIMER1); if (timer) gus_timer_stop(); /* Stop all voices */ for (voice = 0; voice < 32; voice++) { __gus_select_voice(voice); __gus_stop_voice(); gus.cur_wave[voice] = NULL; gus.cur_vol[voice] = 0; __gus_delay(); /* Reset voice parameters to reasonable values */ __gus_set_current(0, 0); __gus_set_loop_start(0, 0); __gus_set_loop_end(0, 0); __gus_outregw(GF1R_VOLUME, 0); __gus_outregb(GF1R_VOLUME_RATE, 0); __gus_outregb(GF1R_VOLUME_START, 0); __gus_outregb(GF1R_VOLUME_END, 0); __gus_outregb(GF1R_BALANCE, 0x7); } voice = (__gus_inregb(GF1R_VOICES) & 0x1f) + 1; if (voice != voices) { int reset = __gus_inregb(GF1R_RESET); __gus_outregb(GF1R_RESET, reset & ~GF1M_OUTPUT_ENABLE); __gus_delay(); __gus_outregb(GF1R_VOICES, 0xc0 | (voices - 1)); __gus_delay(); __gus_outregb(GF1R_RESET, reset); } /* Compute the discretization frequence */ gus.voices = voices; if (gus.interwave) gus.freq = 44100; else gus.freq = freq_table[voices - 14]; gus_reset_engine_only(); if (timer) gus_timer_continue(); return gus.voices;}int gus_do_flush(){ DEBUG_PRINT(("gus_do_flush: top = %d\n", gus.cmd_pool_top)) gus.cmd_pool_ready = 1; return 0;}/* set new tempo */void gus_do_tempo(unsigned int tempo){ DEBUG_PRINT(("gus_do_tempo (%d)\n", tempo)) gus_timer_tempo(tempo); gus_timer_start();}/* set voice frequency in Hz */void gus_do_voice_frequency(unsigned char voice, unsigned int freq){ DEBUG_PRINT(("gus_do_voice_frequency (%d, %d)\n", voice, freq)) __pool_select_voice(voice); __pool_command_w(PCMD_FREQ, (((freq << 9) + (gus.freq >> 1)) / gus.freq) << 1);}/* set voice pan (0-16384) (full left - full right) */void gus_do_voice_pan(unsigned char voice, unsigned short pan){ DEBUG_PRINT(("gus_do_voice_pan (%d, %d)\n", voice, pan)) pan >>= 10; if (pan > 15) pan = 15; __pool_select_voice(voice); __pool_command_b(PCMD_PAN, pan);}/* set voice volume level 0-16384 (linear) */void gus_do_voice_volume(unsigned char voice, unsigned short vol){ DEBUG_PRINT(("gus_do_voice_volume (%d, %d)\n", voice, vol)) if (vol > 0x3fff) vol = 0x3fff; __pool_select_voice(voice); __pool_command_w(PCMD_VOLUME, __gus_volume_table[vol >> 5]);}/* start voice * voice : voice # * program : program # or ~0 = current * freq : frequency in Hz * volume : volume level (0-16384) or ~0 = current * pan : pan level (0-16384) or ~0 = current */void gus_do_voice_start(unsigned char voice, unsigned int program, unsigned int freq, unsigned short volume, unsigned short pan){ gus_do_voice_start_position(voice, program, freq, volume, pan, 0);}/* start voice * voice : voice # * program : program # or ~0 = current * freq : frequency in Hz * volume : volume level (0-16384) or ~0 = current * pan : pan level (0-16384) or ~0 = current * position : offset to wave in bytes * 16 (lowest 4 bits - fraction) */void gus_do_voice_start_position(unsigned char voice, unsigned int program, unsigned int freq, unsigned short volume, unsigned short pan, unsigned int position){ gus_instrument_t *instrument; gus_wave_t *wave; DEBUG_PRINT( ("gus_do_voice_start_position (%d, %d, pos: %d)\n", voice, program, position)) instrument = __gus_instrument_get(program); if (!instrument || !instrument->info.layer || !instrument->info.layer->wave || instrument->flags == GUS_INSTR_F_NOT_FOUND || instrument->flags == GUS_INSTR_F_NOT_LOADED) return; gus_do_voice_frequency(voice, freq); gus_do_voice_pan(voice, pan); /* We have to set volume different way, to avoid unneeded work in handler */ if (volume > 0x3fff) volume = 0x3fff; __pool_command_w(PCMD_VOLUME_PREPARE, __gus_volume_table[volume >> 5]); switch (instrument->mode) { case GUS_INSTR_SIMPLE: wave = instrument->info.layer->wave; if (position) __pool_command_l(PCMD_OFFSET, position); __pool_command_l(PCMD_START, (unsigned long)wave); break; }}/* stop voice * mode = 0 : stop voice now * mode = 1 : disable wave loop and finish it */void gus_do_voice_stop(unsigned char voice, unsigned char mode){ __pool_select_voice(voice); if (mode) __pool_command(PCMD_STOP_LOOP); else __pool_command(PCMD_STOP);}/* wait x ticks - this command is block separator all commands between blocks are interpreted in the begining of one tick */void gus_do_wait(unsigned int ticks){ DEBUG_PRINT(("gus_do_wait (%d)\n", ticks)) ticks += gus.t1_ticks; while ((int)(ticks - gus.t1_ticks) > 0);}int gus_get_voice_status(int voice){ __gus_select_voice(voice); return __gus_inregb(GF1R_VOICE_CONTROL) & GF1VC_STOPPED ? 0 : 1;}/* return value: file handle (descriptor) for /dev/gus */int gus_get_handle(){ /* Return stdout handle so that select() will "work" with it */ return 0;}/* return value: zero if instrument was successfully allocated */int gus_memory_alloc(gus_instrument_t * instrument){ gus_instrument_t *instr = __gus_instrument_copy(instrument); gus_layer_t *cur_layer; gus_wave_t *cur_wave; DEBUG_PRINT(("gus_memory_alloc (%d)\n", instrument->number.instrument)) if (!instr) return -1; for (cur_layer = instr->info.layer; cur_layer; cur_layer = cur_layer->next) for (cur_wave = cur_layer->wave; cur_wave; cur_wave = cur_wave->next) { if (cur_layer->mode == GUS_INSTR_SIMPLE) { cur_wave->begin.memory = __gus_mem_alloc(cur_wave->size, cur_wave->format & GUS_WAVE_16BIT); if (cur_wave->begin.memory == (unsigned int)-1) { __gus_instrument_free(instr); return -1; } gus.transfer(cur_wave->begin.memory, cur_wave->begin.ptr, cur_wave->size, cur_wave->format); } else if (cur_layer->mode == GUS_INSTR_PATCH) /* not supported yet */ ; } return 0;}/* return value: zero if instrument was successfully removed */int gus_memory_free(gus_instrument_t * instrument){ gus_instrument_t *cur_instr = gus.instr; DEBUG_PRINT(("gus_memory_free (%d)\n", instrument->number.instrument)) for (; cur_instr; cur_instr = cur_instr->next) if (cur_instr->number.instrument == instrument->number.instrument) return __gus_instrument_free(cur_instr); return -1;}/* return value: unused gus memory in bytes */int gus_memory_free_size(){ return __gus_mem_get_free();}/* return value: zero if success */int gus_memory_pack(){ __gus_mem_pack(); return 0;}/* return value: gus memory size in bytes */int gus_memory_size(){ return gus.ram * 1024;}/* return value: current largest free block for 8-bit or 16-bit wave */int gus_memory_free_block(int w_16bit){ return w_16bit ? __gus_mem_get_free_16() : __gus_mem_get_free_8();}/* input value: see to GUS_DOWNLOAD_MODE_XXXX constants (gus.h) return value: zero if samples & instruments was successfully removed from GF1 memory manager */int gus_memory_reset(int mode){ __gus_mem_clear(); __gus_instruments_clear(); return 0;}/* return value: zero if command queue was successfully flushed */int gus_queue_flush(){ return 0;}/* input value: echo buffer size in items (if 0 - erase echo buffer) */int gus_queue_read_set_size(int items){ return 0;}/* input value: write queue size in items (each item have 8 bytes) */int gus_queue_write_set_size(int items){ return 0;}/* return value: zero if successfull */int gus_timer_start(){ gus.timer_ctl_reg |= GF1M_TIMER1; __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg); gus.timer_ctl = gus.timer_ctl & ~GF1M_MASK_TIMER1; outportb(GF1_TIMER_CTRL, 0x04); outportb(GF1_TIMER_DATA, gus.timer_ctl | GF1M_START_TIMER1); return 0;}/* return value: zero if timer was stoped */int gus_timer_stop(){ gus.timer_ctl_reg &= ~GF1M_TIMER1; __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg); gus.timer_ctl = gus.timer_ctl | GF1M_MASK_TIMER1; outportb(GF1_TIMER_CTRL, 0x04); outportb(GF1_TIMER_DATA, gus.timer_ctl); return 0;}/* return value: zero if setup was success */int gus_timer_tempo(int ticks){ unsigned int counter; /* Limit ticks per second to 1..1000 range */ if (ticks < 1) ticks = 1; if (ticks > 1000) ticks = 1000; /* GF1 timer1 period is 80 usecs, 12500 times per second */ counter = 1250000 / (ticks * gus.timer_base); gus.t1_multiple = 1; while (counter > 255) { counter >>= 1; gus.t1_multiple <<= 1; } gus.t1_countdown = gus.t1_multiple; __gus_outregb(GF1R_TIMER1, 256 - counter); return 0;}/* return value: zero if timer will be continue */int gus_timer_continue(){ return gus_timer_start();}/* return value: zero if setup was success (default timebase = 100) */int gus_timer_base(int base){ gus.timer_base = base; return 0;}void gus_timer_callback(void (*timer_callback) ()){ gus.timer_callback = timer_callback;}void gus_convert_delta(unsigned int type, unsigned char *dest, unsigned char *src, size_t size){ if (!(type & GUS_WAVE_DELTA)) return; /* This doesn't depend much on wave signedness, since addition/subtraction do not depend on operand signedness */ if (type & GUS_WAVE_16BIT) { unsigned short delta = type & GUS_WAVE_UNSIGNED ? 0x8000 : 0; while (size--) { delta = *(unsigned short *)dest = *(unsigned short *)src + delta; src += sizeof(unsigned short); dest += sizeof(unsigned short); } } else { unsigned char delta = type & GUS_WAVE_UNSIGNED ? 0x80 : 0; while (size--) { delta = *(unsigned char *)dest = *(unsigned char *)src + delta; src++; dest++; } }}int gus_dma_usage (int use){ if (gus.dma_buff) return -1; gus.transfer = __gus_transfer_io; return 0;}/* ex:set ts=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -