2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
15 #pragma off (unreferenced)
16 static char rcsid[] = "$Id: ds.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $";
17 #pragma on (unreferenced)
19 #define WIN32_LEAN_AND_MEAN
34 // Samir's Hacked Musical Interface (HMI) mixer
36 struct SSMixerObject {
42 SSoundBuffer *ch_list;
43 } SSMixer = { NULL, 0, 0, 0, NULL };
46 long XlatSSToDSPan(unsigned short pan);
47 long XlatSSToDSVol(unsigned vol);
48 DWORD XlatSSToWAVVol(unsigned short vol);
49 unsigned short XlatWAVToSSVol(DWORD vol);
54 // ----------------------------------------------------------------------------
56 BOOL SSInit(HWND hWnd, int channels, unsigned flags)
58 LPDIRECTSOUNDBUFFER lpPrimaryBuffer;
62 if (SSMixer.lpds) return TRUE;
64 // Perform Direct Sound Initialization
65 if (DirectSoundCreate(NULL, &lpDS, NULL) != DS_OK)
70 if (IDirectSound_SetCooperativeLevel(lpDS, hWnd, DSSCL_NORMAL) != DS_OK) {
76 memset(&dsbd, 0, sizeof(DSBUFFERDESC));
77 dsbd.dwSize = sizeof(DSBUFFERDESC);
78 dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
79 if (IDirectSound_CreateSoundBuffer(SSMixer.lpds, &dsbd, &lpPrimaryBuffer, NULL) == DS_OK) {
80 if (IDirectSoundBuffer_Play(lpPrimaryBuffer, 0, 0, DSBPLAY_LOOPING) != DS_OK) {
81 IDirectSoundBuffer_Release(lpPrimaryBuffer);
85 IDirectSoundBuffer_Release(lpPrimaryBuffer);
93 // Finish initializing SSMixer.
95 SSMixer.ch_list = (SSoundBuffer *)malloc(sizeof(SSoundBuffer)*channels);
96 if (!SSMixer.ch_list) return FALSE;
98 memset(SSMixer.ch_list, 0, sizeof(SSoundBuffer)*channels);
100 SSMixer.ch_num = channels;
102 // Determine Sound technology and volume caps
103 waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, (LPDWORD)&SSMixer.old_master_vol);
104 // waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, 0x40004000);
114 if (!SSMixer.lpds) return;
116 // Free sound buffers currently allocated.
117 for (i=0; i<SSMixer.ch_num; i++)
118 if (SSMixer.ch_list[i].obj) {
120 IDirectSoundBuffer_Release(SSMixer.ch_list[i].obj);
123 if (j) mprintf((1, "SS: Releasing %d sound buffers!\n", j));
124 free(SSMixer.ch_list);
126 // Restore old WAV volume
127 waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, SSMixer.old_master_vol);
129 // Turn off DirectSound
130 if (SSMixer.lpds) IDirectSound_Release(SSMixer.lpds);
132 memset(&SSMixer, 0, sizeof(SSMixer));
136 LPDIRECTSOUND SSGetObject()
142 void SSGetCaps(SSCaps *caps)
146 dscaps.dwSize = sizeof(DSCAPS);
147 IDirectSound_GetCaps(SSMixer.lpds, &dscaps);
149 if ((dscaps.dwFlags&DSCAPS_SECONDARY16BIT)) caps->bits_per_sample = 16;
150 else caps->bits_per_sample = 8;
152 caps->sample_rate = dscaps.dwMaxSecondarySampleRate;
156 void SSSetVolume(DWORD vol)
158 vol = XlatSSToWAVVol((WORD)vol);
159 waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, vol);
167 waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &vol);
169 return XlatWAVToSSVol(vol);
175 // Must Create a DirectSound Secondary Buffer for the sound info.
177 BOOL SSInitBuffer(SSoundBuffer *sample)
185 DWORD writesize1, writesize2;
187 char *auxdata, *aux2data;
189 int auxlength, aux2length;
192 length = sample->length;
194 // Separate buffer into two for looping effects.
195 if (sample->looping) {
196 if (sample->loop_start > -1) {
197 auxdata = sample->data + sample->loop_start;
198 length = sample->loop_start;
199 auxlength = sample->loop_end - sample->loop_start;
200 aux2data = sample->data + sample->loop_end;
201 aux2length = sample->length - sample->loop_end;
205 // Create sound buffer
207 sample->auxobj = NULL;
208 sample->auxobj2 = NULL;
210 wav.wFormatTag = WAVE_FORMAT_PCM;
211 wav.nChannels = sample->channels;
212 wav.nSamplesPerSec = sample->rate;
213 wav.nBlockAlign = (sample->channels * sample->bits_per_sample) >> 3;
214 wav.nAvgBytesPerSec = wav.nBlockAlign * wav.nSamplesPerSec;
215 wav.wBitsPerSample = sample->bits_per_sample;
217 memset(&dsbd, 0, sizeof(dsbd));
218 dsbd.dwSize = sizeof(dsbd);
219 dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLDEFAULT;
220 dsbd.lpwfxFormat = &wav;
221 dsbd.dwBufferBytes = length;
223 if (IDirectSound_CreateSoundBuffer(SSMixer.lpds, &dsbd, &sample->obj, NULL)
228 // Copy main data to buffer
230 dsresult = IDirectSoundBuffer_Lock(sample->obj, 0, length, &databuf,
231 &writesize1, &databuf2, &writesize2, 0);
233 if (dsresult != DS_OK) return FALSE;
234 memcpy(databuf, data, writesize1);
235 if (databuf2) memcpy(databuf2, data+writesize1, writesize2);
237 IDirectSoundBuffer_Unlock(sample->obj, databuf, writesize1, databuf2, writesize2);
240 // Take care of looping buffer
241 if (sample->looping && sample->loop_start>-1) {
242 memset(&dsbd, 0, sizeof(dsbd));
244 wav.wFormatTag = WAVE_FORMAT_PCM;
245 wav.nChannels = sample->channels;
246 wav.nSamplesPerSec = sample->rate;
247 wav.nBlockAlign = (sample->channels * sample->bits_per_sample) >> 3;
248 wav.nAvgBytesPerSec = wav.nBlockAlign * wav.nSamplesPerSec;
249 wav.wBitsPerSample = sample->bits_per_sample;
251 dsbd.dwSize = sizeof(dsbd);
252 dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLDEFAULT;
253 dsbd.lpwfxFormat = &wav;
254 dsbd.dwBufferBytes = auxlength;
256 if (IDirectSound_CreateSoundBuffer(SSMixer.lpds, &dsbd, &sample->auxobj, NULL)
258 mprintf((1, "SS: Unable to create aux-buffer.\n"));
262 dsresult = IDirectSoundBuffer_Lock(sample->auxobj, 0, auxlength, &databuf,
263 &writesize1, &databuf2, &writesize2, 0);
265 if (dsresult != DS_OK) return FALSE;
266 memcpy(databuf, auxdata, writesize1);
267 if (databuf2) memcpy(databuf2, auxdata+writesize1, writesize2);
269 IDirectSoundBuffer_Unlock(sample->auxobj, databuf, writesize1, databuf2, writesize2);
271 //@@ memset(&dsbd, 0, sizeof(dsbd));
273 //@@ wav.wFormatTag = WAVE_FORMAT_PCM;
274 //@@ wav.nChannels = sample->channels;
275 //@@ wav.nSamplesPerSec = sample->rate;
276 //@@ wav.nBlockAlign = (sample->channels * sample->bits_per_sample) >> 3;
277 //@@ wav.nAvgBytesPerSec = wav.nBlockAlign * wav.nSamplesPerSec;
278 //@@ wav.wBitsPerSample = sample->bits_per_sample;
280 //@@ dsbd.dwSize = sizeof(dsbd);
281 //@@ dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLDEFAULT;
282 //@@ dsbd.lpwfxFormat = &wav;
283 //@@ dsbd.dwBufferBytes = aux2length;
285 //@@ if (IDirectSound_CreateSoundBuffer(SSMixer.lpds, &dsbd, &sample->auxobj2, NULL)
287 //@@ mprintf((1, "SS: Unable to create aux-buffer.\n"));
291 //@@ dsresult = IDirectSoundBuffer_Lock(sample->auxobj2, 0, aux2length, &databuf,
292 //@@ &writesize1, &databuf2, &writesize2, 0);
294 //@@ if (dsresult != DS_OK) return FALSE;
295 //@@ memcpy(databuf, aux2data, writesize1);
296 //@@ if (databuf2) memcpy(databuf2, aux2data+writesize1, writesize2);
298 //@@ IDirectSoundBuffer_Unlock(sample->auxobj2, databuf, writesize1, databuf2, writesize2);
306 void SSDestroyBuffer(SSoundBuffer *sample)
308 if (sample->obj) IDirectSoundBuffer_Release(sample->obj);
309 if (sample->auxobj) IDirectSoundBuffer_Release(sample->auxobj);
310 if (sample->auxobj2) IDirectSoundBuffer_Release(sample->auxobj2);
312 sample->auxobj = NULL;
313 sample->auxobj2 = NULL;
317 int SSInitChannel(SSoundBuffer *sample)
320 int start_channel, this_channel;
321 LPDIRECTSOUNDBUFFER lpdsb;
325 start_channel = SSMixer.ch_cur;
329 if (!SSMixer.ch_list[SSMixer.ch_cur].obj)
331 else if (!SSChannelPlaying(SSMixer.ch_cur)) {
332 SSDestroyBuffer(&SSMixer.ch_list[SSMixer.ch_cur]);
336 if (SSMixer.ch_cur >= SSMixer.ch_num) SSMixer.ch_cur=0;
337 if (SSMixer.ch_cur == start_channel) return -1;
340 // Create sound object for mixer.
343 if (sample->looping) {
344 if (sample->loop_start == -1) {
345 flags = DSBPLAY_LOOPING;
346 // mprintf((0,"SS: looping sample (%d).\n", sample->loop_start));
350 if (!SSInitBuffer(sample)) return -1;
352 // Set up mixing parameters
354 IDirectSoundBuffer_SetVolume(lpdsb, XlatSSToDSVol(sample->vol));
355 IDirectSoundBuffer_SetPan(lpdsb, XlatSSToDSPan(sample->pan));
357 // Mix in main sound object.
358 dsresult = IDirectSoundBuffer_Play(lpdsb, 0, 0, flags);
359 if (dsresult != DS_OK) return -1;
361 // Mix in auxillary object (loop portion)
362 lpdsb = sample->auxobj;
364 if (sample->looping) flags = DSBPLAY_LOOPING;
365 IDirectSoundBuffer_SetVolume(lpdsb, XlatSSToDSVol(sample->vol));
366 IDirectSoundBuffer_SetPan(lpdsb, XlatSSToDSPan(sample->pan));
368 dsresult = IDirectSoundBuffer_Play(lpdsb, 0, 0, flags);
369 if (dsresult != DS_OK) return -1;
370 mprintf((0, "SS: looping midsample (%d).\n", sample->loop_start));
373 // Add to mixer list.
374 this_channel = SSMixer.ch_cur;
375 memcpy(&SSMixer.ch_list[SSMixer.ch_cur++], sample, sizeof(SSoundBuffer));
376 if (SSMixer.ch_cur >= SSMixer.ch_num) SSMixer.ch_cur = 0;
382 BOOL SSChannelPlaying(int channel)
390 if (SSMixer.ch_list[i].obj) {
391 dsresult = IDirectSoundBuffer_GetStatus(SSMixer.ch_list[i].obj,
393 if (dsresult != DS_OK) return FALSE;
394 if (status & DSBSTATUS_PLAYING) {
398 if (SSMixer.ch_list[i].auxobj) {
399 dsresult = IDirectSoundBuffer_GetStatus(SSMixer.ch_list[i].auxobj,
401 if (dsresult != DS_OK) return FALSE;
402 if (status & DSBSTATUS_PLAYING) {
411 BOOL SSStopChannel(int channel)
413 if (SSMixer.ch_list[channel].obj) {
414 if (SSMixer.ch_list[channel].auxobj) {
415 IDirectSoundBuffer_Stop(SSMixer.ch_list[channel].auxobj);
416 mprintf((0, "DS: stopping midsample looping!\n"));
419 if (IDirectSoundBuffer_Stop(SSMixer.ch_list[channel].obj) != DS_OK) {
423 SSDestroyBuffer(&SSMixer.ch_list[channel]);
430 BOOL SSSetChannelPan(int channel, unsigned short pan)
437 if (SSMixer.ch_list[i].obj) {
438 dsresult = IDirectSoundBuffer_SetPan(SSMixer.ch_list[i].obj,
440 if (dsresult != DS_OK) return FALSE;
448 BOOL SSSetChannelVolume(int channel, unsigned short vol)
455 if (SSMixer.ch_list[i].obj) {
456 dsresult = IDirectSoundBuffer_SetVolume(SSMixer.ch_list[i].obj,
458 if (dsresult != DS_OK) return FALSE;
466 // ----------------------------------------------------------------------------
468 long XlatSSToDSPan(unsigned short pan)
473 pan1 = fixdiv(pan,0x8000);
474 pan2 = fixmul(pan1, i2f(10000));
476 panr = (long)f2i(pan2);
483 long XlatSSToDSVol(unsigned vol)
488 atten = 32768.0 / ((float)(vol));
489 fvol = log(atten) / log(2.0);
490 fvol = -1.0 * (fvol * 1000.0);
492 if (fvol < -10000.0) fvol = -10000.0;
493 if (fvol > 0.0) fvol = 0.0;
499 DWORD XlatSSToWAVVol(unsigned short vol)
508 unsigned short XlatWAVToSSVol(DWORD vol)
512 return (WORD)(wvol/2);