1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // Copyright (C) 2001 by DooM Legacy Team.
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //-----------------------------------------------------------------------------
16 /// \file
17 /// \brief General driver for 3D sound system
18 ///
19 ///	Implementend via DirectSound3D API
20 
21 #define INITGUID
22 //#define WIN32_LEAN_AND_MEAN
23 #define RPC_NO_WINDOWS_H
24 #include <windows.h>
25 #include <cguid.h>
26 #define DIRECTSOUND_VERSION  0x0700       /* version 7.0 */
27 
28 #ifdef __MINGW32__
29 #define NONAMELESSUNION
30 #endif
31 #include <dsound.h>
32 
33 #if (defined (DIRECTSOUND_VERSION) && (DIRECTSOUND_VERSION >= 0x0700))
34 #define DX7 //Enable DX7 or up  only code
35 #undef DUMMYUNIONNAMEN
36 #endif
37 
38 #ifdef __MINGW32__
39 //#undef DX7
40 #endif
41 
42 #define  _CREATE_DLL_
43 #include "../hw3dsdrv.h"
44 #include "../../m_fixed.h"
45 #include "../../doomdef.h"
46 //#define VERSIONSTRING "v1.08"
47 
48 #undef DEBUG_TO_FILE
49 #define DEBUG_TO_FILE
50 
51 #if defined ( HAVE_SDL ) && !defined ( LOGMESSAGES )
52 #undef DEBUG_TO_FILE
53 #endif
54 
55 
56 // Internal sound stack
57 typedef struct stack_snd_s
58 {
59 	// Sound data
60 	LPDIRECTSOUNDBUFFER     dsbuffer;
61 
62 	// 3D data of 3D source
63 	LPDIRECTSOUND3DBUFFER   dsbuffer3D;     // 3D data
64 
65 	// Current parameters of 3D source
66 	// Valid only when source is 3D source
67 	// (dsbuffer3D is not NULL)
68 	DS3DBUFFER              parameters;
69 
70 	// Currently unused
71 	INT32                     sfx_id;
72 
73 	// Currently unused
74 	INT32                     LRU;
75 
76 	// Flag of static source
77 	// Driver does not manage intrenally such sources
78 	INT32                     permanent;
79 
80 } stack_t;
81 
82 // Just for now...
83 #define SOUND_ALLOCATE_DELTA    16       // Amount of sources per stack incrementation
84 #define MAX_LRU                 16       // Maximum iterations to keep source in stack
85 
86 static stack_t  *_stack;                 // Sound stack
87 static INT32      allocated_sounds;        // Size of stack
88 
89 static INT32      srate;                   // Default sample rate
90 
91 
92 // output all debugging messages to this file
93 #if defined (DEBUG_TO_FILE)
94 #include <stdio.h>
95 FILE *logstream = NULL;
96 #endif
97 
98 static LPDIRECTSOUND            DSnd            = NULL;  // Main DirectSound object
99 static LPDIRECTSOUNDBUFFER      PrimaryBuffer   = NULL;  //
100 static LPDIRECTSOUND3DLISTENER  Listener        = NULL;  //
101 
102 static DS3DLISTENER             listener_parms;          // Listener papameters
103 
104 #ifdef DX7
105 static BOOL                     virtualization;          // TRUE if HRTF virtualization enabled
106 #endif
107 
108 static DWORD                    update_mode;             // Current update mode of listener
109 //static DWORD                    max_3d_buffers;
110 
111 static I_Error_t I_ErrorDS3D = NULL;
112 
113 //static stack_snd_t sound_stack[MAX_SOUNDS];
114 
115 // Safe buffer release
116 #define RELEASE_BUFFER(buf)     {if (buf) { IDirectSoundBuffer_Release(buf); (buf) = NULL; }}
117 #define RELEASE_3DBUFFER(buf)   {if (buf) { IDirectSound3DBuffer_Release(buf); (buf) = NULL; }}
118 
119 // Default flags for buffers
120 #define _2DSOURCE_FLAGS (DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_STICKYFOCUS | DSBCAPS_STATIC | DSBCAPS_CTRLFREQUENCY)
121 #define _3DSOURCE_FLAGS (DSBCAPS_CTRL3D | DSBCAPS_STATIC | DSBCAPS_MUTE3DATMAXDISTANCE | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY)
122 
123 
124 enum {IS_2DSOURCE = 0, IS_3DSOURCE = 1};
125 
126 #define NEW_HANDLE  -1
127 
128 #ifdef _WINDOWS
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)129 BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module
130                     DWORD fdwReason,    // reason for calling function
131                     LPVOID lpvReserved) // reserved
132 {
133 	// Perform actions based on the reason for calling
134 	UNREFERENCED_PARAMETER(lpvReserved);
135 	switch ( fdwReason )
136 	{
137 		case DLL_PROCESS_ATTACH:
138 			// Initialize once for each new process.
139 			// Return FALSE to fail DLL load.
140 #ifdef DEBUG_TO_FILE
141 			logstream = fopen("s_ds3d.log", "wt");
142 			if (logstream == NULL)
143 				return FALSE;
144 #endif
145 			DisableThreadLibraryCalls(hinstDLL);
146 			break;
147 
148 		case DLL_THREAD_ATTACH:
149 			// Do thread-specific initialization.
150 			break;
151 
152 		case DLL_THREAD_DETACH:
153 			// Do thread-specific cleanup.
154 			break;
155 
156 		case DLL_PROCESS_DETACH:
157 			// Perform any necessary cleanup.
158 #ifdef DEBUG_TO_FILE
159 			if (logstream)
160 			{
161 				fclose(logstream);
162 				logstream = NULL;
163 			}
164 #endif
165 			break;
166 	}
167 	return TRUE;  // Successful DLL_PROCESS_ATTACH.
168 }
169 #endif
170 
171 // **************************************************************************
172 //                                                                  FUNCTIONS
173 // **************************************************************************
174 
175 /***************************************************************
176  *
177  * DBG_Printf
178  * Output error messages to debug log if DEBUG_TO_FILE is defined,
179  * else do nothing
180  *
181  ***************************************************************
182  */
183 // -----------------+
184 // DBG_Printf       : Output error messages to debug log if DEBUG_TO_FILE is defined,
185 //                  : else do nothing
186 // Returns          :
187 // -----------------+
DBG_Printf(const char * lpFmt,...)188 void DBG_Printf(const char *lpFmt, ... )
189 {
190 #ifdef DEBUG_TO_FILE
191 	char    str[4096] = "";
192 	va_list arglist;
193 
194 	va_start(arglist, lpFmt);
195 	vsnprintf(str, 4096, lpFmt, arglist);
196 	va_end(arglist);
197 
198 	if (logstream)
199 		fwrite(str, strlen(str), 1, logstream);
200 #endif
201 }
202 
203 
204 /***************************************************************
205  *
206  * Grow intrenal sound stack by SOUND_ALLOCATE_DELTA amount
207  *
208  ***************************************************************
209  */
reallocate_stack(void)210 static BOOL reallocate_stack(void)
211 {
212 	stack_t *new_stack;
213 
214 	if (_stack)
215 		new_stack = realloc(_stack, sizeof (stack_t) * (allocated_sounds + SOUND_ALLOCATE_DELTA));
216 	else
217 		new_stack = malloc(sizeof (stack_t) * (allocated_sounds + SOUND_ALLOCATE_DELTA));
218 	if (new_stack)
219 	{
220 		_stack = new_stack;
221 		ZeroMemory(&_stack[allocated_sounds], SOUND_ALLOCATE_DELTA * sizeof (stack_t));
222 		allocated_sounds += SOUND_ALLOCATE_DELTA;
223 	}
224 	return (new_stack != NULL);
225 }
226 
227 
228 /***************************************************************
229  *
230  * Destroys source in stack
231  *
232  ***************************************************************
233  */
kill_sound(stack_t * snd)234 static void kill_sound(stack_t *snd)
235 {
236 	//stack_t *snd = _stack + handle;
237 
238 	if (snd->dsbuffer3D)
239 		RELEASE_3DBUFFER(snd->dsbuffer3D);
240 
241 	if (snd->dsbuffer)
242 		RELEASE_BUFFER(snd->dsbuffer);
243 
244 	ZeroMemory(snd, sizeof (stack_t));
245 }
246 
247 
248 /***************************************************************
249  *
250  * Returns TRUE if source currently playing
251  *
252  ***************************************************************
253  */
is_playing(stack_t * snd)254 static BOOL is_playing(stack_t *snd)
255 {
256 	DWORD               status;
257 	LPDIRECTSOUNDBUFFER dsbuffer = snd->dsbuffer;
258 
259 	if (dsbuffer == NULL)
260 		return 0;
261 
262 	IDirectSoundBuffer_GetStatus(dsbuffer, &status);
263 
264 	return (status & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING));
265 }
266 
267 
268 /***************************************************************
269  *
270  * Creates DirectSound buffer and fills with sound data
271  * NULL sound data pointer are valid (empty buffer
272  * will be created)
273  *
274  ***************************************************************
275  */
create_buffer(void * data,INT32 length,BOOL as3d)276 static LPDIRECTSOUNDBUFFER create_buffer (void *data, INT32 length, BOOL as3d)
277 {
278 	LPDIRECTSOUNDBUFFER dsbuffer;
279 	HRESULT             hr;
280 	WAVEFORMATEX        wfm;
281 	DSBUFFERDESC        dsbdesc;
282 	LPVOID              lpvAudio1; // receives address of lock start
283 	DWORD               dwBytes1;  // receives number of bytes locked
284 	LPVOID              lpvAudio2; // receives address of lock start
285 	DWORD               dwBytes2;  // receives number of bytes locked
286 
287 	ZeroMemory(&wfm, sizeof (WAVEFORMATEX));
288 	wfm.wFormatTag = WAVE_FORMAT_PCM;
289 	wfm.nChannels = 1;
290 	wfm.nSamplesPerSec = data?*((UINT16 *)data+1):srate;      //mostly 11025, but some at 22050.
291 	wfm.wBitsPerSample = 8;
292 	wfm.nBlockAlign = (WORD)(wfm.wBitsPerSample / 8 * wfm.nChannels);
293 	wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign;
294 
295 	// Set up DSBUFFERDESC structure.
296 	ZeroMemory (&dsbdesc, sizeof (DSBUFFERDESC) );
297 	dsbdesc.dwSize = sizeof (DSBUFFERDESC);
298 	dsbdesc.dwFlags = as3d?_3DSOURCE_FLAGS:_2DSOURCE_FLAGS;
299 	dsbdesc.dwBufferBytes = length;
300 	dsbdesc.lpwfxFormat = &wfm;
301 
302 	// DirectX 7.0 and above!
303 	// Try to enable full HRTF virtualization algorithm for
304 	// two-speakers or headphones
305 #ifdef DX7
306 	if (as3d)
307 		dsbdesc.guid3DAlgorithm = (virtualization?DS3DALG_HRTF_FULL:DS3DALG_DEFAULT);
308 #endif
309 
310 	hr = IDirectSound_CreateSoundBuffer (DSnd, &dsbdesc, &dsbuffer, NULL);
311 
312 	// CreateSoundBuffer might return DS_NO_VIRTUALIZATION so uses FAILED
313 	// macro rather than check explictly for DS_OK value
314 	if (FAILED(hr))
315 	{
316 		DBG_Printf("CreateSoundBuffer FAILED. Code %d\n", hr);
317 		return NULL;
318 	}
319 
320 	if (data)
321 	{
322 		hr = IDirectSoundBuffer_Lock(dsbuffer, 0, length, &lpvAudio1, &dwBytes1, &lpvAudio2, &dwBytes2, 0);
323 
324 		// If DSERR_BUFFERLOST is returned, restore and retry lock.
325 		if (hr == DSERR_BUFFERLOST)
326 		{
327 			hr = IDirectSoundBuffer_Restore(dsbuffer);
328 			if (FAILED(hr))
329 				I_ErrorDS3D("Restore fail on %x, code %d\n",dsbuffer, hr);
330 			hr = IDirectSoundBuffer_Lock(dsbuffer, 0, length, &lpvAudio1, &dwBytes1, &lpvAudio2, &dwBytes2, 0);
331 			if (FAILED(hr))
332 				I_ErrorDS3D("Lock fail(2) on %x, code %d\n",dsbuffer, hr);
333 		}
334 		else
335 			if (FAILED(hr))
336 				I_ErrorDS3D("Lock fail(1) on %x, code %d\n",dsbuffer, hr);
337 
338 		// copy wave data into the buffer (note: dwBytes1 should equal to dsbdesc->dwBufferBytes ...)
339 		CopyMemory (lpvAudio1, (LPBYTE)data+8, dwBytes1);
340 
341 		if ( dwBytes2 && lpvAudio2)
342 			CopyMemory(lpvAudio2, ((LPBYTE)data + 8) + dwBytes1, dwBytes2);
343 
344 
345 		// finally, unlock the buffer
346 		hr = IDirectSoundBuffer_Unlock(dsbuffer, lpvAudio1, dwBytes1, lpvAudio2, dwBytes2);
347 
348 		if (FAILED(hr))
349 			I_ErrorDS3D("Unlock fail on %x, code %d\n",dsbuffer, hr);
350 	}
351 
352 	return dsbuffer;
353 }
354 
355 
356 /***************************************************************
357  *
358  * Creates 3D source data buffer
359  *
360  ***************************************************************
361  */
create_3dbuffer(LPDIRECTSOUNDBUFFER dsbuffer,LPDIRECTSOUND3DBUFFER source3d)362 static LPDIRECTSOUND3DBUFFER create_3dbuffer(LPDIRECTSOUNDBUFFER dsbuffer, LPDIRECTSOUND3DBUFFER source3d)
363 {
364 	HRESULT hr;
365 
366 	hr = IDirectSoundBuffer_QueryInterface(dsbuffer,
367 	 &IID_IDirectSound3DBuffer, (void **)&source3d);
368 
369 	if (FAILED(hr))
370 	{
371 		DBG_Printf("Couldn't obtain 3D Buffer interface. Code %d\n", hr);
372 		return NULL;
373 	}
374 #ifdef DX7
375 	if (hr == DS_NO_VIRTUALIZATION)
376 	{
377 		DBG_Printf("The 3D virtualization is not supported under this OS.\n");
378 			virtualization = FALSE;
379 	}
380 #endif
381 	return source3d;
382 }
383 
384 
385 /***************************************************************
386  *
387  * Returns free (unused) source stack slot
388  * If none available sound stack will be increased
389  *
390  ***************************************************************
391  */
find_handle(INT32 new_sfx_id,INT32 new_is3d)392 static INT32 find_handle(INT32 new_sfx_id, INT32 new_is3d)
393 {
394 	INT32      free_sfx;
395 	stack_t *snd;
396 
397 	// At first do look for sound with same sfx ID and reuse it
398 	new_sfx_id = new_is3d = 0;
399 	for (free_sfx = 0, snd = _stack; free_sfx < allocated_sounds; snd++, free_sfx++)
400 	{
401 
402 		if (snd->permanent)
403 			continue;
404 /*
405 		if (!is_playing(snd))
406 		{
407 			if (same_sfx == 0 && snd->sfx_id == new_sfx_id && snd->dsbuffer)
408 			{
409 				same_sfx = i;
410 				continue;
411 			}
412 
413 			if (snd->sfx_id && ++snd->LRU >= MAX_LRU)
414 				kill_sound(snd);
415 		}
416 */
417 		if (snd->dsbuffer == 0)
418 			break;
419 			//free_sfx = i;
420 	}
421 
422 	// No suitable resource found so increase sound stack
423 	if (free_sfx == allocated_sounds)
424 	{
425 		DBG_Printf("No free or same sfx found so increase stack (currently %d srcs)\n", allocated_sounds);
426 		free_sfx = reallocate_stack() ? free_sfx : -1;
427 	}
428 
429 	return free_sfx;
430 }
431 
432 
433 /***************************************************************
434  *
435  * Recalculates volume from Doom scale to DirectSound scale
436  *
437  ***************************************************************
438  */
recalc_volume(INT32 base_vol,INT32 steps)439 static INT32 recalc_volume(INT32 base_vol, INT32 steps)
440 {
441 	return (base_vol * ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4)) / steps
442 	       + (DSBVOLUME_MAX - ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4));
443 }
444 
445 
446 /***************************************************************
447  *
448  * Updates sound volume of the DirectSound buffer
449  *
450  ***************************************************************
451  */
UpdateSoundVolume(LPDIRECTSOUNDBUFFER lpSnd,INT32 volume)452 static void UpdateSoundVolume (LPDIRECTSOUNDBUFFER lpSnd, INT32 volume)
453 {
454 	/*volume = (volume * ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4)) / 256 +
455 	         (DSBVOLUME_MAX - ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4));
456 
457 	IDirectSoundBuffer_SetVolume (lpSnd, volume);*/
458 	IDirectSoundBuffer_SetVolume (lpSnd, recalc_volume(volume, 256));
459 }
460 
461 
462 // --------------------------------------------------------------------------
463 // Update the panning for a secondary buffer, make sure it was created with
464 // DSBCAPS_CTRLPAN
465 // --------------------------------------------------------------------------
466 #define DSBPAN_RANGE    (DSBPAN_RIGHT-(DSBPAN_LEFT))
467 
468 //Doom sounds pan range 0-255 (128 is centre)
469 #define SEP_RANGE       256
Update2DSoundPanning(LPDIRECTSOUNDBUFFER lpSnd,INT32 sep)470 static void Update2DSoundPanning (LPDIRECTSOUNDBUFFER lpSnd, INT32 sep)
471 {
472 	HRESULT hr;
473 	hr = IDirectSoundBuffer_SetPan (lpSnd, (sep * DSBPAN_RANGE)/SEP_RANGE - DSBPAN_RIGHT);
474 	//if (FAILED(hr))
475 	//	DEBFILE(va("SetPan FAILED for sep %d pan %d\n", sep, (sep * DSBPAN_RANGE)/SEP_RANGE - DSBPAN_RIGHT));
476 }
477 
478 
479 
480 /******************************************************************************
481  *
482  * Initialise driver and listener
483  *
484  *****************************************************************************/
HWRAPI(Startup)485 EXPORT BOOL HWRAPI( Startup ) (I_Error_t FatalErrorFunction, snddev_t *snd_dev)
486 {
487 	HRESULT      hr;
488 	DSBUFFERDESC desc;
489 	WAVEFORMATEX wfm;
490 	DSCAPS       dscaps;
491 	DWORD        speakers;
492 	DWORD        speaker_config;
493 	DWORD        speaker_geometry;
494 
495 	I_ErrorDS3D = FatalErrorFunction;
496 	DBG_Printf ("S_DS3D Init(): DirectSound3D driver for SRB2 v1.09"); // Tails
497 
498 	DBG_Printf("Initialising DirectSound3D...\n");
499 	hr = DirectSoundCreate( NULL, &DSnd, NULL);
500 	if (FAILED(hr))
501 	{
502 		DBG_Printf("Failed to obtain DirectSound\n");
503 		return FALSE;
504 	}
505 
506 	hr = IDirectSound_SetCooperativeLevel(DSnd, snd_dev->hWnd, snd_dev->cooplevel);
507 	if (FAILED(hr))
508 	{
509 		DBG_Printf("Couldn't set coopertive level\n");
510 		return FALSE;
511 	}
512 
513 	dscaps.dwSize = sizeof (DSCAPS);
514 
515 	IDirectSound_GetCaps(DSnd, &dscaps);
516 	IDirectSound_GetSpeakerConfig(DSnd, &speakers);
517 
518 	DBG_Printf("Sound hardware capabilities:\n");
519 	DBG_Printf("   Driver is %scertified.\n", (dscaps.dwFlags & DSCAPS_CERTIFIED) == DSCAPS_CERTIFIED?"":"not ");
520 	DBG_Printf("   Maximum hardware mixing buffers %d\n", dscaps.dwMaxHwMixingAllBuffers);
521 	DBG_Printf("   Maximum hardware 3D buffers %d\n", dscaps.dwFreeHw3DAllBuffers);
522 
523 	speaker_config = DSSPEAKER_CONFIG(speakers);
524 	speaker_geometry = DSSPEAKER_GEOMETRY(speakers);
525 
526 	DBG_Printf("Current speaker configuration: ");
527 
528 	switch (speaker_config)
529 	{
530 #ifdef DX7
531 		case DSSPEAKER_5POINT1:
532 			DBG_Printf("5.1 (5 speakers with subwoofer).\n");
533 			break;
534 #endif
535 		case DSSPEAKER_HEADPHONE:
536 			DBG_Printf("headphone.\n");
537 			break;
538 
539 		case DSSPEAKER_MONO:
540 			DBG_Printf("single speaker (mono).\n");
541 			break;
542 
543 		case DSSPEAKER_QUAD:
544 			DBG_Printf("quadrophonic\n");
545 			break;
546 
547 		case DSSPEAKER_SURROUND:
548 			DBG_Printf("surround.\n");
549 			break;
550 
551 		case DSSPEAKER_STEREO:
552 			DBG_Printf("stereo with %s geometry ",
553 				speaker_geometry == DSSPEAKER_GEOMETRY_WIDE
554 					? "wide (arc of 20 deg.)"
555 					: speaker_geometry == DSSPEAKER_GEOMETRY_NARROW
556 						? "narrow (arc of 10 deg.)"
557 						: speaker_geometry == DSSPEAKER_GEOMETRY_MIN
558 							? "min (arc of 5 deg.)"
559 							: speaker_geometry == DSSPEAKER_GEOMETRY_MAX
560 								? "max (arc of 180 deg.)"
561 								: "unknown");
562 			break;
563 		default:
564 			DBG_Printf("undetectable.\n");
565 
566 	}
567 
568 	update_mode = DS3D_IMMEDIATE;
569 
570 	// Create primary sound buffer
571 	ZeroMemory(&desc, sizeof (DSBUFFERDESC));
572 	desc.dwSize = sizeof (DSBUFFERDESC);
573 	desc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
574 	desc.dwBufferBytes = 0;
575 	desc.lpwfxFormat = NULL;
576 
577 	hr = IDirectSound_CreateSoundBuffer(DSnd, &desc, &PrimaryBuffer, NULL);
578 	if (FAILED(hr))
579 	{
580 		DBG_Printf("CreateSoundBuffer FAILED (ErrNo %d)\n", hr);
581 		return FALSE;
582 	}
583 
584 	// Query for 3D Listener object
585 	hr = IDirectSoundBuffer_QueryInterface(PrimaryBuffer,
586 	 &IID_IDirectSound3DListener, (void **)&Listener);
587 
588 	if (FAILED(hr))
589 	{
590 		DBG_Printf("Couldn't obtain 3D Listener interface (ErrNo %d)\n", hr);
591 		return FALSE;
592 	}
593 
594 	// Set up initial listsner parameters
595 	IDirectSound3DListener_SetDistanceFactor(Listener, 1.0f/72.0f, DS3D_IMMEDIATE);
596 	IDirectSound3DListener_SetRolloffFactor(Listener, 1.6f, DS3D_IMMEDIATE);
597 	//IDirectSound3DListener_SetRolloffFactor(Listener, DS3D_MAXROLLOFFFACTOR, DS3D_IMMEDIATE);
598 	listener_parms.dwSize = sizeof (DS3DLISTENER);
599 	IDirectSound3DListener_GetAllParameters(Listener, &listener_parms);
600 
601 	ZeroMemory (&wfm, sizeof (WAVEFORMATEX));
602 	wfm.wFormatTag = WAVE_FORMAT_PCM;
603 	wfm.nChannels = 2;
604 	wfm.nSamplesPerSec = srate = snd_dev->sample_rate;
605 	wfm.wBitsPerSample = (WORD)snd_dev->bps;
606 	wfm.nBlockAlign = (WORD)(wfm.wBitsPerSample / 8 * wfm.nChannels);
607 	wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign;
608 
609 	if (snd_dev->cooplevel >= DSSCL_PRIORITY)
610 	{
611 		hr = IDirectSoundBuffer_SetFormat(PrimaryBuffer, &wfm);
612 		if (FAILED(hr))
613 			DBG_Printf("Couldn't set primary buffer format.\n");
614 
615 		DBG_Printf(" Compacting onboard sound-memory...");
616 		hr = IDirectSound_Compact(DSnd);
617 		DBG_Printf(" %s\n", SUCCEEDED(hr) ? M_GetText("Done\n") : M_GetText("Failed\n"));
618 	}
619 
620 #ifdef DX7
621 	// Initially enables HRTF virtualization (may be changed later)
622 	virtualization = TRUE;
623 #endif
624 
625 	_stack = NULL;
626 	allocated_sounds = 0;
627 	IDirectSoundBuffer_Play(PrimaryBuffer, 0, 0, DSBPLAY_LOOPING);
628 	return reallocate_stack();
629 }
630 
631 
632 
633 /***************************************************************
634  *
635  * Shutdown driver
636  *
637  ***************************************************************
638  */
HWRAPI(Shutdown)639 EXPORT void HWRAPI( Shutdown ) (void)
640 {
641 	INT32 i;
642 
643 	DBG_Printf ("S_DS3D Shutdown()\n");
644 
645 	for (i = 0; i < allocated_sounds; i++)
646 	{
647 		StopSource(i);
648 		kill_sound(_stack + i);
649 	}
650 
651 	if (_stack)
652 		free(_stack);
653 
654 	if (Listener)
655 	{
656 		IDirectSound3DListener_Release(Listener);
657 		Listener = NULL;
658 	}
659 
660 	if (PrimaryBuffer)
661 		RELEASE_BUFFER(PrimaryBuffer);
662 
663 	if (DSnd)
664 	{
665 		IDirectSound_Release(DSnd);
666 		DSnd = NULL;
667 	}
668 
669 }
670 
671 
672 
HWRAPI(IsPlaying)673 EXPORT INT32 HWRAPI (IsPlaying) (INT32 handle)
674 {
675 	if (handle < 0 || handle >= allocated_sounds)
676 		return FALSE;
677 
678 	return is_playing(_stack + handle);
679 }
680 
681 
682 // Calculate sound pitching
recalc_pitch(INT32 doom_pitch)683 static float recalc_pitch(INT32 doom_pitch)
684 {
685 	return doom_pitch < NORMAL_PITCH ?
686 	 (float)(doom_pitch + NORMAL_PITCH) / (NORMAL_PITCH * 2)
687 	 :(float)doom_pitch / (float)NORMAL_PITCH;
688 }
689 
690 
setup_source(INT32 handle,sfx_data_t * sfx,BOOL is_3dsource)691 static stack_t *setup_source(INT32 handle, sfx_data_t *sfx, BOOL is_3dsource)
692 {
693 	stack_t               *snd;
694 	//INT32                  handle;
695 	INT32                    data_length;
696 	LPDIRECTSOUNDBUFFER    dsbuffer = NULL;
697 	LPDIRECTSOUND3DBUFFER  ds3dbuffer = NULL;
698 
699 	if (handle == NEW_HANDLE)
700 		handle = find_handle(sfx?sfx->id:0, is_3dsource);
701 
702 	snd = _stack + handle;
703 
704 	// Check for reused source
705 	if (snd->dsbuffer)
706 		return snd;
707 
708 	data_length = sfx?sfx->length - 8:DSBSIZE_MIN;
709 
710 	dsbuffer = create_buffer(sfx ? sfx->data : NULL, data_length, is_3dsource);
711 	if (dsbuffer)
712 	{
713 
714 		if (is_3dsource)
715 		{
716 			ds3dbuffer = create_3dbuffer(dsbuffer, ds3dbuffer);
717 			if (!ds3dbuffer)
718 			{
719 				RELEASE_BUFFER(dsbuffer);
720 				return NULL;
721 			}
722 			snd->parameters.dwSize = sizeof (DS3DBUFFER);
723 			IDirectSound3DBuffer_GetAllParameters(ds3dbuffer, &snd->parameters);
724 		}
725 
726 		// judgecutor: sound pitching
727 		if (sfx)
728 		{
729 			DWORD freq;
730 
731 			freq = (DWORD)((float)(*((UINT16 *)sfx->data+1)) * recalc_pitch(sfx->pitch));
732 			IDirectSoundBuffer_SetFrequency(dsbuffer, freq);
733 		}
734 
735 		snd->dsbuffer = dsbuffer;
736 		snd->dsbuffer3D = ds3dbuffer;
737 		snd->LRU = 0;
738 		snd->sfx_id = sfx ? sfx->id : 0;
739 		if (!is_3dsource)
740 			snd->permanent = 0;
741 		return snd;
742 	}
743 	return NULL;
744 
745 }
746 
747 /******************************************************************************
748  *
749  * Creates 2D (stereo) source
750  *
751  ******************************************************************************/
HWRAPI(Add2DSource)752 EXPORT INT32 HWRAPI ( Add2DSource ) (sfx_data_t *sfx)
753 {
754 	stack_t *snd;
755 
756 	if (!sfx)
757 		return -1;
758 
759 	snd = setup_source(NEW_HANDLE, sfx, IS_2DSOURCE);
760 	if (snd)
761 	{
762 		UpdateSoundVolume(snd->dsbuffer, sfx->volume);
763 		Update2DSoundPanning(snd->dsbuffer, sfx->sep);
764 	}
765 	return snd - _stack;
766 }
767 
768 /******************************************************************************
769  *
770  * Creates 3D source
771  *
772  ******************************************************************************/
773 
HWRAPI(Add3DSource)774 EXPORT INT32 HWRAPI ( Add3DSource ) (source3D_data_t *src, sfx_data_t *sfx)
775 {
776 	stack_t *snd;
777 
778 	snd = setup_source(NEW_HANDLE, sfx, IS_3DSOURCE);
779 
780 	if (snd)
781 	{
782 
783 		/*x = src->pos.x;
784 		y = src->pos.z;
785 		z = src->pos.y;
786 
787 		IDirectSound3DBuffer_SetPosition(source, x, y, z, update_mode);
788 		IDirectSound3DBuffer_SetVelocity(source, src->pos.momx, src->pos.momz, src->pos.momy, update_mode);
789 		IDirectSound3DBuffer_SetMode(source, src->head_relative?DS3DMODE_HEADRELATIVE:DS3DMODE_NORMAL, update_mode);*/
790 
791 #ifdef DUMMYUNIONNAMEN
792 		snd->parameters.vPosition.DUMMYUNIONNAMEN(9).x = src->pos.x;
793 		snd->parameters.vPosition.DUMMYUNIONNAMEN(10).y = src->pos.z;
794 		snd->parameters.vPosition.DUMMYUNIONNAMEN(11).z = src->pos.y;
795 
796 		snd->parameters.vVelocity.DUMMYUNIONNAMEN(9).x = src->pos.momx;
797 		snd->parameters.vVelocity.DUMMYUNIONNAMEN(10).y = src->pos.momz;
798 		snd->parameters.vVelocity.DUMMYUNIONNAMEN(11).z = src->pos.momy;
799 #else
800 		snd->parameters.vPosition.x = src->pos.x;
801 		snd->parameters.vPosition.y = src->pos.z;
802 		snd->parameters.vPosition.z = src->pos.y;
803 
804 		snd->parameters.vVelocity.x = src->pos.momx;
805 		snd->parameters.vVelocity.y = src->pos.momz;
806 		snd->parameters.vVelocity.z = src->pos.momy;
807 #endif
808 		snd->parameters.dwMode = src->head_relative ? DS3DMODE_HEADRELATIVE : DS3DMODE_NORMAL;
809 
810 		snd->parameters.flMinDistance = src->min_distance;
811 		snd->parameters.flMaxDistance = src->max_distance;
812 		//snd->parameters.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
813 
814 		snd->permanent = src->permanent;
815 
816 		UpdateSoundVolume(snd->dsbuffer, sfx?sfx->volume:255);
817 		IDirectSound3DBuffer_SetAllParameters(snd->dsbuffer3D, &snd->parameters, DS3D_IMMEDIATE);
818 		IDirectSoundBuffer_SetCurrentPosition(snd->dsbuffer, 0);
819 	}
820 
821 	return (snd - _stack);
822 }
823 
824 /******************************************************************************
825  *
826  * Destroy source and remove it from stack if it is a 2D source.
827  * Otherwise put source into cache
828  *
829  *****************************************************************************/
HWRAPI(KillSource)830 EXPORT void HWRAPI (KillSource) (INT32 handle)
831 {
832 
833 	if (handle < 0 || handle >= allocated_sounds)
834 		return;
835 /*
836 		if (_stack[handle].dsbuffer3D)
837 	{
838 		// It's a 3D source so let him chance to be reused :-)
839 		_stack[handle].LRU = 1;
840 	}
841 	else
842 	{ */
843 		// No, it is a 2D source so kill him
844 		kill_sound(_stack + handle);
845 	//}
846 }
847 
848 
849 /******************************************************************************
850  *
851  * Update volume and separation (panning) of 2D source
852  *
853  *****************************************************************************/
HWRAPI(Update2DSoundParms)854 EXPORT void HWRAPI (Update2DSoundParms) (INT32 handle, INT32 vol, INT32 sep)
855 {
856 	LPDIRECTSOUNDBUFFER dsbuffer;
857 
858 	if (handle < 0 || handle >= allocated_sounds)
859 		return;
860 
861 	if ((_stack+handle)->dsbuffer3D)
862 		return;
863 	dsbuffer = (_stack + handle)->dsbuffer;
864 
865 	UpdateSoundVolume(dsbuffer, vol);
866 	Update2DSoundPanning(dsbuffer, sep);
867 }
868 
869 
870 
871 // --------------------------------------------------------------------------
872 // Set the global volume for sound effects
873 // --------------------------------------------------------------------------
HWRAPI(SetGlobalSfxVolume)874 EXPORT void HWRAPI (SetGlobalSfxVolume) (INT32 volume)
875 {
876 	INT32     vol;
877 	HRESULT hr;
878 
879 	// use the last quarter of volume range
880 	if (volume)
881 		vol = recalc_volume(volume, 31);
882 	else
883 		vol = DSBVOLUME_MIN;
884 
885 	hr = IDirectSoundBuffer_SetVolume (PrimaryBuffer, vol);
886 }
887 
HWRAPI(StopSource)888 EXPORT void HWRAPI ( StopSource) (INT32 handle)
889 {
890 	LPDIRECTSOUNDBUFFER dsbuffer;
891 
892 	if (handle < 0 || handle >= allocated_sounds)
893 		return;
894 
895 	dsbuffer = (_stack + handle)->dsbuffer;
896 
897 	if (dsbuffer)
898 	{
899 		IDirectSoundBuffer_Stop(dsbuffer);
900 		IDirectSoundBuffer_SetCurrentPosition(dsbuffer, 0);
901 	}
902 }
903 
904 
HWRAPI(GetHW3DSVersion)905 EXPORT INT32 HWRAPI ( GetHW3DSVersion) (void)
906 {
907 	return VERSION;
908 }
909 
910 
HWRAPI(BeginFrameUpdate)911 EXPORT void HWRAPI (BeginFrameUpdate) (void)
912 {
913 	update_mode = DS3D_DEFERRED;
914 }
915 
916 
HWRAPI(EndFrameUpdate)917 EXPORT void HWRAPI (EndFrameUpdate) (void)
918 {
919 	if (update_mode == DS3D_DEFERRED)
920 		IDirectSound3DListener_CommitDeferredSettings(Listener);
921 
922 	update_mode = DS3D_IMMEDIATE;
923 }
924 
925 
926 /******************************************************************************
927  * UpdateListener
928  *
929  * Set up main listener properties:
930  * - position
931  * - orientation
932  * - velocity
933  *****************************************************************************/
HWRAPI(UpdateListener)934 EXPORT void HWRAPI (UpdateListener) (listener_data_t *data)
935 {
936 	D3DVECTOR pos;
937 	D3DVECTOR face;
938 	D3DVECTOR head;
939 	D3DVECTOR velocity;
940 	double      f_angle;
941 	//double      h_angle, t_angle;
942 	//double      f_cos, f_sin, t_sin;
943 
944 #ifdef DUMMYUNIONNAMEN
945 	pos.DUMMYUNIONNAMEN(9).x = (D3DVALUE)data->x;
946 	pos.DUMMYUNIONNAMEN(10).y = (D3DVALUE)data->z;
947 	pos.DUMMYUNIONNAMEN(11).z = (D3DVALUE)data->y;
948 
949 	velocity.DUMMYUNIONNAMEN(9).x = (D3DVALUE)data->momx;
950 	velocity.DUMMYUNIONNAMEN(10).y = (D3DVALUE)data->momz;
951 	velocity.DUMMYUNIONNAMEN(11).z = (D3DVALUE)data->momy;
952 #else
953 	pos.x = (D3DVALUE)data->x;
954 	pos.y = (D3DVALUE)data->z;
955 	pos.z = (D3DVALUE)data->y;
956 
957 	velocity.x = (D3DVALUE)data->momx;
958 	velocity.y = (D3DVALUE)data->momz;
959 	velocity.z = (D3DVALUE)data->momy;
960 #endif
961 	f_angle = (data->f_angle) / 180 * M_PI;
962 	//h_angle = data->h_angle / 180 * M_PI;
963 	//h_angle = 90 / 180 * M_PI;
964 
965 	// Treat listener orientation angles as spherical coordinates.
966 	// x = sin h * cos f
967 	// y = sin h * sin f
968 	// z = cos h
969 
970 	// Front vector
971 	//t_angle = (M_PI/2 - h_angle);
972 	//t_angle = M_PI/2;
973 
974 	//face.x = (t_sin = sin(t_angle)) * (f_cos = cos(f_angle));
975 	//face.z = t_sin * (f_sin = sin(f_angle));
976 	//face.y = cos(t_angle);
977 #ifdef DUMMYUNIONNAMEN
978 	face.DUMMYUNIONNAMEN(9).x = (D3DVALUE)cos(f_angle);
979 	face.DUMMYUNIONNAMEN(11).z = (D3DVALUE)sin(f_angle);
980 	face.DUMMYUNIONNAMEN(10).y = 0.0f;
981 
982 	head.DUMMYUNIONNAMEN(9).x = 0.0f;
983 	head.DUMMYUNIONNAMEN(10).y = 1.0f;
984 	head.DUMMYUNIONNAMEN(11).z = 0.0f;
985 #else
986 	face.x = (D3DVALUE)cos(f_angle);
987 	face.z = (D3DVALUE)sin(f_angle);
988 	face.y = 0.0f;
989 
990 	head.x = 0.0f;
991 	head.y = 1.0f;
992 	head.z = 0.0f;
993 #endif
994 	// Top vector
995 	//h_angle = (-data->h_angle) / 180 * M_PI;
996 
997 /*
998 	t_angle = -h_angle;
999 
1000 	head.z = (t_sin = sin(t_angle)) * f_cos;
1001 	head.x = t_sin * f_sin;
1002 	head.y = cos(t_angle);
1003 */
1004 
1005 	// Update at once
1006 	CopyMemory(&listener_parms.vPosition, &pos, sizeof (D3DVECTOR));
1007 	CopyMemory(&listener_parms.vOrientFront, &face, sizeof (D3DVECTOR));
1008 	CopyMemory(&listener_parms.vOrientTop, &head, sizeof (D3DVECTOR));
1009 	CopyMemory(&listener_parms.vVelocity, &velocity, sizeof (D3DVECTOR));
1010 	//IDirectSound3DListener_SetAllParameters(Listener, &listener_parms, DS3D_IMMEDIATE);
1011 	IDirectSound3DListener_SetAllParameters(Listener, &listener_parms, update_mode);
1012 }
1013 
HWRAPI(UpdateListener2)1014 EXPORT void HWRAPI (UpdateListener2) (listener_data_t *data)
1015 {
1016 	D3DVECTOR pos;
1017 	D3DVECTOR face;
1018 	D3DVECTOR head;
1019 	D3DVECTOR velocity;
1020 	double      f_angle;
1021 	//double      h_angle, t_angle;
1022 	//double      f_cos, f_sin, t_sin;
1023 
1024 	if (!data) return;
1025 
1026 #ifdef DUMMYUNIONNAMEN
1027 	pos.DUMMYUNIONNAMEN(9).x = (D3DVALUE)data->x;
1028 	pos.DUMMYUNIONNAMEN(10).y = (D3DVALUE)data->z;
1029 	pos.DUMMYUNIONNAMEN(11).z = (D3DVALUE)data->y;
1030 
1031 	velocity.DUMMYUNIONNAMEN(9).x = (D3DVALUE)data->momx;
1032 	velocity.DUMMYUNIONNAMEN(10).y = (D3DVALUE)data->momz;
1033 	velocity.DUMMYUNIONNAMEN(11).z = (D3DVALUE)data->momy;
1034 #else
1035 	pos.x = (D3DVALUE)data->x;
1036 	pos.y = (D3DVALUE)data->z;
1037 	pos.z = (D3DVALUE)data->y;
1038 
1039 	velocity.x = (D3DVALUE)data->momx;
1040 	velocity.y = (D3DVALUE)data->momz;
1041 	velocity.z = (D3DVALUE)data->momy;
1042 #endif
1043 	f_angle = (data->f_angle) / 180 * M_PI;
1044 	//h_angle = data->h_angle / 180 * M_PI;
1045 	//h_angle = 90 / 180 * M_PI;
1046 
1047 	// Treat listener orientation angles as spherical coordinates.
1048 	// x = sin h * cos f
1049 	// y = sin h * sin f
1050 	// z = cos h
1051 
1052 	// Front vector
1053 	//t_angle = (M_PI/2 - h_angle);
1054 	//t_angle = M_PI/2;
1055 
1056 	//face.x = (t_sin = sin(t_angle)) * (f_cos = cos(f_angle));
1057 	//face.z = t_sin * (f_sin = sin(f_angle));
1058 	//face.y = cos(t_angle);
1059 #ifdef DUMMYUNIONNAMEN
1060 	face.DUMMYUNIONNAMEN(9).x = cos(f_angle);
1061 	face.DUMMYUNIONNAMEN(11).z = sin(f_angle);
1062 	face.DUMMYUNIONNAMEN(10).y = 0.0f;
1063 
1064 	head.DUMMYUNIONNAMEN(9).x = 0.0f;
1065 	head.DUMMYUNIONNAMEN(10).y = 1.0f;
1066 	head.DUMMYUNIONNAMEN(11).z = 0.0f;
1067 #else
1068 	face.x = (D3DVALUE)cos(f_angle);
1069 	face.z = (D3DVALUE)sin(f_angle);
1070 	face.y = 0.0f;
1071 
1072 	head.x = 0.0f;
1073 	head.y = 1.0f;
1074 	head.z = 0.0f;
1075 #endif
1076 
1077 	// Top vector
1078 	//h_angle = (-data->h_angle) / 180 * M_PI;
1079 
1080 /*
1081 	t_angle = -h_angle;
1082 
1083 	head.z = (t_sin = sin(t_angle)) * f_cos;
1084 	head.x = t_sin * f_sin;
1085 	head.y = cos(t_angle);
1086 */
1087 
1088 	// Update at once
1089 	CopyMemory(&listener_parms.vPosition, &pos, sizeof (D3DVECTOR));
1090 	CopyMemory(&listener_parms.vOrientFront, &face, sizeof (D3DVECTOR));
1091 	CopyMemory(&listener_parms.vOrientTop, &head, sizeof (D3DVECTOR));
1092 	CopyMemory(&listener_parms.vVelocity, &velocity, sizeof (D3DVECTOR));
1093 	//IDirectSound3DListener_SetAllParameters(Listener, &listener_parms, DS3D_IMMEDIATE);
1094 	//Alam_GBC: 2 Listeners?
1095 	//IDirectSound3DListener_SetAllParameters(Listener, &listener_parms, update_mode);
1096 }
1097 
HWRAPI(SetCone)1098 EXPORT INT32 HWRAPI (SetCone) (INT32 handle, cone_def_t *cone_def)
1099 {
1100 	stack_t     *snd;
1101 	//DS3DBUFFER  parms;
1102 
1103 	if (handle < 0 || handle >= allocated_sounds)
1104 		return -1;
1105 
1106 	snd = _stack + handle;
1107 
1108 	if (snd->dsbuffer3D)
1109 	{
1110 
1111 		/*f_angle = cone_def->f_angle / 180 * M_PI;
1112 		h_angle = (90 - cone_def->h_angle) / 180 * M_PI;
1113 		parms.vConeOrientation.x = sin(h_angle) * cos(f_angle);
1114 		parms.vConeOrientation.z = sin(h_angle) * sin(f_angle);
1115 		parms.vConeOrientation.y = cos(h_angle);*/
1116 
1117 		snd->parameters.dwInsideConeAngle = (DWORD)cone_def->inner;
1118 		snd->parameters.dwOutsideConeAngle = (DWORD)cone_def->outer;
1119 		snd->parameters.lConeOutsideVolume = recalc_volume(cone_def->outer_gain, 256);
1120 
1121 		return IDirectSound3DBuffer_SetAllParameters(snd->dsbuffer3D, &snd->parameters, update_mode);
1122 	}
1123 
1124 	return -1;
1125 }
1126 
HWRAPI(Update3DSource)1127 EXPORT void HWRAPI (Update3DSource) (INT32 handle, source3D_pos_t *data)
1128 {
1129 	stack_t     *snd;
1130 
1131 	if (handle < 0 || handle >= allocated_sounds)
1132 		return;
1133 
1134 	snd = _stack + handle;
1135 	if (snd->dsbuffer3D)
1136 	{
1137 
1138 		/*parms.dwSize = sizeof (DS3DBUFFER);
1139 		IDirectSound3DBuffer_GetAllParameters(snd, &parms);*/
1140 
1141 		//angle = data->angle * 180 / M_PI;
1142 
1143 #ifdef DUMMYUNIONNAMEN
1144 		snd->parameters.vPosition.DUMMYUNIONNAMEN(9).x = data->x;
1145 		snd->parameters.vPosition.DUMMYUNIONNAMEN(10).y = data->z;
1146 		snd->parameters.vPosition.DUMMYUNIONNAMEN(11).z = data->y;
1147 #else
1148 		snd->parameters.vPosition.x = data->x;
1149 		snd->parameters.vPosition.y = data->z;
1150 		snd->parameters.vPosition.z = data->y;
1151 #endif
1152 
1153 		/*parms.vConeOrientation.x = cos(angle);
1154 		parms.vConeOrientation.z = sin(angle);
1155 		parms.vConeOrientation.y = 0;*/
1156 
1157 #ifdef DUMMYUNIONNAMEN
1158 		snd->parameters.vVelocity.x = data->momx;
1159 		snd->parameters.vVelocity.y = data->momz;
1160 		snd->parameters.vVelocity.z = data->momy;
1161 #else
1162 		snd->parameters.vVelocity.x = data->momx;
1163 		snd->parameters.vVelocity.y = data->momz;
1164 		snd->parameters.vVelocity.z = data->momy;
1165 #endif
1166 
1167 		//snd->parameters.flMinDistance = data->min_distance;
1168 		//snd->parameters.flMaxDistance = data->max_distance;
1169 		//snd->parameters.dwMode = pos->head_realtive?DS3DMODE_HEADREALTIVE:DS3DMODE_NORMAL;
1170 
1171 		IDirectSound3DBuffer_SetAllParameters(snd->dsbuffer3D, &snd->parameters, update_mode);
1172 	}
1173 }
1174 
1175 
HWRAPI(StartSource)1176 EXPORT INT32 HWRAPI (StartSource) (INT32 handle)
1177 {
1178 	LPDIRECTSOUNDBUFFER snd;
1179 
1180 	if (handle < 0 || handle >= allocated_sounds)
1181 		return -1;
1182 
1183 	snd = (_stack + handle)->dsbuffer;
1184 	IDirectSoundBuffer_SetCurrentPosition(snd, 0);
1185 	return IDirectSoundBuffer_Play(snd, 0, 0, 0);
1186 
1187 }
1188 
1189 //-------------------------------------------------------------
1190 // Load new sound data into source
1191 //-------------------------------------------------------------
HWRAPI(Reload3DSource)1192 EXPORT INT32 HWRAPI (Reload3DSource) (INT32 handle, sfx_data_t *data)
1193 {
1194 	DS3DBUFFER  temp;
1195 	stack_t    *snd;
1196 	INT32         perm;
1197 
1198 	// DirectX could not load new sound data into source
1199 	// so recreate sound buffers
1200 	if (handle < 0 || handle >= allocated_sounds)
1201 		return -1;
1202 
1203 	snd = _stack + handle;
1204 	CopyMemory(&temp, &snd->parameters, sizeof (DS3DBUFFER));
1205 	perm = snd->permanent;
1206 
1207 	kill_sound(snd);
1208 
1209 	snd = setup_source(handle, data, IS_3DSOURCE);
1210 	/*snd->dsbuffer = create_buffer(data->data, data->length, true);
1211 	if (snd->dsbuffer == NULL)
1212 		return -1;
1213 	snd->dsbuffer3D = create_3dbuffer(snd->dsbuffer, snd->dsbuffer3D);
1214 	if (snd->dsbuffer3D == NULL)
1215 	{
1216 		RELEASE_BUFFER(snd->dsbuffer);
1217 		return -1;
1218 	}
1219 
1220 	snd->sfx_id = data->id;
1221 	snd->LRU = 0;*/
1222 	if (snd)
1223 	{
1224 		snd->permanent = perm;
1225 		IDirectSound3DBuffer_SetAllParameters(snd->dsbuffer3D, &temp, DS3D_IMMEDIATE);
1226 		CopyMemory(&snd->parameters, &temp, sizeof (DS3DBUFFER));
1227 	}
1228 
1229 	return(snd - _stack);
1230 }
1231 
HWRAPI(UpdateSourceVolume)1232 EXPORT void HWRAPI (UpdateSourceVolume) (INT32 handle, INT32 volume)
1233 {
1234 	if (handle < 0 || handle >= allocated_sounds)
1235 		return;
1236 	UpdateSoundVolume((_stack + handle)->dsbuffer, volume);
1237 }
1238