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

📄 dsound_wrapper.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: dsound_wrapper.c,v 1.2 2004/04/22 04:19:51 mbrubeck Exp $ * Simplified DirectSound interface. * * Author: Phil Burk & Robert Marsanyi * * PortAudio Portable Real-Time Audio Library * For more information see: http://www.softsynth.com/portaudio/ * DirectSound Implementation * Copyright (c) 1999-2000 Phil Burk & Robert Marsanyi * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */#include <stdio.h>#include <stdlib.h>#include <math.h>#include "dsound_wrapper.h"#include "pa_trace.h"/*    Rather than linking with dxguid.a or using "#define INITGUID" to force a    header file to instantiate the required GUID(s), we define them directly    below.*/#include <initguid.h> // needed for the DEFINE_GUID macroDEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);/************************************************************************************/DSoundEntryPoints dswDSoundEntryPoints = { 0, 0, 0, 0, 0, 0, 0 };/************************************************************************************/static HRESULT WINAPI DummyDirectSoundCreate(LPGUID lpcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter){    (void)lpcGuidDevice; /* unused parameter */    (void)ppDS; /* unused parameter */    (void)pUnkOuter; /* unused parameter */    return E_NOTIMPL;}static HRESULT WINAPI DummyDirectSoundEnumerateW(LPDSENUMCALLBACKW lpDSEnumCallback, LPVOID lpContext){    (void)lpDSEnumCallback; /* unused parameter */    (void)lpContext; /* unused parameter */    return E_NOTIMPL;}static HRESULT WINAPI DummyDirectSoundEnumerateA(LPDSENUMCALLBACKA lpDSEnumCallback, LPVOID lpContext){    (void)lpDSEnumCallback; /* unused parameter */    (void)lpContext; /* unused parameter */    return E_NOTIMPL;}static HRESULT WINAPI DummyDirectSoundCaptureCreate(LPGUID lpcGUID, LPDIRECTSOUNDCAPTURE *lplpDSC, LPUNKNOWN pUnkOuter){    (void)lpcGUID; /* unused parameter */    (void)lplpDSC; /* unused parameter */    (void)pUnkOuter; /* unused parameter */    return E_NOTIMPL;}static HRESULT WINAPI DummyDirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW lpDSCEnumCallback, LPVOID lpContext){    (void)lpDSCEnumCallback; /* unused parameter */    (void)lpContext; /* unused parameter */    return E_NOTIMPL;}static HRESULT WINAPI DummyDirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA lpDSCEnumCallback, LPVOID lpContext){    (void)lpDSCEnumCallback; /* unused parameter */    (void)lpContext; /* unused parameter */    return E_NOTIMPL;}/************************************************************************************/void DSW_InitializeDSoundEntryPoints(void){    dswDSoundEntryPoints.hInstance_ = LoadLibrary("dsound.dll");    if( dswDSoundEntryPoints.hInstance_ != NULL )    {        dswDSoundEntryPoints.DirectSoundCreate =                (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN))                GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundCreate" );        if( dswDSoundEntryPoints.DirectSoundCreate == NULL )            dswDSoundEntryPoints.DirectSoundCreate = DummyDirectSoundCreate;        dswDSoundEntryPoints.DirectSoundEnumerateW =                (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))                GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundEnumerateW" );        if( dswDSoundEntryPoints.DirectSoundEnumerateW == NULL )            dswDSoundEntryPoints.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;        dswDSoundEntryPoints.DirectSoundEnumerateA =                (HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))                GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundEnumerateA" );        if( dswDSoundEntryPoints.DirectSoundEnumerateA == NULL )            dswDSoundEntryPoints.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;        dswDSoundEntryPoints.DirectSoundCaptureCreate =                (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUNDCAPTURE *, LPUNKNOWN))                GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundCaptureCreate" );        if( dswDSoundEntryPoints.DirectSoundCaptureCreate == NULL )            dswDSoundEntryPoints.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;        dswDSoundEntryPoints.DirectSoundCaptureEnumerateW =                (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))                GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundCaptureEnumerateW" );        if( dswDSoundEntryPoints.DirectSoundCaptureEnumerateW == NULL )            dswDSoundEntryPoints.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;        dswDSoundEntryPoints.DirectSoundCaptureEnumerateA =                (HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))                GetProcAddress( dswDSoundEntryPoints.hInstance_, "DirectSoundCaptureEnumerateA" );        if( dswDSoundEntryPoints.DirectSoundCaptureEnumerateA == NULL )            dswDSoundEntryPoints.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;    }    else    {        /* initialize with dummy entry points to make live easy when ds isn't present */        dswDSoundEntryPoints.DirectSoundCreate = DummyDirectSoundCreate;        dswDSoundEntryPoints.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;        dswDSoundEntryPoints.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;        dswDSoundEntryPoints.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;        dswDSoundEntryPoints.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;        dswDSoundEntryPoints.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;    }}/************************************************************************************/void DSW_TerminateDSoundEntryPoints(void){    if( dswDSoundEntryPoints.hInstance_ != NULL )    {        FreeLibrary( dswDSoundEntryPoints.hInstance_ );        dswDSoundEntryPoints.hInstance_ = NULL;        /* ensure that we crash reliably if the entry points arent initialised */        dswDSoundEntryPoints.DirectSoundCreate = 0;        dswDSoundEntryPoints.DirectSoundEnumerateW = 0;        dswDSoundEntryPoints.DirectSoundEnumerateA = 0;        dswDSoundEntryPoints.DirectSoundCaptureCreate = 0;        dswDSoundEntryPoints.DirectSoundCaptureEnumerateW = 0;        dswDSoundEntryPoints.DirectSoundCaptureEnumerateA = 0;    }}/************************************************************************************/void DSW_Term( DSoundWrapper *dsw ){    // Cleanup the sound buffers    if (dsw->dsw_OutputBuffer)    {        IDirectSoundBuffer_Stop( dsw->dsw_OutputBuffer );        IDirectSoundBuffer_Release( dsw->dsw_OutputBuffer );        dsw->dsw_OutputBuffer = NULL;    }    if (dsw->dsw_InputBuffer)    {        IDirectSoundCaptureBuffer_Stop( dsw->dsw_InputBuffer );        IDirectSoundCaptureBuffer_Release( dsw->dsw_InputBuffer );        dsw->dsw_InputBuffer = NULL;    }    if (dsw->dsw_pDirectSoundCapture)    {        IDirectSoundCapture_Release( dsw->dsw_pDirectSoundCapture );        dsw->dsw_pDirectSoundCapture = NULL;    }    if (dsw->dsw_pDirectSound)    {        IDirectSound_Release( dsw->dsw_pDirectSound );        dsw->dsw_pDirectSound = NULL;    }}/************************************************************************************/HRESULT DSW_Init( DSoundWrapper *dsw ){    memset( dsw, 0, sizeof(DSoundWrapper) );    return 0;}/************************************************************************************/HRESULT DSW_InitOutputDevice( DSoundWrapper *dsw, LPGUID lpGUID ){    // Create the DS object    HRESULT hr = dswDSoundEntryPoints.DirectSoundCreate( lpGUID, &dsw->dsw_pDirectSound, NULL );    if( hr != DS_OK ) return hr;    return hr;}/************************************************************************************/HRESULT DSW_InitOutputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, WORD nChannels, int bytesPerBuffer ){    DWORD          dwDataLen;    DWORD          playCursor;    HRESULT        result;    LPDIRECTSOUNDBUFFER pPrimaryBuffer;    HWND           hWnd;    HRESULT        hr;    WAVEFORMATEX   wfFormat;    DSBUFFERDESC   primaryDesc;    DSBUFFERDESC   secondaryDesc;    unsigned char* pDSBuffData;    LARGE_INTEGER  counterFrequency;    dsw->dsw_OutputSize = bytesPerBuffer;    dsw->dsw_OutputRunning = FALSE;    dsw->dsw_OutputUnderflows = 0;    dsw->dsw_FramesWritten = 0;    dsw->dsw_BytesPerOutputFrame = nChannels * sizeof(short);    // We were using getForegroundWindow() but sometimes the ForegroundWindow may not be the    // applications's window. Also if that window is closed before the Buffer is closed    // then DirectSound can crash. (Thanks for Scott Patterson for reporting this.)    // So we will use GetDesktopWindow() which was suggested by Miller Puckette.    // hWnd = GetForegroundWindow();    //    //  FIXME: The example code I have on the net creates a hidden window that    //      is managed by our code - I think we should do that - one hidden    //      window for the whole of Pa_DS    //    hWnd = GetDesktopWindow();    // Set cooperative level to DSSCL_EXCLUSIVE so that we can get 16 bit output, 44.1 KHz.    // Exclusize also prevents unexpected sounds from other apps during a performance.    if ((hr = IDirectSound_SetCooperativeLevel( dsw->dsw_pDirectSound,              hWnd, DSSCL_EXCLUSIVE)) != DS_OK)    {        return hr;    }    // -----------------------------------------------------------------------    // Create primary buffer and set format just so we can specify our custom format.    // Otherwise we would be stuck with the default which might be 8 bit or 22050 Hz.    // Setup the primary buffer description    ZeroMemory(&primaryDesc, sizeof(DSBUFFERDESC));    primaryDesc.dwSize        = sizeof(DSBUFFERDESC);    primaryDesc.dwFlags       = DSBCAPS_PRIMARYBUFFER; // all panning, mixing, etc done by synth    primaryDesc.dwBufferBytes = 0;    primaryDesc.lpwfxFormat   = NULL;    // Create the buffer    if ((result = IDirectSound_CreateSoundBuffer( dsw->dsw_pDirectSound,                  &primaryDesc, &pPrimaryBuffer, NULL)) != DS_OK) return result;    // Define the buffer format    wfFormat.wFormatTag = WAVE_FORMAT_PCM;    wfFormat.nChannels = nChannels;    wfFormat.nSamplesPerSec = nFrameRate;    wfFormat.wBitsPerSample = 8 * sizeof(short);    wfFormat.nBlockAlign = (WORD)(wfFormat.nChannels * (wfFormat.wBitsPerSample / 8));    wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign;    wfFormat.cbSize = 0;  /* No extended format info. */    // Set the primary buffer's format    if((result = IDirectSoundBuffer_SetFormat( pPrimaryBuffer, &wfFormat)) != DS_OK) return result;    // ----------------------------------------------------------------------    // Setup the secondary buffer description    ZeroMemory(&secondaryDesc, sizeof(DSBUFFERDESC));    secondaryDesc.dwSize = sizeof(DSBUFFERDESC);    secondaryDesc.dwFlags =  DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;    secondaryDesc.dwBufferBytes = bytesPerBuffer;    secondaryDesc.lpwfxFormat = &wfFormat;    // Create the secondary buffer    if ((result = IDirectSound_CreateSoundBuffer( dsw->dsw_pDirectSound,                  &secondaryDesc, &dsw->dsw_OutputBuffer, NULL)) != DS_OK) return result;    // Lock the DS buffer    if ((result = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, 0, dsw->dsw_OutputSize, (LPVOID*)&pDSBuffData,                                           &dwDataLen, NULL, 0, 0)) != DS_OK) return result;    // Zero the DS buffer    ZeroMemory(pDSBuffData, dwDataLen);    // Unlock the DS buffer    if ((result = IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, pDSBuffData, dwDataLen, NULL, 0)) != DS_OK) return result;    if( QueryPerformanceFrequency( &counterFrequency ) )    {        int framesInBuffer = bytesPerBuffer / (nChannels * sizeof(short));        dsw->dsw_CounterTicksPerBuffer.QuadPart = (counterFrequency.QuadPart * framesInBuffer) / nFrameRate;    }    else    {        dsw->dsw_CounterTicksPerBuffer.QuadPart = 0;    }    // Let DSound set the starting write position because if we set it to zero, it looks like the    // buffer is full to begin with. This causes a long pause before sound starts when using large buffers.    hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &dsw->dsw_WriteOffset );    if( hr != DS_OK )    {        return hr;    }    dsw->dsw_FramesWritten = dsw->dsw_WriteOffset / dsw->dsw_BytesPerOutputFrame;

⌨️ 快捷键说明

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