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

📄 pa_win_ds.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * $Id: pa_win_ds.c,v 1.2 2004/04/22 04:19:51 mbrubeck Exp $ * Portable Audio I/O Library DirectSound implementation * * Based on the Open Source API proposed by Ross Bencina * Copyright (c) 1999-2002 Ross Bencina, Phil Burk * * 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. *//** @file    @todo implement paInputOverflow callback status flag        @todo implement paNeverDropInput.    @todo implement host api specific extension to set i/o buffer sizes in frames    @todo implement initialisation of PaDeviceInfo default*Latency fields (currently set to 0.)    @todo implement ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable    @todo audit handling of DirectSound result codes - in many cases we could convert a HRESULT into        a native portaudio error code. Standard DirectSound result codes are documented at msdn.    @todo implement IsFormatSupported    @todo implement PaDeviceInfo.defaultSampleRate;    @todo check that CoInitialize() CoUninitialize() are always correctly        paired, even in error cases.    @todo call PaUtil_SetLastHostErrorInfo with a specific error string (currently just "DSound error").    @todo make sure all buffers have been played before stopping the stream        when the stream callback returns paComplete    old TODOs from phil, need to work out if these have been done:        O- fix "patest_stop.c"*/#include <stdio.h>#include <string.h> /* strlen() */#include "pa_util.h"#include "pa_allocation.h"#include "pa_hostapi.h"#include "pa_stream.h"#include "pa_cpuload.h"#include "pa_process.h"#include "dsound_wrapper.h"#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */#pragma comment( lib, "dsound.lib" )#pragma comment( lib, "winmm.lib" )#endif#define PRINT(x) /* { printf x; fflush(stdout); } */#define ERR_RPT(x) PRINT(x)#define DBUG(x)  /* PRINT(x) */#define DBUGX(x) /* PRINT(x) */#define PA_USE_HIGH_LATENCY   (0)#if PA_USE_HIGH_LATENCY#define PA_WIN_9X_LATENCY     (500)#define PA_WIN_NT_LATENCY     (600)#else#define PA_WIN_9X_LATENCY     (140)#define PA_WIN_NT_LATENCY     (280)#endif#define PA_WIN_WDM_LATENCY       (120)#define SECONDS_PER_MSEC      (0.001)#define MSEC_PER_SECOND       (1000)/* prototypes for functions declared in this file */#ifdef __cplusplusextern "C"{#endif /* __cplusplus */PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );#ifdef __cplusplus}#endif /* __cplusplus */static void Terminate( struct PaUtilHostApiRepresentation *hostApi );static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,                           PaStream** s,                           const PaStreamParameters *inputParameters,                           const PaStreamParameters *outputParameters,                           double sampleRate,                           unsigned long framesPerBuffer,                           PaStreamFlags streamFlags,                           PaStreamCallback *streamCallback,                           void *userData );static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,                                  const PaStreamParameters *inputParameters,                                  const PaStreamParameters *outputParameters,                                  double sampleRate );static PaError CloseStream( PaStream* stream );static PaError StartStream( PaStream *stream );static PaError StopStream( PaStream *stream );static PaError AbortStream( PaStream *stream );static PaError IsStreamStopped( PaStream *s );static PaError IsStreamActive( PaStream *stream );static PaTime GetStreamTime( PaStream *stream );static double GetStreamCpuLoad( PaStream* stream );static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );static signed long GetStreamReadAvailable( PaStream* stream );static signed long GetStreamWriteAvailable( PaStream* stream );/* FIXME: should convert hr to a string */#define PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr ) \    PaUtil_SetLastHostErrorInfo( paDirectSound, hr, "DirectSound error" )/************************************************* DX Prototypes **********/static BOOL CALLBACK CollectGUIDsProc(LPGUID lpGUID,                                     LPCTSTR lpszDesc,                                     LPCTSTR lpszDrvName,                                     LPVOID lpContext );/************************************************************************************//********************** Structures **************************************************//************************************************************************************//* PaWinDsHostApiRepresentation - host api datastructure specific to this implementation */typedef struct PaWinDsDeviceInfo{    GUID                             guid;    GUID                            *lpGUID;    double                           sampleRates[3];} PaWinDsDeviceInfo;typedef struct{    PaUtilHostApiRepresentation inheritedHostApiRep;    PaUtilStreamInterface    callbackStreamInterface;    PaUtilStreamInterface    blockingStreamInterface;    PaUtilAllocationGroup   *allocations;    /* implementation specific data goes here */    PaWinDsDeviceInfo       *winDsDeviceInfos;} PaWinDsHostApiRepresentation;/* PaWinDsStream - a stream data structure specifically for this implementation */typedef struct PaWinDsStream{    PaUtilStreamRepresentation streamRepresentation;    PaUtilCpuLoadMeasurer cpuLoadMeasurer;    PaUtilBufferProcessor bufferProcessor;/* DirectSound specific data. */    DSoundWrapper    directSoundWrapper;    MMRESULT         timerID;    BOOL             ifInsideCallback;  /* Test for reentrancy. */    int              framesPerDSBuffer;    double           framesWritten;    double           secondsPerHostByte; /* Used to optimize latency calculation for outTime */    PaStreamCallbackFlags callbackFlags;    /* FIXME - move all below to PaUtilStreamRepresentation */    volatile int     isStarted;    volatile int     isActive;    volatile int     stopProcessing; /* stop thread once existing buffers have been returned */    volatile int     abortProcessing; /* stop thread immediately */} PaWinDsStream;/************************************************************************************** Duplicate the input string using the allocations allocator.** A NULL string is converted to a zero length string.** If memory cannot be allocated, NULL is returned.**/static char *DuplicateDeviceNameString( PaUtilAllocationGroup *allocations, const char* src ){    char *result = 0;        if( src != NULL )    {        int len = strlen(src);        result = (char*)PaUtil_GroupAllocateMemory( allocations, len + 1 );        if( result )            memcpy( (void *) result, src, len+1 );    }    else    {        result = (char*)PaUtil_GroupAllocateMemory( allocations, 1 );        if( result )            result[0] = '\0';    }    return result;}/************************************************************************************** DSDeviceNameAndGUID, DSDeviceNameAndGUIDVector used for collecting preliminary** information during device enumeration.*/typedef struct DSDeviceNameAndGUID{    char *name; // allocated from parent's allocations, never deleted by this structure    GUID guid;    LPGUID lpGUID;} DSDeviceNameAndGUID;typedef struct DSDeviceNameAndGUIDVector{    PaUtilAllocationGroup *allocations;    PaError enumerationError;    int count;    int free;    DSDeviceNameAndGUID *items; // Allocated using LocalAlloc()} DSDeviceNameAndGUIDVector;static PaError InitializeDSDeviceNameAndGUIDVector(        DSDeviceNameAndGUIDVector *guidVector, PaUtilAllocationGroup *allocations ){    PaError result = paNoError;    guidVector->allocations = allocations;    guidVector->enumerationError = paNoError;    guidVector->count = 0;    guidVector->free = 8;    guidVector->items = (DSDeviceNameAndGUID*)LocalAlloc( LMEM_FIXED, sizeof(DSDeviceNameAndGUID) * guidVector->free );    if( guidVector->items == NULL )        result = paInsufficientMemory;        return result;}static PaError ExpandDSDeviceNameAndGUIDVector( DSDeviceNameAndGUIDVector *guidVector ){    PaError result = paNoError;    DSDeviceNameAndGUID *newItems;    int i;        /* double size of vector */    int size = guidVector->count + guidVector->free;    guidVector->free += size;    newItems = (DSDeviceNameAndGUID*)LocalAlloc( LMEM_FIXED, sizeof(DSDeviceNameAndGUID) * size * 2 );    if( newItems == NULL )    {        result = paInsufficientMemory;    }    else    {        for( i=0; i < guidVector->count; ++i )        {            newItems[i].name = guidVector->items[i].name;            if( guidVector->items[i].lpGUID == NULL )            {                newItems[i].lpGUID = NULL;            }            else            {                newItems[i].lpGUID = &newItems[i].guid;                memcpy( &newItems[i].guid, guidVector->items[i].lpGUID, sizeof(GUID) );;            }        }        LocalFree( guidVector->items );        guidVector->items = newItems;    }                                    return result;}/*    it's safe to call DSDeviceNameAndGUIDVector multiple times*/static PaError TerminateDSDeviceNameAndGUIDVector( DSDeviceNameAndGUIDVector *guidVector ){    PaError result = paNoError;    if( guidVector->items != NULL )    {        if( LocalFree( guidVector->items ) != NULL )            result = paInsufficientMemory;              /** @todo this isn't the correct error to return from a deallocation failure */        guidVector->items = NULL;    }    return result;}/************************************************************************************** Collect preliminary device information during DirectSound enumeration */static BOOL CALLBACK CollectGUIDsProc(LPGUID lpGUID,                                     LPCTSTR lpszDesc,                                     LPCTSTR lpszDrvName,                                     LPVOID lpContext ){    DSDeviceNameAndGUIDVector *namesAndGUIDs = (DSDeviceNameAndGUIDVector*)lpContext;    PaError error;    (void) lpszDrvName; /* unused variable */    if( namesAndGUIDs->free == 0 )    {        error = ExpandDSDeviceNameAndGUIDVector( namesAndGUIDs );        if( error != paNoError )        {            namesAndGUIDs->enumerationError = error;            return FALSE;        }    }        /* Set GUID pointer, copy GUID to storage in DSDeviceNameAndGUIDVector. */    if( lpGUID == NULL )    {        namesAndGUIDs->items[namesAndGUIDs->count].lpGUID = NULL;    }    else    {        namesAndGUIDs->items[namesAndGUIDs->count].lpGUID =                &namesAndGUIDs->items[namesAndGUIDs->count].guid;              memcpy( &namesAndGUIDs->items[namesAndGUIDs->count].guid, lpGUID, sizeof(GUID) );    }    namesAndGUIDs->items[namesAndGUIDs->count].name =            DuplicateDeviceNameString( namesAndGUIDs->allocations, lpszDesc );    if( namesAndGUIDs->items[namesAndGUIDs->count].name == NULL )    {        namesAndGUIDs->enumerationError = paInsufficientMemory;        return FALSE;    }    ++namesAndGUIDs->count;    --namesAndGUIDs->free;        return TRUE;}              /************************************************************************************** Extract capabilities from an output device, and add it to the device info list** if successful. This function assumes that there is enough room in the** device info list to accomodate all entries.**** The device will not be added to the device list if any errors are encountered.*/static PaError AddOutputDeviceInfoFromDirectSound(        PaWinDsHostApiRepresentation *winDsHostApi, char *name, LPGUID lpGUID ){    PaUtilHostApiRepresentation  *hostApi = &winDsHostApi->inheritedHostApiRep;    PaDeviceInfo                 *deviceInfo = hostApi->deviceInfos[hostApi->info.deviceCount];    PaWinDsDeviceInfo            *winDsDeviceInfo = &winDsHostApi->winDsDeviceInfos[hostApi->info.deviceCount];    HRESULT                       hr;    LPDIRECTSOUND                 lpDirectSound;    DSCAPS                        caps;    int                           deviceOK = TRUE;    PaError                       result = paNoError;        /* Copy GUID to the device info structure. Set pointer. */    if( lpGUID == NULL )    {        winDsDeviceInfo->lpGUID = NULL;    }    else    {        memcpy( &winDsDeviceInfo->guid, lpGUID, sizeof(GUID) );        winDsDeviceInfo->lpGUID = &winDsDeviceInfo->guid;    }        /* Create a DirectSound object for the specified GUID        Note that using CoCreateInstance doesn't work on windows CE.    */    hr = dswDSoundEntryPoints.DirectSoundCreate( lpGUID, &lpDirectSound, NULL );    /** try using CoCreateInstance because DirectSoundCreate was hanging under        some circumstances - note this was probably related to the        #define BOOL short bug which has now been fixed        @todo delete this comment and the following code once we've ensured        there is no bug.    */    /*    hr = CoCreateInstance( &CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,            &IID_IDirectSound, (void**)&lpDirectSound );    if( hr == S_OK )    {        hr = IDirectSound_Initialize( lpDirectSound, lpGUID );    }    */        if( hr != DS_OK )    {        DBUG(("Cannot create DirectSound for %s. Result = 0x%x\n", name, hr ));        deviceOK = FALSE;    }    else    {        /* Query device characteristics. */

⌨️ 快捷键说明

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