]> icculus.org git repositories - btb/d2x.git/blob - unused/win95/ds.c
use the orientation parameter of g3_draw_bitmap
[btb/d2x.git] / unused / win95 / ds.c
1 /*
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.
12 */
13
14
15 #define WIN32_LEAN_AND_MEAN
16 #define _WIN32
17 #define WIN95
18 #include <windows.h>
19 #include <mmsystem.h>
20
21 #include <stdlib.h>
22 #include <math.h>
23 #include <mem.h>
24
25 #include "fix.h"
26 #include        "ds.h"
27 #include "mono.h"
28
29
30 //      Samir's Hacked Musical Interface (HMI) mixer
31
32 struct SSMixerObject {
33         LPDIRECTSOUND lpds;
34         DWORD old_master_vol;
35         int active;
36         int ch_num;
37         int ch_cur;
38         SSoundBuffer *ch_list;
39 } SSMixer = { NULL, 0, 0, 0, NULL };            
40
41
42 long XlatSSToDSPan(unsigned short pan);
43 long XlatSSToDSVol(unsigned vol);
44 DWORD XlatSSToWAVVol(unsigned short vol);
45 unsigned short XlatWAVToSSVol(DWORD vol);
46
47
48
49 //      Functions
50 //      ----------------------------------------------------------------------------
51
52 BOOL SSInit(HWND hWnd, int channels, unsigned flags)
53 {
54         LPDIRECTSOUNDBUFFER lpPrimaryBuffer;
55         LPDIRECTSOUND lpDS;
56         DSBUFFERDESC dsbd;
57
58         if (SSMixer.lpds) return TRUE;
59
60 //      Perform Direct Sound Initialization
61         if (DirectSoundCreate(NULL, &lpDS, NULL) != DS_OK) 
62                 return FALSE;
63
64         SSMixer.lpds = lpDS;
65
66         if (IDirectSound_SetCooperativeLevel(lpDS, hWnd, DSSCL_NORMAL) != DS_OK) {
67                 SSDestroy();
68                 return FALSE;
69         }
70
71 //      Start Mixer
72         memset(&dsbd, 0, sizeof(DSBUFFERDESC));
73         dsbd.dwSize = sizeof(DSBUFFERDESC);
74         dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
75         if (IDirectSound_CreateSoundBuffer(SSMixer.lpds, &dsbd, &lpPrimaryBuffer, NULL) == DS_OK) {
76                 if (IDirectSoundBuffer_Play(lpPrimaryBuffer, 0, 0, DSBPLAY_LOOPING) != DS_OK) {
77                         IDirectSoundBuffer_Release(lpPrimaryBuffer);
78                         SSDestroy();
79                         return FALSE;
80                 }
81                 IDirectSoundBuffer_Release(lpPrimaryBuffer);
82         }
83         else {
84                 SSDestroy();
85                 return FALSE;
86         }
87
88
89 //      Finish initializing SSMixer.
90         SSMixer.ch_cur = 0;
91         SSMixer.ch_list = (SSoundBuffer *)malloc(sizeof(SSoundBuffer)*channels);
92         if (!SSMixer.ch_list) return FALSE;
93         
94         memset(SSMixer.ch_list, 0, sizeof(SSoundBuffer)*channels);
95         
96         SSMixer.ch_num = channels;
97
98 //      Determine Sound technology and volume caps
99         waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, (LPDWORD)&SSMixer.old_master_vol);
100 //      waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, 0x40004000);
101         return TRUE;
102 }
103                 
104                 
105 void SSDestroy()
106 {
107         int i;
108         int j = 0;
109
110         if (!SSMixer.lpds) return;
111         
112 //      Free sound buffers currently allocated.
113         for (i=0; i<SSMixer.ch_num; i++)
114                 if (SSMixer.ch_list[i].obj) {
115                         j++;
116                         IDirectSoundBuffer_Release(SSMixer.ch_list[i].obj);
117                 }
118
119         if (j) mprintf((1, "SS: Releasing %d sound buffers!\n", j));
120         free(SSMixer.ch_list);
121
122 //      Restore old WAV volume
123         waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, SSMixer.old_master_vol);
124
125 //      Turn off DirectSound
126         if (SSMixer.lpds) IDirectSound_Release(SSMixer.lpds);
127         
128         memset(&SSMixer, 0, sizeof(SSMixer));
129
130
131
132 LPDIRECTSOUND SSGetObject()
133 {
134         return SSMixer.lpds;
135 }
136
137
138 void SSGetCaps(SSCaps *caps)
139 {
140         DSCAPS dscaps;
141
142         dscaps.dwSize = sizeof(DSCAPS);
143         IDirectSound_GetCaps(SSMixer.lpds, &dscaps);
144         
145         if ((dscaps.dwFlags&DSCAPS_SECONDARY16BIT)) caps->bits_per_sample = 16;
146         else caps->bits_per_sample = 8;
147
148         caps->sample_rate = dscaps.dwMaxSecondarySampleRate;
149 }
150
151
152 void SSSetVolume(DWORD vol)
153 {
154         vol = XlatSSToWAVVol((WORD)vol);
155         waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, vol);
156 }
157
158
159 WORD SSGetVolume()
160 {
161         DWORD vol;
162
163         waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &vol);
164         
165         return XlatWAVToSSVol(vol);
166 }
167  
168         
169
170 //      SSInitBuffer
171 //              Must Create a DirectSound Secondary Buffer for the sound info.
172
173 BOOL SSInitBuffer(SSoundBuffer *sample)
174 {
175         
176         DSBUFFERDESC dsbd;
177         WAVEFORMATEX wav;
178         HRESULT dsresult;
179         LPVOID databuf;
180         LPVOID databuf2;
181         DWORD writesize1, writesize2;
182         char *data;
183         char *auxdata, *aux2data;
184         int length;
185         int auxlength, aux2length;
186
187         data = sample->data;
188         length = sample->length;
189
190 //      Separate buffer into two for looping effects.
191         if (sample->looping) {
192                 if (sample->loop_start > -1) {
193                         auxdata = sample->data + sample->loop_start;
194                         length = sample->loop_start;
195                         auxlength = sample->loop_end - sample->loop_start;
196                         aux2data        = sample->data + sample->loop_end;
197                         aux2length = sample->length - sample->loop_end;
198                 }
199         }
200
201 //      Create sound buffer
202         sample->obj = NULL;
203         sample->auxobj = NULL;
204         sample->auxobj2 = NULL;
205
206         wav.wFormatTag = WAVE_FORMAT_PCM;
207         wav.nChannels = sample->channels;
208         wav.nSamplesPerSec = sample->rate;
209         wav.nBlockAlign = (sample->channels * sample->bits_per_sample) >> 3;
210         wav.nAvgBytesPerSec = wav.nBlockAlign * wav.nSamplesPerSec;
211         wav.wBitsPerSample = sample->bits_per_sample;
212
213         memset(&dsbd, 0, sizeof(dsbd));
214         dsbd.dwSize = sizeof(dsbd);
215         dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLDEFAULT;
216         dsbd.lpwfxFormat = &wav;
217         dsbd.dwBufferBytes = length;
218         
219         if (IDirectSound_CreateSoundBuffer(SSMixer.lpds, &dsbd, &sample->obj, NULL)  
220                         != DS_OK) {
221                 return FALSE;
222         }
223
224 //      Copy main data to buffer
225         if (data) {
226                 dsresult = IDirectSoundBuffer_Lock(sample->obj, 0, length, &databuf,            
227                                                                         &writesize1, &databuf2, &writesize2, 0); 
228                 {
229                         if (dsresult != DS_OK) return FALSE;
230                         memcpy(databuf, data, writesize1);
231                         if (databuf2) memcpy(databuf2, data+writesize1, writesize2);
232                 }
233                 IDirectSoundBuffer_Unlock(sample->obj, databuf, writesize1, databuf2, writesize2);
234         }
235
236 //      Take care of looping buffer
237         if (sample->looping && sample->loop_start>-1) {
238                 memset(&dsbd, 0, sizeof(dsbd));
239
240                 wav.wFormatTag = WAVE_FORMAT_PCM;
241                 wav.nChannels = sample->channels;
242                 wav.nSamplesPerSec = sample->rate;
243                 wav.nBlockAlign = (sample->channels * sample->bits_per_sample) >> 3;
244                 wav.nAvgBytesPerSec = wav.nBlockAlign * wav.nSamplesPerSec;
245                 wav.wBitsPerSample = sample->bits_per_sample;
246
247                 dsbd.dwSize = sizeof(dsbd);
248                 dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLDEFAULT;
249                 dsbd.lpwfxFormat = &wav;
250                 dsbd.dwBufferBytes = auxlength;
251         
252                 if (IDirectSound_CreateSoundBuffer(SSMixer.lpds, &dsbd, &sample->auxobj, NULL)  
253                         != DS_OK) {
254                         mprintf((1, "SS: Unable to create aux-buffer.\n"));
255                         return FALSE;
256                 }
257
258                 dsresult = IDirectSoundBuffer_Lock(sample->auxobj, 0, auxlength, &databuf,              
259                                                                         &writesize1, &databuf2, &writesize2, 0); 
260                 {
261                         if (dsresult != DS_OK) return FALSE;
262                         memcpy(databuf, auxdata, writesize1);
263                         if (databuf2) memcpy(databuf2, auxdata+writesize1, writesize2);
264                 }
265                 IDirectSoundBuffer_Unlock(sample->auxobj, databuf, writesize1, databuf2, writesize2);
266
267 //@@            memset(&dsbd, 0, sizeof(dsbd));
268 //@@
269 //@@            wav.wFormatTag = WAVE_FORMAT_PCM;
270 //@@            wav.nChannels = sample->channels;
271 //@@            wav.nSamplesPerSec = sample->rate;
272 //@@            wav.nBlockAlign = (sample->channels * sample->bits_per_sample) >> 3;
273 //@@            wav.nAvgBytesPerSec = wav.nBlockAlign * wav.nSamplesPerSec;
274 //@@            wav.wBitsPerSample = sample->bits_per_sample;
275 //@@
276 //@@            dsbd.dwSize = sizeof(dsbd);
277 //@@            dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLDEFAULT;
278 //@@            dsbd.lpwfxFormat = &wav;
279 //@@            dsbd.dwBufferBytes = aux2length;
280 //@@    
281 //@@            if (IDirectSound_CreateSoundBuffer(SSMixer.lpds, &dsbd, &sample->auxobj2, NULL)  
282 //@@                    != DS_OK) {
283 //@@                    mprintf((1, "SS: Unable to create aux-buffer.\n"));
284 //@@                    return FALSE;
285 //@@            }
286 //@@
287 //@@            dsresult = IDirectSoundBuffer_Lock(sample->auxobj2, 0, aux2length, &databuf,            
288 //@@                                                                    &writesize1, &databuf2, &writesize2, 0); 
289 //@@            {
290 //@@                    if (dsresult != DS_OK) return FALSE;
291 //@@                    memcpy(databuf, aux2data, writesize1);
292 //@@                    if (databuf2) memcpy(databuf2, aux2data+writesize1, writesize2);
293 //@@            }
294 //@@            IDirectSoundBuffer_Unlock(sample->auxobj2, databuf, writesize1, databuf2, writesize2);
295
296         }                                                                                                
297
298         return TRUE;
299 }
300
301
302 void SSDestroyBuffer(SSoundBuffer *sample)
303 {
304         if (sample->obj) IDirectSoundBuffer_Release(sample->obj);
305         if (sample->auxobj) IDirectSoundBuffer_Release(sample->auxobj);
306         if (sample->auxobj2) IDirectSoundBuffer_Release(sample->auxobj2);
307         sample->obj = NULL;
308         sample->auxobj = NULL;
309         sample->auxobj2 = NULL;
310 }       
311
312
313 int SSInitChannel(SSoundBuffer *sample)
314 {
315         HRESULT dsresult;
316         int start_channel, this_channel;
317         LPDIRECTSOUNDBUFFER lpdsb;
318         DWORD flags;
319
320 //      Find Free channel
321         start_channel = SSMixer.ch_cur;
322         
323         while (1)
324         {
325                 if (!SSMixer.ch_list[SSMixer.ch_cur].obj) 
326                         break;
327                 else if (!SSChannelPlaying(SSMixer.ch_cur)) {
328                         SSDestroyBuffer(&SSMixer.ch_list[SSMixer.ch_cur]);
329                         break;
330                 }
331                 SSMixer.ch_cur++;
332                 if (SSMixer.ch_cur >= SSMixer.ch_num) SSMixer.ch_cur=0;
333                 if (SSMixer.ch_cur == start_channel) return -1;
334         }
335   
336 //      Create sound object for mixer.          
337         flags = 0;
338
339         if (sample->looping) {
340                 if (sample->loop_start == -1) {
341                         flags = DSBPLAY_LOOPING;
342 //                      mprintf((0,"SS: looping sample (%d).\n", sample->loop_start));
343                 }
344         }
345
346         if (!SSInitBuffer(sample)) return -1;
347
348 //      Set up mixing parameters
349         lpdsb = sample->obj;
350         IDirectSoundBuffer_SetVolume(lpdsb, XlatSSToDSVol(sample->vol));
351         IDirectSoundBuffer_SetPan(lpdsb, XlatSSToDSPan(sample->pan));
352
353 //      Mix in main sound object.
354         dsresult = IDirectSoundBuffer_Play(lpdsb, 0, 0, flags);
355         if (dsresult != DS_OK) return -1;
356
357 //      Mix in auxillary object (loop portion)
358         lpdsb = sample->auxobj;
359         if (lpdsb) {
360                 if (sample->looping) flags = DSBPLAY_LOOPING;
361                 IDirectSoundBuffer_SetVolume(lpdsb, XlatSSToDSVol(sample->vol));
362                 IDirectSoundBuffer_SetPan(lpdsb, XlatSSToDSPan(sample->pan));
363
364                 dsresult = IDirectSoundBuffer_Play(lpdsb, 0, 0, flags);
365                 if (dsresult != DS_OK) return -1;
366                 mprintf((0, "SS: looping midsample (%d).\n", sample->loop_start));
367         }
368         
369 //      Add to mixer list.
370         this_channel = SSMixer.ch_cur;
371         memcpy(&SSMixer.ch_list[SSMixer.ch_cur++], sample, sizeof(SSoundBuffer));
372         if (SSMixer.ch_cur >= SSMixer.ch_num) SSMixer.ch_cur = 0; 
373
374         return this_channel;
375 }
376
377
378 BOOL SSChannelPlaying(int channel)
379 {
380         HRESULT dsresult;
381         DWORD status;
382         int i;
383
384         i = channel;
385
386         if (SSMixer.ch_list[i].obj) {
387                 dsresult = IDirectSoundBuffer_GetStatus(SSMixer.ch_list[i].obj,
388                                                         &status);
389                 if (dsresult != DS_OK) return FALSE;
390                 if (status & DSBSTATUS_PLAYING) {
391                         return TRUE;
392                 }
393
394                 if (SSMixer.ch_list[i].auxobj) {
395                         dsresult = IDirectSoundBuffer_GetStatus(SSMixer.ch_list[i].auxobj, 
396                                                                                                                         &status);
397                         if (dsresult != DS_OK) return FALSE;
398                         if (status & DSBSTATUS_PLAYING) {
399                                 return TRUE;
400                         }
401                 } 
402         }
403         return FALSE;
404 }
405                 
406
407 BOOL SSStopChannel(int channel)
408 {
409         if (SSMixer.ch_list[channel].obj) {
410                 if (SSMixer.ch_list[channel].auxobj) {
411                         IDirectSoundBuffer_Stop(SSMixer.ch_list[channel].auxobj);
412                         mprintf((0, "DS: stopping midsample looping!\n"));
413                 }
414
415                 if (IDirectSoundBuffer_Stop(SSMixer.ch_list[channel].obj) != DS_OK) {
416                         return TRUE;
417                 }
418                 
419                 SSDestroyBuffer(&SSMixer.ch_list[channel]);
420         }
421
422         return TRUE;
423 }
424
425
426 BOOL SSSetChannelPan(int channel, unsigned short pan)
427 {
428         HRESULT dsresult;
429         int i;
430
431         i = channel;
432
433         if (SSMixer.ch_list[i].obj) {
434                 dsresult = IDirectSoundBuffer_SetPan(SSMixer.ch_list[i].obj,
435                                                         XlatSSToDSPan(pan));
436                 if (dsresult != DS_OK) return FALSE;
437                 return TRUE;
438                 
439         }
440         return FALSE;
441 }       
442
443
444 BOOL SSSetChannelVolume(int channel, unsigned short vol)
445 {
446         HRESULT dsresult;
447         int i;
448
449         i = channel;
450
451         if (SSMixer.ch_list[i].obj) {
452                 dsresult = IDirectSoundBuffer_SetVolume(SSMixer.ch_list[i].obj,
453                                                         XlatSSToDSVol(vol));
454                 if (dsresult != DS_OK) return FALSE;
455                 return TRUE;
456                 
457         }
458         return FALSE;
459 }       
460
461
462 //      ----------------------------------------------------------------------------
463
464 long XlatSSToDSPan(unsigned short pan)
465 {
466         fix pan1, pan2;
467         long panr;
468
469         pan1 = fixdiv(pan,0x8000);
470         pan2 = fixmul(pan1, i2f(10000));
471                 
472         panr = (long)f2i(pan2);
473         panr = -10000+panr;
474         
475         return panr;
476 }
477
478
479 long XlatSSToDSVol(unsigned vol)
480 {
481         float atten;
482         float fvol;     
483
484         atten = 32768.0 / ((float)(vol));
485         fvol = log(atten) / log(2.0);
486         fvol = -1.0 * (fvol * 1000.0);
487
488         if (fvol < -10000.0) fvol = -10000.0;
489         if (fvol > 0.0) fvol = 0.0;
490
491         return (int)(fvol);
492 }
493
494
495 DWORD XlatSSToWAVVol(unsigned short vol)
496 {
497         DWORD dw;
498         vol=vol*2;
499         dw = (vol<<16)+vol;
500         return (long)dw;
501 }
502
503
504 unsigned short XlatWAVToSSVol(DWORD vol)
505 {
506         WORD wvol;
507         wvol = (WORD)vol;
508         return (WORD)(wvol/2);
509 }