3 * DOS digital audio support
20 #include "gr.h" // needed for piggy.h
24 int digi_sample_rate = SAMPLE_RATE_11K;
25 int digi_timer_rate = 9943; // rate for the timer to go off to handle the driver system (120 Hz)
27 //edited 05/17/99 Matt Mueller - added ifndef NO_ASM
28 //added on 980905 by adb to add inline fixmul for mixer on i386
31 #define do_fixmul(x,y) \
34 asm("imull %2\n\tshrdl %3,%1,%0" \
35 : "=a"(_ax), "=d"(_dx) \
36 : "rm"(y), "i"(16), "0"(x)); \
39 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
45 //changed on 980905 by adb to increase number of concurrent sounds
46 #define MAX_SOUND_SLOTS 32
48 #define SOUND_BUFFER_SIZE 512
52 /* This table is used to add two sound values together and pin
53 * the value to avoid overflow. (used with permission from ARDI)
54 * DPH: Taken from SDL/src/SDL_mixer.c.
56 static const unsigned char mix8[] =
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x01, 0x02, 0x03,
70 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
71 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
72 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
73 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
74 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
75 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
76 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
77 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
78 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
79 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
80 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
81 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
82 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
83 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
84 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
85 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
86 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
87 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
88 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
89 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
90 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
91 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
92 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
93 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
94 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
95 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
96 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
97 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 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,
108 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
109 #define SOUND_MAX_VOLUME (F1_0 / 2)
111 int digi_volume = SOUND_MAX_VOLUME;
114 static int Digi_initialized = 0;
118 int playing; // Is there a sample playing on this channel?
119 int looped; // Play this sample looped?
120 fix pan; // 0 = far left, 1 = far right
121 fix volume; // 0 = nothing, 1 = fully on
122 //changed on 980905 by adb from char * to unsigned char *
123 unsigned char *samples;
125 unsigned int length; // Length of the sample
126 unsigned int position; // Position we are at at the moment.
127 int soundobj; // Which soundobject is on this channel
128 int persistent; // This can't be pre-empted
129 } SoundSlots[MAX_SOUND_SLOTS];
131 static int digi_max_channels = 16;
133 static int next_channel = 0;
135 /* Audio mixing callback */
136 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
137 static void audio_mixcallback(void *userdata, unsigned char *stream, int len)
139 unsigned char *streamend = stream + len;
140 struct sound_slot *sl;
142 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
146 unsigned char *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
147 unsigned char *sp = stream;
152 if ((x = sl->pan) & 0x8000)
154 vl = 0x20000 - x * 2;
162 vl = fixmul(vl, (x = sl->volume));
164 while (sp < streamend)
173 sldata = sl->samples;
175 v = *(sldata++) - 0x80;
176 *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ];
177 *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ];
179 sl->position = sldata - sl->samples;
185 /* Initialise audio devices. */
188 /* this is just here now to stop gcc from complaining about
189 * audio_mixcallback being declared static and not used...
191 if (0) audio_mixcallback(NULL,NULL,0);
197 void digi_reset() { }
199 /* Shut down audio */
202 if (!Digi_initialized) return;
203 Digi_initialized = 0;
206 void digi_stop_all_channels()
210 for (i = 0; i < MAX_SOUND_SLOTS; i++)
215 extern void digi_end_soundobj(int channel);
216 extern int SoundQ_channel;
217 extern void SoundQ_end();
218 int verify_sound_channel_free(int channel);
221 int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj)
223 int i, starting_channel;
225 if (!Digi_initialized) return -1;
227 if (soundnum < 0) return -1;
229 Assert(GameSounds[soundnum].data != (void *)-1);
231 starting_channel = next_channel;
235 if (!SoundSlots[next_channel].playing)
238 if (!SoundSlots[next_channel].persistent)
239 break; // use this channel!
242 if (next_channel >= digi_max_channels)
244 if (next_channel == starting_channel)
246 mprintf((1, "OUT OF SOUND CHANNELS!!!\n"));
250 if (SoundSlots[next_channel].playing)
252 SoundSlots[next_channel].playing = 0;
253 if (SoundSlots[next_channel].soundobj > -1)
255 digi_end_soundobj(SoundSlots[next_channel].soundobj);
257 if (SoundQ_channel == next_channel)
262 verify_sound_channel_free(next_channel);
265 SoundSlots[next_channel].soundno = soundnum;
266 SoundSlots[next_channel].samples = GameSounds[soundnum].data;
267 SoundSlots[next_channel].length = GameSounds[soundnum].length;
268 SoundSlots[next_channel].volume = fixmul(digi_volume, volume);
269 SoundSlots[next_channel].pan = pan;
270 SoundSlots[next_channel].position = 0;
271 SoundSlots[next_channel].looped = looping;
272 SoundSlots[next_channel].playing = 1;
273 SoundSlots[next_channel].soundobj = soundobj;
274 SoundSlots[next_channel].persistent = 0;
275 if ((soundobj > -1) || (looping) || (volume > F1_0))
276 SoundSlots[next_channel].persistent = 1;
280 if (next_channel >= digi_max_channels)
287 // Returns the channel a sound number is playing on, or
289 int digi_find_channel(int soundno)
291 if (!Digi_initialized)
297 if (GameSounds[soundno].data == NULL)
303 //FIXME: not implemented
308 //added on 980905 by adb from original source to make sfx volume work
309 void digi_set_digi_volume( int dvolume )
311 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
312 if ( dvolume > SOUND_MAX_VOLUME )
313 digi_volume = SOUND_MAX_VOLUME;
314 else if ( dvolume < 0 )
317 digi_volume = dvolume;
319 if ( !Digi_initialized ) return;
325 void digi_set_volume( int dvolume, int mvolume ) { }
327 int digi_is_sound_playing(int soundno)
331 soundno = digi_xlat_sound(soundno);
333 for (i = 0; i < MAX_SOUND_SLOTS; i++)
334 //changed on 980905 by adb: added SoundSlots[i].playing &&
335 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
342 //added on 980905 by adb to make sound channel setting work
343 void digi_set_max_channels(int n) {
344 digi_max_channels = n;
346 if ( digi_max_channels < 1 )
347 digi_max_channels = 1;
348 if (digi_max_channels > MAX_SOUND_SLOTS)
349 digi_max_channels = MAX_SOUND_SLOTS;
351 if ( !Digi_initialized ) return;
353 digi_stop_all_channels();
356 int digi_get_max_channels() {
357 return digi_max_channels;
361 int digi_is_channel_playing(int channel)
363 if (!Digi_initialized)
366 return SoundSlots[channel].playing;
369 void digi_set_channel_volume(int channel, int volume)
371 if (!Digi_initialized)
374 if (!SoundSlots[channel].playing)
377 SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0);
380 void digi_set_channel_pan(int channel, int pan)
382 if (!Digi_initialized)
385 if (!SoundSlots[channel].playing)
388 SoundSlots[channel].pan = pan;
391 void digi_stop_sound(int channel)
393 SoundSlots[channel].playing = 0;
394 SoundSlots[channel].soundobj = -1;
395 SoundSlots[channel].persistent = 0;
398 void digi_end_sound(int channel)
400 if (!Digi_initialized)
403 if (!SoundSlots[channel].playing)
406 SoundSlots[channel].soundobj = -1;
407 SoundSlots[channel].persistent = 0;
410 void digi_reset_digi_sounds() {
413 for (i=0; i< MAX_SOUND_SLOTS; i++)
414 SoundSlots[i].playing=0;
416 //added on 980905 by adb to reset sound kill system
417 memset(SampleHandles, 255, sizeof(SampleHandles));
423 // MIDI stuff follows.
424 //added/killed on 11/25/98 by Matthew Mueller
425 //void digi_set_midi_volume( int mvolume ) { }
426 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
427 //void digi_stop_current_song()
436 //void digi_pause_midi() {}
437 //void digi_resume_midi() {}
438 //end this section kill - MM
446 if (!Digi_initialized)
449 for (i = 0; i < digi_max_channels; i++)
451 if (digi_is_channel_playing(i))
455 mprintf_at((0, 2, 0, "DIGI: Active Sound Channels: %d/%d (HMI says %d/32) ", n_voices, digi_max_channels, -1));
456 //mprintf_at((0, 3, 0, "DIGI: Number locked sounds: %d ", digi_total_locks ));