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

📄 pa_win_ds.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        goto error;    }    memset( stream, 0, sizeof(PaWinDsStream) ); /* initialize all stream variables to 0 */    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 );    }	else	{		hostInputSampleFormat = 0;	}    if( outputParameters )    {        /* IMPLEMENT ME - establish which  host formats are available */        hostOutputSampleFormat =            PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputParameters->sampleFormat );    }    else	{		hostOutputSampleFormat = 0;	}    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;        int              userLatencyFrames;        int              minLatencyFrames;        stream->timerID = 0;    /* 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 = paWinDsDSoundEntryPoints.DirectSoundCreate( winDsHostApi->winDsDeviceInfos[outputParameters->device].lpGUID,                        &stream->pDirectSound, NULL );            if( hr != DS_OK )            {                ERR_RPT(("PortAudio: DirectSoundCreate() failed!\n"));                result = paUnanticipatedHostError;                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );                goto error;            }            hr = InitOutputBuffer( stream,                                       (unsigned long) (sampleRate + 0.5),                                       (WORD)outputParameters->channelCount, bytesPerDirectSoundBuffer );            DBUG(("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 = paWinDsDSoundEntryPoints.DirectSoundCaptureCreate( winDsHostApi->winDsDeviceInfos[inputParameters->device].lpGUID,                        &stream->pDirectSoundCapture,   NULL );            if( hr != DS_OK )            {                ERR_RPT(("PortAudio: DirectSoundCaptureCreate() failed!\n"));                result = paUnanticipatedHostError;                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );                goto error;            }            hr = InitInputBuffer( stream,                                      (unsigned long) (sampleRate + 0.5),                                      (WORD)inputParameters->channelCount, bytesPerDirectSoundBuffer );            DBUG(("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;}/************************************************************************************ * Determine how much space can be safely written to in DS buffer. * Detect underflows and overflows. * Does not allow writing into safety gap maintained by DirectSound. */static HRESULT QueryOutputSpace( PaWinDsStream *stream, long *bytesEmpty ){    HRESULT hr;    DWORD   playCursor;    DWORD   writeCursor;    long    numBytesEmpty;    long    playWriteGap;    // Query to see how much room is in buffer.    hr = IDirectSoundBuffer_GetCurrentPosition( stream->pDirectSoundOutputBuffer,            &playCursor, &writeCursor );    if( hr != DS_OK )    {        return hr;    }    // Determine size of gap between playIndex and WriteIndex that we cannot write into.    playWriteGap = writeCursor - playCursor;    if( playWriteGap < 0 ) playWriteGap += stream->outputBufferSizeBytes; // unwrap    /* DirectSound doesn't have a large enough playCursor so we cannot detect wrap-around. */    /* Attempt to detect playCursor wrap-around and correct it. */    if( stream->outputIsRunning && (stream->perfCounterTicksPerBuffer.QuadPart != 0) )    {        /* How much time has elapsed since last check. */        LARGE_INTEGER   currentTime;        LARGE_INTEGER   elapsedTime;        long            bytesPlayed;        long            bytesExpected;        long            buffersWrapped;        QueryPerformanceCounter( &currentTime );        elapsedTime.QuadPart = currentTime.QuadPart - stream->previousPlayTime.QuadPart;        stream->previousPlayTime = currentTime;        /* How many bytes does DirectSound say have been played. */        bytesPlayed = playCursor - stream->previousPlayCursor;        if( bytesPlayed < 0 ) bytesPlayed += stream->outputBufferSizeBytes; // unwrap        stream->previousPlayCursor = playCursor;        /* Calculate how many bytes we would have expected to been played by now. */        bytesExpected = (long) ((elapsedTime.QuadPart * stream->outputBufferSizeBytes) / stream->perfCounterTicksPerBuffer.QuadPart);        buffersWrapped = (bytesExpected - bytesPlayed) / stream->outputBufferSizeBytes;        if( buffersWrapped > 0 )        {            playCursor += (buffersWrapped * stream->outputBufferSizeBytes);            bytesPlayed += (buffersWrapped * stream->outputBufferSizeBytes);        }        /* Maintain frame output cursor. */        stream->framesPlayed += (bytesPlayed / stream->bytesPerOutputFrame);    }    numBytesEmpty = playCursor - stream->outputBufferWriteOffsetBytes;    if( numBytesEmpty < 0 ) numBytesEmpty += stream->outputBufferSizeBytes; // unwrap offset    /* Have we underflowed? */    if( numBytesEmpty > (stream->outputBufferSizeBytes - playWriteGap) )    {        if( stream->outputIsRunning )        {            stream->outputUnderflowCount += 1;        }        stream->outputBufferWriteOffsetBytes = writeCursor;        numBytesEmpty = stream->outputBufferSizeBytes - playWriteGap;    }    *bytesEmpty = numBytesEmpty;    return hr;}/***********************************************************************************/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)*/    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;    /* How much input data is available? */    if( stream->bufferProcessor.inputChannelCount > 0 )    {        HRESULT hr;        DWORD capturePos;        DWORD readPos;        long  filled = 0;        // Query to see how much data is in buffer.        // We don't need the capture position but sometimes DirectSound doesn't handle NULLS correctly        // so let's pass a pointer just to be safe.        hr = IDirectSoundCaptureBuffer_GetCurrentPosition( stream->pDirectSoundInputBuffer, &capturePos, &readPos );        if( hr == DS_OK )        {            filled = readPos - stream->readOffset;            if( filled < 0 ) filled += stream->inputSize; // unwrap offset            bytesFilled = filled;        }            // FIXME: what happens if IDirectSoundCaptureBuffer_GetCurrentPosition fails?        framesToXfer = numInFramesReady = bytesFilled / stream->bytesPerInputFrame;        outputLatency = ((double)bytesFilled) * stream->secondsPerHostByte;        /** @todo Check for overflow */    }    /* How much output room is available? */    if( stream->bufferProcessor.outputChannelCount > 0 )    {        UINT previousUnderflowCount = stream->outputUnderflowCount;        QueryOutputSpace( stream, &bytesEmpty );        framesToXfer = numOutFramesReady = bytesEmpty / stream->bytesPerOutputFrame;        /* Check for underflow */        if( stream->outputUnderflowCount != previousUnderflowCount )            stream->callbackFlags |= paOutputUnderflow;    }    if( (numInFramesReady > 0) && (numOutFramesReady > 0) )    {        framesToXfer = (n

⌨️ 快捷键说明

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