pa_win_ds.c

来自「基于sip协议的网络电话源码」· C语言 代码 · 共 1,801 行 · 第 1/5 页

C
1,801
字号
            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;        /* Check for underflow */        if( dsw->dsw_OutputUnderflows != previousUnderflowCount )            stream->callbackFlags |= paOutputUnderflow;    }    if( (numInFramesReady > 0) && (numOutFramesReady > 0) )    {        framesToXfer = (numOutFramesReady < numInFramesReady) ? numOutFramesReady : numInFramesReady;    }    if( framesToXfer > 0 )    {        PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );    /* The outputBufferDacTime parameter should indicates the time at which        the first sample of the output buffer is heard at the DACs. */        timeInfo.currentTime = PaUtil_GetTime();        timeInfo.outputBufferDacTime = timeInfo.currentTime + outputLatency;        PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, stream->callbackFlags );        stream->callbackFlags = 0;            /* Input */        if( stream->bufferProcessor.inputChannelCount > 0 )        {            bytesToXfer = framesToXfer * dsw->dsw_BytesPerInputFrame;            hresult = IDirectSoundCaptureBuffer_Lock ( dsw->dsw_InputBuffer,                dsw->dsw_ReadOffset, bytesToXfer,                (void **) &lpInBuf1, &dwInSize1,                (void **) &lpInBuf2, &dwInSize2, 0);            if (hresult != DS_OK)

⌨️ 快捷键说明

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