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

📄 pa_win_wasapi.cpp

📁 一个开源的sip源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
											(int)in.SubFormat.Data4[6],
											(int)in.SubFormat.Data4[7]));
			}
			PRINT(("Samples.wValidBitsPerSample=%d\n",  in.Samples.wValidBitsPerSample));
			PRINT(("dwChannelMask=0x%X\n",in.dwChannelMask));
		}break;
		
		case WAVE_FORMAT_PCM:        PRINT(("wFormatTag=WAVE_FORMAT_PCM\n")); break;
		case WAVE_FORMAT_IEEE_FLOAT: PRINT(("wFormatTag=WAVE_FORMAT_IEEE_FLOAT\n")); break;
		default : PRINT(("wFormatTag=UNKNOWN(%d)\n",old->wFormatTag)); break;
	}

	PRINT(("nChannels      =%d\n",old->nChannels)); 
	PRINT(("nSamplesPerSec =%d\n",old->nSamplesPerSec));  
	PRINT(("nAvgBytesPerSec=%d\n",old->nAvgBytesPerSec));  
	PRINT(("nBlockAlign    =%d\n",old->nBlockAlign));  
	PRINT(("wBitsPerSample =%d\n",old->wBitsPerSample));  
	PRINT(("cbSize         =%d\n",old->cbSize));  
}



/*
 WAVEFORMATXXX is always interleaved
 */
static PaSampleFormat
waveformatToPaFormat(const WAVEFORMATEXTENSIBLE &in){

    const WAVEFORMATEX *old = (WAVEFORMATEX *)∈

    switch (old->wFormatTag){

        case WAVE_FORMAT_EXTENSIBLE:
        {
            if (in.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT){
                if (in.Samples.wValidBitsPerSample == 32)
                    return paFloat32;
                else
                    return paCustomFormat;
            }
            else if (in.SubFormat == KSDATAFORMAT_SUBTYPE_PCM){
                switch (old->wBitsPerSample){
                    case 32: return paInt32; break;
                    case 24: return paInt24;break;
                    case  8: return paUInt8;break;
                    case 16: return paInt16;break;
                    default: return paCustomFormat;break;
                }
            }
            else
                return paCustomFormat;
        }
        break;

        case WAVE_FORMAT_IEEE_FLOAT:
            return paFloat32;
        break;

        case WAVE_FORMAT_PCM:
        {
            switch (old->wBitsPerSample){
                case 32: return paInt32; break;
                case 24: return paInt24;break;
                case  8: return paUInt8;break;
                case 16: return paInt16;break;
                default: return paCustomFormat;break;
            }
        }
        break;

        default:
            return paCustomFormat;
        break;
    }

    return paCustomFormat;
}



static PaError
waveformatFromParams(WAVEFORMATEXTENSIBLE &wav,
                          const PaStreamParameters * params,
                          double sampleRate){

    size_t bytesPerSample = 0;
    switch( params->sampleFormat & ~paNonInterleaved ){
        case paFloat32:
        case paInt32: bytesPerSample=4;break;
        case paInt16: bytesPerSample=2;break;
        case paInt24: bytesPerSample=3;break;
        case paInt8:
        case paUInt8: bytesPerSample=1;break;
        case paCustomFormat:
        default: return paSampleFormatNotSupported;break;
    }

    memset(&wav,0,sizeof(WAVEFORMATEXTENSIBLE));

    WAVEFORMATEX *old    = (WAVEFORMATEX *)&wav;
    old->nChannels       = (WORD)params->channelCount;
    old->nSamplesPerSec  = (DWORD)sampleRate;
    old->wBitsPerSample  = bytesPerSample*8;
    old->nAvgBytesPerSec = old->nSamplesPerSec * old->nChannels * bytesPerSample;
    old->nBlockAlign     = (WORD)(old->nChannels * bytesPerSample);

    //WAVEFORMATEX
    if (params->channelCount <=2 && (bytesPerSample == 2 || bytesPerSample == 1)){
        old->cbSize          = 0;
        old->wFormatTag      = WAVE_FORMAT_PCM;
    }
    //WAVEFORMATEXTENSIBLE
    else{
        old->wFormatTag = WAVE_FORMAT_EXTENSIBLE;

        old->cbSize = sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX);

        if ((params->sampleFormat & ~paNonInterleaved) == paFloat32)
            wav.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
        else
            wav.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;

        wav.Samples.wValidBitsPerSample = old->wBitsPerSample; //no extra padding!

        switch(params->channelCount){
            case 1:  wav.dwChannelMask = SPEAKER_FRONT_CENTER; break;
            case 2:  wav.dwChannelMask = 0x1 | 0x2; break;
            case 4:  wav.dwChannelMask = 0x1 | 0x2 | 0x10 | 0x20; break;
            case 6:  wav.dwChannelMask = 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20; break;
            case 8:  wav.dwChannelMask = 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80; break;
            default: wav.dwChannelMask = 0; break;
        }
    }

    return paNoError;
}


enum PaWasapiFormatAnswer {PWFA_OK,PWFA_NO,PWFA_SUGGESTED};


static PaWasapiFormatAnswer 
IsFormatSupportedInternal(IAudioClient * myClient, WAVEFORMATEXTENSIBLE &wavex){

	PaWasapiFormatAnswer answer = PWFA_OK;

    WAVEFORMATEX *closestMatch=0;
    HRESULT hResult = myClient->IsFormatSupported(
        //AUDCLNT_SHAREMODE_EXCLUSIVE,
        AUDCLNT_SHAREMODE_SHARED,
        (WAVEFORMATEX*)&wavex,&closestMatch);

	if (hResult == S_OK)
		answer = PWFA_OK;
    else if (closestMatch){
        WAVEFORMATEXTENSIBLE* ext = (WAVEFORMATEXTENSIBLE*)closestMatch;
		
		if (closestMatch->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
			memcpy(&wavex,closestMatch,sizeof(WAVEFORMATEXTENSIBLE));
		else
			memcpy(&wavex,closestMatch,sizeof(WAVEFORMATEX));

        CoTaskMemFree(closestMatch);
		answer = PWFA_SUGGESTED;
	
	}else if (hResult != S_OK){
		logAUDCLNT_E(hResult);
		answer = PWFA_NO;
	}

	return answer;
}


static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
                                  const PaStreamParameters *inputParameters,
                                  const PaStreamParameters *outputParameters,
                                  double sampleRate )
{
    int inputChannelCount, outputChannelCount;
    PaSampleFormat inputSampleFormat, outputSampleFormat;

    if( inputParameters )
    {
        inputChannelCount = inputParameters->channelCount;
        inputSampleFormat = inputParameters->sampleFormat;

        /* all standard sample formats are supported by the buffer adapter,
            this implementation doesn't support any custom sample formats */
        if( inputSampleFormat & paCustomFormat )
            return paSampleFormatNotSupported;

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


        PaWinWasapiHostApiRepresentation *paWasapi = (PaWinWasapiHostApiRepresentation*)hostApi;

        WAVEFORMATEXTENSIBLE wavex;
        waveformatFromParams(wavex,inputParameters,sampleRate);
	
		IAudioClient *myClient=0;
		HRESULT hResult = paWasapi->devInfo[inputParameters->device].device->Activate(
			__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, (void**)&myClient);
		if (hResult != S_OK){
			logAUDCLNT_E(hResult);
			return paInvalidDevice;
		}

		PaWasapiFormatAnswer answer = IsFormatSupportedInternal(myClient,wavex);
		myClient->Release();

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


    }
    else
    {
        inputChannelCount = 0;
    }

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

        /* all standard sample formats are supported by the buffer adapter,
            this implementation doesn't support any custom sample formats */
        if( outputSampleFormat & paCustomFormat )
            return paSampleFormatNotSupported;

        /* unless alternate device specification is supported, reject the use of
            paUseHostApiSpecificDeviceSpecification */

        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
            return paInvalidDevice;

        /* check that output device can support outputChannelCount */
        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
            return paInvalidChannelCount;

        /* validate outputStreamInfo */
        if( outputParameters->hostApiSpecificStreamInfo )
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */


        PaWinWasapiHostApiRepresentation *paWasapi = (PaWinWasapiHostApiRepresentation*)hostApi;

        WAVEFORMATEXTENSIBLE wavex;
        waveformatFromParams(wavex,outputParameters,sampleRate);
	
		IAudioClient *myClient=0;
		HRESULT hResult = paWasapi->devInfo[outputParameters->device].device->Activate(
			__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, (void**)&myClient);
		if (hResult != S_OK){
			logAUDCLNT_E(hResult);
			return paInvalidDevice;
		}

		PaWasapiFormatAnswer answer = IsFormatSupportedInternal(myClient,wavex);
		myClient->Release();

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


    }
    else
    {
        outputChannelCount = 0;
    }


    return paFormatIsSupported;
}



/* 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;
    PaWinWasapiHostApiRepresentation *paWasapi = (PaWinWasapiHostApiRepresentation*)hostApi;
    PaWinWasapiStream *stream = 0;
    int inputChannelCount, outputChannelCount;
    PaSampleFormat inputSampleFormat, outputSampleFormat;
    PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;


    stream = (PaWinWasapiStream*)PaUtil_AllocateMemory( sizeof(PaWinWasapiStream) );
    if( !stream ){
        result = paInsufficientMemory;
        goto error;
    }

    if( inputParameters )
    {
        inputChannelCount = inputParameters->channelCount;
        inputSampleFormat = inputParameters->sampleFormat;

        /* 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 inputStreamInfo */
        if( inputParameters->hostApiSpecificStreamInfo )

⌨️ 快捷键说明

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