1 // SDL digital audio support
11 //#include "SDL_audio.h"
17 #include "gr.h" // needed for piggy.h
26 int digi_driver_board = 0;
27 int digi_driver_port = 0;
28 int digi_driver_irq = 0;
29 int digi_driver_dma = 0;
30 //int digi_midi_type = 0; // Midi driver type
31 //int digi_midi_port = 0; // Midi driver port
32 int digi_timer_rate = 9943; // rate for the timer to go off to handle the driver system (120 Hz)
35 /* stub vars/functions for midi */
36 int digi_midi_type = 0;
37 int digi_midi_port = 0;
39 void digi_set_midi_volume( int mvolume ) {}
40 void digi_play_midi_song( char * filename, char * melodic_bank,
41 char * drum_bank, int loop ) {}
42 void digi_midi_pause() {}
43 void digi_midi_resume() {}
44 void digi_midi_stop() {}
48 //added on 980905 by adb to add inline fixmul for mixer on i386
50 #define do_fixmul(x,y) \
53 asm("imull %2\n\tshrdl %3,%1,%0" \
54 : "=a"(_ax), "=d"(_dx) \
55 : "rm"(y), "i"(16), "0"(x)); \
58 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
62 //changed on 980905 by adb to increase number of concurrent sounds
63 #define MAX_SOUND_SLOTS 32
65 #define SOUND_BUFFER_SIZE 512
69 /* This table is used to add two sound values together and pin
70 * the value to avoid overflow. (used with permission from ARDI)
71 * DPH: Taken from SDL/src/SDL_mixer.c.
73 static const unsigned char mix8[] =
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
87 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
88 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
89 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
90 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
91 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
92 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
93 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
94 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
95 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
96 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
97 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
98 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
99 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
100 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
101 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
102 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
103 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
104 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
105 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
106 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
107 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
108 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
109 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
110 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
111 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
112 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
113 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
114 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
115 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
116 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
117 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
118 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
119 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
120 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
121 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
125 //added/changed on 980905 by adb to make sfx volume work
126 #define SOUND_MAX_VOLUME (F1_0/2) // don't use real max like in original
127 int digi_volume = SOUND_MAX_VOLUME;
130 static int digi_initialised = 0;
131 static int timer_system_initialized = 0;
135 int playing; // Is there a sample playing on this channel?
136 int looped; // Play this sample looped?
137 fix pan; // 0 = far left, 1 = far right
138 fix volume; // 0 = nothing, 1 = fully on
139 //changed on 980905 by adb from char * to unsigned char *
140 unsigned char *samples;
142 unsigned int length; // Length of the sample
143 unsigned int position; // Position we are at at the moment.
144 int soundobj; // Which soundobject is on this channel
145 int persistent; // This can't be pre-empted
146 } SoundSlots[MAX_SOUND_SLOTS];
148 //static SDL_AudioSpec WaveSpec;
150 static int digi_max_channels = 16;
152 static int next_channel = 0;
154 /* Audio mixing callback */
155 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
156 ULONG VC_WriteBytes(SBYTE *stream, ULONG len)
158 unsigned char *streamend;
159 struct sound_slot *sl;
161 // if (grd_curscreen)
162 // grd_curscreen->sc_canvas.cv_bitmap.bm_data[8]++;
163 len &= ~1; /* stereo -> always write 2 byte pairs */
164 streamend = stream + len;
169 while(stream < streamend) {
170 *(stream++) = (n & 256) ? 256 - (n & 255) : (n & 255);
177 memset(stream, 0x80, len);
179 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
183 unsigned char *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
184 unsigned char *sp = stream;
189 if ((x = sl->pan) & 0x8000)
191 vl = 0x20000 - x * 2;
199 vl = fixmul(vl, (x = sl->volume));
201 while (sp < streamend)
210 sldata = sl->samples;
212 v = *(sldata++) - 0x80;
213 *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ];
214 *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ];
216 sl->position = sldata - sl->samples;
223 extern MDRIVER drv_sb;
224 MDRIVER *drv = &drv_sb;
225 char allegro_error[128];
227 int md_mode = DMODE_STEREO;
228 int md_mixfreq = digi_sample_rate; //11025;
229 int md_dmabufsize = 1024;
231 void install_int_ex(void (*)(), long speed);
232 void remove_int(void(*)());
236 // if (grd_curscreen)
237 // (*grd_curscreen->sc_canvas.cv_bitmap.bm_data)++;
240 /* Initialise audio devices. */
244 WaveSpec.freq = digi_sample_rate; //11025;
245 WaveSpec.format = AUDIO_U8 | AUDIO_STEREO;
246 WaveSpec.samples = SOUND_BUFFER_SIZE;
247 WaveSpec.callback = audio_mixcallback;
249 if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
250 printf("Couldn't open audio: %s\n", SDL_GetError());
256 printf("Couldn't open audio: %s", myerr);
261 if (!timer_system_initialized)
264 install_int_ex(mm_timer, digi_timer_rate);
266 timer_set_function(mm_timer);
268 timer_system_initialized = 1;
276 digi_initialised = 1;
281 void digi_reset() { }
283 /* Shut down audio */
286 if (!digi_initialised) return;
287 digi_initialised = 0;
290 if (timer_system_initialized)
293 remove_int(mm_timer);
295 timer_set_function(NULL);
297 timer_system_initialized = 0;
304 void digi_stop_all_channels()
308 for (i = 0; i < MAX_SOUND_SLOTS; i++)
313 extern void digi_end_soundobj(int channel);
314 extern int SoundQ_channel;
315 extern void SoundQ_end();
316 int verify_sound_channel_free(int channel);
319 int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj)
321 int i, starting_channel;
323 if (!digi_initialised) return -1;
325 if (soundnum < 0) return -1;
327 Assert(GameSounds[soundnum].data != (void *)-1);
329 starting_channel = next_channel;
333 if (!SoundSlots[next_channel].playing)
336 if (!SoundSlots[next_channel].persistent)
337 break; // use this channel!
340 if (next_channel >= digi_max_channels)
342 if (next_channel == starting_channel)
344 mprintf((1, "OUT OF SOUND CHANNELS!!!\n"));
348 if (SoundSlots[next_channel].playing)
350 SoundSlots[next_channel].playing = 0;
351 if (SoundSlots[next_channel].soundobj > -1)
353 digi_end_soundobj(SoundSlots[next_channel].soundobj);
355 if (SoundQ_channel == next_channel)
360 verify_sound_channel_free(next_channel);
363 SoundSlots[next_channel].soundno = soundnum;
364 SoundSlots[next_channel].samples = GameSounds[soundnum].data;
365 SoundSlots[next_channel].length = GameSounds[soundnum].length;
366 SoundSlots[next_channel].volume = fixmul(digi_volume, volume);
367 SoundSlots[next_channel].pan = pan;
368 SoundSlots[next_channel].position = 0;
369 SoundSlots[next_channel].looped = looping;
370 SoundSlots[next_channel].playing = 1;
371 SoundSlots[next_channel].soundobj = soundobj;
372 SoundSlots[next_channel].persistent = 0;
373 if ((soundobj > -1) || (looping) || (volume > F1_0))
374 SoundSlots[next_channel].persistent = 1;
378 if (next_channel >= digi_max_channels)
384 // Returns the channel a sound number is playing on, or
386 int digi_find_channel(int soundno)
388 if (!digi_initialised)
394 if (GameSounds[soundno].data == NULL)
400 //FIXME: not implemented
405 //added on 980905 by adb from original source to make sfx volume work
406 void digi_set_digi_volume( int dvolume )
408 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
409 if ( dvolume > SOUND_MAX_VOLUME )
410 digi_volume = SOUND_MAX_VOLUME;
411 else if ( dvolume < 0 )
414 digi_volume = dvolume;
416 if ( !digi_initialised ) return;
422 void digi_set_volume( int dvolume, int mvolume )
424 digi_set_midi_volume(mvolume);
425 digi_set_digi_volume(dvolume);
429 int digi_is_sound_playing(int soundno)
433 soundno = digi_xlat_sound(soundno);
435 for (i = 0; i < MAX_SOUND_SLOTS; i++)
436 //changed on 980905 by adb: added SoundSlots[i].playing &&
437 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
444 //added on 980905 by adb to make sound channel setting work
445 void digi_set_max_channels(int n) {
446 digi_max_channels = n;
448 if ( digi_max_channels < 1 )
449 digi_max_channels = 1;
450 if (digi_max_channels > MAX_SOUND_SLOTS)
451 digi_max_channels = MAX_SOUND_SLOTS;
453 if ( !digi_initialised ) return;
455 digi_stop_all_channels();
458 int digi_get_max_channels() {
459 return digi_max_channels;
463 int digi_is_channel_playing(int channel)
465 if (!digi_initialised)
468 return SoundSlots[channel].playing;
471 void digi_set_channel_volume(int channel, int volume)
473 if (!digi_initialised)
476 if (!SoundSlots[channel].playing)
479 SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0);
482 void digi_set_channel_pan(int channel, int pan)
484 if (!digi_initialised)
487 if (!SoundSlots[channel].playing)
490 SoundSlots[channel].pan = pan;
493 void digi_stop_sound(int channel)
495 SoundSlots[channel].playing=0;
496 SoundSlots[channel].soundobj = -1;
497 SoundSlots[channel].persistent = 0;
500 void digi_end_sound(int channel)
502 if (!digi_initialised)
505 if (!SoundSlots[channel].playing)
508 SoundSlots[channel].soundobj = -1;
509 SoundSlots[channel].persistent = 0;
518 if (!digi_initialised)
521 for (i = 0; i < digi_max_channels; i++)
523 if (digi_is_channel_playing(i))
527 mprintf_at((0, 2, 0, "DIGI: Active Sound Channels: %d/%d (HMI says %d/32) ", n_voices, digi_max_channels, -1));
528 //mprintf_at((0, 3, 0, "DIGI: Number locked sounds: %d ", digi_total_locks ));
534 BOOL VC_Init(void) { return 1; }
535 void VC_Exit(void) { }
536 BOOL VC_SetNumVoices(void) { return 0; }
537 ULONG VC_SampleSpace(int type) { return 0; }
538 ULONG VC_SampleLength(int type, SAMPLE *s) { return 0; }
540 BOOL VC_PlayStart(void) { return 0; }
541 void VC_PlayStop(void) { }
544 SWORD VC_SampleLoad(SAMPLOAD *sload, int type, FILE *fp) { return 0; }
546 SWORD VC_SampleLoad(FILE *fp,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { return 0; }
548 void VC_SampleUnload(SWORD handle) { }
550 void VC_WriteSamples(SBYTE *buf,ULONG todo) { }
551 void VC_SilenceBytes(SBYTE *buf,ULONG todo) { }
554 void VC_VoiceSetVolume(UBYTE voice, UWORD vol) { }
555 void VC_VoiceSetPanning(UBYTE voice, ULONG pan) { }
557 void VC_VoiceSetVolume(UBYTE voice, UBYTE vol) { }
558 void VC_VoiceSetPanning(UBYTE voice, UBYTE pan) { }
560 void VC_VoiceSetFrequency(UBYTE voice, ULONG frq) { }
561 void VC_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { }
563 void VC_VoiceStop(UBYTE voice) { }
564 BOOL VC_VoiceStopped(UBYTE voice) { return 0; }
565 void VC_VoiceReleaseSustain(UBYTE voice) { }
566 SLONG VC_VoiceGetPosition(UBYTE voice) { return 0; }
567 ULONG VC_VoiceRealVolume(UBYTE voice) { return 0; }