]> icculus.org git repositories - btb/d2x.git/blob - arch/dos/allg_snd/sound/mixer.c
use the orientation parameter of g3_draw_bitmap
[btb/d2x.git] / arch / dos / allg_snd / sound / mixer.c
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  *      Sample mixing code.
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 typedef struct MIXER_VOICE
39 {
40    int playing;               /* are we active? */
41    unsigned char *data8;      /* data for 8 bit samples */
42    unsigned short *data16;    /* data for 16 bit samples */
43    long pos;                  /* fixed point position in sample */
44    long diff;                 /* fixed point speed of play */
45    long len;                  /* fixed point sample length */
46    long loop_start;           /* fixed point loop start position */
47    long loop_end;             /* fixed point loop end position */
48    int lvol;                  /* left channel volume */
49    int rvol;                  /* right channel volume */
50 } MIXER_VOICE;
51
52
53 #define MIXER_VOLUME_LEVELS         32
54 #define MIXER_FIX_SHIFT             8
55
56 #define UPDATE_FREQ                 16
57
58
59 /* the samples currently being played */
60 static MIXER_VOICE mixer_voice[MIXER_MAX_SFX];
61
62 /* temporary sample mixing buffer */
63 static unsigned short *mix_buffer = NULL; 
64
65 /* lookup table for converting sample volumes */
66 typedef signed short MIXER_VOL_TABLE[256];
67 static MIXER_VOL_TABLE *mix_vol_table = NULL;
68
69 /* lookup table for amplifying and clipping samples */
70 static unsigned short *mix_clip_table = NULL;
71
72 #define MIX_RES_16      14
73 #define MIX_RES_8       10
74
75 /* flags for the mixing code */
76 static int mix_voices;
77 static int mix_size;
78 static int mix_freq;
79 static int mix_stereo;
80 static int mix_16bit;
81
82
83 static void mixer_lock_mem();
84
85
86
87 /* _mixer_init:
88  *  Initialises the sample mixing code, returning 0 on success. You should
89  *  pass it the number of samples you want it to mix each time the refill
90  *  buffer routine is called, the sample rate to mix at, and two flags 
91  *  indicating whether the mixing should be done in stereo or mono and with 
92  *  eight or sixteen bits. The bufsize parameter is the number of samples,
93  *  not bytes. It should take into account whether you are working in stereo 
94  *  or not (eg. double it if in stereo), but it should not be affected by
95  *  whether each sample is 8 or 16 bits.
96  */
97 int _mixer_init(int bufsize, int freq, int stereo, int is16bit, int *voices)
98 {
99    int i, j;
100    int clip_size;
101    int clip_scale;
102    int clip_max;
103
104    mix_voices = 1;
105    while ((mix_voices < MIXER_MAX_SFX) && (mix_voices < *voices))
106       mix_voices <<= 1;
107
108    *voices = mix_voices;
109
110    mix_size = bufsize;
111    mix_freq = freq;
112    mix_stereo = stereo;
113    mix_16bit = is16bit;
114
115    for (i=0; i<MIXER_MAX_SFX; i++) {
116       mixer_voice[i].playing = FALSE;
117       mixer_voice[i].data8 = NULL;
118       mixer_voice[i].data16 = NULL;
119    }
120
121    /* temporary buffer for sample mixing */
122    mix_buffer = malloc(mix_size*sizeof(short));
123    if (!mix_buffer)
124       return -1;
125
126    _go32_dpmi_lock_data(mix_buffer, mix_size*sizeof(short));
127
128    /* volume table for mixing samples into the temporary buffer */
129    mix_vol_table = malloc(sizeof(MIXER_VOL_TABLE) * MIXER_VOLUME_LEVELS);
130    if (!mix_vol_table) {
131       free(mix_buffer);
132       mix_buffer = NULL;
133       return -1;
134    }
135
136    _go32_dpmi_lock_data(mix_vol_table, sizeof(MIXER_VOL_TABLE) * MIXER_VOLUME_LEVELS);
137
138    for (j=0; j<MIXER_VOLUME_LEVELS; j++)
139       for (i=0; i<256; i++)
140          mix_vol_table[j][i] = (i-128) * j * 256 / MIXER_VOLUME_LEVELS / mix_voices;
141
142    /* lookup table for amplifying and clipping sample buffers */
143    if (mix_16bit) {
144       clip_size = 1 << MIX_RES_16;
145       clip_scale = 18 - MIX_RES_16;
146       clip_max = 0xFFFF;
147    }
148    else {
149       clip_size = 1 << MIX_RES_8;
150       clip_scale = 10 - MIX_RES_8;
151       clip_max = 0xFF;
152    }
153
154    mix_clip_table = malloc(sizeof(short) * clip_size);
155    if (!mix_clip_table) {
156       free(mix_buffer);
157       mix_buffer = NULL;
158       free(mix_vol_table);
159       mix_vol_table = NULL;
160       return -1;
161    }
162
163    _go32_dpmi_lock_data(mix_clip_table, sizeof(short) * clip_size);
164
165    if (mix_voices >= 8) {
166       /* clip extremes of the sample range */
167       for (i=0; i<clip_size*3/8; i++) {
168          mix_clip_table[i] = 0;
169          mix_clip_table[clip_size-1-i] = clip_max;
170       }
171
172       for (i=0; i<clip_size/4; i++)
173          mix_clip_table[clip_size*3/8 + i] = i<<clip_scale;
174    }
175    else {
176       /* simple linear amplification */
177       for (i=0; i<clip_size; i++)
178          mix_clip_table[i] = (i<<clip_scale)/4;
179    }
180
181    mixer_lock_mem();
182
183    return 0;
184 }
185
186
187
188 /* _mixer_exit:
189  *  Cleans up the sample mixer code when you are done with it.
190  */
191 void _mixer_exit()
192 {
193    free(mix_buffer);
194    mix_buffer = NULL;
195
196    free(mix_vol_table);
197    mix_vol_table = NULL;
198
199    free(mix_clip_table);
200    mix_clip_table = NULL;
201 }
202
203
204
205 /* update_mixer_volume:
206  *  Called whenever the voice volume or pan changes, to update the mixer 
207  *  amplification table indexes.
208  */
209 static inline void update_mixer_volume(MIXER_VOICE *mv, PHYS_VOICE *pv)
210 {
211    int vol = pv->vol >> 12;
212    int pan = pv->pan >> 12;
213    int lvol, rvol;
214
215    if (mix_stereo) {
216       lvol = vol * (256-pan) * MIXER_VOLUME_LEVELS / 32768;
217       rvol = vol * pan * MIXER_VOLUME_LEVELS / 32768;
218    }
219    else
220       lvol = rvol = vol * MIXER_VOLUME_LEVELS / 256;
221
222    mv->lvol = MID(0, lvol, MIXER_VOLUME_LEVELS-1);
223    mv->rvol = MID(0, rvol, MIXER_VOLUME_LEVELS-1);
224 }
225
226
227
228 /* update_mixer_freq:
229  *  Called whenever the voice frequency changes, to update the sample
230  *  delta value.
231  */
232 static inline void update_mixer_freq(MIXER_VOICE *mv, PHYS_VOICE *pv)
233 {
234    mv->diff = (pv->freq >> (12 - MIXER_FIX_SHIFT)) / mix_freq;
235
236    if (pv->playmode & PLAYMODE_BACKWARD)
237       mv->diff = -mv->diff;
238 }
239
240
241
242 /* helper for constructing the body of a sample mixing routine */
243 #define MIXER()                                                              \
244 {                                                                            \
245    if ((voice->playmode & PLAYMODE_LOOP) &&                                  \
246        (spl->loop_start < spl->loop_end)) {                                  \
247       restart:                                                               \
248       if (voice->playmode & PLAYMODE_BACKWARD) {                             \
249          /* mix a backward looping sample */                                 \
250          while (len-- > 0) {                                                 \
251             MIX();                                                           \
252             spl->pos += spl->diff;                                           \
253             if (spl->pos < spl->loop_start) {                                \
254                if (voice->playmode & PLAYMODE_BIDIR) {                       \
255                   spl->diff = -spl->diff;                                    \
256                   spl->pos += spl->diff * 2;                                 \
257                   voice->playmode ^= PLAYMODE_BACKWARD;                      \
258                   goto restart;                                              \
259                }                                                             \
260                else                                                          \
261                   spl->pos += (spl->loop_end - spl->loop_start);             \
262             }                                                                \
263             UPDATE();                                                        \
264          }                                                                   \
265       }                                                                      \
266       else {                                                                 \
267          /* mix a forward looping sample */                                  \
268          while (len-- > 0) {                                                 \
269             MIX();                                                           \
270             spl->pos += spl->diff;                                           \
271             if (spl->pos >= spl->loop_end) {                                 \
272                if (voice->playmode & PLAYMODE_BIDIR) {                       \
273                   spl->diff = -spl->diff;                                    \
274                   spl->pos += spl->diff * 2;                                 \
275                   voice->playmode ^= PLAYMODE_BACKWARD;                      \
276                   goto restart;                                              \
277                }                                                             \
278                else                                                          \
279                   spl->pos -= (spl->loop_end - spl->loop_start);             \
280             }                                                                \
281             UPDATE();                                                        \
282          }                                                                   \
283       }                                                                      \
284    }                                                                         \
285    else {                                                                    \
286       /* mix a non-looping sample */                                         \
287       while (len-- > 0) {                                                    \
288          MIX();                                                              \
289          spl->pos += spl->diff;                                              \
290          if ((unsigned long)spl->pos >= (unsigned long)spl->len) {           \
291             /* note: we don't need a different version for reverse play, */  \
292             /* as this will wrap and automatically do the Right Thing */     \
293             spl->playing = FALSE;                                            \
294             return;                                                          \
295          }                                                                   \
296          UPDATE();                                                           \
297       }                                                                      \
298    }                                                                         \
299 }
300
301
302
303 #define UPDATE()
304
305
306
307 /* mix_mono_8_samples:
308  *  Mixes from an eight bit sample into a mono buffer, until either len 
309  *  samples have been mixed or until the end of the sample is reached.
310  */
311 static void mix_mono_8_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
312 {
313    signed short *vol = (short *)(mix_vol_table + spl->lvol);
314
315    #define MIX()                                                             \
316       *(buf++) += vol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]];
317
318    MIXER();
319
320    #undef MIX
321 }
322
323 static END_OF_FUNCTION(mix_mono_8_samples);
324
325
326
327 /* mix_stereo_8_samples:
328  *  Mixes from an eight bit sample into a stereo buffer, until either len 
329  *  samples have been mixed or until the end of the sample is reached.
330  */
331 static void mix_stereo_8_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
332 {
333    signed short *lvol = (short *)(mix_vol_table + spl->lvol);
334    signed short *rvol = (short *)(mix_vol_table + spl->rvol);
335
336    len >>= 1;
337
338    #define MIX()                                                             \
339       *(buf++) += lvol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]];               \
340       *(buf++) += rvol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]];
341
342    MIXER();
343
344    #undef MIX
345 }
346
347 static END_OF_FUNCTION(mix_stereo_8_samples);
348
349
350
351 /* mix_mono_16_samples:
352  *  Mixes from a 16 bit sample into a mono buffer, until either len samples 
353  *  have been mixed or until the end of the sample is reached.
354  */
355 static void mix_mono_16_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
356 {
357    signed short *vol = (short *)(mix_vol_table + spl->lvol);
358
359    #define MIX()                                                             \
360       *(buf++) += vol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8];
361
362    MIXER();
363
364    #undef MIX
365 }
366
367 static END_OF_FUNCTION(mix_mono_16_samples);
368
369
370
371 /* mix_stereo_16_samples:
372  *  Mixes from a 16 bit sample into a stereo buffer, until either len samples 
373  *  have been mixed or until the end of the sample is reached.
374  */
375 static void mix_stereo_16_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
376 {
377    signed short *lvol = (short *)(mix_vol_table + spl->lvol);
378    signed short *rvol = (short *)(mix_vol_table + spl->rvol);
379
380    len >>= 1;
381
382    #define MIX()                                                             \
383       *(buf++) += lvol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8];         \
384       *(buf++) += rvol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8];
385
386    MIXER();
387
388    #undef MIX
389 }
390
391 static END_OF_FUNCTION(mix_stereo_16_samples);
392
393
394
395 #undef UPDATE
396
397
398 /* helper for updating the volume ramp and pitch/pan sweep status */
399 #define UPDATE()                                                             \
400 {                                                                            \
401    if ((len & (UPDATE_FREQ-1)) == 0) {                                       \
402       /* update volume ramp */                                               \
403       if (voice->dvol) {                                                     \
404          voice->vol += voice->dvol;                                          \
405          if (((voice->dvol > 0) && (voice->vol >= voice->target_vol)) ||     \
406              ((voice->dvol < 0) && (voice->vol <= voice->target_vol))) {     \
407             voice->vol = voice->target_vol;                                  \
408             voice->dvol = 0;                                                 \
409          }                                                                   \
410       }                                                                      \
411                                                                              \
412       /* update frequency sweep */                                           \
413       if (voice->dfreq) {                                                    \
414          voice->freq += voice->dfreq;                                        \
415          if (((voice->dfreq > 0) && (voice->freq >= voice->target_freq)) ||  \
416              ((voice->dfreq < 0) && (voice->freq <= voice->target_freq))) {  \
417             voice->freq = voice->target_freq;                                \
418             voice->dfreq = 0;                                                \
419          }                                                                   \
420       }                                                                      \
421                                                                              \
422       /* update pan sweep */                                                 \
423       if (voice->dpan) {                                                     \
424          voice->pan += voice->dpan;                                          \
425          if (((voice->dpan > 0) && (voice->pan >= voice->target_pan)) ||     \
426              ((voice->dpan < 0) && (voice->pan <= voice->target_pan))) {     \
427             voice->pan = voice->target_pan;                                  \
428             voice->dpan = 0;                                                 \
429          }                                                                   \
430       }                                                                      \
431                                                                              \
432       update_mixer_volume(spl, voice);                                       \
433       update_mixer_freq(spl, voice);                                         \
434    }                                                                         \
435 }
436
437
438
439 /* mix_mono_8_samples_slow:
440  *  Mixes from an eight bit sample into a mono buffer, until either len 
441  *  samples have been mixed or until the end of the sample is reached,
442  *  using the slow mixing code that supports volume ramps and frequency/pan
443  *  sweep effects.
444  */
445 static void mix_mono_8_samples_slow(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
446 {
447    signed short *vol = (short *)(mix_vol_table + spl->lvol);
448
449    #define MIX()                                                             \
450       *(buf++) += vol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]];
451
452    MIXER();
453
454    #undef MIX
455 }
456
457 static END_OF_FUNCTION(mix_mono_8_samples_slow);
458
459
460
461 /* mix_stereo_8_samples_slow:
462  *  Mixes from an eight bit sample into a stereo buffer, until either len 
463  *  samples have been mixed or until the end of the sample is reached,
464  *  using the slow mixing code that supports volume ramps and frequency/pan
465  *  sweep effects.
466  */
467 static void mix_stereo_8_samples_slow(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
468 {
469    signed short *lvol = (short *)(mix_vol_table + spl->lvol);
470    signed short *rvol = (short *)(mix_vol_table + spl->rvol);
471
472    len >>= 1;
473
474    #define MIX()                                                             \
475       *(buf++) += lvol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]];               \
476       *(buf++) += rvol[spl->data8[spl->pos>>MIXER_FIX_SHIFT]];
477
478    MIXER();
479
480    #undef MIX
481 }
482
483 static END_OF_FUNCTION(mix_stereo_8_samples_slow);
484
485
486
487 /* mix_mono_16_samples_slow:
488  *  Mixes from a 16 bit sample into a mono buffer, until either len samples 
489  *  have been mixed or until the end of the sample is reached, using the 
490  *  slow mixing code that supports volume ramps and frequency/pan sweep 
491  *  effects.
492  */
493 static void mix_mono_16_samples_slow(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
494 {
495    signed short *vol = (short *)(mix_vol_table + spl->lvol);
496
497    #define MIX()                                                             \
498       *(buf++) += vol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8];
499
500    MIXER();
501
502    #undef MIX
503 }
504
505 static END_OF_FUNCTION(mix_mono_16_samples_slow);
506
507
508
509 /* mix_stereo_16_samples_slow:
510  *  Mixes from a 16 bit sample into a stereo buffer, until either len samples 
511  *  have been mixed or until the end of the sample is reached, using the 
512  *  slow mixing code that supports volume ramps and frequency/pan sweep 
513  *  effects.
514  */
515 static void mix_stereo_16_samples_slow(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
516 {
517    signed short *lvol = (short *)(mix_vol_table + spl->lvol);
518    signed short *rvol = (short *)(mix_vol_table + spl->rvol);
519
520    len >>= 1;
521
522    #define MIX()                                                             \
523       *(buf++) += lvol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8];         \
524       *(buf++) += rvol[(spl->data16[spl->pos>>MIXER_FIX_SHIFT])>>8];
525
526    MIXER();
527
528    #undef MIX
529 }
530
531 static END_OF_FUNCTION(mix_stereo_16_samples_slow);
532
533
534
535 /* _mix_some_samples:
536  *  Mixes samples into a buffer in conventional memory (the buf parameter
537  *  should be a linear offset into the specified segment), using the buffer 
538  *  size, sample frequency, etc, set when you called _mixer_init(). This 
539  *  should be called by the hardware end-of-buffer interrupt routine to 
540  *  get the next buffer full of samples to DMA to the card.
541  */
542 void _mix_some_samples(unsigned long buf, unsigned short seg, int issigned)
543 {
544    int i;
545    unsigned short *p = mix_buffer;
546    unsigned long *l = (unsigned long *)p;
547
548    /* clear mixing buffer */
549    for (i=0; i<mix_size/2; i++)
550       *(l++) = 0x80008000;
551
552    /* mix the samples */
553    if (mix_stereo) { 
554       for (i=0; i<mix_voices; i++) {
555          if ((mixer_voice[i].playing) &&
556              ((_phys_voice[i].vol > 0) || (_phys_voice[i].dvol > 0)))  {
557             if ((_phys_voice[i].dvol) || (_phys_voice[i].dfreq) || (_phys_voice[i].dpan)) {
558                if (mixer_voice[i].data8)
559                   mix_stereo_8_samples_slow(mixer_voice+i, _phys_voice+i, p, mix_size);
560                else
561                   mix_stereo_16_samples_slow(mixer_voice+i, _phys_voice+i, p, mix_size);
562             }
563             else {
564                if (mixer_voice[i].data8)
565                   mix_stereo_8_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
566                else
567                   mix_stereo_16_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
568             }
569          }
570       }
571    }
572    else {
573       for (i=0; i<mix_voices; i++) {
574          if ((mixer_voice[i].playing) &&
575              ((_phys_voice[i].vol > 0) || (_phys_voice[i].dvol > 0)))  {
576             if ((_phys_voice[i].dvol) || (_phys_voice[i].dfreq) || (_phys_voice[i].dpan)) {
577                if (mixer_voice[i].data8)
578                   mix_mono_8_samples_slow(mixer_voice+i, _phys_voice+i, p, mix_size);
579                else
580                   mix_mono_16_samples_slow(mixer_voice+i, _phys_voice+i, p, mix_size);
581             }
582             else {
583                if (mixer_voice[i].data8)
584                   mix_mono_8_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
585                else
586                   mix_mono_16_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
587             }
588          }
589       }
590    }
591
592    _farsetsel(seg);
593
594    /* transfer to conventional memory buffer */
595    if (mix_16bit) {
596       if (issigned) {
597          for (i=0; i<mix_size; i++) {
598             _farnspokew(buf, mix_clip_table[*p >> (16-MIX_RES_16)] ^ 0x8000);
599             buf += 2;
600             p++;
601          }
602       }
603       else {
604          for (i=0; i<mix_size; i++) {
605             _farnspokew(buf, mix_clip_table[*p >> (16-MIX_RES_16)]);
606             buf += 2;
607             p++;
608          }
609       }
610    }
611    else {
612       for (i=0; i<mix_size; i++) {
613          _farnspokeb(buf, mix_clip_table[*p >> (16-MIX_RES_8)]);
614          buf++;
615          p++;
616       }
617    }
618 }
619
620 END_OF_FUNCTION(_mix_some_samples);
621
622
623
624 /* _mixer_init_voice:
625  *  Initialises the specificed voice ready for playing a sample.
626  */
627 void _mixer_init_voice(int voice, SAMPLE *sample)
628 {
629    mixer_voice[voice].playing = FALSE;
630    mixer_voice[voice].pos = 0;
631    mixer_voice[voice].len = sample->len << MIXER_FIX_SHIFT;
632    mixer_voice[voice].loop_start = sample->loop_start << MIXER_FIX_SHIFT;
633    mixer_voice[voice].loop_end = sample->loop_end << MIXER_FIX_SHIFT;
634
635    if (sample->bits == 8) {
636       mixer_voice[voice].data8 = sample->data;
637       mixer_voice[voice].data16 = NULL;
638    }
639    else {
640       mixer_voice[voice].data8 = NULL;
641       mixer_voice[voice].data16 = sample->data;
642    }
643
644    update_mixer_volume(mixer_voice+voice, _phys_voice+voice);
645    update_mixer_freq(mixer_voice+voice, _phys_voice+voice);
646 }
647
648 END_OF_FUNCTION(_mixer_init_voice);
649
650
651
652 /* _mixer_release_voice:
653  *  Releases a voice when it is no longer required.
654  */
655 void _mixer_release_voice(int voice)
656 {
657    mixer_voice[voice].playing = FALSE;
658    mixer_voice[voice].data8 = NULL;
659    mixer_voice[voice].data16 = NULL;
660 }
661
662 END_OF_FUNCTION(_mixer_release_voice);
663
664
665
666 /* _mixer_start_voice:
667  *  Activates a voice, with the currently selected parameters.
668  */
669 void _mixer_start_voice(int voice)
670 {
671    if (mixer_voice[voice].pos >= mixer_voice[voice].len)
672       mixer_voice[voice].pos = 0;
673
674    mixer_voice[voice].playing = TRUE;
675 }
676
677 END_OF_FUNCTION(_mixer_start_voice);
678
679
680
681 /* _mixer_stop_voice:
682  *  Stops a voice from playing.
683  */
684 void _mixer_stop_voice(int voice)
685 {
686    mixer_voice[voice].playing = FALSE;
687 }
688
689 END_OF_FUNCTION(_mixer_stop_voice);
690
691
692
693 /* _mixer_loop_voice:
694  *  Sets the loopmode for a voice.
695  */
696 void _mixer_loop_voice(int voice, int loopmode)
697 {
698    update_mixer_freq(mixer_voice+voice, _phys_voice+voice);
699 }
700
701 END_OF_FUNCTION(_mixer_loop_voice);
702
703
704
705 /* _mixer_get_position:
706  *  Returns the current play position of a voice, or -1 if it has finished.
707  */
708 int _mixer_get_position(int voice)
709 {
710    if (mixer_voice[voice].pos >= mixer_voice[voice].len)
711       return -1;
712
713    return (mixer_voice[voice].pos >> MIXER_FIX_SHIFT);
714 }
715
716 END_OF_FUNCTION(_mixer_get_position);
717
718
719
720 /* _mixer_set_position:
721  *  Sets the current play position of a voice.
722  */
723 void _mixer_set_position(int voice, int position)
724 {
725    mixer_voice[voice].pos = (position << MIXER_FIX_SHIFT);
726
727    if (mixer_voice[voice].pos >= mixer_voice[voice].len)
728       mixer_voice[voice].playing = FALSE;
729 }
730
731 END_OF_FUNCTION(_mixer_set_position);
732
733
734
735 /* _mixer_get_volume:
736  *  Returns the current volume of a voice.
737  */
738 int _mixer_get_volume(int voice)
739 {
740    return (_phys_voice[voice].vol >> 12);
741 }
742
743 END_OF_FUNCTION(_mixer_get_volume);
744
745
746
747 /* _mixer_set_volume:
748  *  Sets the volume of a voice.
749  */
750 void _mixer_set_volume(int voice, int volume)
751 {
752    update_mixer_volume(mixer_voice+voice, _phys_voice+voice);
753 }
754
755 END_OF_FUNCTION(_mixer_set_volume);
756
757
758
759 /* _mixer_ramp_volume:
760  *  Starts a volume ramping operation.
761  */
762 void _mixer_ramp_volume(int voice, int time, int endvol)
763 {
764    int d = (endvol << 12) - _phys_voice[voice].vol;
765    time = MAX(time * (mix_freq / UPDATE_FREQ) / 1000, 1);
766
767    _phys_voice[voice].target_vol = endvol << 12;
768    _phys_voice[voice].dvol = d / time;
769 }
770
771 END_OF_FUNCTION(_mixer_ramp_volume);
772
773
774
775 /* _mixer_stop_volume_ramp:
776  *  Ends a volume ramp operation.
777  */
778 void _mixer_stop_volume_ramp(int voice)
779 {
780    _phys_voice[voice].dvol = 0;
781 }
782
783 END_OF_FUNCTION(_mixer_stop_volume_ramp);
784
785
786
787 /* _mixer_get_frequency:
788  *  Returns the current frequency of a voice.
789  */
790 int _mixer_get_frequency(int voice)
791 {
792    return (_phys_voice[voice].freq >> 12);
793 }
794
795 END_OF_FUNCTION(_mixer_get_frequency);
796
797
798
799 /* _mixer_set_frequency:
800  *  Sets the frequency of a voice.
801  */
802 void _mixer_set_frequency(int voice, int frequency)
803 {
804    update_mixer_freq(mixer_voice+voice, _phys_voice+voice);
805 }
806
807 END_OF_FUNCTION(_mixer_set_frequency);
808
809
810
811 /* _mixer_sweep_frequency:
812  *  Starts a frequency sweep.
813  */
814 void _mixer_sweep_frequency(int voice, int time, int endfreq)
815 {
816    int d = (endfreq << 12) - _phys_voice[voice].freq;
817    time = MAX(time * (mix_freq / UPDATE_FREQ) / 1000, 1);
818
819    _phys_voice[voice].target_freq = endfreq << 12;
820    _phys_voice[voice].dfreq = d / time;
821 }
822
823 END_OF_FUNCTION(_mixer_sweep_frequency);
824
825
826
827 /* _mixer_stop_frequency_sweep:
828  *  Ends a frequency sweep.
829  */
830 void _mixer_stop_frequency_sweep(int voice)
831 {
832    _phys_voice[voice].dfreq = 0;
833 }
834
835 END_OF_FUNCTION(_mixer_stop_frequency_sweep);
836
837
838
839 /* _mixer_get_pan:
840  *  Returns the current pan position of a voice.
841  */
842 int _mixer_get_pan(int voice)
843 {
844    return (_phys_voice[voice].pan >> 12);
845 }
846
847 END_OF_FUNCTION(_mixer_get_pan);
848
849
850
851 /* _mixer_set_pan:
852  *  Sets the pan position of a voice.
853  */
854 void _mixer_set_pan(int voice, int pan)
855 {
856    update_mixer_volume(mixer_voice+voice, _phys_voice+voice);
857 }
858
859 END_OF_FUNCTION(_mixer_set_pan);
860
861
862
863 /* _mixer_sweep_pan:
864  *  Starts a pan sweep.
865  */
866 void _mixer_sweep_pan(int voice, int time, int endpan)
867 {
868    int d = (endpan << 12) - _phys_voice[voice].pan;
869    time = MAX(time * (mix_freq / UPDATE_FREQ) / 1000, 1);
870
871    _phys_voice[voice].target_pan = endpan << 12;
872    _phys_voice[voice].dpan = d / time;
873 }
874
875 END_OF_FUNCTION(_mixer_sweep_pan);
876
877
878
879 /* _mixer_stop_pan_sweep:
880  *  Ends a pan sweep.
881  */
882 void _mixer_stop_pan_sweep(int voice)
883 {
884    _phys_voice[voice].dpan = 0;
885 }
886
887 END_OF_FUNCTION(_mixer_stop_pan_sweep);
888
889
890
891 /* _mixer_set_echo:
892  *  Sets the echo parameters for a voice.
893  */
894 void _mixer_set_echo(int voice, int strength, int delay)
895 {
896    /* not implemented */
897 }
898
899 END_OF_FUNCTION(_mixer_set_echo);
900
901
902
903 /* _mixer_set_tremolo:
904  *  Sets the tremolo parameters for a voice.
905  */
906 void _mixer_set_tremolo(int voice, int rate, int depth)
907 {
908    /* not implemented */
909 }
910
911 END_OF_FUNCTION(_mixer_set_tremolo);
912
913
914
915 /* _mixer_set_vibrato:
916  *  Sets the amount of vibrato for a voice.
917  */
918 void _mixer_set_vibrato(int voice, int rate, int depth)
919 {
920    /* not implemented */
921 }
922
923 END_OF_FUNCTION(_mixer_set_vibrato);
924
925
926
927 /* mixer_lock_mem:
928  *  Locks memory used by the functions in this file.
929  */
930 static void mixer_lock_mem()
931 {
932    LOCK_VARIABLE(mixer_voice);
933    LOCK_VARIABLE(mix_buffer);
934    LOCK_VARIABLE(mix_vol_table);
935    LOCK_VARIABLE(mix_clip_table);
936    LOCK_VARIABLE(mix_voices);
937    LOCK_VARIABLE(mix_size);
938    LOCK_VARIABLE(mix_freq);
939    LOCK_VARIABLE(mix_stereo);
940    LOCK_VARIABLE(mix_16bit);
941    LOCK_FUNCTION(mix_mono_8_samples);
942    LOCK_FUNCTION(mix_stereo_8_samples);
943    LOCK_FUNCTION(mix_mono_16_samples);
944    LOCK_FUNCTION(mix_stereo_16_samples);
945    LOCK_FUNCTION(mix_mono_8_samples_slow);
946    LOCK_FUNCTION(mix_stereo_8_samples_slow);
947    LOCK_FUNCTION(mix_mono_16_samples_slow);
948    LOCK_FUNCTION(mix_stereo_16_samples_slow);
949    LOCK_FUNCTION(_mix_some_samples);
950    LOCK_FUNCTION(_mixer_init_voice);
951    LOCK_FUNCTION(_mixer_release_voice);
952    LOCK_FUNCTION(_mixer_start_voice);
953    LOCK_FUNCTION(_mixer_stop_voice);
954    LOCK_FUNCTION(_mixer_loop_voice);
955    LOCK_FUNCTION(_mixer_get_position);
956    LOCK_FUNCTION(_mixer_set_position);
957    LOCK_FUNCTION(_mixer_get_volume);
958    LOCK_FUNCTION(_mixer_set_volume);
959    LOCK_FUNCTION(_mixer_ramp_volume);
960    LOCK_FUNCTION(_mixer_stop_volume_ramp);
961    LOCK_FUNCTION(_mixer_get_frequency);
962    LOCK_FUNCTION(_mixer_set_frequency);
963    LOCK_FUNCTION(_mixer_sweep_frequency);
964    LOCK_FUNCTION(_mixer_stop_frequency_sweep);
965    LOCK_FUNCTION(_mixer_get_pan);
966    LOCK_FUNCTION(_mixer_set_pan);
967    LOCK_FUNCTION(_mixer_sweep_pan);
968    LOCK_FUNCTION(_mixer_stop_pan_sweep);
969    LOCK_FUNCTION(_mixer_set_echo);
970    LOCK_FUNCTION(_mixer_set_tremolo);
971    LOCK_FUNCTION(_mixer_set_vibrato);
972 }
973
974
975