drv_ultra.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:20k
源码类别:

Windows CE

开发平台:

C/C++

  1. /* MikMod sound library
  2. (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
  3. complete list.
  4. This library is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of
  7. the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15. 02111-1307, USA.
  16. */
  17. /*==============================================================================
  18.   $Id: drv_ultra.c,v 1.4 2004/02/05 17:34:49 raph Exp $
  19.   Driver for Gravis Ultrasound cards using libGUS.
  20.   A subset of libGUS is provided for DOS/DJGPP and OS/2
  21. ==============================================================================*/
  22. /*
  23. Written by Andy Lo A Foe <andy@alsa-project.org>
  24. Updated to work with later versions of both the ultrasound driver and
  25. libmikmod by C. Ray C. <crayc@pyro.net>
  26. Major fixes by Andrew Zabolotny <bit@eltech.ru>
  27. + Ported to OS/2 and DOS.
  28. + Eight-bit samples are not converted to 16-bit anymore.
  29. + Samples are no longer kept in normal memory.
  30. + Removed sample 'unclick' logic... libGUS does unclick internally.
  31. */
  32. #ifdef HAVE_CONFIG_H
  33. #include "config.h"
  34. #endif
  35. #include "mikmod_internals.h"
  36. #ifdef DRV_ULTRA
  37. #ifdef HAVE_UNISTD_H
  38. #include <unistd.h>
  39. #endif
  40. #ifdef HAVE_MEMORY_H
  41. #include <memory.h>
  42. #endif
  43. #ifdef MIKMOD_DYNAMIC
  44. #include <dlfcn.h>
  45. #endif
  46. #include <errno.h>
  47. #include <stdlib.h>
  48. #include <string.h>
  49. #include <libgus.h>
  50. /* DOS/DJGPP and OS/2 libGUS'es have gus_get_voice_status() */
  51. #if defined (__EMX__) || defined (__DJGPP__)
  52. #define HAVE_VOICE_STATUS
  53. #else
  54. #include <time.h>
  55. #endif
  56. #ifdef MIKMOD_DYNAMIC
  57. /* runtime link with libgus */
  58. static int (*libgus_cards) (void);
  59. static int (*libgus_close) (int);
  60. static int (*libgus_do_flush) (void);
  61. static void (*libgus_do_tempo) (unsigned int);
  62. static void (*libgus_do_voice_frequency) (unsigned char, unsigned int);
  63. static void (*libgus_do_voice_pan) (unsigned char, unsigned short);
  64. static void (*libgus_do_voice_start) (unsigned char, unsigned int,
  65.   unsigned int, unsigned short,
  66.   unsigned short);
  67. static void (*libgus_do_voice_start_position) (unsigned char, unsigned int,
  68.    unsigned int, unsigned short,
  69.    unsigned short, unsigned int);
  70. static void (*libgus_do_voice_stop) (unsigned char, unsigned char);
  71. static void (*libgus_do_voice_volume) (unsigned char, unsigned short);
  72. static void (*libgus_do_wait) (unsigned int);
  73. static int (*libgus_get_handle) (void);
  74. static int (*libgus_info) (gus_info_t *, int);
  75. static int (*libgus_memory_alloc) (gus_instrument_t *);
  76. static int (*libgus_memory_free) (gus_instrument_t *);
  77. static int (*libgus_memory_free_size) (void);
  78. static int (*libgus_memory_pack) (void);
  79. static int (*libgus_open) (int, size_t, int);
  80. static int (*libgus_queue_flush) (void);
  81. static int (*libgus_queue_read_set_size) (int);
  82. static int (*libgus_queue_write_set_size) (int);
  83. static int (*libgus_reset) (int, unsigned int);
  84. static int (*libgus_select) (int);
  85. static int (*libgus_timer_start) (void);
  86. static int (*libgus_timer_stop) (void);
  87. static int (*libgus_timer_tempo) (int);
  88. static void *libgus = NULL;
  89. #ifndef HAVE_RTLD_GLOBAL
  90. #define RTLD_GLOBAL 0
  91. #endif
  92. #else
  93. /* compile-time link with libgus */
  94. #define libgus_cards gus_cards
  95. #define libgus_close gus_close
  96. #define libgus_do_flush gus_do_flush
  97. #define libgus_do_tempo gus_do_tempo
  98. #define libgus_do_voice_frequency gus_do_voice_frequency
  99. #define libgus_do_voice_pan gus_do_voice_pan
  100. #define libgus_do_voice_start gus_do_voice_start
  101. #define libgus_do_voice_start_position gus_do_voice_start_position
  102. #define libgus_do_voice_stop            gus_do_voice_stop
  103. #define libgus_do_voice_volume gus_do_voice_volume
  104. #define libgus_do_wait gus_do_wait
  105. #define libgus_get_handle gus_get_handle
  106. #define libgus_info gus_info
  107. #define libgus_memory_alloc gus_memory_alloc
  108. #define libgus_memory_free gus_memory_free
  109. #define libgus_memory_free_size gus_memory_free_size
  110. #define libgus_memory_pack gus_memory_pack
  111. #define libgus_open gus_open
  112. #define libgus_queue_flush gus_queue_flush
  113. #define libgus_queue_read_set_size gus_queue_read_set_size
  114. #define libgus_queue_write_set_size gus_queue_write_set_size
  115. #define libgus_reset gus_reset
  116. #define libgus_select gus_select
  117. #define libgus_timer_start gus_timer_start
  118. #define libgus_timer_stop gus_timer_stop
  119. #define libgus_timer_tempo gus_timer_tempo
  120. #endif
  121. #define GUS_SAMPLES 256 /* Max. GUS samples loadable */
  122. #define GUS_CHANNELS 32 /* Max. GUS channels available */
  123. #define SIZE_OF_SEQBUF (8 * 1024) /* Size of the sequence buffer */
  124. #define ULTRA_PAN_MIDDLE (16383 >> 1) /* Middle balance position */
  125. #define CH_FREQ 1
  126. #define CH_VOL  2
  127. #define CH_PAN  4
  128. /* This structure holds the current state of a GUS voice channel. */
  129. typedef struct GUS_VOICE {
  130. UBYTE kick;
  131. UBYTE active;
  132. UWORD flags;
  133. SWORD handle;
  134. ULONG start;
  135. ULONG size;
  136. ULONG reppos;
  137. ULONG repend;
  138. ULONG frq;
  139. int vol;
  140. int decvol;
  141. int pan;
  142. int changes;
  143. #ifndef HAVE_VOICE_STATUS
  144. time_t started;
  145. #endif
  146. } GUS_VOICE;
  147. /* Global declarations follow */
  148. static SAMPLE *samples[GUS_SAMPLES]; /* sample handles */
  149. static GUS_VOICE voices[GUS_CHANNELS]; /* channel status */
  150. static int ultra_dev = 0; /* GUS index, if more than one card */
  151. static int ultra_handle = -1; /* GUS handle */
  152. static int ultra_fd = -1; /* GUS file descriptor */
  153. #ifdef MIKMOD_DYNAMIC
  154. static BOOL Ultra_Link(void)
  155. {
  156. if (libgus)
  157. return 0;
  158. /* load libgus.so */
  159. libgus = dlopen("libgus.so", RTLD_LAZY | RTLD_GLOBAL);
  160. if (!libgus)
  161. return 1;
  162. /* resolve function references */
  163. #define IMPORT_SYMBOL(x) 
  164. if (!(lib##x = dlsym(libgus, #x))) return 1
  165. IMPORT_SYMBOL(gus_cards);
  166. IMPORT_SYMBOL(gus_close);
  167. IMPORT_SYMBOL(gus_do_flush);
  168. IMPORT_SYMBOL(gus_do_tempo);
  169. IMPORT_SYMBOL(gus_do_voice_frequency);
  170. IMPORT_SYMBOL(gus_do_voice_pan);
  171. IMPORT_SYMBOL(gus_do_voice_start);
  172. IMPORT_SYMBOL(gus_do_voice_start_position);
  173. IMPORT_SYMBOL(gus_do_voice_stop);
  174. IMPORT_SYMBOL(gus_do_voice_volume);
  175. IMPORT_SYMBOL(gus_do_wait);
  176. IMPORT_SYMBOL(gus_get_handle);
  177. IMPORT_SYMBOL(gus_info);
  178. IMPORT_SYMBOL(gus_memory_alloc);
  179. IMPORT_SYMBOL(gus_memory_free);
  180. IMPORT_SYMBOL(gus_memory_free_size);
  181. IMPORT_SYMBOL(gus_memory_pack);
  182. IMPORT_SYMBOL(gus_open);
  183. IMPORT_SYMBOL(gus_queue_flush);
  184. IMPORT_SYMBOL(gus_queue_read_set_size);
  185. IMPORT_SYMBOL(gus_queue_write_set_size);
  186. IMPORT_SYMBOL(gus_reset);
  187. IMPORT_SYMBOL(gus_select);
  188. IMPORT_SYMBOL(gus_timer_start);
  189. IMPORT_SYMBOL(gus_timer_stop);
  190. IMPORT_SYMBOL(gus_timer_tempo);
  191. #undef IMPORT_SYMBOL
  192. return 0;
  193. }
  194. static void Ultra_Unlink(void)
  195. {
  196. libgus_cards = NULL;
  197. libgus_close = NULL;
  198. libgus_do_flush = NULL;
  199. libgus_do_tempo = NULL;
  200. libgus_do_voice_frequency = NULL;
  201. libgus_do_voice_pan = NULL;
  202. libgus_do_voice_start = NULL;
  203. libgus_do_voice_start_position = NULL;
  204. libgus_do_voice_stop = NULL;
  205. libgus_do_voice_volume = NULL;
  206. libgus_do_wait = NULL;
  207. libgus_get_handle = NULL;
  208. libgus_info = NULL;
  209. libgus_memory_alloc = NULL;
  210. libgus_memory_free = NULL;
  211. libgus_memory_free_size = NULL;
  212. libgus_memory_pack = NULL;
  213. libgus_open = NULL;
  214. libgus_queue_flush = NULL;
  215. libgus_queue_read_set_size = NULL;
  216. libgus_queue_write_set_size = NULL;
  217. libgus_reset = NULL;
  218. libgus_select = NULL;
  219. libgus_timer_start = NULL;
  220. libgus_timer_stop = NULL;
  221. libgus_timer_tempo = NULL;
  222. if (libgus) {
  223. dlclose(libgus);
  224. libgus = NULL;
  225. }
  226. }
  227. #endif
  228. static void Ultra_CommandLine(CHAR *cmdline)
  229. {
  230. CHAR *ptr = MD_GetAtom("card", cmdline, 0);
  231. if (ptr) {
  232. int buf = atoi(ptr);
  233. if (buf >= 0 && buf <= 8)
  234. ultra_dev = buf;
  235. free(ptr);
  236. }
  237. #ifdef __DJGPP__
  238. if ((ptr = MD_GetAtom("dma", cmdline, 0))) {
  239. gus_dma_usage (atoi(ptr));
  240. free(ptr);
  241. }
  242. #endif
  243. }
  244. /* Checks for the presence of GUS cards */
  245. static BOOL Ultra_IsThere(void)
  246. {
  247. int retval;
  248. #ifdef MIKMOD_DYNAMIC
  249. if (Ultra_Link())
  250. return 0;
  251. #endif
  252. retval = libgus_cards()? 1 : 0;
  253. #ifdef MIKMOD_DYNAMIC
  254. Ultra_Unlink();
  255. #endif
  256. return retval;
  257. }
  258. /* Load a new sample directly into GUS DRAM and return a handle */
  259. static SWORD Ultra_SampleLoad(struct SAMPLOAD *sload)
  260. {
  261. int handle;
  262. SAMPLE *s = sload->sample;
  263. gus_instrument_t instrument;
  264. gus_layer_t layer;
  265. gus_wave_t wave;
  266. unsigned char *buffer;
  267. unsigned int length, loopstart, loopend;
  268. /* Find empty slot to put sample in */
  269. for (handle = 0; handle < GUS_SAMPLES; handle++)
  270. if (!samples[handle])
  271. break;
  272. if (handle == GUS_SAMPLES) {
  273. _mm_errno = MMERR_OUT_OF_HANDLES;
  274. return -1;
  275. }
  276. /* Fill an gus_instrument_t structure and feed it to libgus. We can
  277.    download 8 and 16 bit, both signed and unsigned samples into GUS, so
  278.    don't bother much about formats here. */
  279. /* convert position/length data from samples to bytes */
  280. length = s->length;
  281. loopstart = s->loopstart;
  282. loopend = s->loopend ? s->loopend : length;
  283. /* sanity checks */
  284. if (loopend > length)
  285. loopend = length;
  286. if (loopstart > loopend)
  287. loopstart = loopend;
  288. if (s->flags & SF_16BITS) {
  289. length <<= 1;
  290. loopstart <<= 1;
  291. loopend <<= 1;
  292. }
  293. /* Load sample into normal memory */
  294. if (!(buffer = _mm_malloc(length))) {
  295. _mm_errno = MMERR_SAMPLE_TOO_BIG;
  296. return -1;
  297. }
  298. if (SL_Load(buffer, sload, s->length)) {
  299. free(buffer);
  300. return -1;
  301. }
  302. samples[handle] = s;
  303. memset(&wave, 0, sizeof(wave));
  304. memset(&layer, 0, sizeof(layer));
  305. memset(&instrument, 0, sizeof(instrument));
  306. wave.format =
  307. ((s->flags & SF_SIGNED) ? 0 : GUS_WAVE_INVERT) |
  308. ((s->flags & SF_16BITS) ? GUS_WAVE_16BIT : 0) |
  309. ((s->flags & SF_DELTA ) ? GUS_WAVE_DELTA : 0) |
  310. ((s->flags & SF_LOOP  ) ? GUS_WAVE_LOOP  : 0) |
  311. ((s->flags & SF_BIDI  ) ? GUS_WAVE_BIDIR : 0);
  312. wave.begin.ptr = buffer;
  313. wave.loop_start = loopstart << 4;
  314. wave.loop_end = loopend << 4;
  315. wave.size = length;
  316. layer.wave = &wave;
  317. instrument.mode = layer.mode = wave.mode = GUS_INSTR_SIMPLE;
  318. instrument.number.instrument = handle;
  319. instrument.info.layer = &layer;
  320. /* Download the sample to GUS RAM */
  321. if (libgus_memory_alloc(&instrument)) {
  322. free(buffer);
  323. _mm_errno = MMERR_SAMPLE_TOO_BIG;
  324. return -1;
  325. }
  326. free(buffer);
  327. return handle;
  328. }
  329. /* Discards a sample from the GUS memory and mark handle as free */
  330. static void Ultra_SampleUnload(SWORD handle)
  331. {
  332. gus_instrument_t instrument;
  333. if (handle >= GUS_SAMPLES || handle < 0 || !samples[handle])
  334. return;
  335. memset(&instrument, 0, sizeof(instrument));
  336. instrument.mode = GUS_INSTR_SIMPLE;
  337. instrument.number.instrument = handle;
  338. libgus_memory_free(&instrument);
  339. samples[handle] = NULL;
  340. }
  341. /* Reports available sample space */
  342. static ULONG Ultra_SampleSpace(void)
  343. {
  344. libgus_memory_pack();
  345. return (libgus_memory_free_size());
  346. }
  347. /* Reports the size of a sample */
  348. static ULONG Ultra_SampleLength(SAMPLE *s)
  349. {
  350. if (!s)
  351. return 0;
  352. if (s->flags & SF_16BITS)
  353. return ((s->length << 1) + 31) & ~31;
  354. else
  355. return ( s->length       + 15) & ~15;
  356. }
  357. /* Initializes the driver */
  358. static BOOL Ultra_Init_internal(void)
  359. {
  360. gus_info_t info;
  361. /* Open the GUS card */
  362. if ((ultra_handle = libgus_open(ultra_dev, SIZE_OF_SEQBUF, 0)) < 0) {
  363. _mm_errno =
  364.   (errno == ENOMEM) ? MMERR_OUT_OF_MEMORY : MMERR_INVALID_DEVICE;
  365. return 1;
  366. }
  367. libgus_select(ultra_handle);
  368. ultra_fd = libgus_get_handle();
  369. /* Get card information */
  370. libgus_info(&info, 0);
  371. /* We support only 16-bit stereo with 44K mixing frequency. On UltraSound
  372.    Classic mixing frequency depends on number of channels, on Interwave it
  373.    is always 44KHz. */
  374. md_mode |= DMODE_16BITS | DMODE_STEREO;
  375. md_mixfreq = info.mixing_freq;
  376. #ifdef MIKMOD_DEBUG
  377. switch (info.version) {
  378.   case 0x24:
  379. fputs("GUS 2.4", stderr);
  380. break;
  381.   case 0x35:
  382. fputs("GUS 3.7 (flipped)", stderr);
  383. break;
  384.   case 0x37:
  385. fputs("GUS 3.7", stderr);
  386. break;
  387.   case 0x90:
  388. fputs("GUS ACE", stderr);
  389. break;
  390.   case 0xa0:
  391. fputs("GUS MAX 10", stderr);
  392. break;
  393.   case 0xa1:
  394. fputs("GUS MAX 11", stderr);
  395. break;
  396.   case 0x100:
  397. fputs("Interwave/GUS PnP", stderr);
  398. break;
  399.   default:
  400. fprintf(stderr, "Unknown GUS type %x", info.version);
  401. break;
  402. }
  403. fprintf(stderr, " with %dKb RAM on boardn", info.memory_size >> 10);
  404. #endif
  405. /* Zero the voice states and sample handles */
  406. memset (&voices, 0, sizeof (voices));
  407. memset (&samples, 0, sizeof (samples));
  408. return 0;
  409. }
  410. static BOOL Ultra_Init(void)
  411. {
  412. #ifdef MIKMOD_DYNAMIC
  413. if (Ultra_Link()) {
  414. _mm_errno = MMERR_DYNAMIC_LINKING;
  415. return 1;
  416. }
  417. #endif
  418. return Ultra_Init_internal();
  419. }
  420. /* Closes the driver */
  421. static void Ultra_Exit_internal(void)
  422. {
  423. if (ultra_handle >= 0) {
  424. ultra_handle = -1;
  425. libgus_close(ultra_dev);
  426. }
  427. ultra_fd = -1;
  428. }
  429. static void Ultra_Exit(void)
  430. {
  431. Ultra_Exit_internal();
  432. #ifdef MIKMOD_DYNAMIC
  433. Ultra_Unlink();
  434. #endif
  435. }
  436. /* Poor man's reset function */
  437. static BOOL Ultra_Reset(void)
  438. {
  439. Ultra_Exit_internal();
  440. return Ultra_Init_internal();
  441. }
  442. static BOOL Ultra_SetNumVoices(void)
  443. {
  444. return 0;
  445. }
  446. /* Module player tick function */
  447. static void UltraPlayer(void)
  448. {
  449. int channel, panning;
  450. struct GUS_VOICE *voice;
  451. static BOOL ultra_pause = 1; /* paused status */
  452. md_player();
  453. if (ultra_pause != Player_Paused())
  454. if ((ultra_pause = Player_Paused()))
  455. for (channel = 0, voice = voices; channel < md_numchn;
  456.      channel++, voice++) {
  457. libgus_do_voice_volume (channel, 0);
  458. voices->changes |= (CH_VOL | CH_FREQ | CH_PAN);
  459. }
  460. if (ultra_pause)
  461. return;
  462. for (channel = 0, voice = voices; channel < md_numchn; channel++, voice++) {
  463. panning = (voice->pan == PAN_SURROUND) ?
  464.        ULTRA_PAN_MIDDLE : (voice->pan << 6);
  465. if (voice->kick) {
  466. voice->kick = 0;
  467. voice->decvol = voice->vol;
  468. if (voice->start > 0)
  469. libgus_do_voice_start_position(channel, voice->handle,
  470.       voice->frq, voice->vol << 6, panning, voice->start << 4);
  471. else
  472. libgus_do_voice_start(channel, voice->handle, voice->frq,
  473.                                  voice->vol << 6, voice->pan << 6);
  474. } else {
  475. if (voice->changes & CH_FREQ)
  476. libgus_do_voice_frequency(channel, voice->frq);
  477. if (voice->changes & CH_VOL)
  478. libgus_do_voice_volume(channel, voice->vol << 6);
  479. if (voice->changes & CH_PAN)
  480. libgus_do_voice_pan(channel, panning);
  481. if (voice->decvol)
  482. voice->decvol -= 4;
  483. }
  484. voice->changes = 0;
  485. }
  486. }
  487. /* Play sound */
  488. #if defined (__DJGPP__) || defined (__EMX__)
  489. static void Ultra_Callback(void)
  490. {
  491. UltraPlayer();
  492. libgus_do_flush();
  493. }
  494. static void Ultra_Update(void)
  495. {
  496. static UWORD ultra_bpm = 0; /* current GUS tempo */
  497. /* All real work is done during GF1 timer 1 interrupt */
  498. if (ultra_bpm != md_bpm) {
  499. libgus_do_tempo((md_bpm * 50) / 125);
  500. ultra_bpm = md_bpm;
  501. }
  502. }
  503. #else
  504. static void Ultra_Update(void)
  505. {
  506. fd_set write_fds;
  507. int need_write;
  508. static UWORD ultra_bpm = 0; /* current GUS tempo */
  509. if (ultra_bpm != md_bpm) {
  510. libgus_do_tempo((md_bpm * 50) / 125);
  511. ultra_bpm = md_bpm;
  512. }
  513. UltraPlayer();
  514. do {
  515. need_write = libgus_do_flush();
  516. FD_ZERO(&write_fds);
  517. do {
  518. FD_SET(ultra_fd, &write_fds);
  519. select(ultra_fd + 1, NULL, &write_fds, NULL, NULL);
  520. } while (!FD_ISSET(ultra_fd, &write_fds));
  521. } while(need_write > 0);
  522. /* Wait so that all voice commands gets executed */
  523. libgus_do_wait (1);
  524. }
  525. #endif
  526. /* Start playback */
  527. static BOOL Ultra_PlayStart(void)
  528. {
  529. int t;
  530. gus_info_t info;
  531. for (t = 0; t < md_numchn; t++) {
  532. voices[t].flags = 0;
  533. voices[t].handle = 0;
  534. voices[t].size = 0;
  535. voices[t].start = 0;
  536. voices[t].reppos = 0;
  537. voices[t].repend = 0;
  538. voices[t].changes = 0;
  539. voices[t].kick = 0;
  540. voices[t].frq = 10000;
  541. voices[t].vol = 0;
  542. voices[t].pan = ULTRA_PAN_MIDDLE;
  543. voices[t].active = 0;
  544. }
  545. libgus_select(ultra_handle);
  546. if (libgus_reset(md_numchn, 0) < 0) {
  547. _mm_errno = MMERR_GUS_RESET;
  548. return 1;
  549. }
  550. /* Query mixing frequency */
  551. libgus_info(&info, 0);
  552. md_mixfreq = info.mixing_freq;
  553. libgus_queue_write_set_size(1024);
  554. libgus_queue_read_set_size(128);
  555. if (libgus_timer_start() < 0) {
  556. _mm_errno = MMERR_GUS_TIMER;
  557. return 1;
  558. }
  559. #if defined (__DJGPP__) || defined (__EMX__)
  560. gus_timer_callback(Ultra_Callback);
  561. #endif
  562. libgus_timer_tempo(50);
  563. for (t = 0; t < md_numchn; t++) {
  564. libgus_do_voice_pan(t, ULTRA_PAN_MIDDLE);
  565. libgus_do_voice_volume(t, 0 << 8);
  566. }
  567. libgus_do_flush();
  568. return 0;
  569. }
  570. /* Stop playback */
  571. static void Ultra_PlayStop(void)
  572. {
  573. int voice;
  574. libgus_queue_flush();
  575. libgus_timer_stop();
  576. libgus_queue_write_set_size(0);
  577. libgus_queue_read_set_size(0);
  578. for(voice = 0; voice < md_numchn; voice++)
  579. libgus_do_voice_stop(voice, 0);
  580. #if defined (__DJGPP__) || defined (__EMX__)
  581. gus_timer_callback(NULL);
  582. #endif
  583. libgus_do_flush();
  584. }
  585. /* Set the volume for the given voice */
  586. static void Ultra_VoiceSetVolume(UBYTE voice, UWORD vol)
  587. {
  588. if (voice < md_numchn)
  589. if (vol != voices[voice].vol) {
  590. voices[voice].decvol =
  591. voices[voice].vol = vol;
  592. voices[voice].changes |= CH_VOL;
  593. }
  594. }
  595. /* Returns the volume of the given voice */
  596. static UWORD Ultra_VoiceGetVolume(UBYTE voice)
  597. {
  598. return (voice < md_numchn) ? voices[voice].vol : 0;
  599. }
  600. /* Set the pitch for the given voice */
  601. static void Ultra_VoiceSetFrequency(UBYTE voice, ULONG frq)
  602. {
  603. if (voice < md_numchn)
  604. if (frq != voices[voice].frq) {
  605. voices[voice].frq = frq;
  606. voices[voice].changes |= CH_FREQ;
  607. }
  608. }
  609. /* Returns the frequency of the given voice */
  610. static ULONG Ultra_VoiceGetFrequency(UBYTE voice)
  611. {
  612. return (voice < md_numchn) ? voices[voice].frq : 0;
  613. }
  614. /* Set the panning position for the given voice */
  615. static void Ultra_VoiceSetPanning(UBYTE voice, ULONG pan)
  616. {
  617. if (voice < md_numchn)
  618. if (pan != voices[voice].pan) {
  619. voices[voice].pan = pan;
  620. voices[voice].changes |= CH_PAN;
  621. }
  622. }
  623. /* Returns the panning of the given voice */
  624. static ULONG Ultra_VoiceGetPanning(UBYTE voice)
  625. {
  626. return (voice < md_numchn) ? voices[voice].pan : 0;
  627. }
  628. /* Start a new sample on a voice */
  629. static void Ultra_VoicePlay(UBYTE voice, SWORD handle, ULONG start,
  630. ULONG size, ULONG reppos, ULONG repend,
  631. UWORD flags)
  632. {
  633. if ((voice >= md_numchn) || (start >= size))
  634. return;
  635. if (flags & SF_LOOP)
  636. if (repend > size)
  637. repend = size;
  638. voices[voice].flags = flags;
  639. voices[voice].handle = handle;
  640. voices[voice].start = start;
  641. voices[voice].size = size;
  642. voices[voice].reppos = reppos;
  643. voices[voice].repend = repend;
  644. voices[voice].kick = 1;
  645. voices[voice].active = 1;
  646. #ifndef HAVE_VOICE_STATUS
  647. voices[voice].started = time(NULL);
  648. #endif
  649. }
  650. /* Stops a voice */
  651. static void Ultra_VoiceStop(UBYTE voice)
  652. {
  653. if (voice < md_numchn)
  654. voices[voice].active = 0;
  655. }
  656. /* Returns whether a voice is stopped */
  657. static BOOL Ultra_VoiceStopped(UBYTE voice)
  658. {
  659. if (voice >= md_numchn)
  660. return 1;
  661. #ifdef HAVE_VOICE_STATUS
  662. if (voices[voice].active)
  663. return gus_get_voice_status(voice) ? 0 : 1;
  664. else
  665. return 1;
  666. #else
  667. if (voices[voice].active) {
  668. /* is sample looping ? */
  669. if (voices[voice].flags & (SF_LOOP | SF_BIDI))
  670. return 0;
  671. else
  672.   if (time(NULL) - voices[voice].started >=
  673.   ((voices[voice].size - voices[voice].start + md_mixfreq -1)
  674.   / md_mixfreq)) {
  675. voices[voice].active = 0;
  676. return 1;
  677. }
  678. return 0;
  679. } else
  680. return 1;
  681. #endif
  682. }
  683. /* Returns current voice position */
  684. static SLONG Ultra_VoiceGetPosition(UBYTE voice)
  685. {
  686. /* NOTE This information can not be determined. */
  687. return -1;
  688. }
  689. /* Returns voice real volume */
  690. static ULONG Ultra_VoiceRealVolume(UBYTE voice)
  691. {
  692. int retval = 0;
  693. if (!Ultra_VoiceStopped (voice)) {
  694. /* NOTE This information can not be accurately determined. */
  695. retval = (voices [voice].decvol) << 8;
  696. if (retval > 0xffff) retval = 0xffff;
  697. }
  698. return retval;
  699. }
  700. MDRIVER drv_ultra = {
  701. NULL,
  702. "Gravis Ultrasound native mode",
  703. "Gravis Ultrasound native mode driver v1.2",
  704. 0, (GUS_CHANNELS)-1,
  705. "ultra",
  706. #ifdef __DJGPP__
  707.         "dma:b:1:Use DMA for transferring samples into GUS DRAMn"
  708. #endif
  709. "card:r:0,8,0:Soundcard numbern",
  710. Ultra_CommandLine,
  711. Ultra_IsThere,
  712. Ultra_SampleLoad,
  713. Ultra_SampleUnload,
  714. Ultra_SampleSpace,
  715. Ultra_SampleLength,
  716. Ultra_Init,
  717. Ultra_Exit,
  718. Ultra_Reset,
  719. Ultra_SetNumVoices,
  720. Ultra_PlayStart,
  721. Ultra_PlayStop,
  722. Ultra_Update,
  723. NULL,
  724. Ultra_VoiceSetVolume,
  725. Ultra_VoiceGetVolume,
  726. Ultra_VoiceSetFrequency,
  727. Ultra_VoiceGetFrequency,
  728. Ultra_VoiceSetPanning,
  729. Ultra_VoiceGetPanning,
  730. Ultra_VoicePlay,
  731. Ultra_VoiceStop,
  732. Ultra_VoiceStopped,
  733. Ultra_VoiceGetPosition,
  734. Ultra_VoiceRealVolume
  735. };
  736. #else
  737. MISSING(drv_ultra);
  738. #endif // DRV_ULTRA
  739. /* ex:set ts=4: */