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

📄 dsound_wrapper.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: dsound_wrapper.c,v 1.3 2003/03/02 08:01:45 dmazzoni 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>#define INITGUID     // Needed to build IID_IDirectSoundNotify. See objbase.h for info.#include <objbase.h>#include <unknwn.h>#include "dsound_wrapper.h"#include "pa_trace.h"/************************************************************************************/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 SUPPORT_AUDIO_CAPTURE    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;    }#endif /* SUPPORT_AUDIO_CAPTURE */    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 = DirectSoundCreate( lpGUID, &dsw->dsw_pDirectSound, NULL );    if( hr != DS_OK ) return hr;    return hr;}/************************************************************************************/HRESULT DSW_InitOutputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, int 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_BytesPerFrame = 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();    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 = 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;        AddTraceMessage("dsw_CounterTicksPerBuffer = %d\n", dsw->dsw_CounterTicksPerBuffer.LowPart );    }    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_BytesPerFrame;    /* printf("DSW_InitOutputBuffer: playCursor = %d, writeCursor = %d\n", playCursor, dsw->dsw_WriteOffset ); */    return DS_OK;}/************************************************************************************/HRESULT DSW_StartOutput( DSoundWrapper *dsw ){    HRESULT        hr;    QueryPerformanceCounter( &dsw->dsw_LastPlayTime );    dsw->dsw_LastPlayCursor = 0;    dsw->dsw_FramesPlayed = 0;    hr = IDirectSoundBuffer_SetCurrentPosition( dsw->dsw_OutputBuffer, 0 );    if( hr != DS_OK )    {        return hr;    }    // Start the buffer playback in a loop.    if( dsw->dsw_OutputBuffer != NULL )    {        hr = IDirectSoundBuffer_Play( dsw->dsw_OutputBuffer, 0, 0, DSBPLAY_LOOPING );        if( hr != DS_OK )        {            return hr;        }        dsw->dsw_OutputRunning = TRUE;    }    return 0;}/************************************************************************************/HRESULT DSW_StopOutput( DSoundWrapper *dsw ){    // Stop the buffer playback    if( dsw->dsw_OutputBuffer != NULL )    {        dsw->dsw_OutputRunning = FALSE;        return IDirectSoundBuffer_Stop( dsw->dsw_OutputBuffer );    }    else return 0;}/************************************************************************************/HRESULT DSW_QueryOutputSpace( DSoundWrapper *dsw, long *bytesEmpty ){    HRESULT hr;    DWORD   playCursor;    DWORD   writeCursor;    long    numBytesEmpty;    long    playWriteGap;    // Query to see how much room is in buffer.    // Note: Even though writeCursor is not used, it must be passed to prevent DirectSound from dieing    // under WinNT. The Microsoft documentation says we can pass NULL but apparently not.    // Thanks to Max Rheiner for the fix.    hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &writeCursor );    if( hr != DS_OK )    {        return hr;

⌨️ 快捷键说明

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