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

📄 pa_win_wmme.c

📁 ppciaxclient softphone
💻 C
📖 第 1 页 / 共 4 页
字号:
    
    return NULL;
}
/*************************************************************************
** Returns recommended device ID.
** On the PC, the recommended device can be specified by the user by
** setting an environment variable. For example, to use device #1.
**
**    set PA_RECOMMENDED_OUTPUT_DEVICE=1
**
** The user should first determine the available device ID by using
** the supplied application "pa_devs".
*/
#define PA_ENV_BUF_SIZE  (32)
#define PA_REC_IN_DEV_ENV_NAME  ("PA_RECOMMENDED_INPUT_DEVICE")
#define PA_REC_OUT_DEV_ENV_NAME  ("PA_RECOMMENDED_OUTPUT_DEVICE")

static PaDeviceID PaHost_GetEnvDefaultDeviceID( char *envName )
{
	DWORD   hresult;
	char    envbuf[PA_ENV_BUF_SIZE];
	PaDeviceID recommendedID = paNoDevice;
/* Let user determine default device by setting environment variable. */
/*	hresult = GetEnvironmentVariable( envName, envbuf, PA_ENV_BUF_SIZE ); */
/* GJG20020928 - Windows CE does not support environment variables */
    hresult=0;
	if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) )
	{
		recommendedID = atoi( envbuf );
	}
//	return recommendedID;
	return -1; /* GJG20021013 */    
}


static PaError Pa_MaybeQueryDevices( void )
{
	if( sNumDevices == 0 )
	{
		return Pa_QueryDevices();
	}
	return 0;
}
/**********************************************************************
** Check for environment variable, else query devices and use result.
*/
PaDeviceID Pa_GetDefaultInputDeviceID( void )
{
	PaError result;
	result = PaHost_GetEnvDefaultDeviceID( PA_REC_IN_DEV_ENV_NAME );
	if( result < 0 )
	{
		result = Pa_MaybeQueryDevices();
		if( result < 0 ) return result;
		result = sDefaultInputDeviceID;
	}
	return result;
}
PaDeviceID Pa_GetDefaultOutputDeviceID( void )
{
	PaError result;
	result = PaHost_GetEnvDefaultDeviceID( PA_REC_OUT_DEV_ENV_NAME );
	if( result < 0 )
	{
		result = Pa_MaybeQueryDevices();
		if( result < 0 ) return result;
		result = sDefaultOutputDeviceID;
	}
	return result;
}
/**********************************************************************
** Initialize Host dependant part of API.
*/
PaError PaHost_Init( void )
{
#if PA_SIMULATE_UNDERFLOW
	PRINT(("WARNING - Underflow Simulation Enabled - Expect a Big Glitch!!!\n"));
#endif
	return Pa_MaybeQueryDevices();
}
/**********************************************************************
** Check WAVE buffers to see if they are done.
** Fill any available output buffers and use any available
** input buffers by calling user callback.
*/
static PaError Pa_TimeSlice( internalPortAudioStream   *past )
{
	PaError           result = 0;
	long              bytesEmpty = 0;
	long              bytesFilled = 0;
	long              buffersEmpty = 0;
	MMRESULT          mresult;
	char             *inBufPtr;
	char             *outBufPtr;
	int               gotInput = 0;
	int               gotOutput = 0;
	int               i;
	int               buffersProcessed = 0;
	int               done = 0;
	PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
	if( pahsc == NULL ) return paInternalError;
	past->past_NumCallbacks += 1;
#if PA_SIMULATE_UNDERFLOW
	if(gUnderCallbackCounter++ == UNDER_SLEEP_AT)
	{
		Sleep(UNDER_SLEEP_FOR);
	}
#endif
#if PA_TRACE_RUN
	AddTraceMessage("Pa_TimeSlice: past_NumCallbacks ", past->past_NumCallbacks );
#endif
	while(!done)
	{
/* If we are using output, then we need an empty output buffer. */
		gotOutput = 0;
		outBufPtr = NULL;
		if( past->past_NumOutputChannels > 0 )
		{
			if((pahsc->pahsc_OutputBuffers[ pahsc->pahsc_CurrentOutputBuffer ].dwFlags & WHDR_DONE) == 0)
			{	
				break;  /* If none empty then bail and try again later. */
			}
			else
			{
				outBufPtr = pahsc->pahsc_OutputBuffers[ pahsc->pahsc_CurrentOutputBuffer ].lpData;
				gotOutput = 1;
			}
		}
/* Use an input buffer if one is available. */
		gotInput = 0;
		inBufPtr = NULL;
		if( ( past->past_NumInputChannels > 0 ) &&
			(pahsc->pahsc_InputBuffers[ pahsc->pahsc_CurrentInputBuffer ].dwFlags & WHDR_DONE) )
		{
			inBufPtr = pahsc->pahsc_InputBuffers[ pahsc->pahsc_CurrentInputBuffer ].lpData;
			gotInput = 1;
#if PA_TRACE_RUN
			AddTraceMessage("Pa_TimeSlice: got input buffer at ", (int)inBufPtr );
			AddTraceMessage("Pa_TimeSlice: got input buffer # ", pahsc->pahsc_CurrentInputBuffer );
#endif
		}
/* If we can't do anything then bail out. */
		if( !gotInput && !gotOutput ) break;
		buffersProcessed += 1;
/* Each Wave buffer contains multiple user buffers so do them all now. */
/* Base Usage on time it took to process one host buffer. */
		Pa_StartUsageCalculation( past );
		for( i=0; i<pahsc->pahsc_UserBuffersPerHostBuffer; i++ )
		{
			if( done )
			{
				if( gotOutput )
				{
		/* Clear remainder of wave buffer if we are waiting for stop. */
					AddTraceMessage("Pa_TimeSlice: zero rest of wave buffer ", i );
					memset( outBufPtr, 0, pahsc->pahsc_BytesPerUserOutputBuffer );
				}
			}
			else
			{
	/* Convert 16 bit native data to user data and call user routine. */
				result = Pa_CallConvertInt16( past, (short *) inBufPtr, (short *) outBufPtr );
				if( result != 0) done = 1;
			}
			if( gotInput ) inBufPtr += pahsc->pahsc_BytesPerUserInputBuffer;
			if( gotOutput) outBufPtr += pahsc->pahsc_BytesPerUserOutputBuffer;
		}
		Pa_EndUsageCalculation( past );
/* Send WAVE buffer to Wave Device to be refilled. */
		if( gotInput )
		{
			mresult = waveInAddBuffer( pahsc->pahsc_HWaveIn,
				&pahsc->pahsc_InputBuffers[ pahsc->pahsc_CurrentInputBuffer ],
				sizeof(WAVEHDR) );
			if( mresult != MMSYSERR_NOERROR )
			{
				sPaHostError = mresult;
				result = paHostError;
				break;
			}
			pahsc->pahsc_CurrentInputBuffer = (pahsc->pahsc_CurrentInputBuffer+1 >= pahsc->pahsc_NumHostBuffers) ?
				0 : pahsc->pahsc_CurrentInputBuffer+1;
		}
/* Write WAVE buffer to Wave Device. */
		if( gotOutput )
		{
#if PA_TRACE_START_STOP
    AddTraceMessage( "Pa_TimeSlice: writing buffer ", pahsc->pahsc_CurrentOutputBuffer );
#endif
			mresult = waveOutWrite( pahsc->pahsc_HWaveOut,
				&pahsc->pahsc_OutputBuffers[ pahsc->pahsc_CurrentOutputBuffer ],
				sizeof(WAVEHDR) );
			if( mresult != MMSYSERR_NOERROR )
			{
				sPaHostError = mresult;
				result = paHostError;
				break;
			}
			pahsc->pahsc_CurrentOutputBuffer = (pahsc->pahsc_CurrentOutputBuffer+1 >= pahsc->pahsc_NumHostBuffers) ?
				0 : pahsc->pahsc_CurrentOutputBuffer+1;
		}
	}
			
#if PA_TRACE_RUN
	AddTraceMessage("Pa_TimeSlice: buffersProcessed ", buffersProcessed );
#endif
	return (result != 0) ? result : done;
}
/*******************************************************************/
static PaError PaHost_BackgroundManager( internalPortAudioStream   *past )
{
	PaError      result = 0;
    int          i;
	int          numQueuedOutputBuffers = 0;
	PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData;
/* Has someone asked us to abort by calling Pa_AbortStream()? */
	if( past->past_StopNow )
	{
        past->past_IsActive = 0; /* Will cause thread to return. */
    }
/* Has someone asked us to stop by calling Pa_StopStream()
 * OR has a user callback returned '1' to indicate finished.
 */
	else if( past->past_StopSoon )
	{
/* Poll buffer and when all have played then exit thread. */
/* Count how many output buffers are queued. */
        numQueuedOutputBuffers = 0;
        if( past->past_NumOutputChannels > 0 )
		{
			for( i=0; i<pahsc->pahsc_NumHostBuffers; i++ )
			{
				if( !( pahsc->pahsc_OutputBuffers[ i ].dwFlags & WHDR_DONE) )
				{
#if PA_TRACE_START_STOP
AddTraceMessage( "WinMMPa_OutputThreadProc: waiting for buffer ", i );
#endif
					numQueuedOutputBuffers++;
				}
			}
		}
#if PA_TRACE_START_STOP
AddTraceMessage( "WinMMPa_OutputThreadProc: numQueuedOutputBuffers ", numQueuedOutputBuffers );
#endif
        if( numQueuedOutputBuffers == 0 )
		{
            past->past_IsActive = 0; /* Will cause thread to return. */
		}
    }
	else
	{
/* Process full input buffer and fill up empty output buffers. */
		if( (result = Pa_TimeSlice( past )) != 0) 
		{
	/* User callback has asked us to stop. */
#if PA_TRACE_START_STOP
AddTraceMessage( "WinMMPa_OutputThreadProc: TimeSlice() returned ", result );
#endif
            past->past_StopSoon = 1; /* Request that audio play out then stop. */
			result = paNoError;
		}
	}
	
	PaHost_UpdateStreamTime( pahsc );
	return result;
}
#if PA_USE_TIMER_CALLBACK
/*******************************************************************/
static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
	internalPortAudioStream   *past;
	PaHostSoundControl        *pahsc;
	PaError                    result;
	past = (internalPortAudioStream *) dwUser;
	if( past == NULL ) return;
	pahsc = (PaHostSoundControl *) past->past_DeviceData;
	if( pahsc == NULL ) return;
	if( pahsc->pahsc_IfInsideCallback )
	{
		if( pahsc->pahsc_TimerID != 0 )
		{
			timeKillEvent(pahsc->pahsc_TimerID);  /* Stop callback timer. */
			pahsc->pahsc_TimerID = 0;
		}
		return;
	}
	pahsc->pahsc_IfInsideCallback = 1;
/* Manage flags and audio processing. */
 	result = PaHost_BackgroundManager( past );
	if( result != paNoError )
	{
		past->past_IsActive = 0;
	}
	pahsc->pahsc_IfInsideCallback = 0;
}
#else /* PA_USE_TIMER_CALLBACK */
/*******************************************************************/
static DWORD WINAPI WinMMPa_OutputThreadProc( void *pArg )
{
	internalPortAudioStream *past;
 	PaHostSoundControl      *pahsc;
    void        *inputBuffer=NULL;
    HANDLE       events[2];
	int          numEvents = 0;
	DWORD        result = 0;
	DWORD        waitResult;
	DWORD        numTimeouts = 0;
	DWORD        timeOut;
	past = (internalPortAudioStream *) pArg;
	pahsc = (PaHostSoundControl *) past->past_DeviceData;
#if PA_TRACE_START_STOP
    AddTraceMessage( "WinMMPa_OutputThreadProc: timeoutPeriod", timeoutPeriod );
    AddTraceMessage( "WinMMPa_OutputThreadProc: past_NumUserBuffers", past->past_NumUserBuffers );
#endif
/* Calculate timeOut as half the time it would take to play all buffers. */
	timeOut = (DWORD) (500.0 * PaHost_GetTotalBufferFrames( past ) / past->past_SampleRate);
/* Get event(s) ready for wait. */
    events[numEvents++] = pahsc->pahsc_BufferEvent;
    if( pahsc->pahsc_AbortEventInited ) events[numEvents++] = pahsc->pahsc_AbortEvent;
/* Stay in this thread as long as we are "active". */
    while( past->past_IsActive )
	{
/*******************************************************************/
/******** WAIT here for an event from WMME or PA *******************/
/*******************************************************************/
        waitResult = WaitForMultipleObjects( numEvents, events, FALSE, timeOut );
	/* Error? */
		if( waitResult == WAIT_FAILED )
		{
			sPaHostError = GetLastError();
			result = paHostError;
			past->past_IsActive = 0;
		}
	/* Timeout? Don't stop. Just keep polling for DONE.*/
		else if( waitResult == WAIT_TIMEOUT )
		{
#if PA_TRACE_START_STOP
	AddTraceMessage( "WinMMPa_OutputThreadProc: timed out ", numQueuedOutputBuffers );
#endif
			numTimeouts += 1;
		}
		/* Manage flags and audio processing. */
 		result = PaHost_BackgroundManager( past );
		if( result != paNoError )
		{
			past->past_IsActive = 0;
		}
	}
	return result;
}
#endif
/*******************************************************************/
PaError PaHost_OpenInputStream( internalPortAudioStream   *past )
{
	MMRESULT         mr;
	PaError          result = paNoError;
	PaHostSoundControl *pahsc;
	int              i;
	int              inputMmId;
	int              bytesPerInputFrame;
	WAVEFORMATEX     wfx;
	const PaDeviceInfo  *pad;
	pahsc = (PaHostSoundControl *) past->past_DeviceData;
	DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", past->past_InputDeviceID));
	pad = Pa_GetDeviceInfo( past->past_InputDeviceID );
	if( pad == NULL ) return paInternalError;
	switch( pad->nativeSampleFormats  )
	{
		case paInt32:
		case paFloat32:
			bytesPerInputFrame = sizeof(float) * past->past_NumInputChannels;
			break;
		default:
			bytesPerInputFrame = sizeof(short) * past->past_NumInputChannels;
			break;

⌨️ 快捷键说明

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