⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s_ds3d.c

📁 The source code of Doom legacy for windows
💻 C
📖 第 1 页 / 共 3 页
字号:
// Emacs style mode select   -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id: s_ds3d.c,v 1.2 2001/04/06 21:36:53 judgecutor Exp $
//
// Copyright (C) 2001 by DooM Legacy Team.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
//
// $Log: s_ds3d.c,v $
// Revision 1.2  2001/04/06 21:36:53  judgecutor
// Added detection for speaker configuration
//
// Revision 1.1  2001/04/04 19:49:44  judgecutor
// Initial release
//
//
// DESCRIPTION:
//      General driver for 3D sound system.
//      Implementend via DirectSound3D API
//
//-----------------------------------------------------------------------------

#define INITGUID
#include <windows.h>
#include <cguid.h>
#include <dsound.h>


#define  _CREATE_DLL_
#include "../hw3dsdrv.h"
#include "../../m_fixed.h"

#undef DEBUG_TO_FILE
#define DEBUG_TO_FILE


// Internal sound stack
typedef struct stack_snd_s
{
    // Sound data
    LPDIRECTSOUNDBUFFER     dsbuffer;

    // 3D data of 3D source
    LPDIRECTSOUND3DBUFFER   dsbuffer3D;     // 3D data

    // Current parameters of 3D source
    // Valid only when source is 3D source
    // (dsbuffer3D is not NULL)
    DS3DBUFFER              parameters;

    // Currently unused
    int                     sfx_id;

    // Currently unused
    int                     LRU;

    // Flag of static source
    // Driver does not manage intrenally such sources
    int                     permanent;
    
} stack_t;

// Just for now...
#define SOUND_ALLOCATE_DELTA    16       // Amount of sources per stack incrementation
#define MAX_LRU                 16       // Maximum iterations to keep source in stack

static stack_t  *_stack;                 // Sound stack
static int      allocated_sounds;        // Size of stack

static int      srate;                   // Default sample rate


// output all debugging messages to this file
#ifdef DEBUG_TO_FILE
static HANDLE  logstream;
#endif

static LPDIRECTSOUND            DSnd            = NULL;  // Main DirectSound object
static LPDIRECTSOUNDBUFFER      PrimaryBuffer   = NULL;  // 
static LPDIRECTSOUND3DLISTENER  Listener        = NULL;  //

static DS3DLISTENER             listener_parms;          // Listener papameters

static BOOL                     virtualization;          // TRUE if HRTF virtualization enabled
static DWORD                    update_mode;             // Current update mode of listener
//static DWORD                    max_3d_buffers;

static I_Error_t I_ErrorDS3D = NULL;

//static stack_snd_t sound_stack[MAX_SOUNDS];

// Safe buffer release
#define RELEASE_BUFFER(buf)     {if (buf) { IDirectSoundBuffer_Release(buf); (buf) = NULL; }}
#define RELEASE_3DBUFFER(buf)   {if (buf) { IDirectSound3DBuffer_Release(buf); (buf) = NULL; }}

// Default flags for buffers
#define _2DSOURCE_FLAGS (DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_STICKYFOCUS | DSBCAPS_STATIC)
#define _3DSOURCE_FLAGS (DSBCAPS_CTRL3D | DSBCAPS_STATIC | DSBCAPS_MUTE3DATMAXDISTANCE | DSBCAPS_CTRLVOLUME)


enum {IS_2DSOURCE = 0, IS_3DSOURCE = 1};

#define NEW_HANDLE  -1


BOOL APIENTRY DllMain( HANDLE hModule,      // handle to DLL module
                       DWORD fdwReason,     // reason for calling function
                       LPVOID lpReserved )  // reserved
{
    // Perform actions based on the reason for calling.
    switch( fdwReason )
    {
        case DLL_PROCESS_ATTACH:
         // Initialize once for each new process.
         // Return FALSE to fail DLL load.
#ifdef DEBUG_TO_FILE
            logstream = INVALID_HANDLE_VALUE;
            logstream = CreateFile ("s_ds3d.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
                                     FILE_ATTRIBUTE_NORMAL/*|FILE_FLAG_WRITE_THROUGH*/, NULL);
            if (logstream == INVALID_HANDLE_VALUE)
                return FALSE;
#endif
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
#ifdef DEBUG_TO_FILE
            if ( logstream != INVALID_HANDLE_VALUE ) {
                CloseHandle ( logstream );
                logstream  = INVALID_HANDLE_VALUE;
            }
#endif
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

/***************************************************************
 *
 * DBG_Printf
 * Output error messages to debug log if DEBUG_TO_FILE is defined,
 * else do nothing
 *
 ***************************************************************
 */
void DBG_Printf (LPCTSTR lpFmt, ...)
{
#ifdef DEBUG_TO_FILE
    char    str[1999];
    va_list arglist;
    DWORD   bytesWritten;

    va_start  (arglist, lpFmt);
    vsprintf (str, lpFmt, arglist);
    va_end    (arglist);

    if ( logstream != INVALID_HANDLE_VALUE )
        WriteFile (logstream, str, lstrlen(str), &bytesWritten, NULL);
#endif
}


/***************************************************************
 *
 * Grow intrenal sound stack by SOUND_ALLOCATE_DELTA amount
 *
 ***************************************************************
 */
static BOOL reallocate_stack(void)
{
    stack_t*   new_stack;

    new_stack = realloc(_stack, sizeof(stack_t) * (allocated_sounds + SOUND_ALLOCATE_DELTA));
    if (new_stack)
    {
       _stack = new_stack;
       ZeroMemory(&_stack[allocated_sounds], SOUND_ALLOCATE_DELTA * sizeof(stack_t));
       allocated_sounds += SOUND_ALLOCATE_DELTA;
    }
    return (new_stack != NULL);
}


/***************************************************************
 *
 * Destroys source in stack
 *
 ***************************************************************
 */
static void kill_sound(stack_t *snd)
{
    //stack_t *snd = _stack + handle;
    
    if (snd->dsbuffer3D)
        RELEASE_3DBUFFER(snd->dsbuffer3D);
    
    if (snd->dsbuffer)
        RELEASE_BUFFER(snd->dsbuffer);

    ZeroMemory(snd, sizeof(stack_t));

}


/***************************************************************
 *
 * Returns TRUE if source currently playing
 *
 ***************************************************************
 */
BOOL is_playing(stack_t *snd)
{
    DWORD               status;
    LPDIRECTSOUNDBUFFER dsbuffer = snd->dsbuffer;

    if (dsbuffer == NULL)
        return 0;

	IDirectSoundBuffer_GetStatus(dsbuffer, &status);
    return (status & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING));

}


/***************************************************************
 *
 * Creates DirectSound buffer and fills with sound data
 * NULL sound data pointer are valid (empty buffer
 * will be created)
 *
 ***************************************************************
 */
static LPDIRECTSOUNDBUFFER create_buffer (void *data, int length, BOOL as3d)
{
    LPDIRECTSOUNDBUFFER     dsbuffer;
    HRESULT                 hr;
    WAVEFORMATEX            wfm;
    DSBUFFERDESC            dsbdesc;
    LPVOID                  lpvAudio1;              // receives address of lock start
    DWORD                   dwBytes1;               // receives number of bytes locked
    LPVOID                  lpvAudio2;              // receives address of lock start
    DWORD                   dwBytes2;               // receives number of bytes locked

    ZeroMemory (&wfm, sizeof(WAVEFORMATEX));
    wfm.wFormatTag = WAVE_FORMAT_PCM;
    wfm.nChannels = 1;
    wfm.nSamplesPerSec = data?*((unsigned short*)data+1):srate;      //mostly 11025, but some at 22050.
    wfm.wBitsPerSample = 8;
    wfm.nBlockAlign = wfm.wBitsPerSample / 8 * wfm.nChannels;
    wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign;

    // Set up DSBUFFERDESC structure.
    ZeroMemory (&dsbdesc, sizeof(DSBUFFERDESC) );
    dsbdesc.dwSize = sizeof (DSBUFFERDESC);
    dsbdesc.dwFlags = as3d?_3DSOURCE_FLAGS:_2DSOURCE_FLAGS;
    dsbdesc.dwBufferBytes = length;
    dsbdesc.lpwfxFormat = &wfm;

    // DirectX 7.0 and above!
    // Try to enable full HRTF virtualization algorithm for 
    // two-speakers or headphones
    if (as3d) 
        dsbdesc.guid3DAlgorithm = (virtualization?DS3DALG_HRTF_FULL:DS3DALG_DEFAULT);

    hr = IDirectSound_CreateSoundBuffer (DSnd, &dsbdesc, &dsbuffer, NULL);

    // CreateSoundBuffer might return DS_NO_VIRTUALIZATION so uses FAILED
    // macro rather than check explictly for DS_OK value
    if (FAILED(hr))
    {
        DBG_Printf("CreateSoundBuffer FAILED. Code %d\n", hr);
        return NULL;
    }

    if (data)
    {
        hr = IDirectSoundBuffer_Lock (dsbuffer, 0, length, &lpvAudio1, &dwBytes1, &lpvAudio2, &dwBytes2, 0);

        // If DSERR_BUFFERLOST is returned, restore and retry lock. 
        if (hr == DSERR_BUFFERLOST) 
        { 
            hr = IDirectSoundBuffer_Restore (dsbuffer);
            if( FAILED (hr) )
                I_ErrorDS3D("Restore fail on %x, code %d\n",dsbuffer, hr);
            hr = IDirectSoundBuffer_Lock (dsbuffer, 0, length, &lpvAudio1, &dwBytes1, NULL, NULL, 0);
            if( FAILED (hr) )
                I_ErrorDS3D("Lock fail(2) on %x, code %d\n",dsbuffer, hr);
        }
        else
            if( FAILED (hr) )
                I_ErrorDS3D("Lock fail(1) on %x, code %d\n",dsbuffer, hr);

        // copy wave data into the buffer (note: dwBytes1 should equal to dsbdesc->dwBufferBytes ...)
        CopyMemory (lpvAudio1, (byte*)data+8, dwBytes1);

        if ( dwBytes2 && lpvAudio2)  
            CopyMemory(lpvAudio2, ((byte*)data + 8) + dwBytes1, dwBytes2); 

    
        // finally, unlock the buffer
        hr = IDirectSoundBuffer_Unlock (dsbuffer, lpvAudio1, dwBytes1, lpvAudio2, dwBytes2);

        if( FAILED (hr) )
            I_ErrorDS3D("Unlock fail on %x, code %d\n",dsbuffer, hr);
    }

    return dsbuffer;
}


/***************************************************************
 *
 * Creates 3D source data buffer
 *
 ***************************************************************
 */
static LPDIRECTSOUND3DBUFFER create_3dbuffer(LPDIRECTSOUNDBUFFER dsbuffer, LPDIRECTSOUND3DBUFFER source3d)
{
    HRESULT hr;

    hr = IDirectSoundBuffer_QueryInterface(dsbuffer,
            &IID_IDirectSound3DBuffer, (void **)&source3d);

    if (FAILED(hr))
    {
        DBG_Printf("Couldn't obtain 3D Buffer interface. Code %d\n", hr);
        return NULL;
    }

    if (hr == DS_NO_VIRTUALIZATION)
    {
        DBG_Printf("The 3D virtualization not supported under this OS.\n");
            virtualization = FALSE;
    }
    return source3d;
}


/***************************************************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -