7 #define WIN32_LEAN_AND_MEAN
18 #include "gr.h" // needed for piggy.h
32 #define MAX_SOUND_SLOTS 32
36 //added/changed on 980905 by adb to make sfx volume work
37 #define SOUND_MAX_VOLUME F1_0
38 int digi_volume = SOUND_MAX_VOLUME;
42 WAVEFORMATEX waveformat;
49 int playing; // Is there a sample playing on this channel?
50 int looped; // Play this sample looped?
51 fix pan; // 0 = far left, 1 = far right
52 fix volume; // 0 = nothing, 1 = fully on
53 //changed on 980905 by adb from char * to unsigned char *
54 unsigned char *samples;
56 unsigned int length; // Length of the sample
57 unsigned int position; // Position we are at at the moment.
58 LPDIRECTSOUNDBUFFER lpsb;
59 } SoundSlots[MAX_SOUND_SLOTS];
62 int midi_volume = 255;
63 int digi_midi_song_playing = 0;
64 int digi_last_midi_song = 0;
65 int digi_last_midi_song_loop = 0;
67 static int digi_initialised = 0;
68 static int digi_atexit_initialised=0;
70 //added on 980905 by adb to add rotating/volume based sound kill system
71 static int digi_max_channels = 16;
72 static int next_handle = 0;
73 int SampleHandles[32];
74 void reset_sounds_on_channel(int channel);
77 void digi_reset_digi_sounds(void);
85 digi_reset_digi_sounds();
86 IDirectSound_Release(lpds);
91 /* Initialise audio devices. */
96 if (!digi_initialised && g_hWnd){
98 memset(&waveformat, 0, sizeof(waveformat));
99 waveformat.wFormatTag=WAVE_FORMAT_PCM;
100 waveformat.wBitsPerSample=8;
101 waveformat.nChannels = 1;
102 waveformat.nSamplesPerSec = digi_sample_rate; //11025;
103 waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8);
104 waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign;
106 if ((hr = DirectSoundCreate(NULL, &lpds, NULL)) != DS_OK)
109 if ((hr = IDirectSound_SetCooperativeLevel(lpds, g_hWnd, DSSCL_PRIORITY)) //hWndMain
112 IDirectSound_Release(lpds);
116 memset(&dsbd, 0, sizeof(dsbd));
117 dsbd.dwSize = sizeof(dsbd);
118 dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;
119 dsbd.dwBufferBytes = 8192;
121 dsbd.lpwfxFormat = &waveformat;
123 digi_initialised = 1;
126 if (!digi_atexit_initialised){
128 digi_atexit_initialised=1;
133 // added 2000/01/15 Matt Mueller -- remove some duplication (and fix a big memory leak, in the kill=0 one case)
134 static int DS_release_slot(int slot, int kill)
136 if (SoundSlots[slot].lpsb)
140 IDirectSoundBuffer_GetStatus(SoundSlots[slot].lpsb, &s);
141 if (s & DSBSTATUS_PLAYING)
144 IDirectSoundBuffer_Stop(SoundSlots[slot].lpsb);
148 IDirectSoundBuffer_Release(SoundSlots[slot].lpsb);
149 SoundSlots[slot].lpsb = NULL;
151 SoundSlots[slot].playing = 0;
155 void digi_stop_all_channels()
159 for (i = 0; i < MAX_SOUND_SLOTS; i++)
164 static int get_free_slot()
168 for (i=0; i<MAX_SOUND_SLOTS; i++)
170 if (DS_release_slot(i, 0))
176 int D1vol2DSvol(fix d1v){
177 //multiplying by 1.5 doesn't help. DirectSound uses dB for volume, rather than a linear scale like d1 wants.
178 //I had to pull out a math book, but here is the code to fix it :) -Matt Mueller
184 // return log2(f2fl(d1v))*1000;//no log2? hm.
185 return log(f2fl(d1v))/log(2)*1000.0;
189 int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj)
195 if (!digi_initialised)
198 // added on 980905 by adb from original source to add sound kill system
199 // play at most digi_max_channel samples, if possible kill sample with low volume
203 if ((SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing))
205 if ((SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries < digi_max_channels))
207 //mprintf((0, "Not stopping loud sound %d.\n", next_handle));
209 if (next_handle >= digi_max_channels)
214 //mprintf((0, "[SS:%d]", next_handle));
215 SampleHandles[next_handle] = -1;
219 slot = get_free_slot();
223 SoundSlots[slot].soundno = soundnum;
224 SoundSlots[slot].samples = Sounddat(soundnum)->data;
225 SoundSlots[slot].length = Sounddat(soundnum)->length;
226 SoundSlots[slot].volume = fixmul(digi_volume, volume);
227 SoundSlots[slot].pan = pan;
228 SoundSlots[slot].position = 0;
229 SoundSlots[slot].looped = 0;
230 SoundSlots[slot].playing = 1;
232 memset(&waveformat, 0, sizeof(waveformat));
233 waveformat.wFormatTag = WAVE_FORMAT_PCM;
234 waveformat.wBitsPerSample = Sounddat(soundnum)->bits;
235 waveformat.nChannels = 1;
236 waveformat.nSamplesPerSec = Sounddat(soundnum)->freq; //digi_sample_rate;
237 waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8);
238 waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign;
240 memset(&dsbd, 0, sizeof(dsbd));
241 dsbd.dwSize = sizeof(dsbd);
242 dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;
244 dsbd.dwBufferBytes = SoundSlots[slot].length;
245 dsbd.lpwfxFormat = &waveformat;
247 hr = IDirectSound_CreateSoundBuffer(lpds, &dsbd, &SoundSlots[slot].lpsb, NULL);
250 printf("Createsoundbuffer failed! hr=0x%X\n", (int)hr);
258 IDirectSoundBuffer_Lock(SoundSlots[slot].lpsb, 0, Sounddat(soundnum)->length,
259 &ptr1, &len1, &ptr2, &len2, 0);
260 memcpy(ptr1, Sounddat(soundnum)->data, MIN(len1, Sounddat(soundnum)->length));
261 IDirectSoundBuffer_Unlock(SoundSlots[slot].lpsb, ptr1, len1, ptr2, len2);
264 IDirectSoundBuffer_SetPan(SoundSlots[slot].lpsb, ((int)(f2fl(pan) * 20000.0)) - 10000);
265 IDirectSoundBuffer_SetVolume(SoundSlots[slot].lpsb, D1vol2DSvol(SoundSlots[slot].volume));
266 IDirectSoundBuffer_Play(SoundSlots[slot].lpsb, 0, 0, 0);
268 // added on 980905 by adb to add sound kill system from original sos digi.c
269 reset_sounds_on_channel(slot);
270 SampleHandles[next_handle] = slot;
272 if (next_handle >= digi_max_channels)
279 // Returns the channel a sound number is playing on, or
281 int digi_find_channel(int soundno)
283 if (!digi_initialised)
289 if (GameSounds[soundno].data == NULL)
295 //FIXME: not implemented
299 //added on 980905 by adb to add sound kill system from original sos digi.c
300 void reset_sounds_on_channel( int channel )
304 for (i=0; i<digi_max_channels; i++)
305 if (SampleHandles[i] == channel)
306 SampleHandles[i] = -1;
310 //added on 980905 by adb from original source to make sfx volume work
311 void digi_set_digi_volume( int dvolume )
313 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
314 if ( dvolume > SOUND_MAX_VOLUME )
315 digi_volume = SOUND_MAX_VOLUME;
316 else if ( dvolume < 0 )
319 digi_volume = dvolume;
321 if ( !digi_initialised ) return;
327 void digi_set_volume( int dvolume, int mvolume )
329 digi_set_digi_volume(dvolume);
330 digi_set_midi_volume(mvolume);
333 int digi_is_sound_playing(int soundno)
337 soundno = digi_xlat_sound(soundno);
339 for (i = 0; i < MAX_SOUND_SLOTS; i++)
340 //changed on 980905 by adb: added SoundSlots[i].playing &&
341 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
348 //added on 980905 by adb to make sound channel setting work
349 void digi_set_max_channels(int n) {
350 digi_max_channels = n;
352 if ( digi_max_channels < 1 )
353 digi_max_channels = 1;
354 if (digi_max_channels > MAX_SOUND_SLOTS)
355 digi_max_channels = MAX_SOUND_SLOTS;
357 if ( !digi_initialised ) return;
359 digi_reset_digi_sounds();
362 int digi_get_max_channels() {
363 return digi_max_channels;
367 void digi_reset_digi_sounds() {
370 for (i=0; i< MAX_SOUND_SLOTS; i++) {
371 DS_release_slot(i, 1);
374 //added on 980905 by adb to reset sound kill system
375 memset(SampleHandles, 255, sizeof(SampleHandles));
380 int digi_is_channel_playing(int channel)
382 if (!digi_initialised)
385 return SoundSlots[channel].playing;
388 void digi_set_channel_volume(int channel, int volume)
390 if (!digi_initialised)
393 if (!SoundSlots[channel].playing)
396 SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0);
399 void digi_set_channel_pan(int channel, int pan)
401 if (!digi_initialised)
404 if (!SoundSlots[channel].playing)
407 SoundSlots[channel].pan = pan;
410 void digi_stop_sound(int channel)
412 SoundSlots[channel].playing=0;
413 SoundSlots[channel].soundobj = -1;
414 SoundSlots[channel].persistent = 0;
417 void digi_end_sound(int channel)
419 if (!digi_initialised)
422 if (!SoundSlots[channel].playing)
425 SoundSlots[channel].soundobj = -1;
426 SoundSlots[channel].persistent = 0;
430 int digi_midi_song_playing = 0;
431 static int digi_initialised = 0;
432 int midi_volume = 255;
434 int digi_get_settings() { return 0; }
435 int digi_init() { digi_initialised = 1; return 0; }
439 void digi_set_digi_volume( int dvolume ) {}
440 void digi_set_volume( int dvolume, int mvolume ) {}
442 int digi_is_sound_playing(int soundno) { return 0; }
444 void digi_set_max_channels(int n) {}
445 int digi_get_max_channels() { return 0; }
450 // MIDI stuff follows.
452 void digi_stop_current_song()
454 if ( digi_midi_song_playing ) {
457 digi_midi_song_playing = 0;
461 void digi_set_midi_volume( int n )
472 // scale up from 0-127 to 0-0xffff
473 mm_volume = (midi_volume << 1) | (midi_volume & 1);
474 mm_volume |= (mm_volume << 8);
477 midiOutSetVolume((HMIDIOUT)hmp->hmidi, mm_volume | mm_volume << 16);
480 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop )
482 if (!digi_initialised) return;
484 digi_stop_current_song();
486 //added on 5/20/99 by Victor Rachels to fix crash/etc
487 if(filename == NULL) return;
488 if(midi_volume < 1) return;
489 //end this section addition - VR
491 if ((hmp = hmp_open(filename))) {
493 digi_midi_song_playing = 1;
494 digi_set_midi_volume(midi_volume);
497 printf("hmp_open failed\n");
499 void digi_pause_midi() {}
500 void digi_resume_midi() {}
503 void digi_stop_current_song() {}
504 void digi_set_midi_volume( int n ) {}
505 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
506 void digi_pause_midi() {}
507 void digi_resume_midi() {}
516 if (!digi_initialised)
519 for (i = 0; i < digi_max_channels; i++)
521 if (digi_is_channel_playing(i))
525 mprintf_at((0, 2, 0, "DIGI: Active Sound Channels: %d/%d (HMI says %d/32) ", n_voices, digi_max_channels, -1));
526 //mprintf_at((0, 3, 0, "DIGI: Number locked sounds: %d ", digi_total_locks ));