1 // SDL digital audio support
11 //#include "SDL_audio.h"
16 #include "gr.h" // needed for piggy.h
21 int digi_driver_board = 0;
22 int digi_driver_port = 0;
23 int digi_driver_irq = 0;
24 int digi_driver_dma = 0;
25 //int digi_midi_type = 0; // Midi driver type
26 //int digi_midi_port = 0; // Midi driver port
27 int digi_timer_rate = 9943; // rate for the timer to go off to handle the driver system (120 Hz)
30 /* stub vars/functions for midi */
31 int digi_midi_type = 0;
32 int digi_midi_port = 0;
34 void digi_set_midi_volume( int mvolume ) {}
35 void digi_play_midi_song( char * filename, char * melodic_bank,
36 char * drum_bank, int loop ) {}
37 void digi_midi_pause() {}
38 void digi_midi_resume() {}
39 void digi_midi_stop() {}
43 //added on 980905 by adb to add inline fixmul for mixer on i386
45 #define do_fixmul(x,y) \
48 asm("imull %2\n\tshrdl %3,%1,%0" \
49 : "=a"(_ax), "=d"(_dx) \
50 : "rm"(y), "i"(16), "0"(x)); \
53 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
57 //changed on 980905 by adb to increase number of concurrent sounds
58 #define MAX_SOUND_SLOTS 32
60 #define SOUND_BUFFER_SIZE 512
64 /* This table is used to add two sound values together and pin
65 * the value to avoid overflow. (used with permission from ARDI)
66 * DPH: Taken from SDL/src/SDL_mixer.c.
68 static const unsigned char mix8[] =
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, 0x00, 0x00, 0x00,
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, 0x01, 0x02, 0x03,
82 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
83 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
84 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
85 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
86 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
87 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
88 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
89 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
90 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
91 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
92 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
93 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
94 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
95 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
96 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
97 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
98 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
99 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
100 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
101 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
102 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
103 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
104 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 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, 0xFF, 0xFF, 0xFF, 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,
120 //added/changed on 980905 by adb to make sfx volume work
121 #define SOUND_MAX_VOLUME (F1_0/2) // don't use real max like in original
122 int digi_volume = SOUND_MAX_VOLUME;
125 static int Digi_initialized = 0;
126 static int timer_system_initialized = 0;
130 int playing; // Is there a sample playing on this channel?
131 int looped; // Play this sample looped?
132 fix pan; // 0 = far left, 1 = far right
133 fix volume; // 0 = nothing, 1 = fully on
134 //changed on 980905 by adb from char * to unsigned char *
135 unsigned char *samples;
137 unsigned int length; // Length of the sample
138 unsigned int position; // Position we are at at the moment.
139 int soundobj; // Which soundobject is on this channel
140 int persistent; // This can't be pre-empted
141 } SoundSlots[MAX_SOUND_SLOTS];
143 //static SDL_AudioSpec WaveSpec;
145 static int digi_max_channels = 16;
147 static int next_channel = 0;
149 /* Audio mixing callback */
150 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
151 ULONG VC_WriteBytes(SBYTE *stream, ULONG len)
153 unsigned char *streamend;
154 struct sound_slot *sl;
156 // if (grd_curscreen)
157 // grd_curscreen->sc_canvas.cv_bitmap.bm_data[8]++;
158 len &= ~1; /* stereo -> always write 2 byte pairs */
159 streamend = stream + len;
164 while(stream < streamend) {
165 *(stream++) = (n & 256) ? 256 - (n & 255) : (n & 255);
172 memset(stream, 0x80, len);
174 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
178 unsigned char *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
179 unsigned char *sp = stream;
184 if ((x = sl->pan) & 0x8000)
186 vl = 0x20000 - x * 2;
194 vl = fixmul(vl, (x = sl->volume));
196 while (sp < streamend)
205 sldata = sl->samples;
207 v = *(sldata++) - 0x80;
208 *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ];
209 *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ];
211 sl->position = sldata - sl->samples;
218 extern MDRIVER drv_sb;
219 MDRIVER *drv = &drv_sb;
220 char allegro_error[128];
222 int md_mode = DMODE_STEREO;
223 int md_mixfreq = digi_sample_rate; //11025;
224 int md_dmabufsize = 1024;
226 void install_int_ex(void (*)(), long speed);
227 void remove_int(void(*)());
231 // if (grd_curscreen)
232 // (*grd_curscreen->sc_canvas.cv_bitmap.bm_data)++;
235 /* Initialise audio devices. */
239 WaveSpec.freq = digi_sample_rate; //11025;
240 WaveSpec.format = AUDIO_U8 | AUDIO_STEREO;
241 WaveSpec.samples = SOUND_BUFFER_SIZE;
242 WaveSpec.callback = audio_mixcallback;
244 if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
245 printf("Couldn't open audio: %s\n", SDL_GetError());
251 printf("Couldn't open audio: %s", myerr);
256 if (!timer_system_initialized)
259 install_int_ex(mm_timer, digi_timer_rate);
261 timer_set_function(mm_timer);
263 timer_system_initialized = 1;
271 Digi_initialized = 1;
276 void digi_reset() { }
278 /* Shut down audio */
281 if (!Digi_initialized) return;
282 Digi_initialized = 0;
285 if (timer_system_initialized)
288 remove_int(mm_timer);
290 timer_set_function(NULL);
292 timer_system_initialized = 0;
299 void digi_stop_all_channels()
303 for (i = 0; i < MAX_SOUND_SLOTS; i++)
308 extern void digi_end_soundobj(int channel);
309 extern int SoundQ_channel;
310 extern void SoundQ_end();
311 int verify_sound_channel_free(int channel);
314 int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj)
316 int i, starting_channel;
318 if (!Digi_initialized) return -1;
320 if (soundnum < 0) return -1;
322 Assert(GameSounds[soundnum].data != (void *)-1);
324 starting_channel = next_channel;
328 if (!SoundSlots[next_channel].playing)
331 if (!SoundSlots[next_channel].persistent)
332 break; // use this channel!
335 if (next_channel >= digi_max_channels)
337 if (next_channel == starting_channel)
339 mprintf((1, "OUT OF SOUND CHANNELS!!!\n"));
343 if (SoundSlots[next_channel].playing)
345 SoundSlots[next_channel].playing = 0;
346 if (SoundSlots[next_channel].soundobj > -1)
348 digi_end_soundobj(SoundSlots[next_channel].soundobj);
350 if (SoundQ_channel == next_channel)
355 verify_sound_channel_free(next_channel);
358 SoundSlots[next_channel].soundno = soundnum;
359 SoundSlots[next_channel].samples = GameSounds[soundnum].data;
360 SoundSlots[next_channel].length = GameSounds[soundnum].length;
361 SoundSlots[next_channel].volume = fixmul(digi_volume, volume);
362 SoundSlots[next_channel].pan = pan;
363 SoundSlots[next_channel].position = 0;
364 SoundSlots[next_channel].looped = looping;
365 SoundSlots[next_channel].playing = 1;
366 SoundSlots[next_channel].soundobj = soundobj;
367 SoundSlots[next_channel].persistent = 0;
368 if ((soundobj > -1) || (looping) || (volume > F1_0))
369 SoundSlots[next_channel].persistent = 1;
373 if (next_channel >= digi_max_channels)
379 // Returns the channel a sound number is playing on, or
381 int digi_find_channel(int soundno)
383 if (!Digi_initialized)
389 if (GameSounds[soundno].data == NULL)
395 //FIXME: not implemented
400 //added on 980905 by adb from original source to make sfx volume work
401 void digi_set_digi_volume( int dvolume )
403 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
404 if ( dvolume > SOUND_MAX_VOLUME )
405 digi_volume = SOUND_MAX_VOLUME;
406 else if ( dvolume < 0 )
409 digi_volume = dvolume;
411 if ( !Digi_initialized ) return;
417 void digi_set_volume( int dvolume, int mvolume )
419 digi_set_midi_volume(mvolume);
420 digi_set_digi_volume(dvolume);
424 int digi_is_sound_playing(int soundno)
428 soundno = digi_xlat_sound(soundno);
430 for (i = 0; i < MAX_SOUND_SLOTS; i++)
431 //changed on 980905 by adb: added SoundSlots[i].playing &&
432 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
439 //added on 980905 by adb to make sound channel setting work
440 void digi_set_max_channels(int n) {
441 digi_max_channels = n;
443 if ( digi_max_channels < 1 )
444 digi_max_channels = 1;
445 if (digi_max_channels > MAX_SOUND_SLOTS)
446 digi_max_channels = MAX_SOUND_SLOTS;
448 if ( !Digi_initialized ) return;
450 digi_stop_all_channels();
453 int digi_get_max_channels() {
454 return digi_max_channels;
458 int digi_is_channel_playing(int channel)
460 if (!Digi_initialized)
463 return SoundSlots[channel].playing;
466 void digi_set_channel_volume(int channel, int volume)
468 if (!Digi_initialized)
471 if (!SoundSlots[channel].playing)
474 SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0);
477 void digi_set_channel_pan(int channel, int pan)
479 if (!Digi_initialized)
482 if (!SoundSlots[channel].playing)
485 SoundSlots[channel].pan = pan;
488 void digi_stop_sound(int channel)
490 SoundSlots[channel].playing=0;
491 SoundSlots[channel].soundobj = -1;
492 SoundSlots[channel].persistent = 0;
495 void digi_end_sound(int channel)
497 if (!Digi_initialized)
500 if (!SoundSlots[channel].playing)
503 SoundSlots[channel].soundobj = -1;
504 SoundSlots[channel].persistent = 0;
513 if (!Digi_initialized)
516 for (i = 0; i < digi_max_channels; i++)
518 if (digi_is_channel_playing(i))
522 mprintf_at((0, 2, 0, "DIGI: Active Sound Channels: %d/%d (HMI says %d/32) ", n_voices, digi_max_channels, -1));
523 //mprintf_at((0, 3, 0, "DIGI: Number locked sounds: %d ", digi_total_locks ));
529 BOOL VC_Init(void) { return 1; }
530 void VC_Exit(void) { }
531 BOOL VC_SetNumVoices(void) { return 0; }
532 ULONG VC_SampleSpace(int type) { return 0; }
533 ULONG VC_SampleLength(int type, SAMPLE *s) { return 0; }
535 BOOL VC_PlayStart(void) { return 0; }
536 void VC_PlayStop(void) { }
539 SWORD VC_SampleLoad(SAMPLOAD *sload, int type, FILE *fp) { return 0; }
541 SWORD VC_SampleLoad(FILE *fp,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { return 0; }
543 void VC_SampleUnload(SWORD handle) { }
545 void VC_WriteSamples(SBYTE *buf,ULONG todo) { }
546 void VC_SilenceBytes(SBYTE *buf,ULONG todo) { }
549 void VC_VoiceSetVolume(UBYTE voice, UWORD vol) { }
550 void VC_VoiceSetPanning(UBYTE voice, ULONG pan) { }
552 void VC_VoiceSetVolume(UBYTE voice, UBYTE vol) { }
553 void VC_VoiceSetPanning(UBYTE voice, UBYTE pan) { }
555 void VC_VoiceSetFrequency(UBYTE voice, ULONG frq) { }
556 void VC_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { }
558 void VC_VoiceStop(UBYTE voice) { }
559 BOOL VC_VoiceStopped(UBYTE voice) { return 0; }
560 void VC_VoiceReleaseSustain(UBYTE voice) { }
561 SLONG VC_VoiceGetPosition(UBYTE voice) { return 0; }
562 ULONG VC_VoiceRealVolume(UBYTE voice) { return 0; }