1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *      By Shawn Hargreaves,
11  *      1 Salisbury Road,
12  *      Market Drayton,
13  *      Shropshire,
14  *      England, TF9 1AJ.
15  *
16  *      Sound setup routines and API framework functions.
17  *
18  *      See readme.txt for copyright information.
19  */
20 
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <dir.h>
28 
29 #ifdef DJGPP
30 #include <go32.h>
31 #include <sys/farptr.h>
32 #endif
33 
34 #include "allegro.h"
35 #include "internal.h"
36 
37 
38 
39 /* dummy functions for the nosound drivers */
_dummy_detect()40 int  _dummy_detect() { return TRUE; }
_dummy_init(int voices)41 int  _dummy_init(int voices) { return 0; }
_dummy_exit()42 void _dummy_exit() { }
_dummy_mixer_volume(int volume)43 int  _dummy_mixer_volume(int volume) { return 0; }
_dummy_init_voice(int voice,SAMPLE * sample)44 void _dummy_init_voice(int voice, SAMPLE *sample) { }
_dummy_noop1(int p)45 void _dummy_noop1(int p) { }
_dummy_noop2(int p1,int p2)46 void _dummy_noop2(int p1, int p2) { }
_dummy_noop3(int p1,int p2,int p3)47 void _dummy_noop3(int p1, int p2, int p3) { }
_dummy_get_position(int voice)48 int  _dummy_get_position(int voice) { return -1; }
_dummy_get(int voice)49 int  _dummy_get(int voice) { return 0; }
_dummy_raw_midi(unsigned char data)50 void _dummy_raw_midi(unsigned char data) { }
_dummy_load_patches(char * patches,char * drums)51 int  _dummy_load_patches(char *patches, char *drums) { return 0; }
_dummy_adjust_patches(char * patches,char * drums)52 void _dummy_adjust_patches(char *patches, char *drums) { }
_dummy_key_on(int inst,int note,int bend,int vol,int pan)53 void _dummy_key_on(int inst, int note, int bend, int vol, int pan) { }
54 
55 /* put this after all the dummy functions, so they will all get locked */
56 END_OF_FUNCTION(_dummy_detect);
57 
58 
59 
60 DIGI_DRIVER digi_none =
61 {
62    "No sound", "The sound of silence",
63    0, 0, 0xFFFF, 0,
64    _dummy_detect,
65    _dummy_init,
66    _dummy_exit,
67    _dummy_mixer_volume,
68    _dummy_init_voice,
69    _dummy_noop1,
70    _dummy_noop1,
71    _dummy_noop1,
72    _dummy_noop2,
73    _dummy_get_position,
74    _dummy_noop2,
75    _dummy_get,
76    _dummy_noop2,
77    _dummy_noop3,
78    _dummy_noop1,
79    _dummy_get,
80    _dummy_noop2,
81    _dummy_noop3,
82    _dummy_noop1,
83    _dummy_get,
84    _dummy_noop2,
85    _dummy_noop3,
86    _dummy_noop1,
87    _dummy_noop3,
88    _dummy_noop3,
89    _dummy_noop3
90 };
91 
92 
93 MIDI_DRIVER midi_none =
94 {
95    "No sound", "The sound of silence",
96    0, 0, 0xFFFF, 0, -1, -1,
97    _dummy_detect,
98    _dummy_init,
99    _dummy_exit,
100    _dummy_mixer_volume,
101    _dummy_raw_midi,
102    _dummy_load_patches,
103    _dummy_adjust_patches,
104    _dummy_key_on,
105    _dummy_noop1,
106    _dummy_noop2,
107    _dummy_noop3,
108    _dummy_noop2,
109    _dummy_noop2
110 };
111 
112 
113 int digi_card = DIGI_AUTODETECT;          /* current driver ID numbers */
114 int midi_card = MIDI_AUTODETECT;
115 
116 DIGI_DRIVER *digi_driver = &digi_none;    /* these things do all the work */
117 MIDI_DRIVER *midi_driver = &midi_none;
118 
119 static int sound_installed = FALSE;       /* are we installed? */
120 
121 static int digi_reserve = -1;             /* how many voices to reserve */
122 static int midi_reserve = -1;
123 
124 VOICE _voice[VIRTUAL_VOICES];             /* list of active samples */
125 
126 PHYS_VOICE _phys_voice[DIGI_VOICES];      /* physical -> virtual voice map */
127 
128 int _digi_volume = -1;                    /* current volume settings */
129 int _midi_volume = -1;
130 
131 int _flip_pan = FALSE;                    /* reverse l/r sample panning? */
132 
133 int _sb_freq = -1;                        /* hardware parameters */
134 int _sb_port = -1;
135 int _sb_dma = -1;
136 int _sb_irq = -1;
137 int _fm_port = -1;
138 int _mpu_port = -1;
139 
140 #define SWEEP_FREQ   50
141 
142 static void update_sweeps();
143 static void sound_lock_mem();
144 
145 int (*_midi_init)() = NULL;
146 void (*_midi_exit)() = NULL;
147 
148 
149 
150 /* read_sound_config:
151  *  Helper for reading the sound hardware configuration data.
152  */
read_sound_config()153 static void read_sound_config()
154 {
155    _flip_pan = get_config_int("sound", "flip_pan", FALSE);
156    _sb_port = get_config_hex("sound", "sb_port", -1);
157    _sb_dma = get_config_int("sound", "sb_dma", -1);
158    _sb_irq = get_config_int("sound", "sb_irq", -1);
159    _sb_freq = get_config_int("sound", "sb_freq", -1);
160    _fm_port = get_config_hex("sound", "fm_port", -1);
161    _mpu_port = get_config_hex("sound", "mpu_port", -1);
162    _digi_volume = get_config_int("sound", "digi_volume", -1);
163    _midi_volume = get_config_int("sound", "midi_volume", -1);
164 }
165 
166 
167 
168 /* detect_digi_driver:
169  *  Detects whether the specified digital sound driver is available,
170  *  returning the maximum number of voices that it can provide, or
171  *  zero if the device is not present. This function must be called
172  *  _before_ install_sound().
173  */
detect_digi_driver(int driver_id)174 int detect_digi_driver(int driver_id)
175 {
176    int i;
177 
178    if (sound_installed)
179       return 0;
180 
181    read_sound_config();
182 
183    for (i=0; _digi_driver_list[i].driver_id; i++) {
184       if (_digi_driver_list[i].driver_id == driver_id) {
185 	 digi_card = driver_id;
186 	 midi_card = MIDI_AUTODETECT;
187 	 if (_digi_driver_list[i].driver->detect())
188 	    return _digi_driver_list[i].driver->max_voices;
189 	 else
190 	    return 0;
191       }
192    }
193 
194    return digi_none.max_voices;
195 }
196 
197 
198 
199 /* detect_midi_driver:
200  *  Detects whether the specified midi sound driver is available,
201  *  returning the maximum number of voices that it can provide, or
202  *  zero if the device is not present. If this routine returns -1,
203  *  it is a note-stealing MIDI driver, which shares voices with the
204  *  current digital driver. In this situation you can use the
205  *  reserve_voices() function to specify how the available voices are
206  *  divided between the digital and MIDI playback routines. This function
207  *  must be called _before_ install_sound().
208  */
detect_midi_driver(int driver_id)209 int detect_midi_driver(int driver_id)
210 {
211    int i;
212 
213    if (sound_installed)
214       return 0;
215 
216    read_sound_config();
217 
218    for (i=0; _midi_driver_list[i].driver_id; i++) {
219       if (_midi_driver_list[i].driver_id == driver_id) {
220 	 digi_card = DIGI_AUTODETECT;
221 	 midi_card = driver_id;
222 	 if (_midi_driver_list[i].driver->detect())
223 	    return _midi_driver_list[i].driver->max_voices;
224 	 else
225 	    return 0;
226       }
227    }
228 
229    return midi_none.max_voices;
230 }
231 
232 
233 
234 /* reserve_voices:
235  *  Reserves a number of voices for the digital and MIDI sound drivers
236  *  respectively. This must be called _before_ install_sound(). If you
237  *  attempt to reserve too many voices, subsequent calls to install_sound()
238  *  will fail. Note that depending on the driver you may actually get
239  *  more voices than you reserve: these values just specify the minimum
240  *  that is appropriate for your application. Pass a negative reserve value
241  *  to use the default settings.
242  */
reserve_voices(int digi_voices,int midi_voices)243 void reserve_voices(int digi_voices, int midi_voices)
244 {
245    digi_reserve = digi_voices;
246    midi_reserve = midi_voices;
247 }
248 
249 
250 
251 /* install_sound:
252  *  Initialises the sound module, returning zero on success. The two card
253  *  parameters should use the DIGI_* and MIDI_* constants defined in
254  *  allegro.h. Pass DIGI_AUTODETECT and MIDI_AUTODETECT if you don't know
255  *  what the soundcard is.
256  */
install_sound(int digi,int midi,char * cfg_path)257 int install_sound(int digi, int midi, char *cfg_path)
258 {
259    int digi_voices, midi_voices;
260    int c;
261 
262    if (sound_installed)
263       return 0;
264 
265    for (c=0; c<VIRTUAL_VOICES; c++) {
266       _voice[c].sample = NULL;
267       _voice[c].num = -1;
268    }
269 
270    for (c=0; c<DIGI_VOICES; c++)
271       _phys_voice[c].num = -1;
272 
273    /* initialise the midi file player */
274    if (_midi_init)
275       if (_midi_init() != 0)
276 	 return -1;
277 
278 /*	 register_datafile_object(DAT_SAMPLE, NULL, (void (*)(void *))destroy_sample);*/
279 
280    digi_card = digi;
281    midi_card = midi;
282 
283    /* read config information */
284    if (digi_card == DIGI_AUTODETECT)
285       digi_card = get_config_int("sound", "digi_card", DIGI_AUTODETECT);
286 
287    if (midi_card == MIDI_AUTODETECT)
288       midi_card = get_config_int("sound", "midi_card", MIDI_AUTODETECT);
289 
290    if (digi_reserve < 0)
291       digi_reserve = get_config_int("sound", "digi_voices", -1);
292 
293    if (midi_reserve < 0)
294       midi_reserve = get_config_int("sound", "midi_voices", -1);
295 
296    read_sound_config();
297 
298    sound_lock_mem();
299    _dma_lock_mem();
300 
301    digi_driver = NULL;
302 
303    /* search table for a specific digital driver */
304    for (c=0; _digi_driver_list[c].driver; c++) {
305       if (_digi_driver_list[c].driver_id == digi_card) {
306 	 digi_driver = _digi_driver_list[c].driver;
307 	 if (!digi_driver->detect()) {
308 	    digi_driver = &digi_none;
309 	    if (_midi_exit)
310 	       _midi_exit();
311 	    return -1;
312 	 }
313 	 break;
314       }
315    }
316 
317    /* autodetect digital driver */
318    if (!digi_driver) {
319       for (c=0; _digi_driver_list[c].driver; c++) {
320 	 digi_card = _digi_driver_list[c].driver_id;
321 	 if ((_digi_driver_list[c].autodetect) &&
322 	     (_digi_driver_list[c].driver->detect())) {
323 	    digi_driver = _digi_driver_list[c].driver;
324 	    break;
325 	 }
326       }
327    }
328 
329    midi_driver = NULL;
330 
331    /* search table for a specific MIDI driver */
332    for (c=0; _midi_driver_list[c].driver; c++) {
333       if (_midi_driver_list[c].driver_id == midi_card) {
334 	 midi_driver = _midi_driver_list[c].driver;
335 	 if (!midi_driver->detect()) {
336 	    digi_driver = &digi_none;
337 	    midi_driver = &midi_none;
338 	    if (_midi_exit)
339 	       _midi_exit();
340 	    return -1;
341 	 }
342 	 break;
343       }
344    }
345 
346    /* autodetect MIDI driver */
347    if (!midi_driver) {
348       for (c=0; _midi_driver_list[c].driver; c++) {
349 	 midi_card = _midi_driver_list[c].driver_id;
350 	 if ((_midi_driver_list[c].autodetect) &&
351 	     (_midi_driver_list[c].driver->detect())) {
352 	    midi_driver = _midi_driver_list[c].driver;
353 	    break;
354 	 }
355       }
356    }
357 
358    /* work out how many voices to allocate for each driver */
359    if (digi_reserve >= 0)
360       digi_voices = digi_reserve;
361    else
362       digi_voices = digi_driver->def_voices;
363 
364    if (midi_driver->max_voices < 0) {
365       /* MIDI driver steals voices from the digital player */
366       if (midi_reserve >= 0)
367 	 midi_voices = midi_reserve;
368       else
369 	 midi_voices = MID(0, digi_driver->max_voices - digi_voices, midi_driver->def_voices);
370 
371       digi_voices += midi_voices;
372    }
373    else {
374       /* MIDI driver has voices of its own */
375       if (midi_reserve >= 0)
376 	 midi_voices = midi_reserve;
377       else
378 	 midi_voices = midi_driver->def_voices;
379    }
380 
381    /* make sure this is a reasonable number of voices to use */
382    if ((digi_voices > DIGI_VOICES) || (midi_voices > MIDI_VOICES)) {
383       sprintf(allegro_error, "Insufficient %s voices available",
384 		  (digi_voices > DIGI_VOICES) ? "digital" : "MIDI");
385       digi_driver = &digi_none;
386       midi_driver = &midi_none;
387       if (_midi_exit)
388 	 _midi_exit();
389       return -1;
390    }
391 
392    /* initialise the digital sound driver */
393    if (digi_driver->init(digi_voices) != 0) {
394       digi_driver = &digi_none;
395       midi_driver = &midi_none;
396       if (_midi_exit)
397 	 _midi_exit();
398       return -1;
399    }
400 
401    /* initialise the midi driver */
402    if (midi_driver->init(midi_voices) != 0) {
403       digi_driver->exit();
404       digi_driver = &digi_none;
405       midi_driver = &midi_none;
406       if (_midi_exit)
407 	 _midi_exit();
408       return -1;
409    }
410 
411    digi_driver->voices = MIN(digi_driver->voices, DIGI_VOICES);
412    midi_driver->voices = MIN(midi_driver->voices, MIDI_VOICES);
413 
414    /* check that we actually got enough voices */
415    if ((digi_driver->voices < digi_voices) ||
416        ((midi_driver->voices < midi_voices) && (!midi_driver->raw_midi))) {
417       sprintf(allegro_error, "Insufficient %s voices available",
418 		  (digi_driver->voices < digi_voices) ? "digital" : "MIDI");
419       midi_driver->exit();
420       digi_driver->exit();
421       digi_driver = &digi_none;
422       midi_driver = &midi_none;
423       if (_midi_exit)
424 	 _midi_exit();
425       return -1;
426    }
427 
428    /* adjust for note-stealing MIDI drivers */
429    if (midi_driver->max_voices < 0) {
430       midi_voices += (digi_driver->voices - digi_voices) * 3/4;
431       digi_driver->voices -= midi_voices;
432       midi_driver->basevoice = VIRTUAL_VOICES - midi_voices;
433       midi_driver->voices = midi_voices;
434 
435       for (c=0; c<midi_voices; c++) {
436 	 _voice[midi_driver->basevoice+c].num = digi_driver->voices+c;
437 	 _phys_voice[digi_driver->voices+c].num = midi_driver->basevoice+c;
438       }
439    }
440 
441    /* simulate ramp/sweep effects for drivers that don't do it directly */
442    if ((!digi_driver->ramp_volume) ||
443        (!digi_driver->sweep_frequency) ||
444        (!digi_driver->sweep_pan))
445       install_int_ex(update_sweeps, BPS_TO_TIMER(SWEEP_FREQ));
446 
447    /* set the global sound volume */
448    if ((_digi_volume >= 0) || (_midi_volume >= 0))
449       set_volume(_digi_volume, _midi_volume);
450 
451    _add_exit_func(remove_sound);
452    sound_installed = TRUE;
453    return 0;
454 }
455 
456 
457 
458 /* remove_sound:
459  *  Sound module cleanup routine.
460  */
remove_sound()461 void remove_sound()
462 {
463    int c;
464 
465    if (sound_installed) {
466       remove_int(update_sweeps);
467 
468       for (c=0; c<VIRTUAL_VOICES; c++)
469 	 if (_voice[c].sample)
470 	    deallocate_voice(c);
471 
472       if (_midi_exit)
473 	 _midi_exit();
474 
475       midi_driver->exit();
476       midi_driver = &midi_none;
477 
478       digi_driver->exit();
479       digi_driver = &digi_none;
480 
481       _remove_exit_func(remove_sound);
482       sound_installed = FALSE;
483    }
484 }
485 
486 
487 
488 /* set_volume:
489  *  Alters the global sound output volume. Specify volumes for both digital
490  *  samples and MIDI playback, as integers from 0 to 255. If possible this
491  *  routine will use a hardware mixer to control the volume, otherwise it
492  *  will tell the sample mixer and MIDI player to simulate a mixer in
493  *  software.
494  */
set_volume(int digi_volume,int midi_volume)495 void set_volume(int digi_volume, int midi_volume)
496 {
497    if (digi_volume >= 0) {
498       digi_volume = MID(0, digi_volume, 255);
499 
500       if ((digi_driver->mixer_volume) &&
501 	  (digi_driver->mixer_volume(digi_volume) == 0))
502 	 _digi_volume = -1;
503       else
504 	 _digi_volume = digi_volume;
505    }
506 
507    if (midi_volume >= 0) {
508       midi_volume = MID(0, midi_volume, 255);
509 
510       if ((midi_driver->mixer_volume) &&
511 	  (midi_driver->mixer_volume(midi_volume) == 0))
512 	 _midi_volume = -1;
513       else
514 	 _midi_volume = midi_volume;
515    }
516 }
517 
518 
519 
520 /* lock_sample:
521  *  Locks a SAMPLE struct into physical memory. Pretty important, since
522  *  they are mostly accessed inside interrupt handlers.
523  */
lock_sample(SAMPLE * spl)524 void lock_sample(SAMPLE *spl)
525 {
526    #ifdef DJGPP
527       _go32_dpmi_lock_data(spl, sizeof(SAMPLE));
528       _go32_dpmi_lock_data(spl->data, spl->len*spl->bits/8);
529    #endif
530 }
531 
532 
533 
534 /* load_sample:
535  *  Loads a sample from disk.
536  */
load_sample(char * filename)537 SAMPLE *load_sample(char *filename)
538 {
539    if (stricmp(get_extension(filename), "wav") == 0)
540       return load_wav(filename);
541    else if (stricmp(get_extension(filename), "voc") == 0)
542       return load_voc(filename);
543    else
544       return NULL;
545 }
546 
547 
548 
549 /* load_voc:
550  *  Reads a mono 8 bit VOC format sample file, returning a SAMPLE structure,
551  *  or NULL on error.
552  */
load_voc(char * filename)553 SAMPLE *load_voc(char *filename)
554 {
555    PACKFILE *f;
556    char buffer[30];
557    int freq = 22050;
558    int bits = 8;
559    SAMPLE *spl = NULL;
560    int len;
561    int x;
562 
563    f = pack_fopen(filename, F_READ);
564    if (!f)
565       return NULL;
566 
567    pack_fread(buffer, 0x16, f);
568 
569    if (memcmp(buffer, "Creative Voice File", 0x13))
570       goto getout;
571 
572    if (pack_igetw(f) != 0x010A)        /* version: should be 0x010A */
573       goto getout;
574 
575    if (pack_igetw(f) != 0x1129)        /* subversion: should be 0x1129 */
576       goto getout;
577 
578    if (pack_getc(f) != 0x01)           /* sound data: should be 0x01 */
579       goto getout;
580 
581    len = pack_igetw(f);                /* length is three bytes long: two */
582    x = pack_getc(f);                   /* .. and one byte */
583    x <<= 16;
584    len += x-2;
585 
586    x = pack_getc(f);                   /* one byte of frequency */
587    freq = 1000000 / (256-x);
588 
589    x = pack_getc(f);                   /* skip one byte */
590 
591    spl = malloc(sizeof(SAMPLE));
592 
593    if (spl) {
594       spl->bits = bits;
595       spl->freq = freq;
596       spl->len = len;
597       spl->priority = 255;
598       spl->loop_start = 0;
599       spl->loop_end = len;
600       spl->param = -1;
601 
602       spl->data = malloc(len);
603       if (!spl->data) {
604 	 free(spl);
605 	 spl = NULL;
606       }
607       else {
608 	 pack_fread(spl->data, len, f);
609 	 if (errno) {
610 	    free(spl->data);
611 	    free(spl);
612 	    spl = NULL;
613 	 }
614       }
615    }
616 
617    getout:
618 
619    pack_fclose(f);
620 
621    if (spl)
622       lock_sample(spl);
623 
624    return spl;
625 }
626 
627 
628 
629 /* load_wav:
630  *  Reads a mono RIFF WAV format sample file, returning a SAMPLE structure,
631  *  or NULL on error.
632  */
load_wav(char * filename)633 SAMPLE *load_wav(char *filename)
634 {
635    int trashtmp;
636    PACKFILE *f;
637    char buffer[25];
638    int i;
639    int length, len;
640    int freq = 22050;
641    int bits = 8;
642    signed short s;
643    SAMPLE *spl = NULL;
644 
645    f = pack_fopen(filename, F_READ);
646    if (!f)
647       return NULL;
648 
649    pack_fread(buffer, 12, f);          /* check RIFF header */
650    if (memcmp(buffer, "RIFF", 4) || memcmp(buffer+8, "WAVE", 4))
651       goto getout;
652 
653    while (!pack_feof(f)) {
654       if (pack_fread(buffer, 4, f) != 4)
655 	 break;
656 
657       length = pack_igetl(f);          /* read chunk length */
658 
659       if (memcmp(buffer, "fmt ", 4) == 0) {
660 	 i = pack_igetw(f);            /* should be 1 for PCM data */
661 	 length -= 2;
662 	 if (i != 1)
663 	    goto getout;
664 
665 	 i = pack_igetw(f);            /* should be 1 for mono data */
666 	 length -= 2;
667 	 if (i != 1)
668 	    goto getout;
669 
670 	 freq = pack_igetl(f);         /* sample frequency */
671 	 length -= 4;
672 
673          trashtmp=pack_igetl(f);                /* skip six bytes */
674          trashtmp=pack_igetw(f);
675 	 length -= 6;
676 
677 	 bits = pack_igetw(f);         /* 8 or 16 bit data? */
678 	 length -= 2;
679 	 if ((bits != 8) && (bits != 16))
680 	    goto getout;
681       }
682       else if (memcmp(buffer, "data", 4) == 0) {
683 	 len = length;
684 	 if (bits == 16)
685 	    len /= 2;
686 
687 	 spl = malloc(sizeof(SAMPLE));
688 
689 	 if (spl) {                    /* initialise the sample struct */
690 	    spl->bits = bits;
691 	    spl->freq = freq;
692 	    spl->len = len;
693 	    spl->priority = 255;
694 	    spl->loop_start = 0;
695 	    spl->loop_end = len;
696 	    spl->param = -1;
697 
698 	    spl->data = malloc(length);
699 
700 	    if (!spl->data) {
701 	       free(spl);
702 	       spl = NULL;
703 	    }
704 	    else {                     /* read the actual sample data */
705 	       if (bits == 8) {
706 		  pack_fread(spl->data, length, f);
707 	       }
708 	       else {
709 		  for (i=0; i<len; i++) {
710 		     s = pack_igetw(f);
711 		     ((signed short *)spl->data)[i] = s^0x8000;
712 		  }
713 	       }
714 
715 	       length -= len;
716 
717 	       if (errno) {
718 		  free(spl->data);
719 		  free(spl);
720 		  spl = NULL;
721 	       }
722 	    }
723 	 }
724       }
725 
726       while (length > 0) {             /* skip the remainder of the chunk */
727 	 if (pack_getc(f) == EOF)
728 	    break;
729 
730 	 length--;
731       }
732    }
733 
734    getout:
735 
736    pack_fclose(f);
737 
738    if (spl)
739       lock_sample(spl);
740 
741    return spl;
742 }
743 
744 
745 
746 /* destroy_sample:
747  *  Frees a SAMPLE struct, checking whether the sample is currently playing,
748  *  and stopping it if it is.
749  */
destroy_sample(SAMPLE * spl)750 void destroy_sample(SAMPLE *spl)
751 {
752    if (spl) {
753       stop_sample(spl);
754 
755       if (spl->data) {
756 	 _unlock_dpmi_data(spl->data, spl->len*spl->bits/8);
757 	 free(spl->data);
758       }
759 
760       _unlock_dpmi_data(spl, sizeof(SAMPLE));
761       free(spl);
762    }
763 }
764 
765 
766 
767 /* absolute_freq:
768  *  Converts a pitch from the relative 1000 = original format to an absolute
769  *  value in hz.
770  */
absolute_freq(int freq,SAMPLE * spl)771 static inline int absolute_freq(int freq, SAMPLE *spl)
772 {
773    if (freq == 1000)
774       return spl->freq;
775    else
776       return (spl->freq * freq) / 1000;
777 }
778 
779 
780 
781 /* play_sample:
782  *  Triggers a sample at the specified volume, pan position, and frequency.
783  *  The volume and pan range from 0 (min/left) to 255 (max/right), although
784  *  the resolution actually used by the playback routines is likely to be
785  *  less than this. Frequency is relative rather than absolute: 1000
786  *  represents the frequency that the sample was recorded at, 2000 is
787  *  twice this, etc. If loop is true the sample will repeat until you call
788  *  stop_sample(), and can be manipulated while it is playing by calling
789  *  adjust_sample().
790  */
play_sample(SAMPLE * spl,int vol,int pan,int freq,int loop)791 int play_sample(SAMPLE *spl, int vol, int pan, int freq, int loop)
792 {
793    int voice = allocate_voice(spl);
794 
795    if (voice >= 0) {
796       voice_set_volume(voice, vol);
797       voice_set_pan(voice, pan);
798       voice_set_frequency(voice, absolute_freq(freq, spl));
799       voice_set_playmode(voice, (loop ? PLAYMODE_LOOP : PLAYMODE_PLAY));
800       voice_start(voice);
801       release_voice(voice);
802    }
803 
804    return voice;
805 }
806 
807 END_OF_FUNCTION(play_sample);
808 
809 
810 
811 /* adjust_sample:
812  *  Alters the parameters of a sample while it is playing, useful for
813  *  manipulating looped sounds. You can alter the volume, pan, and
814  *  frequency, and can also remove the looping flag, which will stop
815  *  the sample when it next reaches the end of its loop. If there are
816  *  several copies of the same sample playing, this will adjust the
817  *  first one it comes across. If the sample is not playing it has no
818  *  effect.
819  */
adjust_sample(SAMPLE * spl,int vol,int pan,int freq,int loop)820 void adjust_sample(SAMPLE *spl, int vol, int pan, int freq, int loop)
821 {
822    int c;
823 
824    for (c=0; c<VIRTUAL_VOICES; c++) {
825       if (_voice[c].sample == spl) {
826 	 voice_set_volume(c, vol);
827 	 voice_set_pan(c, pan);
828 	 voice_set_frequency(c, absolute_freq(freq, spl));
829 	 voice_set_playmode(c, (loop ? PLAYMODE_LOOP : PLAYMODE_PLAY));
830 	 return;
831       }
832    }
833 }
834 
835 END_OF_FUNCTION(adjust_sample);
836 
837 
838 
839 /* stop_sample:
840  *  Kills off a sample, which is required if you have set a sample going
841  *  in looped mode. If there are several copies of the sample playing,
842  *  it will stop them all.
843  */
stop_sample(SAMPLE * spl)844 void stop_sample(SAMPLE *spl)
845 {
846    int c;
847 
848    for (c=0; c<VIRTUAL_VOICES; c++)
849       if (_voice[c].sample == spl)
850 	 deallocate_voice(c);
851 }
852 
853 END_OF_FUNCTION(stop_sample);
854 
855 
856 
857 /* allocate_physical_voice:
858  *  Allocates a physical voice, killing off others as required in order
859  *  to make room for it.
860  */
allocate_physical_voice(int priority)861 static inline int allocate_physical_voice(int priority)
862 {
863    VOICE *voice;
864    int best = -1;
865    int best_score = 0;
866    int score;
867    int c;
868 
869    /* look for a free voice */
870    for (c=0; c<digi_driver->voices; c++)
871       if (_phys_voice[c].num < 0)
872 	 return c;
873 
874    /* look for an autokill voice that has stopped */
875    for (c=0; c<digi_driver->voices; c++) {
876       voice = _voice + _phys_voice[c].num;
877       if ((voice->autokill) && (digi_driver->get_position(c) < 0)) {
878 	 digi_driver->release_voice(c);
879 	 voice->sample = NULL;
880 	 voice->num = -1;
881 	 _phys_voice[c].num = -1;
882 	 return c;
883       }
884    }
885 
886    /* ok, we're going to have to get rid of something to make room... */
887    for (c=0; c<digi_driver->voices; c++) {
888       voice = _voice + _phys_voice[c].num;
889 
890       /* sort by voice priorities */
891       if (voice->priority <= priority) {
892 	 score = 65536 - voice->priority * 256;
893 
894 	 /* bias with a least-recently-used counter */
895 	 score += MID(0, retrace_count - voice->time, 32768);
896 
897 	 /* bias according to whether the voice is looping or not */
898 	 if (!(_phys_voice[c].playmode & PLAYMODE_LOOP))
899 	    score += 32768;
900 
901 	 if (score > best_score) {
902 	    best = c;
903 	    best_score = score;
904 	 }
905       }
906    }
907 
908    if (best >= 0) {
909       /* kill off the old voice */
910       digi_driver->stop_voice(best);
911       digi_driver->release_voice(best);
912       _voice[_phys_voice[best].num].num = -1;
913       _phys_voice[best].num = -1;
914       return best;
915    }
916 
917    return -1;
918 }
919 
920 
921 
922 /* allocate_virtual_voice:
923  *  Allocates a virtual voice. This doesn't need to worry about killing off
924  *  others to make room, as we allow up to 256 virtual voices to be used
925  *  simultaneously.
926  */
allocate_virtual_voice()927 static inline int allocate_virtual_voice()
928 {
929    int virt_voices, c;
930 
931    virt_voices = VIRTUAL_VOICES;
932    if (midi_driver->max_voices < 0)
933       virt_voices -= midi_driver->voices;
934 
935    /* look for a free voice */
936    for (c=0; c<virt_voices; c++)
937       if (!_voice[c].sample)
938 	 return c;
939 
940    /* look for a stopped autokill voice */
941    for (c=0; c<virt_voices; c++) {
942       if (_voice[c].autokill) {
943 	 if (_voice[c].num < 0) {
944 	    _voice[c].sample = NULL;
945 	    return c;
946 	 }
947 	 else {
948 	    if (digi_driver->get_position(_voice[c].num) < 0) {
949 	       digi_driver->release_voice(_voice[c].num);
950 	       _phys_voice[_voice[c].num].num = -1;
951 	       _voice[c].sample = NULL;
952 	       _voice[c].num = -1;
953 	       return c;
954 	    }
955 	 }
956       }
957    }
958 
959    return -1;
960 }
961 
962 
963 
964 /* allocate_voice:
965  *  Allocates a voice ready for playing the specified sample, returning
966  *  the voice number (note this is not the same as the physical voice
967  *  number used by the sound drivers, and must only be used with the other
968  *  voice functions, _not_ passed directly to the driver routines).
969  *  Returns -1 if there is no voice available (this should never happen,
970  *  since there are 256 virtual voices and anyone who needs more than that
971  *  needs some urgent repairs to their brain :-)
972  */
allocate_voice(SAMPLE * spl)973 int allocate_voice(SAMPLE *spl)
974 {
975    int phys = allocate_physical_voice(spl->priority);
976    int virt = allocate_virtual_voice();
977 
978    if (virt >= 0) {
979       _voice[virt].sample = spl;
980       _voice[virt].num = phys;
981       _voice[virt].autokill = FALSE;
982       _voice[virt].time = retrace_count;
983       _voice[virt].priority = spl->priority;
984 
985       if (phys >= 0) {
986 	 _phys_voice[phys].num = virt;
987 	 _phys_voice[phys].playmode = 0;
988 	 _phys_voice[phys].vol = ((_digi_volume >= 0) ? _digi_volume : 255) << 12;
989 	 _phys_voice[phys].pan = 128 << 12;
990 	 _phys_voice[phys].freq = spl->freq << 12;
991 	 _phys_voice[phys].dvol = 0;
992 	 _phys_voice[phys].dpan = 0;
993 	 _phys_voice[phys].dfreq = 0;
994 
995 	 digi_driver->init_voice(phys, spl);
996       }
997    }
998 
999    return virt;
1000 }
1001 
1002 END_OF_FUNCTION(allocate_voice);
1003 
1004 
1005 
1006 /* deallocate_voice:
1007  *  Releases a voice that was previously returned by allocate_voice().
1008  */
deallocate_voice(int voice)1009 void deallocate_voice(int voice)
1010 {
1011    if (_voice[voice].num >= 0) {
1012       digi_driver->stop_voice(_voice[voice].num);
1013       digi_driver->release_voice(_voice[voice].num);
1014       _phys_voice[_voice[voice].num].num = -1;
1015       _voice[voice].num = -1;
1016    }
1017 
1018    _voice[voice].sample = NULL;
1019 }
1020 
1021 END_OF_FUNCTION(deallocate_voice);
1022 
1023 
1024 
1025 /* reallocate_voice:
1026  *  Switches an already-allocated voice to use a different sample.
1027  */
reallocate_voice(int voice,SAMPLE * spl)1028 void reallocate_voice(int voice, SAMPLE *spl)
1029 {
1030    int phys = _voice[voice].num;
1031 
1032    if (phys >= 0) {
1033       digi_driver->stop_voice(phys);
1034       digi_driver->release_voice(phys);
1035    }
1036 
1037    _voice[voice].sample = spl;
1038    _voice[voice].autokill = FALSE;
1039    _voice[voice].time = retrace_count;
1040    _voice[voice].priority = spl->priority;
1041 
1042    if (phys >= 0) {
1043       _phys_voice[phys].playmode = 0;
1044       _phys_voice[phys].vol = ((_digi_volume >= 0) ? _digi_volume : 255) << 12;
1045       _phys_voice[phys].pan = 128 << 12;
1046       _phys_voice[phys].freq = spl->freq << 12;
1047       _phys_voice[phys].dvol = 0;
1048       _phys_voice[phys].dpan = 0;
1049       _phys_voice[phys].dfreq = 0;
1050 
1051       digi_driver->init_voice(phys, spl);
1052    }
1053 }
1054 
1055 END_OF_FUNCTION(reallocate_voice);
1056 
1057 
1058 
1059 /* release_voice:
1060  *  Flags that a voice is no longer going to be updated, so it can
1061  *  automatically be freed as soon as the sample finishes playing.
1062  */
release_voice(int voice)1063 void release_voice(int voice)
1064 {
1065    _voice[voice].autokill = TRUE;
1066 }
1067 
1068 END_OF_FUNCTION(release_voice);
1069 
1070 
1071 
1072 /* voice_start:
1073  *  Starts a voice playing.
1074  */
voice_start(int voice)1075 void voice_start(int voice)
1076 {
1077    if (_voice[voice].num >= 0)
1078       digi_driver->start_voice(_voice[voice].num);
1079 
1080    _voice[voice].time = retrace_count;
1081 }
1082 
1083 END_OF_FUNCTION(voice_start);
1084 
1085 
1086 
1087 /* voice_stop:
1088  *  Stops a voice from playing.
1089  */
voice_stop(int voice)1090 void voice_stop(int voice)
1091 {
1092    if (_voice[voice].num >= 0)
1093       digi_driver->stop_voice(_voice[voice].num);
1094 }
1095 
1096 END_OF_FUNCTION(voice_stop);
1097 
1098 
1099 
1100 /* voice_set_priority:
1101  *  Adjusts the priority of a voice (0-255).
1102  */
voice_set_priority(int voice,int priority)1103 void voice_set_priority(int voice, int priority)
1104 {
1105    _voice[voice].priority = priority;
1106 }
1107 
1108 END_OF_FUNCTION(voice_set_priority);
1109 
1110 
1111 
1112 /* voice_check:
1113  *  Checks whether a voice is playing, returning the sample if it is,
1114  *  or NULL if it has finished or been preempted by a different sound.
1115  */
voice_check(int voice)1116 SAMPLE *voice_check(int voice)
1117 {
1118    if (_voice[voice].sample) {
1119       if (_voice[voice].num < 0)
1120 	 return NULL;
1121 
1122       if (_voice[voice].autokill)
1123 	 if (voice_get_position(voice) < 0)
1124 	    return NULL;
1125 
1126       return _voice[voice].sample;
1127    }
1128    else
1129       return NULL;
1130 }
1131 
1132 END_OF_FUNCTION(voice_check);
1133 
1134 
1135 
1136 /* voice_get_position:
1137  *  Returns the current play position of a voice, or -1 if that cannot
1138  *  be determined (because it has finished or been preempted by a
1139  *  different sound).
1140  */
voice_get_position(int voice)1141 int voice_get_position(int voice)
1142 {
1143    if (_voice[voice].num >= 0)
1144       return digi_driver->get_position(_voice[voice].num);
1145    else
1146       return -1;
1147 }
1148 
1149 END_OF_FUNCTION(voice_get_position);
1150 
1151 
1152 
1153 /* voice_set_position:
1154  *  Sets the play position of a voice.
1155  */
voice_set_position(int voice,int position)1156 void voice_set_position(int voice, int position)
1157 {
1158    if (_voice[voice].num >= 0)
1159       digi_driver->set_position(_voice[voice].num, position);
1160 }
1161 
1162 END_OF_FUNCTION(voice_set_position);
1163 
1164 
1165 
1166 /* voice_set_playmode:
1167  *  Sets the loopmode of a voice.
1168  */
voice_set_playmode(int voice,int playmode)1169 void voice_set_playmode(int voice, int playmode)
1170 {
1171    if (_voice[voice].num >= 0) {
1172       _phys_voice[_voice[voice].num].playmode = playmode;
1173       digi_driver->loop_voice(_voice[voice].num, playmode);
1174 
1175       if (playmode & PLAYMODE_BACKWARD)
1176 	 digi_driver->set_position(_voice[voice].num, _voice[voice].sample->len-1);
1177    }
1178 }
1179 
1180 END_OF_FUNCTION(voice_set_playmode);
1181 
1182 
1183 
1184 /* voice_get_volume:
1185  *  Returns the current volume of a voice, or -1 if that cannot
1186  *  be determined (because it has finished or been preempted by a
1187  *  different sound).
1188  */
voice_get_volume(int voice)1189 int voice_get_volume(int voice)
1190 {
1191    int vol;
1192 
1193    if (_voice[voice].num >= 0)
1194       vol = digi_driver->get_volume(_voice[voice].num);
1195    else
1196       vol = -1;
1197 
1198    if ((vol >= 0) && (_digi_volume >= 0)) {
1199       if (_digi_volume > 0)
1200 	 vol = MID(0, (vol * 255) / _digi_volume, 255);
1201       else
1202 	 vol = 0;
1203    }
1204 
1205    return vol;
1206 }
1207 
1208 END_OF_FUNCTION(voice_get_volume);
1209 
1210 
1211 
1212 /* voice_set_volume:
1213  *  Sets the current volume of a voice.
1214  */
voice_set_volume(int voice,int volume)1215 void voice_set_volume(int voice, int volume)
1216 {
1217    if (_digi_volume >= 0)
1218       volume = (volume * _digi_volume) / 255;
1219 
1220    if (_voice[voice].num >= 0) {
1221       _phys_voice[_voice[voice].num].vol = volume << 12;
1222       _phys_voice[_voice[voice].num].dvol = 0;
1223 
1224       digi_driver->set_volume(_voice[voice].num, volume);
1225    }
1226 }
1227 
1228 END_OF_FUNCTION(voice_set_volume);
1229 
1230 
1231 
1232 /* voice_ramp_volume:
1233  *  Begins a volume ramp operation.
1234  */
voice_ramp_volume(int voice,int time,int endvol)1235 void voice_ramp_volume(int voice, int time, int endvol)
1236 {
1237    if (_digi_volume >= 0)
1238       endvol = (endvol * _digi_volume) / 255;
1239 
1240    if (_voice[voice].num >= 0) {
1241       if (digi_driver->ramp_volume) {
1242 	 digi_driver->ramp_volume(_voice[voice].num, time, endvol);
1243       }
1244       else {
1245 	 int d = (endvol << 12) - _phys_voice[_voice[voice].num].vol;
1246 	 time = MAX(time * SWEEP_FREQ / 1000, 1);
1247 	 _phys_voice[_voice[voice].num].target_vol = endvol << 12;
1248 	 _phys_voice[_voice[voice].num].dvol = d / time;
1249       }
1250    }
1251 }
1252 
1253 END_OF_FUNCTION(voice_ramp_volume);
1254 
1255 
1256 
1257 /* voice_stop_volumeramp:
1258  *  Ends a volume ramp operation.
1259  */
voice_stop_volumeramp(int voice)1260 void voice_stop_volumeramp(int voice)
1261 {
1262    if (_voice[voice].num >= 0) {
1263       _phys_voice[_voice[voice].num].dvol = 0;
1264 
1265       if (digi_driver->stop_volume_ramp)
1266 	 digi_driver->stop_volume_ramp(_voice[voice].num);
1267    }
1268 }
1269 
1270 END_OF_FUNCTION(voice_stop_volumeramp);
1271 
1272 
1273 
1274 /* voice_get_frequency:
1275  *  Returns the current frequency of a voice, or -1 if that cannot
1276  *  be determined (because it has finished or been preempted by a
1277  *  different sound).
1278  */
voice_get_frequency(int voice)1279 int voice_get_frequency(int voice)
1280 {
1281    if (_voice[voice].num >= 0)
1282       return digi_driver->get_frequency(_voice[voice].num);
1283    else
1284       return -1;
1285 }
1286 
1287 END_OF_FUNCTION(voice_get_frequency);
1288 
1289 
1290 
1291 /* voice_set_frequency:
1292  *  Sets the pitch of a voice.
1293  */
voice_set_frequency(int voice,int frequency)1294 void voice_set_frequency(int voice, int frequency)
1295 {
1296    if (_voice[voice].num >= 0) {
1297       _phys_voice[_voice[voice].num].freq = frequency << 12;
1298       _phys_voice[_voice[voice].num].dfreq = 0;
1299 
1300       digi_driver->set_frequency(_voice[voice].num, frequency);
1301    }
1302 }
1303 
1304 END_OF_FUNCTION(voice_set_frequency);
1305 
1306 
1307 
1308 /* voice_sweep_frequency:
1309  *  Begins a frequency sweep (glissando) operation.
1310  */
voice_sweep_frequency(int voice,int time,int endfreq)1311 void voice_sweep_frequency(int voice, int time, int endfreq)
1312 {
1313    if (_voice[voice].num >= 0) {
1314       if (digi_driver->sweep_frequency) {
1315 	 digi_driver->sweep_frequency(_voice[voice].num, time, endfreq);
1316       }
1317       else {
1318 	 int d = (endfreq << 12) - _phys_voice[_voice[voice].num].freq;
1319 	 time = MAX(time * SWEEP_FREQ / 1000, 1);
1320 	 _phys_voice[_voice[voice].num].target_freq = endfreq << 12;
1321 	 _phys_voice[_voice[voice].num].dfreq = d / time;
1322       }
1323    }
1324 }
1325 
1326 END_OF_FUNCTION(voice_sweep_frequency);
1327 
1328 
1329 
1330 /* voice_stop_frequency_sweep:
1331  *  Ends a frequency sweep.
1332  */
voice_stop_frequency_sweep(int voice)1333 void voice_stop_frequency_sweep(int voice)
1334 {
1335    if (_voice[voice].num >= 0) {
1336       _phys_voice[_voice[voice].num].dfreq = 0;
1337 
1338       if (digi_driver->stop_frequency_sweep)
1339 	 digi_driver->stop_frequency_sweep(_voice[voice].num);
1340    }
1341 }
1342 
1343 END_OF_FUNCTION(voice_stop_frequency_sweep);
1344 
1345 
1346 
1347 /* voice_get_pan:
1348  *  Returns the current pan position of a voice, or -1 if that cannot
1349  *  be determined (because it has finished or been preempted by a
1350  *  different sound).
1351  */
voice_get_pan(int voice)1352 int voice_get_pan(int voice)
1353 {
1354    int pan;
1355 
1356    if (_voice[voice].num >= 0)
1357       pan = digi_driver->get_pan(_voice[voice].num);
1358    else
1359       pan = -1;
1360 
1361    if ((pan >= 0) && (_flip_pan))
1362       pan = 255 - pan;
1363 
1364    return pan;
1365 }
1366 
1367 END_OF_FUNCTION(voice_get_pan);
1368 
1369 
1370 
1371 /* voice_set_pan:
1372  *  Sets the pan position of a voice.
1373  */
voice_set_pan(int voice,int pan)1374 void voice_set_pan(int voice, int pan)
1375 {
1376    if (_flip_pan)
1377       pan = 255 - pan;
1378 
1379    if (_voice[voice].num >= 0) {
1380       _phys_voice[_voice[voice].num].pan = pan << 12;
1381       _phys_voice[_voice[voice].num].dpan = 0;
1382 
1383       digi_driver->set_pan(_voice[voice].num, pan);
1384    }
1385 }
1386 
1387 END_OF_FUNCTION(voice_set_pan);
1388 
1389 
1390 
1391 /* voice_sweep_pan:
1392  *  Begins a pan sweep (left <-> right movement) operation.
1393  */
voice_sweep_pan(int voice,int time,int endpan)1394 void voice_sweep_pan(int voice, int time, int endpan)
1395 {
1396    if (_flip_pan)
1397       endpan = 255 - endpan;
1398 
1399    if (_voice[voice].num >= 0) {
1400       if (digi_driver->sweep_pan) {
1401 	 digi_driver->sweep_pan(_voice[voice].num, time, endpan);
1402       }
1403       else {
1404 	 int d = (endpan << 12) - _phys_voice[_voice[voice].num].pan;
1405 	 time = MAX(time * SWEEP_FREQ / 1000, 1);
1406 	 _phys_voice[_voice[voice].num].target_pan = endpan << 12;
1407 	 _phys_voice[_voice[voice].num].dpan = d / time;
1408       }
1409    }
1410 }
1411 
1412 END_OF_FUNCTION(voice_sweep_pan);
1413 
1414 
1415 
1416 /* voice_stop_pan_sweep:
1417  *  Ends a pan sweep.
1418  */
voice_stop_pan_sweep(int voice)1419 void voice_stop_pan_sweep(int voice)
1420 {
1421    if (_voice[voice].num >= 0) {
1422       _phys_voice[_voice[voice].num].dpan = 0;
1423 
1424       if (digi_driver->stop_pan_sweep)
1425 	 digi_driver->stop_pan_sweep(_voice[voice].num);
1426    }
1427 }
1428 
1429 END_OF_FUNCTION(voice_stop_pan_sweep);
1430 
1431 
1432 
1433 /* voice_set_echo:
1434  *  Sets the echo parameters of a voice.
1435  */
voice_set_echo(int voice,int strength,int delay)1436 void voice_set_echo(int voice, int strength, int delay)
1437 {
1438    if ((_voice[voice].num >= 0) && (digi_driver->set_echo))
1439       digi_driver->set_echo(_voice[voice].num, strength, delay);
1440 }
1441 
1442 END_OF_FUNCTION(voice_set_echo);
1443 
1444 
1445 
1446 /* voice_set_tremolo:
1447  *  Sets the tremolo parameters of a voice.
1448  */
voice_set_tremolo(int voice,int rate,int depth)1449 void voice_set_tremolo(int voice, int rate, int depth)
1450 {
1451    if ((_voice[voice].num >= 0) && (digi_driver->set_tremolo))
1452       digi_driver->set_tremolo(_voice[voice].num, rate, depth);
1453 }
1454 
1455 END_OF_FUNCTION(voice_set_tremolo);
1456 
1457 
1458 
1459 /* voice_set_vibrato:
1460  *  Sets the vibrato parameters of a voice.
1461  */
voice_set_vibrato(int voice,int rate,int depth)1462 void voice_set_vibrato(int voice, int rate, int depth)
1463 {
1464    if ((_voice[voice].num >= 0) && (digi_driver->set_vibrato))
1465       digi_driver->set_vibrato(_voice[voice].num, rate, depth);
1466 }
1467 
1468 END_OF_FUNCTION(voice_set_vibrato);
1469 
1470 
1471 
1472 /* update_sweeps:
1473  *  Timer callback routine used to implement volume/frequency/pan sweep
1474  *  effects, for those drivers that can't do them directly.
1475  */
update_sweeps()1476 static void update_sweeps()
1477 {
1478    int phys_voices, i;
1479 
1480    phys_voices = digi_driver->voices;
1481    if (midi_driver->max_voices < 0)
1482       phys_voices += midi_driver->voices;
1483 
1484    for (i=0; i<phys_voices; i++) {
1485       if (_phys_voice[i].num >= 0) {
1486 	 /* update volume ramp */
1487 	 if ((!digi_driver->ramp_volume) && (_phys_voice[i].dvol)) {
1488 	    _phys_voice[i].vol += _phys_voice[i].dvol;
1489 
1490 	    if (((_phys_voice[i].dvol > 0) && (_phys_voice[i].vol >= _phys_voice[i].target_vol)) ||
1491 		((_phys_voice[i].dvol < 0) && (_phys_voice[i].vol <= _phys_voice[i].target_vol))) {
1492 	       _phys_voice[i].vol = _phys_voice[i].target_vol;
1493 	       _phys_voice[i].dvol = 0;
1494 	    }
1495 
1496 	    digi_driver->set_volume(i, _phys_voice[i].vol >> 12);
1497 	 }
1498 
1499 	 /* update frequency sweep */
1500 	 if ((!digi_driver->sweep_frequency) && (_phys_voice[i].dfreq)) {
1501 	    _phys_voice[i].freq += _phys_voice[i].dfreq;
1502 
1503 	    if (((_phys_voice[i].dfreq > 0) && (_phys_voice[i].freq >= _phys_voice[i].target_freq)) ||
1504 		((_phys_voice[i].dfreq < 0) && (_phys_voice[i].freq <= _phys_voice[i].target_freq))) {
1505 	       _phys_voice[i].freq = _phys_voice[i].target_freq;
1506 	       _phys_voice[i].dfreq = 0;
1507 	    }
1508 
1509 	    digi_driver->set_frequency(i, _phys_voice[i].freq >> 12);
1510 	 }
1511 
1512 	 /* update pan sweep */
1513 	 if ((!digi_driver->sweep_pan) && (_phys_voice[i].dpan)) {
1514 	    _phys_voice[i].pan += _phys_voice[i].dpan;
1515 
1516 	    if (((_phys_voice[i].dpan > 0) && (_phys_voice[i].pan >= _phys_voice[i].target_pan)) ||
1517 		((_phys_voice[i].dpan < 0) && (_phys_voice[i].pan <= _phys_voice[i].target_pan))) {
1518 	       _phys_voice[i].pan = _phys_voice[i].target_pan;
1519 	       _phys_voice[i].dpan = 0;
1520 	    }
1521 
1522 	    digi_driver->set_pan(i, _phys_voice[i].pan >> 12);
1523 	 }
1524       }
1525    }
1526 }
1527 
1528 static END_OF_FUNCTION(update_sweeps);
1529 
1530 
1531 
1532 /* sound_lock_mem:
1533  *  Locks memory used by the functions in this file.
1534  */
sound_lock_mem()1535 static void sound_lock_mem()
1536 {
1537    LOCK_VARIABLE(digi_none);
1538    LOCK_VARIABLE(midi_none);
1539    LOCK_VARIABLE(digi_card);
1540    LOCK_VARIABLE(midi_card);
1541    LOCK_VARIABLE(digi_driver);
1542    LOCK_VARIABLE(midi_driver);
1543    LOCK_VARIABLE(_voice);
1544    LOCK_VARIABLE(_phys_voice);
1545    LOCK_VARIABLE(_digi_volume);
1546    LOCK_VARIABLE(_midi_volume);
1547    LOCK_VARIABLE(_flip_pan);
1548    LOCK_FUNCTION(_dummy_detect);
1549    LOCK_FUNCTION(play_sample);
1550    LOCK_FUNCTION(adjust_sample);
1551    LOCK_FUNCTION(stop_sample);
1552    LOCK_FUNCTION(allocate_voice);
1553    LOCK_FUNCTION(deallocate_voice);
1554    LOCK_FUNCTION(reallocate_voice);
1555    LOCK_FUNCTION(voice_start);
1556    LOCK_FUNCTION(voice_stop);
1557    LOCK_FUNCTION(voice_set_priority);
1558    LOCK_FUNCTION(voice_check);
1559    LOCK_FUNCTION(voice_get_position);
1560    LOCK_FUNCTION(voice_set_position);
1561    LOCK_FUNCTION(voice_set_playmode);
1562    LOCK_FUNCTION(voice_get_volume);
1563    LOCK_FUNCTION(voice_set_volume);
1564    LOCK_FUNCTION(voice_ramp_volume);
1565    LOCK_FUNCTION(voice_stop_volumeramp);
1566    LOCK_FUNCTION(voice_get_frequency);
1567    LOCK_FUNCTION(voice_set_frequency);
1568    LOCK_FUNCTION(voice_sweep_frequency);
1569    LOCK_FUNCTION(voice_stop_frequency_sweep);
1570    LOCK_FUNCTION(voice_get_pan);
1571    LOCK_FUNCTION(voice_set_pan);
1572    LOCK_FUNCTION(voice_sweep_pan);
1573    LOCK_FUNCTION(voice_stop_pan_sweep);
1574    LOCK_FUNCTION(voice_set_echo);
1575    LOCK_FUNCTION(voice_set_tremolo);
1576    LOCK_FUNCTION(voice_set_vibrato);
1577    LOCK_FUNCTION(update_sweeps);
1578 }
1579 
1580