1 /* $Id: digi.c,v 1.12 2005-02-25 10:49:48 btb Exp $ */
8 #define WIN32_LEAN_AND_MEAN
19 #include "gr.h" // needed for piggy.h
33 #define MAX_SOUND_SLOTS 32
37 //added/changed on 980905 by adb to make sfx volume work
38 #define SOUND_MAX_VOLUME F1_0
39 int digi_volume = SOUND_MAX_VOLUME;
43 WAVEFORMATEX waveformat;
50 int playing; // Is there a sample playing on this channel?
51 int looped; // Play this sample looped?
52 fix pan; // 0 = far left, 1 = far right
53 fix volume; // 0 = nothing, 1 = fully on
54 //changed on 980905 by adb from char * to unsigned char *
55 unsigned char *samples;
57 unsigned int length; // Length of the sample
58 unsigned int position; // Position we are at at the moment.
59 LPDIRECTSOUNDBUFFER lpsb;
60 } SoundSlots[MAX_SOUND_SLOTS];
63 int midi_volume = 255;
64 int digi_midi_song_playing = 0;
65 int digi_last_midi_song = 0;
66 int digi_last_midi_song_loop = 0;
68 static int digi_initialised = 0;
69 static int digi_atexit_initialised=0;
71 //added on 980905 by adb to add rotating/volume based sound kill system
72 static int digi_max_channels = 16;
73 static int next_handle = 0;
74 int SampleHandles[32];
75 void reset_sounds_on_channel(int channel);
78 void digi_reset_digi_sounds(void);
86 digi_reset_digi_sounds();
87 IDirectSound_Release(lpds);
92 /* Initialise audio devices. */
97 if (!digi_initialised && g_hWnd){
99 memset(&waveformat, 0, sizeof(waveformat));
100 waveformat.wFormatTag=WAVE_FORMAT_PCM;
101 waveformat.wBitsPerSample=8;
102 waveformat.nChannels = 1;
103 waveformat.nSamplesPerSec = digi_sample_rate; //11025;
104 waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8);
105 waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign;
107 if ((hr = DirectSoundCreate(NULL, &lpds, NULL)) != DS_OK)
110 if ((hr = IDirectSound_SetCooperativeLevel(lpds, g_hWnd, DSSCL_PRIORITY)) //hWndMain
113 IDirectSound_Release(lpds);
117 memset(&dsbd, 0, sizeof(dsbd));
118 dsbd.dwSize = sizeof(dsbd);
119 dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;
120 dsbd.dwBufferBytes = 8192;
122 dsbd.lpwfxFormat = &waveformat;
124 digi_initialised = 1;
127 if (!digi_atexit_initialised){
129 digi_atexit_initialised=1;
134 // added 2000/01/15 Matt Mueller -- remove some duplication (and fix a big memory leak, in the kill=0 one case)
135 static int DS_release_slot(int slot, int kill)
137 if (SoundSlots[slot].lpsb)
141 IDirectSoundBuffer_GetStatus(SoundSlots[slot].lpsb, &s);
142 if (s & DSBSTATUS_PLAYING)
145 IDirectSoundBuffer_Stop(SoundSlots[slot].lpsb);
149 IDirectSoundBuffer_Release(SoundSlots[slot].lpsb);
150 SoundSlots[slot].lpsb = NULL;
152 SoundSlots[slot].playing = 0;
156 void digi_stop_all_channels()
160 for (i = 0; i < MAX_SOUND_SLOTS; i++)
165 static int get_free_slot()
169 for (i=0; i<MAX_SOUND_SLOTS; i++)
171 if (DS_release_slot(i, 0))
177 int D1vol2DSvol(fix d1v){
178 //multiplying by 1.5 doesn't help. DirectSound uses dB for volume, rather than a linear scale like d1 wants.
179 //I had to pull out a math book, but here is the code to fix it :) -Matt Mueller
185 // return log2(f2fl(d1v))*1000;//no log2? hm.
186 return log(f2fl(d1v))/log(2)*1000.0;
190 int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj)
196 if (!digi_initialised)
199 // added on 980905 by adb from original source to add sound kill system
200 // play at most digi_max_channel samples, if possible kill sample with low volume
204 if ((SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing))
206 if ((SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries < digi_max_channels))
208 //mprintf((0, "Not stopping loud sound %d.\n", next_handle));
210 if (next_handle >= digi_max_channels)
215 //mprintf((0, "[SS:%d]", next_handle));
216 SampleHandles[next_handle] = -1;
220 slot = get_free_slot();
224 SoundSlots[slot].soundno = soundnum;
225 SoundSlots[slot].samples = Sounddat(soundnum)->data;
226 SoundSlots[slot].length = Sounddat(soundnum)->length;
227 SoundSlots[slot].volume = fixmul(digi_volume, volume);
228 SoundSlots[slot].pan = pan;
229 SoundSlots[slot].position = 0;
230 SoundSlots[slot].looped = 0;
231 SoundSlots[slot].playing = 1;
233 memset(&waveformat, 0, sizeof(waveformat));
234 waveformat.wFormatTag = WAVE_FORMAT_PCM;
235 waveformat.wBitsPerSample = Sounddat(soundnum)->bits;
236 waveformat.nChannels = 1;
237 waveformat.nSamplesPerSec = Sounddat(soundnum)->freq; //digi_sample_rate;
238 waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8);
239 waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign;
241 memset(&dsbd, 0, sizeof(dsbd));
242 dsbd.dwSize = sizeof(dsbd);
243 dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;
245 dsbd.dwBufferBytes = SoundSlots[slot].length;
246 dsbd.lpwfxFormat = &waveformat;
248 hr = IDirectSound_CreateSoundBuffer(lpds, &dsbd, &SoundSlots[slot].lpsb, NULL);
251 printf("Createsoundbuffer failed! hr=0x%X\n", (int)hr);
259 IDirectSoundBuffer_Lock(SoundSlots[slot].lpsb, 0, Sounddat(soundnum)->length,
260 &ptr1, &len1, &ptr2, &len2, 0);
261 memcpy(ptr1, Sounddat(soundnum)->data, MIN(len1, Sounddat(soundnum)->length));
262 IDirectSoundBuffer_Unlock(SoundSlots[slot].lpsb, ptr1, len1, ptr2, len2);
265 IDirectSoundBuffer_SetPan(SoundSlots[slot].lpsb, ((int)(f2fl(pan) * 20000.0)) - 10000);
266 IDirectSoundBuffer_SetVolume(SoundSlots[slot].lpsb, D1vol2DSvol(SoundSlots[slot].volume));
267 IDirectSoundBuffer_Play(SoundSlots[slot].lpsb, 0, 0, 0);
269 // added on 980905 by adb to add sound kill system from original sos digi.c
270 reset_sounds_on_channel(slot);
271 SampleHandles[next_handle] = slot;
273 if (next_handle >= digi_max_channels)
280 // Returns the channel a sound number is playing on, or
282 int digi_find_channel(int soundno)
284 if (!digi_initialised)
290 if (GameSounds[soundno].data == NULL)
296 //FIXME: not implemented
300 //added on 980905 by adb to add sound kill system from original sos digi.c
301 void reset_sounds_on_channel( int channel )
305 for (i=0; i<digi_max_channels; i++)
306 if (SampleHandles[i] == channel)
307 SampleHandles[i] = -1;
311 //added on 980905 by adb from original source to make sfx volume work
312 void digi_set_digi_volume( int dvolume )
314 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
315 if ( dvolume > SOUND_MAX_VOLUME )
316 digi_volume = SOUND_MAX_VOLUME;
317 else if ( dvolume < 0 )
320 digi_volume = dvolume;
322 if ( !digi_initialised ) return;
328 void digi_set_volume( int dvolume, int mvolume )
330 digi_set_digi_volume(dvolume);
331 digi_set_midi_volume(mvolume);
334 int digi_is_sound_playing(int soundno)
338 soundno = digi_xlat_sound(soundno);
340 for (i = 0; i < MAX_SOUND_SLOTS; i++)
341 //changed on 980905 by adb: added SoundSlots[i].playing &&
342 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
349 //added on 980905 by adb to make sound channel setting work
350 void digi_set_max_channels(int n) {
351 digi_max_channels = n;
353 if ( digi_max_channels < 1 )
354 digi_max_channels = 1;
355 if (digi_max_channels > MAX_SOUND_SLOTS)
356 digi_max_channels = MAX_SOUND_SLOTS;
358 if ( !digi_initialised ) return;
360 digi_reset_digi_sounds();
363 int digi_get_max_channels() {
364 return digi_max_channels;
368 void digi_reset_digi_sounds() {
371 for (i=0; i< MAX_SOUND_SLOTS; i++) {
372 DS_release_slot(i, 1);
375 //added on 980905 by adb to reset sound kill system
376 memset(SampleHandles, 255, sizeof(SampleHandles));
381 int digi_is_channel_playing(int channel)
383 if (!digi_initialised)
386 return SoundSlots[channel].playing;
389 void digi_set_channel_volume(int channel, int volume)
391 if (!digi_initialised)
394 if (!SoundSlots[channel].playing)
397 SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0);
400 void digi_set_channel_pan(int channel, int pan)
402 if (!digi_initialised)
405 if (!SoundSlots[channel].playing)
408 SoundSlots[channel].pan = pan;
411 void digi_stop_sound(int channel)
413 SoundSlots[channel].playing=0;
414 SoundSlots[channel].soundobj = -1;
415 SoundSlots[channel].persistent = 0;
418 void digi_end_sound(int channel)
420 if (!digi_initialised)
423 if (!SoundSlots[channel].playing)
426 SoundSlots[channel].soundobj = -1;
427 SoundSlots[channel].persistent = 0;
431 int digi_midi_song_playing = 0;
432 static int digi_initialised = 0;
433 int midi_volume = 255;
435 int digi_get_settings() { return 0; }
436 int digi_init() { digi_initialised = 1; return 0; }
440 void digi_set_digi_volume( int dvolume ) {}
441 void digi_set_volume( int dvolume, int mvolume ) {}
443 int digi_is_sound_playing(int soundno) { return 0; }
445 void digi_set_max_channels(int n) {}
446 int digi_get_max_channels() { return 0; }
451 // MIDI stuff follows.
453 void digi_stop_current_song()
455 if ( digi_midi_song_playing ) {
458 digi_midi_song_playing = 0;
462 void digi_set_midi_volume( int n )
473 // scale up from 0-127 to 0-0xffff
474 mm_volume = (midi_volume << 1) | (midi_volume & 1);
475 mm_volume |= (mm_volume << 8);
478 midiOutSetVolume((HMIDIOUT)hmp->hmidi, mm_volume | mm_volume << 16);
481 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop )
483 if (!digi_initialised) return;
485 digi_stop_current_song();
487 //added on 5/20/99 by Victor Rachels to fix crash/etc
488 if(filename == NULL) return;
489 if(midi_volume < 1) return;
490 //end this section addition - VR
492 if ((hmp = hmp_open(filename))) {
494 digi_midi_song_playing = 1;
495 digi_set_midi_volume(midi_volume);
498 printf("hmp_open failed\n");
500 void digi_pause_midi() {}
501 void digi_resume_midi() {}
504 void digi_stop_current_song() {}
505 void digi_set_midi_volume( int n ) {}
506 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
507 void digi_pause_midi() {}
508 void digi_resume_midi() {}
517 if (!digi_initialised)
520 for (i = 0; i < digi_max_channels; i++)
522 if (digi_is_channel_playing(i))
526 mprintf_at((0, 2, 0, "DIGI: Active Sound Channels: %d/%d (HMI says %d/32) ", n_voices, digi_max_channels, -1));
527 //mprintf_at((0, 3, 0, "DIGI: Number locked sounds: %d ", digi_total_locks ));