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

📄 pa_win_wasapi.cpp

📁 一个开源的sip源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */


        PaWinWasapiDeviceInfo &info = paWasapi->devInfo[inputParameters->device];

        HRESULT hResult = info.device->Activate(
            __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL,
            (void**)&stream->in.client);

        if (hResult != S_OK)
            return paInvalidDevice;

        waveformatFromParams(stream->in.wavex,outputParameters,sampleRate);
		
		PaWasapiFormatAnswer answer = IsFormatSupportedInternal(stream->in.client,
			                                                    stream->in.wavex);

		switch (answer){
			case PWFA_OK: break;
			case PWFA_NO: return paSampleFormatNotSupported;
			case PWFA_SUGGESTED:
			{
				PRINT(("Suggested format:"));
				LogWAVEFORMATEXTENSIBLE(stream->in.wavex);
				if (stream->in.wavex.Format.nSamplesPerSec == (DWORD)sampleRate){
					//no problem its a format issue only
				}
				else{
					return paInvalidSampleRate;
				}
			}
		}

        //stream->out.period = info.DefaultDevicePeriod;
        stream->in.period = info.MinimumDevicePeriod;

        hResult = stream->in.client->Initialize(
            AUDCLNT_SHAREMODE_SHARED,
            //AUDCLNT_SHAREMODE_EXCLUSIVE,
            0,  //no flags
            stream->in.period*3, //tripple buffer
            0,//stream->out.period,
            (WAVEFORMATEX*)&stream->in.wavex,
            &stream->session
            );

        if (hResult != S_OK){
            logAUDCLNT_E(hResult);
            return paInvalidDevice;
        }

        hResult = stream->in.client->GetBufferSize(&stream->in.bufferSize);
        if (hResult != S_OK)
            return paInvalidDevice;

        hResult = stream->in.client->GetStreamLatency(&stream->in.latency);
        if (hResult != S_OK)
            return paInvalidDevice;

        double periodsPerSecond = 1.0/nano100ToSeconds(stream->in.period);
        double samplesPerPeriod = (double)(stream->in.wavex.Format.nSamplesPerSec)/periodsPerSecond;

        //this is the number of samples that are required at each period
        stream->in.framesPerHostCallback = (unsigned long)samplesPerPeriod;//unrelated to channels

        /* IMPLEMENT ME - establish which  host formats are available */
        hostInputSampleFormat =
            PaUtil_SelectClosestAvailableFormat( waveformatToPaFormat(stream->in.wavex), inputSampleFormat );
	}
    else
    {
        inputChannelCount = 0;
        inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */
    }

    if( outputParameters )
    {
        outputChannelCount = outputParameters->channelCount;
        outputSampleFormat = outputParameters->sampleFormat;

        /* 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 outputStreamInfo */
        if( outputParameters->hostApiSpecificStreamInfo )
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */


        PaWinWasapiDeviceInfo &info = paWasapi->devInfo[outputParameters->device];

        HRESULT hResult = info.device->Activate(
            __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL,
            (void**)&stream->out.client);

        if (hResult != S_OK)
            return paInvalidDevice;

        waveformatFromParams(stream->out.wavex,outputParameters,sampleRate);
		
		PaWasapiFormatAnswer answer = IsFormatSupportedInternal(stream->out.client,
			                                                    stream->out.wavex);

		switch (answer){
			case PWFA_OK: break;
			case PWFA_NO: return paSampleFormatNotSupported;
			case PWFA_SUGGESTED:
			{
				PRINT(("Suggested format:"));
				LogWAVEFORMATEXTENSIBLE(stream->out.wavex);
				if (stream->out.wavex.Format.nSamplesPerSec == (DWORD)sampleRate){
					//no problem its a format issue only
				}
				else{
					return paInvalidSampleRate;
				}
			}
		}

        //stream->out.period = info.DefaultDevicePeriod;
        stream->out.period = info.MinimumDevicePeriod;

        hResult = stream->out.client->Initialize(
            AUDCLNT_SHAREMODE_SHARED,
            //AUDCLNT_SHAREMODE_EXCLUSIVE,
            0,  //no flags
            stream->out.period*3, //tripple buffer
            0,//stream->out.period,
            (WAVEFORMATEX*)&stream->out.wavex,
            &stream->session
            );

        if (hResult != S_OK){
            logAUDCLNT_E(hResult);
            return paInvalidDevice;
        }

        hResult = stream->out.client->GetBufferSize(&stream->out.bufferSize);
        if (hResult != S_OK)
            return paInvalidDevice;

        hResult = stream->out.client->GetStreamLatency(&stream->out.latency);
        if (hResult != S_OK)
            return paInvalidDevice;

        double periodsPerSecond = 1.0/nano100ToSeconds(stream->out.period);
        double samplesPerPeriod = (double)(stream->out.wavex.Format.nSamplesPerSec)/periodsPerSecond;

        //this is the number of samples that are required at each period
        stream->out.framesPerHostCallback = (unsigned long)samplesPerPeriod;//unrelated to channels

        /* IMPLEMENT ME - establish which  host formats are available */
        hostOutputSampleFormat =
            PaUtil_SelectClosestAvailableFormat( waveformatToPaFormat(stream->out.wavex), outputSampleFormat );
    }
    else
    {
        outputChannelCount = 0;
        outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */
    }



    /*
        IMPLEMENT ME:

        ( the following two checks are taken care of by PaUtil_InitializeBufferProcessor() FIXME - checks needed? )

            - 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 */



    if( streamCallback )
    {
        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
                                               &paWasapi->callbackStreamInterface, streamCallback, userData );
    }
    else
    {
        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
                                               &paWasapi->blockingStreamInterface, streamCallback, userData );
    }

    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );


	if (outputParameters && inputParameters){

		//serious problem #1
		if (stream->in.period != stream->out.period){
			PRINT(("OpenStream: period discrepancy\n"));
			goto error;
		}

		//serious problem #2
		if (stream->out.framesPerHostCallback != stream->in.framesPerHostCallback){
			PRINT(("OpenStream: framesPerHostCallback discrepancy\n"));
			goto error;
		}
	}

	unsigned long framesPerHostCallback = (outputParameters)?
		stream->out.framesPerHostCallback: 
		stream->in.framesPerHostCallback;

    /* we assume a fixed host buffer size in this example, but the buffer processor
        can also support bounded and unknown host buffer sizes by passing
        paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of
        paUtilFixedHostBufferSize below. */

    result =  PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
              inputChannelCount, inputSampleFormat, hostInputSampleFormat,
              outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
              sampleRate, streamFlags, framesPerBuffer,
              framesPerHostCallback, paUtilFixedHostBufferSize,
              streamCallback, userData );
    if( result != paNoError )
        goto error;


    /*
        IMPLEMENT ME: initialise the following fields with estimated or actual
        values.
    */
    stream->streamRepresentation.streamInfo.inputLatency =
            PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor)
			+ ((inputParameters)?nano100ToSeconds(stream->in.latency) :0);

    stream->streamRepresentation.streamInfo.outputLatency =
            PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor)
			+ ((outputParameters)?nano100ToSeconds(stream->out.latency) :0);

    stream->streamRepresentation.streamInfo.sampleRate = sampleRate;


    *s = (PaStream*)stream;


    return result;

error:
    if( stream )
        PaUtil_FreeMemory( stream );

    return result;
}



/*
    When CloseStream() is called, the multi-api layer ensures that
    the stream has already been stopped or aborted.
*/

#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

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

    /*
        IMPLEMENT ME:
            - additional stream closing + cleanup
    */

    SAFE_RELEASE(stream->out.client);
    SAFE_RELEASE(stream->in.client);
    SAFE_RELEASE(stream->cclient);
    SAFE_RELEASE(stream->rclient);
    CloseHandle(stream->hThread);

    PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
    PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
    PaUtil_FreeMemory( stream );

    return result;
}

VOID ProcThread(void *client);

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

    PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
	
	HRESULT hResult=S_OK;

	if (stream->out.client){
		hResult = stream->out.client->GetService(__uuidof(IAudioRenderClient),(void**)&stream->rclient);
		logAUDCLNT_E(hResult);
		if (hResult!=S_OK)
			return paUnanticipatedHostError;
	}
	
	if (stream->in.client){
	 hResult = stream->in.client->GetService(__uuidof(IAudioCaptureClient),(void**)&stream->cclient);
		logAUDCLNT_E(hResult);
		if (hResult!=S_OK)
			return paUnanticipatedHostError;
	}

    // Create a thread for this client.
    stream->hThread = CreateThread(
        NULL,              // no security attribute
        0,                 // default stack size
        (LPTHREAD_START_ROUTINE) ProcThread,
        (LPVOID) stream,    // thread parameter
        0,                 // not suspended
        &stream->dwThreadId);      // returns thread ID

    if (stream->hThread == NULL)
        return paUnanticipatedHostError;

    return paNoError;
}


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

    /* suppress unused variable warnings */
    stream->closeRequest = true;
    //todo something MUCH better than this

⌨️ 快捷键说明

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