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

📄 pa_win_ds.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 4 页
字号:
            return paInvalidChannelCount;        /* validate outputStreamInfo */        if( outputParameters->hostApiSpecificStreamInfo )            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */    }    else    {        outputChannelCount = 0;    }        /*        IMPLEMENT ME:            - if a full duplex stream is requested, check that the combination                of input and output parameters is supported if necessary            - check that the device supports sampleRate        Because the buffer adapter handles conversion between all standard        sample formats, the following checks are only required if paCustomFormat        is implemented, or under some other unusual conditions.            - check that input device can support inputSampleFormat, or that                we have the capability to convert from outputSampleFormat to                a native format            - check that output device can support outputSampleFormat, or that                we have the capability to convert from outputSampleFormat to                a native format    */    return paFormatIsSupported;}/*************************************************************************** Determine minimum number of buffers required for this host based** on minimum latency. Latency can be optionally set by user by setting** an environment variable. For example, to set latency to 200 msec, put:****    set PA_MIN_LATENCY_MSEC=200**** in the AUTOEXEC.BAT file and reboot.** If the environment variable is not set, then the latency will be determined** based on the OS. Windows NT has higher latency than Win95.*/#define PA_LATENCY_ENV_NAME  ("PA_MIN_LATENCY_MSEC")#define PA_ENV_BUF_SIZE  (32)static int PaWinDs_GetMinLatencyFrames( double sampleRate ){    char      envbuf[PA_ENV_BUF_SIZE];    DWORD     hresult;    int       minLatencyMsec = 0;    /* Let user determine minimal latency by setting environment variable. */    hresult = GetEnvironmentVariable( PA_LATENCY_ENV_NAME, envbuf, PA_ENV_BUF_SIZE );    if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) )    {        minLatencyMsec = atoi( envbuf );    }    else    {        minLatencyMsec = PaWinDS_GetMinSystemLatency();#if PA_USE_HIGH_LATENCY        PRINT(("PA - Minimum Latency set to %d msec!\n", minLatencyMsec ));#endif    }    return (int) (minLatencyMsec * sampleRate * SECONDS_PER_MSEC);}/***********************************************************************************//* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */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 ){    PaError result = paNoError;    PaWinDsHostApiRepresentation *winDsHostApi = (PaWinDsHostApiRepresentation*)hostApi;    PaWinDsStream *stream = 0;    int inputChannelCount, outputChannelCount;    PaSampleFormat inputSampleFormat, outputSampleFormat;    PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;    unsigned long suggestedInputLatencyFrames, suggestedOutputLatencyFrames;    if( inputParameters )    {        inputChannelCount = inputParameters->channelCount;        inputSampleFormat = inputParameters->sampleFormat;        suggestedInputLatencyFrames = (unsigned long)(inputParameters->suggestedLatency * sampleRate);        /* IDEA: the following 3 checks could be performed by default by pa_front            unless some flag indicated otherwise */                    /* unless alternate device specification is supported, reject the use of            paUseHostApiSpecificDeviceSpecification */        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )            return paInvalidDevice;        /* check that input device can support inputChannelCount */        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )            return paInvalidChannelCount;                    /* validate hostApiSpecificStreamInfo */        if( inputParameters->hostApiSpecificStreamInfo )            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */    }    else    {        inputChannelCount = 0;        suggestedInputLatencyFrames = 0;    }    if( outputParameters )    {        outputChannelCount = outputParameters->channelCount;        outputSampleFormat = outputParameters->sampleFormat;        suggestedOutputLatencyFrames = (unsigned long)(outputParameters->suggestedLatency * sampleRate);        /* unless alternate device specification is supported, reject the use of            paUseHostApiSpecificDeviceSpecification */        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )            return paInvalidDevice;        /* check that output device can support inputChannelCount */        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )            return paInvalidChannelCount;        /* validate hostApiSpecificStreamInfo */        if( outputParameters->hostApiSpecificStreamInfo )            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */                }    else    {        outputChannelCount = 0;        suggestedOutputLatencyFrames = 0;    }    /*        IMPLEMENT ME:        ( the following two checks are taken care of by PaUtil_InitializeBufferProcessor() )            - check that input device can support inputSampleFormat, or that                we have the capability to convert from outputSampleFormat to                a native format            - check that output device can support outputSampleFormat, or that                we have the capability to convert from outputSampleFormat to                a native format            - if a full duplex stream is requested, check that the combination                of input and output parameters is supported            - check that the device supports sampleRate            - alter sampleRate to a close allowable rate if possible / necessary            - validate suggestedInputLatency and suggestedOutputLatency parameters,                use default values where necessary    */    /* validate platform specific flags */    if( (streamFlags & paPlatformSpecificFlags) != 0 )        return paInvalidFlag; /* unexpected platform specific flag */    stream = (PaWinDsStream*)PaUtil_AllocateMemory( sizeof(PaWinDsStream) );    if( !stream )    {        result = paInsufficientMemory;        goto error;    }    if( streamCallback )    {        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,                                               &winDsHostApi->callbackStreamInterface, streamCallback, userData );    }    else    {        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,                                               &winDsHostApi->blockingStreamInterface, streamCallback, userData );    }        PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );    if( inputParameters )    {        /* IMPLEMENT ME - establish which  host formats are available */        hostInputSampleFormat =            PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputParameters->sampleFormat );    }    if( outputParameters )    {        /* IMPLEMENT ME - establish which  host formats are available */        hostOutputSampleFormat =            PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputParameters->sampleFormat );    }        result =  PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,                    inputChannelCount, inputSampleFormat, hostInputSampleFormat,                    outputChannelCount, outputSampleFormat, hostOutputSampleFormat,                    sampleRate, streamFlags, framesPerBuffer,                    framesPerBuffer, /* ignored in paUtilVariableHostBufferSizePartialUsageAllowed mode. */                /* This next mode is required because DS can split the host buffer when it wraps around. */                    paUtilVariableHostBufferSizePartialUsageAllowed,                    streamCallback, userData );    if( result != paNoError )        goto error;    stream->streamRepresentation.streamInfo.inputLatency =            PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor);   /* FIXME: not initialised anywhere else */    stream->streamRepresentation.streamInfo.outputLatency =            PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor);    /* FIXME: not initialised anywhere else */    stream->streamRepresentation.streamInfo.sampleRate = sampleRate;    /* DirectSound specific initialization */    {        HRESULT          hr;        int              bytesPerDirectSoundBuffer;        DSoundWrapper   *dsw;        int              userLatencyFrames;        int              minLatencyFrames;        stream->timerID = 0;        dsw = &stream->directSoundWrapper;        DSW_Init( dsw );    /* Get system minimum latency. */        minLatencyFrames = PaWinDs_GetMinLatencyFrames( sampleRate );    /* Let user override latency by passing latency parameter. */        userLatencyFrames = (suggestedInputLatencyFrames > suggestedOutputLatencyFrames)                    ? suggestedInputLatencyFrames                    : suggestedOutputLatencyFrames;        if( userLatencyFrames > 0 ) minLatencyFrames = userLatencyFrames;    /* Calculate stream->framesPerDSBuffer depending on framesPerBuffer */        if( framesPerBuffer == paFramesPerBufferUnspecified )        {        /* App support variable framesPerBuffer */            stream->framesPerDSBuffer = minLatencyFrames;            stream->streamRepresentation.streamInfo.outputLatency = (double)(minLatencyFrames - 1) / sampleRate;        }        else        {        /* Round up to number of buffers needed to guarantee that latency. */            int numUserBuffers = (minLatencyFrames + framesPerBuffer - 1) / framesPerBuffer;            if( numUserBuffers < 1 ) numUserBuffers = 1;            numUserBuffers += 1; /* So we have latency worth of buffers ahead of current buffer. */            stream->framesPerDSBuffer = framesPerBuffer * numUserBuffers;            stream->streamRepresentation.streamInfo.outputLatency = (double)(framesPerBuffer * (numUserBuffers-1)) / sampleRate;        }        {            /** @todo REVIEW: this calculation seems incorrect to me - rossb. */            int msecLatency = (int) ((stream->framesPerDSBuffer * MSEC_PER_SECOND) / sampleRate);            PRINT(("PortAudio on DirectSound - Latency = %d frames, %d msec\n", stream->framesPerDSBuffer, msecLatency ));        }        /* ------------------ OUTPUT */        if( outputParameters )        {            /*            PaDeviceInfo *deviceInfo = hostApi->deviceInfos[ outputParameters->device ];            DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", outputParameters->device));            */                        bytesPerDirectSoundBuffer = stream->framesPerDSBuffer * outputParameters->channelCount * sizeof(short);            if( bytesPerDirectSoundBuffer < DSBSIZE_MIN )            {                result = paBufferTooSmall;                goto error;            }            else if( bytesPerDirectSoundBuffer > DSBSIZE_MAX )            {                result = paBufferTooBig;                goto error;            }            hr = dswDSoundEntryPoints.DirectSoundCreate( winDsHostApi->winDsDeviceInfos[outputParameters->device].lpGUID,                &dsw->dsw_pDirectSound,   NULL );            if( hr != DS_OK )            {                ERR_RPT(("PortAudio: DirectSoundCreate() failed!\n"));                result = paUnanticipatedHostError;                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );                goto error;            }            hr = DSW_InitOutputBuffer( dsw,                                       (unsigned long) (sampleRate + 0.5),                                       (WORD)outputParameters->channelCount, bytesPerDirectSoundBuffer );            DBUG(("DSW_InitOutputBuffer() returns %x\n", hr));            if( hr != DS_OK )            {                result = paUnanticipatedHostError;                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );                goto error;            }            /* Calculate value used in latency calculation to avoid real-time divides. */            stream->secondsPerHostByte = 1.0 /                (stream->bufferProcessor.bytesPerHostOutputSample *                outputChannelCount * sampleRate);        }        /* ------------------ INPUT */        if( inputParameters )        {            /*            PaDeviceInfo *deviceInfo = hostApi->deviceInfos[ inputParameters->device ];            DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", inputParameters->device));            */                        bytesPerDirectSoundBuffer = stream->framesPerDSBuffer * inputParameters->channelCount * sizeof(short);            if( bytesPerDirectSoundBuffer < DSBSIZE_MIN )            {                result = paBufferTooSmall;                goto error;            }            else if( bytesPerDirectSoundBuffer > DSBSIZE_MAX )            {                result = paBufferTooBig;                goto error;            }            hr = dswDSoundEntryPoints.DirectSoundCaptureCreate( winDsHostApi->winDsDeviceInfos[inputParameters->device].lpGUID,                &dsw->dsw_pDirectSoundCapture,   NULL );            if( hr != DS_OK )            {                ERR_RPT(("PortAudio: DirectSoundCaptureCreate() failed!\n"));                result = paUnanticipatedHostError;                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );                goto error;            }            hr = DSW_InitInputBuffer( dsw,                                      (unsigned long) (sampleRate + 0.5),                                      (WORD)inputParameters->channelCount, bytesPerDirectSoundBuffer );            DBUG(("DSW_InitInputBuffer() returns %x\n", hr));            if( hr != DS_OK )            {                ERR_RPT(("PortAudio: DSW_InitInputBuffer() returns %x\n", hr));                result = paUnanticipatedHostError;                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );                goto error;            }        }    }    *s = (PaStream*)stream;    return result;error:    if( stream )        PaUtil_FreeMemory( stream );    return result;}/***********************************************************************************/static PaError Pa_TimeSlice( PaWinDsStream *stream ){    PaError           result = 0;   /* FIXME: this should be declared int and this function should also return that type (same as stream callback return type)*/    DSoundWrapper    *dsw;    long              numFrames = 0;    long              bytesEmpty = 0;    long              bytesFilled = 0;    long              bytesToXfer = 0;    long              framesToXfer = 0;    long              numInFramesReady = 0;    long              numOutFramesReady = 0;    long              bytesProcessed;    HRESULT           hresult;    double            outputLatency = 0;    PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /** @todo implement inputBufferAdcTime */    /* Input */    LPBYTE            lpInBuf1 = NULL;    LPBYTE            lpInBuf2 = NULL;    DWORD             dwInSize1 = 0;    DWORD             dwInSize2 = 0;/* Output */    LPBYTE            lpOutBuf1 = NULL;    LPBYTE            lpOutBuf2 = NULL;    DWORD             dwOutSize1 = 0;    DWORD             dwOutSize2 = 0;    dsw = &stream->directSoundWrapper;    /* How much input data is available? */    if( stream->bufferProcessor.inputChannelCount > 0 )    {        DSW_QueryInputFilled( dsw, &bytesFilled );        framesToXfer = numInFramesReady = bytesFilled / dsw->dsw_BytesPerInputFrame;        outputLatency = ((double)bytesFilled) * stream->secondsPerHostByte;        /** @todo Check for overflow */    }    /* How much output room is available? */    if( stream->bufferProcessor.outputChannelCount > 0 )    {        UINT previousUnderflowCount = dsw->dsw_OutputUnderflows;        DSW_QueryOutputSpace( dsw, &bytesEmpty );        framesToXfer = numOutFramesReady = bytesEmpty / dsw->dsw_BytesPerOutputFrame;

⌨️ 快捷键说明

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