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

📄 pa_win_wasapi.cpp

📁 一个开源的sip源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    while(stream->closeRequest)
        Sleep(100);

    /* IMPLEMENT ME, see portaudio.h for required behavior */

    stream->running = false;

    return result;
}


static PaError AbortStream( PaStream *s )
{
    PaError result = paNoError;
    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;

    /* suppress unused variable warnings */
    stream->closeRequest = true;
    //todo something MUCH better than this
    while(stream->closeRequest)
        Sleep(100);

    /* IMPLEMENT ME, see portaudio.h for required behavior */

    return result;
}


static PaError IsStreamStopped( PaStream *s )
{
    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;

    return !stream->running;
}


static PaError IsStreamActive( PaStream *s )
{
    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
    return stream->running;
}


static PaTime GetStreamTime( PaStream *s )
{
    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;

    /* suppress unused variable warnings */
    (void) stream;

    /* IMPLEMENT ME, see portaudio.h for required behavior*/

	//this is lame ds and mme does the same thing, quite useless method imho
	//why dont we fetch the time in the pa callbacks?
	//at least its doing to be clocked to something
    return PaUtil_GetTime();
}


static double GetStreamCpuLoad( PaStream* s )
{
    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;

    return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
}


/*
    As separate stream interfaces are used for blocking and callback
    streams, the following functions can be guaranteed to only be called
    for blocking streams.
*/

static PaError ReadStream( PaStream* s,
                           void *buffer,
                           unsigned long frames )
{
    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;

    /* suppress unused variable warnings */
    (void) buffer;
    (void) frames;
    (void) stream;

    /* IMPLEMENT ME, see portaudio.h for required behavior*/

    return paNoError;
}


static PaError WriteStream( PaStream* s,
                            const void *buffer,
                            unsigned long frames )
{
    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;

    /* suppress unused variable warnings */
    (void) buffer;
    (void) frames;
    (void) stream;

    /* IMPLEMENT ME, see portaudio.h for required behavior*/

    return paNoError;
}


static signed long GetStreamReadAvailable( PaStream* s )
{
    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;

    /* suppress unused variable warnings */
    (void) stream;

    /* IMPLEMENT ME, see portaudio.h for required behavior*/

    return 0;
}


static signed long GetStreamWriteAvailable( PaStream* s )
{
    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;

    /* suppress unused variable warnings */
    (void) stream;

    /* IMPLEMENT ME, see portaudio.h for required behavior*/

    return 0;
}



/*
    ExampleHostProcessingLoop() illustrates the kind of processing which may
    occur in a host implementation.

*/
static void WaspiHostProcessingLoop( void *inputBuffer,  long inputFrames,
                                     void *outputBuffer, long outputFrames,
                                     void *userData )
{
    PaWinWasapiStream *stream = (PaWinWasapiStream*)userData;
    PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* IMPLEMENT ME */
    int callbackResult;
    unsigned long framesProcessed;

    PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );


    /*
        IMPLEMENT ME:
            - generate timing information
            - handle buffer slips
    */

    /*
        If you need to byte swap or shift inputBuffer to convert it into a
        portaudio format, do it here.
    */



    PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, 0 /* IMPLEMENT ME: pass underflow/overflow flags when necessary */ );

    /*
        depending on whether the host buffers are interleaved, non-interleaved
        or a mixture, you will want to call PaUtil_SetInterleaved*Channels(),
        PaUtil_SetNonInterleaved*Channel() or PaUtil_Set*Channel() here.
    */

    if( stream->bufferProcessor.inputChannelCount > 0 )
    {
        PaUtil_SetInputFrameCount( &stream->bufferProcessor, inputFrames );
        PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor,
            0, /* first channel of inputBuffer is channel 0 */
            inputBuffer,
            0 ); /* 0 - use inputChannelCount passed to init buffer processor */
    }

    if( stream->bufferProcessor.outputChannelCount > 0 )
    {
        PaUtil_SetOutputFrameCount( &stream->bufferProcessor, outputFrames);
        PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor,
            0, /* first channel of outputBuffer is channel 0 */
            outputBuffer,
            0 ); /* 0 - use outputChannelCount passed to init buffer processor */
    }

    /* you must pass a valid value of callback result to PaUtil_EndBufferProcessing()
        in general you would pass paContinue for normal operation, and
        paComplete to drain the buffer processor's internal output buffer.
        You can check whether the buffer processor's output buffer is empty
        using PaUtil_IsBufferProcessorOuputEmpty( bufferProcessor )
    */
    callbackResult = paContinue;
    framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult );


    /*
        If you need to byte swap or shift outputBuffer to convert it to
        host format, do it here.
    */

    PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );


    if( callbackResult == paContinue )
    {
        /* nothing special to do */
    }
    else if( callbackResult == paAbort )
    {
        /* IMPLEMENT ME - finish playback immediately  */

        /* once finished, call the finished callback */
        if( stream->streamRepresentation.streamFinishedCallback != 0 )
            stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
    }
    else
    {
        /* User callback has asked us to stop with paComplete or other non-zero value */

        /* IMPLEMENT ME - finish playback once currently queued audio has completed  */

        /* once finished, call the finished callback */
        if( stream->streamRepresentation.streamFinishedCallback != 0 )
            stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
    }
}



VOID
ProcThread(void *param){

	HRESULT hResult;

    DWORD stuff=0;
    HANDLE thCarac = pAvSetMmThreadCharacteristics("Pro Audio",&stuff);
    if (!thCarac){
        PRINT(("AvSetMmThreadCharacteristics failed!\n"));
    }

    BOOL prio = pAvSetMmThreadPriority(thCarac,AVRT_PRIORITY_NORMAL);
    if (!prio){
        PRINT(("AvSetMmThreadPriority failed!\n"));
    }


    PaWinWasapiStream *stream = (PaWinWasapiStream*)param;

    HANDLE context;
    GUID threadOrderGUID;
    memset(&threadOrderGUID,0,sizeof(GUID));
    LARGE_INTEGER large;

    large.QuadPart = stream->out.period;

    BOOL ok = pAvRtCreateThreadOrderingGroup(&context,
        &large,
        &threadOrderGUID,
#ifdef _DEBUG
        0 //THREAD_ORDER_GROUP_INFINITE_TIMEOUT
#else
        0 //default is 5 times the 2nd param
#endif
        //TEXT("Audio")
        );

    if (!ok){
        PRINT(("AvRtCreateThreadOrderingGroup failed!\n"));
    }

	//debug
    {
        HANDLE hh       = GetCurrentThread();
        int  currprio   = GetThreadPriority(hh);
        DWORD currclass = GetPriorityClass(GetCurrentProcess());
        PRINT(("currprio 0x%X currclass 0x%X\n",currprio,currclass));
    }


    //fill up initial buffer latency??

	if (stream->out.client){
		hResult = stream->out.client->Start();
		if (hResult != S_OK)
			logAUDCLNT_E(hResult);
	}

    stream->running = true;

    while(!stream->closeRequest){
        BOOL answer = pAvRtWaitOnThreadOrderingGroup(context);
        if (!answer){
            PRINT(("AvRtWaitOnThreadOrderingGroup failed\n"));
        }

        unsigned long usingBS = stream->out.framesPerHostCallback;

        UINT32 padding=0;
        hResult = stream->out.client->GetCurrentPadding(&padding);
        logAUDCLNT_E(hResult);

        //buffer full dont pursue
        if (padding == stream->out.bufferSize)
            continue;

        //if something is already inside
        if (padding > 0){
            usingBS = stream->out.bufferSize-padding;
            if (usingBS > stream->out.framesPerHostCallback){
                //PRINT(("underflow! %d\n",usingBS));
            }
            else if (usingBS < stream->out.framesPerHostCallback){
                //PRINT(("overflow! %d\n",usingBS));
            }
        }
        else
            usingBS = stream->out.framesPerHostCallback;


        BYTE*indata =0;
        BYTE*outdata=0;

        hResult = stream->rclient->GetBuffer(usingBS,&outdata);

        if (hResult != S_OK || !outdata) {
            logAUDCLNT_E(hResult);
			continue;
        }

        WaspiHostProcessingLoop(indata, usingBS
			                   ,outdata,usingBS,stream);

        hResult = stream->rclient->ReleaseBuffer(usingBS,0);
        if (hResult != S_OK)
            logAUDCLNT_E(hResult);

    }


    BOOL bRes = pAvRtDeleteThreadOrderingGroup(context);
    if (!bRes){
        PRINT(("AvRtDeleteThreadOrderingGroup failure\n"));
    }

    stream->closeRequest = false;
}




#endif //VC 2005

⌨️ 快捷键说明

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