📄 s_ds3d.c
字号:
*
* Returns free (unused) source stack slot
* If none available sound stack will be increased
*
***************************************************************
*/
static int find_handle(int new_sfx_id, int new_is3d)
{
int free_sfx;
stack_t *snd;
// At first do look for sound with same sfx ID and reuse it
for (free_sfx = 0, snd = _stack; free_sfx < allocated_sounds; snd++, free_sfx++)
{
if (snd->permanent)
continue;
/*
if (!is_playing(snd))
{
if (same_sfx == 0 && snd->sfx_id == new_sfx_id && snd->dsbuffer)
{
same_sfx = i;
continue;
}
if (snd->sfx_id && ++snd->LRU >= MAX_LRU)
kill_sound(snd);
}
*/
if (snd->dsbuffer == 0)
break;
//free_sfx = i;
}
// No suitable resource found so increase sound stack
if (free_sfx == allocated_sounds)
{
DBG_Printf("No free or same sfx found so increase stack (currently %d srcs)\n", allocated_sounds);
free_sfx = reallocate_stack() ? free_sfx : -1;
};
return free_sfx;
}
/***************************************************************
*
* Recalculates volume from Doom scale to DirectSound scale
*
***************************************************************
*/
static int recalc_volume(int base_vol, int steps)
{
return (base_vol * ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4)) / steps
+ (DSBVOLUME_MAX - ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4));
}
/***************************************************************
*
* Updates sound volume of the DirectSound buffer
*
***************************************************************
*/
static void UpdateSoundVolume (LPDIRECTSOUNDBUFFER lpSnd, int volume)
{
/*volume = (volume * ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4)) / 256 +
(DSBVOLUME_MAX - ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4));
IDirectSoundBuffer_SetVolume (lpSnd, volume);*/
IDirectSoundBuffer_SetVolume (lpSnd, recalc_volume(volume, 256));
}
// --------------------------------------------------------------------------
// Update the panning for a secondary buffer, make sure it was created with
// DSBCAPS_CTRLPAN
// --------------------------------------------------------------------------
#define DSBPAN_RANGE (DSBPAN_RIGHT-(DSBPAN_LEFT))
//Doom sounds pan range 0-255 (128 is centre)
#define SEP_RANGE 256
static void Update2DSoundPanning (LPDIRECTSOUNDBUFFER lpSnd, int sep)
{
HRESULT hr;
hr = IDirectSoundBuffer_SetPan (lpSnd, (sep * DSBPAN_RANGE)/SEP_RANGE - DSBPAN_RIGHT);
//if (FAILED(hr))
// CONS_Printf ("SetPan FAILED for sep %d pan %d\n", sep, (sep * DSBPAN_RANGE)/SEP_RANGE - DSBPAN_RIGHT);
}
/******************************************************************************
*
* Initialise driver and listener
*
*****************************************************************************/
EXPORT BOOL HWRAPI( Startup ) (I_Error_t FatalErrorFunction, snddev_t *snd_dev)
{
HRESULT hr;
DSBUFFERDESC desc;
WAVEFORMATEX wfm;
DSCAPS dscaps;
DWORD speakers;
DWORD speaker_config;
DWORD speaker_geometry;
I_ErrorDS3D = FatalErrorFunction;
DBG_Printf ("S_DS3D Init(): DirectSound3D driver for Doom Legacy v%d.%d\n", VERSION / 100, VERSION % 100);
DBG_Printf("Initialising DirectSound3D...\n");
hr = DirectSoundCreate( NULL, &DSnd, NULL);
if (FAILED(hr))
{
DBG_Printf("Failed to obtain DirectSound\n");
return FALSE;
}
hr = IDirectSound_SetCooperativeLevel(DSnd, snd_dev->hWnd, snd_dev->cooplevel);
if (FAILED (hr))
{
DBG_Printf("Couldn't set coopertive level\n");
return FALSE;
}
dscaps.dwSize = sizeof(DSCAPS);
IDirectSound_GetCaps(DSnd, &dscaps);
IDirectSound_GetSpeakerConfig(DSnd, &speakers);
DBG_Printf("Sound hardware capabilities:\n");
DBG_Printf(" Driver is %scertified.\n", (dscaps.dwFlags & DSCAPS_CERTIFIED) == DSCAPS_CERTIFIED?"":"not ");
DBG_Printf(" Maximum hardware mixing buffers %d\n", dscaps.dwMaxHwMixingAllBuffers);
DBG_Printf(" Maximum hardware 3D buffers %d\n", dscaps.dwFreeHw3DAllBuffers);
speaker_config = DSSPEAKER_CONFIG(speakers);
speaker_geometry = DSSPEAKER_GEOMETRY(speakers);
DBG_Printf("Current speaker configuration: ");
switch (speaker_config)
{
case DSSPEAKER_5POINT1:
DBG_Printf("5.1 (5 speakers with subwoofer).\n");
break;
case DSSPEAKER_HEADPHONE:
DBG_Printf("headphone.\n");
break;
case DSSPEAKER_MONO:
DBG_Printf("single speaker (mono).\n");
break;
case DSSPEAKER_QUAD:
DBG_Printf("quadrophonic\n");
break;
case DSSPEAKER_SURROUND:
DBG_Printf("surround.\n");
break;
case DSSPEAKER_STEREO:
DBG_Printf("stereo with %s geometry ",
speaker_geometry == DSSPEAKER_GEOMETRY_WIDE
? "wide (arc of 20 deg.)"
: speaker_geometry == DSSPEAKER_GEOMETRY_NARROW
? "narrow (arc of 10 deg.)"
: speaker_geometry == DSSPEAKER_GEOMETRY_MIN
? "min (arc of 5 deg.)"
: speaker_geometry == DSSPEAKER_GEOMETRY_MAX
? "max (arc of 180 deg.)"
: "unknown");
break;
default:
DBG_Printf("undetectable.\n");
}
update_mode = DS3D_IMMEDIATE;
// Create primary sound buffer
ZeroMemory(&desc, sizeof(DSBUFFERDESC));
desc.dwSize = sizeof(DSBUFFERDESC);
desc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
desc.dwBufferBytes = 0;
desc.lpwfxFormat = NULL;
hr = IDirectSound_CreateSoundBuffer(DSnd, &desc, &PrimaryBuffer, NULL);
if (FAILED(hr))
{
DBG_Printf("CreateSoundBuffer FAILED (ErrNo %d)\n", hr);
return FALSE;
}
// Query for 3D Listener object
hr = IDirectSoundBuffer_QueryInterface(PrimaryBuffer,
&IID_IDirectSound3DListener, (void **)&Listener);
if (FAILED( hr ) )
{
DBG_Printf("Couldn't obtain 3D Listener interface (ErrNo %d)\n", hr);
return FALSE;
}
// Set up initial listsner parameters
IDirectSound3DListener_SetDistanceFactor(Listener, (float)1/(float)72.0, DS3D_IMMEDIATE);
IDirectSound3DListener_SetRolloffFactor(Listener, DS3D_DEFAULTROLLOFFFACTOR, DS3D_IMMEDIATE);
listener_parms.dwSize = sizeof(DS3DLISTENER);
IDirectSound3DListener_GetAllParameters(Listener, &listener_parms);
ZeroMemory (&wfm, sizeof(WAVEFORMATEX));
wfm.wFormatTag = WAVE_FORMAT_PCM;
wfm.nChannels = 2;
wfm.nSamplesPerSec = srate = snd_dev->sample_rate;
wfm.wBitsPerSample = snd_dev->bps;
wfm.nBlockAlign = wfm.wBitsPerSample / 8 * wfm.nChannels;
wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign;
if (snd_dev->cooplevel >= DSSCL_PRIORITY)
{
hr = IDirectSoundBuffer_SetFormat (PrimaryBuffer, &wfm);
if (FAILED(hr))
DBG_Printf ("Couldn't set primary buffer format.\n");
DBG_Printf (" Compacting onboard sound-memory...");
hr = IDirectSound_Compact (DSnd);
DBG_Printf (" %s\n", SUCCEEDED(hr) ? "done" : "FAILED");
}
// Initially enables HRTF virtualization (may be changed later)
virtualization = FALSE;
_stack = NULL;
allocated_sounds = 0;
IDirectSoundBuffer_Play(PrimaryBuffer, 0, 0, DSBPLAY_LOOPING);
return reallocate_stack();
}
/***************************************************************
*
* Shutdown driver
*
***************************************************************
*/
EXPORT void HWRAPI( Shutdown ) (void)
{
int i;
DBG_Printf ("S_DS3D Shutdown()\n");
for (i = 0; i < allocated_sounds; i++)
{
StopSource(i);
kill_sound(_stack + i);
}
if (_stack)
free(_stack);
if (Listener)
{
IDirectSound3DListener_Release(Listener);
Listener = NULL;
}
if (PrimaryBuffer)
RELEASE_BUFFER(PrimaryBuffer);
if (DSnd)
{
IDirectSound_Release(DSnd);
DSnd = NULL;
}
}
EXPORT int HWRAPI (IsPlaying) (int handle)
{
if (handle < 0 || handle >= allocated_sounds)
return FALSE;
return is_playing(_stack + handle);
}
static stack_t *setup_source(int handle, sfx_data_t *sfx, BOOL is_3dsource)
{
stack_t *snd;
//int handle;
int data_length;
LPDIRECTSOUNDBUFFER dsbuffer = NULL;
LPDIRECTSOUND3DBUFFER ds3dbuffer = NULL;
if (handle == NEW_HANDLE)
handle = find_handle(sfx?sfx->id:0, is_3dsource);
snd = _stack + handle;
// Check for reused source
if (snd->dsbuffer)
return snd;
data_length = sfx?sfx->length - 8:DSBSIZE_MIN;
dsbuffer = create_buffer(sfx ? sfx->data : NULL, data_length, is_3dsource);
if (dsbuffer)
{
if (is_3dsource)
{
ds3dbuffer = create_3dbuffer(dsbuffer, ds3dbuffer);
if (!ds3dbuffer)
{
RELEASE_BUFFER(dsbuffer);
return NULL;
}
snd->parameters.dwSize = sizeof(DS3DBUFFER);
IDirectSound3DBuffer_GetAllParameters(ds3dbuffer, &snd->parameters);
}
snd->dsbuffer = dsbuffer;
snd->dsbuffer3D = ds3dbuffer;
snd->LRU = 0;
snd->sfx_id = sfx ? sfx->id : 0;
if (!is_3dsource)
snd->permanent = 0;
return snd;
}
return NULL;
}
/******************************************************************************
*
* Creates 2D (stereo) source
*
******************************************************************************/
EXPORT int HWRAPI ( Add2DSource ) (source2D_data_t *src, sfx_data_t *sfx)
{
stack_t *snd;
snd = setup_source(NEW_HANDLE, sfx, IS_2DSOURCE);
if (snd)
{
UpdateSoundVolume(snd->dsbuffer, src->volume);
Update2DSoundPanning(snd->dsbuffer, src->sep);
}
return snd - _stack;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -