]> icculus.org git repositories - btb/d2x.git/blob - arch/dos/digi.c
remove rcs tags
[btb/d2x.git] / arch / dos / digi.c
1 /*
2  *
3  * DOS digital audio support
4  *
5  *
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <conf.h>
10 #endif
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15
16 #include "pstypes.h"
17 #include "error.h"
18 #include "mono.h"
19 #include "fix.h"
20 #include "vecmat.h"
21 #include "gr.h" // needed for piggy.h
22 #include "piggy.h"
23 #include "digi.h"
24 #include "sounds.h"
25 #include "wall.h"
26 #include "newdemo.h"
27 #include "kconfig.h"
28
29 int digi_sample_rate = SAMPLE_RATE_11K;
30 int digi_timer_rate                                     = 9943;                 // rate for the timer to go off to handle the driver system (120 Hz)
31
32 //edited 05/17/99 Matt Mueller - added ifndef NO_ASM
33 //added on 980905 by adb to add inline fixmul for mixer on i386
34 #ifndef NO_ASM
35 #ifdef __i386__
36 #define do_fixmul(x,y)                          \
37 ({                                              \
38         int _ax, _dx;                           \
39         asm("imull %2\n\tshrdl %3,%1,%0"        \
40             : "=a"(_ax), "=d"(_dx)              \
41             : "rm"(y), "i"(16), "0"(x));        \
42         _ax;                                    \
43 })
44 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
45 #endif
46 #endif
47 //end edit by adb
48 //end edit -MM
49
50 //changed on 980905 by adb to increase number of concurrent sounds
51 #define MAX_SOUND_SLOTS 32
52 //end changes by adb
53 #define SOUND_BUFFER_SIZE 512
54
55 #define MIN_VOLUME 10
56
57 /* This table is used to add two sound values together and pin
58  * the value to avoid overflow.  (used with permission from ARDI)
59  * DPH: Taken from SDL/src/SDL_mixer.c.
60  */
61 static const unsigned char mix8[] =
62 {
63   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
75   0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
76   0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
77   0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
78   0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
79   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
80   0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
81   0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
82   0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
83   0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
84   0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
85   0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
86   0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
87   0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
88   0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
89   0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
90   0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
91   0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
92   0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
93   0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
94   0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
95   0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
96   0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
97   0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
98   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
99   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
100   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
101   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
102   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
103   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
105   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
106   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
107   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
108   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
109   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
110 };
111
112
113 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
114 #define SOUND_MAX_VOLUME (F1_0 / 2)
115
116 int digi_volume = SOUND_MAX_VOLUME;
117 //end edit by adb
118
119 static int digi_initialised = 0;
120
121 struct sound_slot {
122  int soundno;
123  int playing;   // Is there a sample playing on this channel?
124  int looped;    // Play this sample looped?
125  fix pan;       // 0 = far left, 1 = far right
126  fix volume;    // 0 = nothing, 1 = fully on
127  //changed on 980905 by adb from char * to unsigned char * 
128  unsigned char *samples;
129  //end changes by adb
130  unsigned int length; // Length of the sample
131  unsigned int position; // Position we are at at the moment.
132         int soundobj;   // Which soundobject is on this channel
133         int persistent; // This can't be pre-empted
134 } SoundSlots[MAX_SOUND_SLOTS];
135
136 static int digi_max_channels = 16;
137
138 static int next_channel = 0;
139
140 /* Audio mixing callback */
141 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
142 static void audio_mixcallback(void *userdata, unsigned char *stream, int len)
143 {
144  unsigned char *streamend = stream + len;
145  struct sound_slot *sl;
146   
147  for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
148  {
149   if (sl->playing)
150   {
151    unsigned char *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
152    unsigned char *sp = stream;
153    signed char v;
154    fix vl, vr;
155    int x;
156
157    if ((x = sl->pan) & 0x8000)
158    {
159     vl = 0x20000 - x * 2;
160     vr = 0x10000;
161    }
162    else
163    {
164     vl = 0x10000;
165     vr = x * 2;
166    }
167    vl = fixmul(vl, (x = sl->volume));
168    vr = fixmul(vr, x);
169    while (sp < streamend) 
170    {
171     if (sldata == slend)
172     {
173      if (!sl->looped)
174      {
175       sl->playing = 0;
176       break;
177      }
178      sldata = sl->samples;
179     }
180     v = *(sldata++) - 0x80;
181     *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ];
182     *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ];
183    }
184    sl->position = sldata - sl->samples;
185   }
186  }
187 }
188 //end changes by adb
189
190 /* Initialise audio devices. */
191 int digi_init()
192 {
193     /* this is just here now to stop gcc from complaining about 
194      * audio_mixcallback being declared static and not used...
195      */
196     if (0) audio_mixcallback(NULL,NULL,0);
197
198  return 1;
199 }
200
201 /* Toggle audio */
202 void digi_reset() { }
203
204 /* Shut down audio */
205 void digi_close()
206 {
207  if (!digi_initialised) return;
208  digi_initialised = 0;
209 }
210
211 void digi_stop_all_channels()
212 {
213         int i;
214
215         for (i = 0; i < MAX_SOUND_SLOTS; i++)
216                 digi_stop_sound(i);
217 }
218
219
220 extern void digi_end_soundobj(int channel);     
221 extern int SoundQ_channel;
222 extern void SoundQ_end();
223 int verify_sound_channel_free(int channel);
224
225 // Volume 0-F1_0
226 int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj)
227 {
228         int i, starting_channel;
229
230         if (!digi_initialised) return -1;
231
232         if (soundnum < 0) return -1;
233
234         Assert(GameSounds[soundnum].data != (void *)-1);
235
236         starting_channel = next_channel;
237
238         while(1)
239         {
240                 if (!SoundSlots[next_channel].playing)
241                         break;
242
243                 if (!SoundSlots[next_channel].persistent)
244                         break;  // use this channel!    
245
246                 next_channel++;
247                 if (next_channel >= digi_max_channels)
248                         next_channel = 0;
249                 if (next_channel == starting_channel)
250                 {
251                         mprintf((1, "OUT OF SOUND CHANNELS!!!\n"));
252                         return -1;
253                 }
254         }
255         if (SoundSlots[next_channel].playing)
256         {
257                 SoundSlots[next_channel].playing = 0;
258                 if (SoundSlots[next_channel].soundobj > -1)
259                 {
260                         digi_end_soundobj(SoundSlots[next_channel].soundobj);
261                 }
262                 if (SoundQ_channel == next_channel)
263                         SoundQ_end();
264         }
265
266 #ifndef NDEBUG
267         verify_sound_channel_free(next_channel);
268 #endif
269
270         SoundSlots[next_channel].soundno = soundnum;
271         SoundSlots[next_channel].samples = GameSounds[soundnum].data;
272         SoundSlots[next_channel].length = GameSounds[soundnum].length;
273         SoundSlots[next_channel].volume = fixmul(digi_volume, volume);
274         SoundSlots[next_channel].pan = pan;
275         SoundSlots[next_channel].position = 0;
276         SoundSlots[next_channel].looped = looping;
277         SoundSlots[next_channel].playing = 1;
278         SoundSlots[next_channel].soundobj = soundobj;
279         SoundSlots[next_channel].persistent = 0;
280         if ((soundobj > -1) || (looping) || (volume > F1_0))
281                 SoundSlots[next_channel].persistent = 1;
282
283         i = next_channel;
284         next_channel++;
285         if (next_channel >= digi_max_channels)
286                 next_channel = 0;
287
288         return i;
289 }
290
291
292 // Returns the channel a sound number is playing on, or
293 // -1 if none.
294 int digi_find_channel(int soundno)
295 {
296         if (!digi_initialised)
297                 return -1;
298
299         if (soundno < 0 )
300                 return -1;
301
302         if (GameSounds[soundno].data == NULL)
303         {
304                 Int3();
305                 return -1;
306         }
307
308         //FIXME: not implemented
309         return -1;
310 }
311
312
313 //added on 980905 by adb from original source to make sfx volume work
314 void digi_set_digi_volume( int dvolume )
315 {
316         dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
317         if ( dvolume > SOUND_MAX_VOLUME )
318                 digi_volume = SOUND_MAX_VOLUME;
319         else if ( dvolume < 0 )
320                 digi_volume = 0;
321         else
322                 digi_volume = dvolume;
323
324         if ( !digi_initialised ) return;
325
326         digi_sync_sounds();
327 }
328 //end edit by adb
329
330 void digi_set_volume( int dvolume, int mvolume ) { }
331
332 int digi_is_sound_playing(int soundno)
333 {
334         int i;
335
336         soundno = digi_xlat_sound(soundno);
337
338         for (i = 0; i < MAX_SOUND_SLOTS; i++)
339                   //changed on 980905 by adb: added SoundSlots[i].playing &&
340                   if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
341                   //end changes by adb
342                         return 1;
343         return 0;
344 }
345
346
347  //added on 980905 by adb to make sound channel setting work
348 void digi_set_max_channels(int n) { 
349         digi_max_channels       = n;
350
351         if ( digi_max_channels < 1 ) 
352                 digi_max_channels = 1;
353         if (digi_max_channels > MAX_SOUND_SLOTS)
354                 digi_max_channels = MAX_SOUND_SLOTS;
355
356         if ( !digi_initialised ) return;
357
358         digi_stop_all_channels();
359 }
360
361 int digi_get_max_channels() { 
362         return digi_max_channels; 
363 }
364 // end edit by adb
365
366 int digi_is_channel_playing(int channel)
367 {
368         if (!digi_initialised)
369                 return 0;
370
371         return SoundSlots[channel].playing;
372 }
373
374 void digi_set_channel_volume(int channel, int volume)
375 {
376         if (!digi_initialised)
377                 return;
378
379         if (!SoundSlots[channel].playing)
380                 return;
381
382         SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0);
383 }
384
385 void digi_set_channel_pan(int channel, int pan)
386 {
387         if (!digi_initialised)
388                 return;
389
390         if (!SoundSlots[channel].playing)
391                 return;
392
393         SoundSlots[channel].pan = pan;
394 }
395
396 void digi_stop_sound(int channel)
397 {
398         SoundSlots[channel].playing = 0;
399         SoundSlots[channel].soundobj = -1;
400         SoundSlots[channel].persistent = 0;
401 }
402
403 void digi_end_sound(int channel)
404 {
405         if (!digi_initialised)
406                 return;
407
408         if (!SoundSlots[channel].playing)
409                 return;
410
411         SoundSlots[channel].soundobj = -1;
412         SoundSlots[channel].persistent = 0;
413 }
414
415 void digi_reset_digi_sounds() {
416  int i;
417
418  for (i=0; i< MAX_SOUND_SLOTS; i++)
419   SoundSlots[i].playing=0;
420  
421  //added on 980905 by adb to reset sound kill system
422  memset(SampleHandles, 255, sizeof(SampleHandles));
423  next_handle = 0;
424  //end edit by adb
425 }
426
427
428 // MIDI stuff follows.
429 //added/killed on 11/25/98 by Matthew Mueller
430 //void digi_set_midi_volume( int mvolume ) { }
431 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
432 //void digi_stop_current_song()
433 //{
434 //#ifdef HMIPLAY
435 //        char buf[10];
436 //    
437 //        sprintf(buf,"s");
438 //        send_ipc(buf);
439 //#endif
440 //}
441 //void digi_pause_midi() {}
442 //void digi_resume_midi() {}
443 //end this section kill - MM
444
445 #ifndef NDEBUG
446 void digi_debug()
447 {
448         int i;
449         int n_voices = 0;
450
451         if (!digi_initialised)
452                 return;
453
454         for (i = 0; i < digi_max_channels; i++)
455         {
456                 if (digi_is_channel_playing(i))
457                         n_voices++;
458         }
459
460         mprintf_at((0, 2, 0, "DIGI: Active Sound Channels: %d/%d (HMI says %d/32)      ", n_voices, digi_max_channels, -1));
461         //mprintf_at((0, 3, 0, "DIGI: Number locked sounds:  %d                          ", digi_total_locks ));
462 }
463 #endif