1 /* $Id: digi.c,v 1.19 2004-11-29 06:09:06 btb Exp $ */
4 * SDL digital audio support
24 #include "gr.h" // needed for piggy.h
32 int digi_sample_rate = SAMPLE_RATE_11K;
34 //edited 05/17/99 Matt Mueller - added ifndef NO_ASM
35 //added on 980905 by adb to add inline fixmul for mixer on i386
38 #define do_fixmul(x,y) \
41 asm("imull %2\n\tshrdl %3,%1,%0" \
42 : "=a"(_ax), "=d"(_dx) \
43 : "rm"(y), "i"(16), "0"(x)); \
46 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
52 //changed on 980905 by adb to increase number of concurrent sounds
53 #define MAX_SOUND_SLOTS 32
55 #define SOUND_BUFFER_SIZE 512
59 /* This table is used to add two sound values together and pin
60 * the value to avoid overflow. (used with permission from ARDI)
61 * DPH: Taken from SDL/src/SDL_mixer.c.
63 static const Uint8 mix8[] =
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, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
77 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
78 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
79 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
80 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
81 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
82 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
83 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
84 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
85 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
86 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
87 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
88 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
89 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
90 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
91 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
92 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
93 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
94 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
95 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
96 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
97 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
98 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
99 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
110 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
111 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
115 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
116 #define SOUND_MAX_VOLUME (F1_0 / 2)
118 int digi_volume = SOUND_MAX_VOLUME;
121 static int digi_initialised = 0;
125 int playing; // Is there a sample playing on this channel?
126 int looped; // Play this sample looped?
127 fix pan; // 0 = far left, 1 = far right
128 fix volume; // 0 = nothing, 1 = fully on
129 //changed on 980905 by adb from char * to unsigned char *
130 unsigned char *samples;
132 unsigned int length; // Length of the sample
133 unsigned int position; // Position we are at at the moment.
134 } SoundSlots[MAX_SOUND_SLOTS];
136 static SDL_AudioSpec WaveSpec;
138 //added on 980905 by adb to add rotating/volume based sound kill system
139 static int digi_max_channels = 16;
140 static int next_handle = 0;
141 int SampleHandles[32];
142 void reset_sounds_on_channel(int channel);
145 void digi_reset_digi_sounds(void);
147 /* Audio mixing callback */
148 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
149 static void audio_mixcallback(void *userdata, Uint8 *stream, int len)
151 Uint8 *streamend = stream + len;
152 struct sound_slot *sl;
154 if (!digi_initialised)
157 memset(stream, 0x80, len); // fix "static" sound bug on Mac OS X
159 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++) {
161 Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
162 Uint8 *sp = stream, s;
167 if ((x = sl->pan) & 0x8000) {
168 vl = 0x20000 - x * 2;
174 vl = fixmul(vl, (x = sl->volume));
176 while (sp < streamend) {
177 if (sldata == slend) {
182 sldata = sl->samples;
184 v = *(sldata++) - 0x80;
186 *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ];
188 *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ];
190 sl->position = sldata - sl->samples;
196 /* Initialise audio devices. */
199 if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0) {
200 Error("SDL audio initialisation failed: %s.",SDL_GetError());
202 //added on 980905 by adb to init sound kill system
203 memset(SampleHandles, 255, sizeof(SampleHandles));
206 WaveSpec.freq = digi_sample_rate;
207 //added/changed by Sam Lantinga on 12/01/98 for new SDL version
208 WaveSpec.format = AUDIO_U8;
209 WaveSpec.channels = 2;
210 //end this section addition/change - SL
211 WaveSpec.samples = SOUND_BUFFER_SIZE;
212 WaveSpec.callback = audio_mixcallback;
214 if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
215 //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
216 Warning("\nError: Couldn't open audio: %s\n", SDL_GetError());
224 digi_initialised = 1;
229 void digi_reset() { }
231 /* Shut down audio */
234 if (!digi_initialised) return;
235 digi_initialised = 0;
239 void digi_stop_all_channels()
243 for (i = 0; i < MAX_SOUND_SLOTS; i++)
247 static int get_free_slot()
250 for (i=0; i<MAX_SOUND_SLOTS; i++) {
251 if (!SoundSlots[i].playing) return i;
256 int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj)
261 if (!digi_initialised) return -1;
263 if (soundnum < 0) return -1;
265 //added on 980905 by adb from original source to add sound kill system
266 // play at most digi_max_channel samples, if possible kill sample with low volume
270 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) ) {
271 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) ) {
272 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
274 if ( next_handle >= digi_max_channels )
279 //mprintf(( 0, "[SS:%d]", next_handle ));
280 SoundSlots[SampleHandles[next_handle]].playing = 0;
281 SampleHandles[next_handle] = -1;
285 slot = get_free_slot();
286 if (slot<0) return -1;
288 SoundSlots[slot].soundno = soundnum;
289 SoundSlots[slot].samples = GameSounds[soundnum].data;
290 SoundSlots[slot].length = GameSounds[soundnum].length;
291 SoundSlots[slot].volume = fixmul(digi_volume, volume);
292 SoundSlots[slot].pan = pan;
293 SoundSlots[slot].position = 0;
294 SoundSlots[slot].looped = looping;
295 SoundSlots[slot].playing = 1;
297 //added on 980905 by adb to add sound kill system from original sos digi.c
298 reset_sounds_on_channel(slot);
299 SampleHandles[next_handle] = slot;
301 if ( next_handle >= digi_max_channels )
308 // Returns the channel a sound number is playing on, or
310 int digi_find_channel(int soundno)
312 if (!digi_initialised)
318 if (GameSounds[soundno].data == NULL)
324 //FIXME: not implemented
328 //added on 980905 by adb to add sound kill system from original sos digi.c
329 void reset_sounds_on_channel( int channel )
333 for (i=0; i<digi_max_channels; i++)
334 if (SampleHandles[i] == channel)
335 SampleHandles[i] = -1;
340 //added on 980905 by adb from original source to make sfx volume work
341 void digi_set_digi_volume( int dvolume )
343 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
344 if ( dvolume > SOUND_MAX_VOLUME )
345 digi_volume = SOUND_MAX_VOLUME;
346 else if ( dvolume < 0 )
349 digi_volume = dvolume;
351 if ( !digi_initialised ) return;
357 void digi_set_volume( int dvolume, int mvolume )
359 digi_set_digi_volume(dvolume);
360 digi_set_midi_volume(mvolume);
361 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
364 int digi_is_sound_playing(int soundno)
368 soundno = digi_xlat_sound(soundno);
370 for (i = 0; i < MAX_SOUND_SLOTS; i++)
371 //changed on 980905 by adb: added SoundSlots[i].playing &&
372 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
379 //added on 980905 by adb to make sound channel setting work
380 void digi_set_max_channels(int n) {
381 digi_max_channels = n;
383 if ( digi_max_channels < 1 )
384 digi_max_channels = 1;
385 if (digi_max_channels > MAX_SOUND_SLOTS)
386 digi_max_channels = MAX_SOUND_SLOTS;
388 if ( !digi_initialised ) return;
390 digi_reset_digi_sounds();
393 int digi_get_max_channels() {
394 return digi_max_channels;
398 int digi_is_channel_playing(int channel)
400 if (!digi_initialised)
403 return SoundSlots[channel].playing;
406 void digi_set_channel_volume(int channel, int volume)
408 if (!digi_initialised)
411 if (!SoundSlots[channel].playing)
414 SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0);
417 void digi_set_channel_pan(int channel, int pan)
419 if (!digi_initialised)
422 if (!SoundSlots[channel].playing)
425 SoundSlots[channel].pan = pan;
428 void digi_stop_sound(int channel)
430 SoundSlots[channel].playing=0;
433 void digi_end_sound(int channel)
435 if (!digi_initialised)
438 if (!SoundSlots[channel].playing)
442 void digi_reset_digi_sounds() {
445 for (i=0; i< MAX_SOUND_SLOTS; i++)
446 SoundSlots[i].playing=0;
448 //added on 980905 by adb to reset sound kill system
449 memset(SampleHandles, 255, sizeof(SampleHandles));
456 // MIDI stuff follows.
457 void digi_set_midi_volume( int mvolume ) { }
458 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
459 void digi_stop_current_song()
468 void digi_pause_midi() {}
469 void digi_resume_midi() {}
478 if (!digi_initialised)
481 for (i = 0; i < digi_max_channels; i++)
483 if (digi_is_channel_playing(i))
487 mprintf_at((0, 2, 0, "DIGI: Active Sound Channels: %d/%d (HMI says %d/32) ", n_voices, digi_max_channels, -1));
488 //mprintf_at((0, 3, 0, "DIGI: Number locked sounds: %d ", digi_total_locks ));