3 * DOS digital audio support
21 #include "gr.h" // needed for piggy.h
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)
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
36 #define do_fixmul(x,y) \
39 asm("imull %2\n\tshrdl %3,%1,%0" \
40 : "=a"(_ax), "=d"(_dx) \
41 : "rm"(y), "i"(16), "0"(x)); \
44 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
50 //changed on 980905 by adb to increase number of concurrent sounds
51 #define MAX_SOUND_SLOTS 32
53 #define SOUND_BUFFER_SIZE 512
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.
61 static const unsigned char mix8[] =
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,
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)
116 int digi_volume = SOUND_MAX_VOLUME;
119 static int digi_initialised = 0;
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;
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];
136 static int digi_max_channels = 16;
138 static int next_channel = 0;
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)
144 unsigned char *streamend = stream + len;
145 struct sound_slot *sl;
147 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
151 unsigned char *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
152 unsigned char *sp = stream;
157 if ((x = sl->pan) & 0x8000)
159 vl = 0x20000 - x * 2;
167 vl = fixmul(vl, (x = sl->volume));
169 while (sp < streamend)
178 sldata = sl->samples;
180 v = *(sldata++) - 0x80;
181 *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ];
182 *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ];
184 sl->position = sldata - sl->samples;
190 /* Initialise audio devices. */
193 /* this is just here now to stop gcc from complaining about
194 * audio_mixcallback being declared static and not used...
196 if (0) audio_mixcallback(NULL,NULL,0);
202 void digi_reset() { }
204 /* Shut down audio */
207 if (!digi_initialised) return;
208 digi_initialised = 0;
211 void digi_stop_all_channels()
215 for (i = 0; i < MAX_SOUND_SLOTS; i++)
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);
226 int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj)
228 int i, starting_channel;
230 if (!digi_initialised) return -1;
232 if (soundnum < 0) return -1;
234 Assert(GameSounds[soundnum].data != (void *)-1);
236 starting_channel = next_channel;
240 if (!SoundSlots[next_channel].playing)
243 if (!SoundSlots[next_channel].persistent)
244 break; // use this channel!
247 if (next_channel >= digi_max_channels)
249 if (next_channel == starting_channel)
251 mprintf((1, "OUT OF SOUND CHANNELS!!!\n"));
255 if (SoundSlots[next_channel].playing)
257 SoundSlots[next_channel].playing = 0;
258 if (SoundSlots[next_channel].soundobj > -1)
260 digi_end_soundobj(SoundSlots[next_channel].soundobj);
262 if (SoundQ_channel == next_channel)
267 verify_sound_channel_free(next_channel);
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;
285 if (next_channel >= digi_max_channels)
292 // Returns the channel a sound number is playing on, or
294 int digi_find_channel(int soundno)
296 if (!digi_initialised)
302 if (GameSounds[soundno].data == NULL)
308 //FIXME: not implemented
313 //added on 980905 by adb from original source to make sfx volume work
314 void digi_set_digi_volume( int dvolume )
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 )
322 digi_volume = dvolume;
324 if ( !digi_initialised ) return;
330 void digi_set_volume( int dvolume, int mvolume ) { }
332 int digi_is_sound_playing(int soundno)
336 soundno = digi_xlat_sound(soundno);
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)
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;
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;
356 if ( !digi_initialised ) return;
358 digi_stop_all_channels();
361 int digi_get_max_channels() {
362 return digi_max_channels;
366 int digi_is_channel_playing(int channel)
368 if (!digi_initialised)
371 return SoundSlots[channel].playing;
374 void digi_set_channel_volume(int channel, int volume)
376 if (!digi_initialised)
379 if (!SoundSlots[channel].playing)
382 SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0);
385 void digi_set_channel_pan(int channel, int pan)
387 if (!digi_initialised)
390 if (!SoundSlots[channel].playing)
393 SoundSlots[channel].pan = pan;
396 void digi_stop_sound(int channel)
398 SoundSlots[channel].playing = 0;
399 SoundSlots[channel].soundobj = -1;
400 SoundSlots[channel].persistent = 0;
403 void digi_end_sound(int channel)
405 if (!digi_initialised)
408 if (!SoundSlots[channel].playing)
411 SoundSlots[channel].soundobj = -1;
412 SoundSlots[channel].persistent = 0;
415 void digi_reset_digi_sounds() {
418 for (i=0; i< MAX_SOUND_SLOTS; i++)
419 SoundSlots[i].playing=0;
421 //added on 980905 by adb to reset sound kill system
422 memset(SampleHandles, 255, sizeof(SampleHandles));
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()
441 //void digi_pause_midi() {}
442 //void digi_resume_midi() {}
443 //end this section kill - MM
451 if (!digi_initialised)
454 for (i = 0; i < digi_max_channels; i++)
456 if (digi_is_channel_playing(i))
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 ));