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

📄 pa_win_wmme.c

📁 一个任天堂掌上游戏机NDS的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    stream->past_StopNow = 0;
    stream->past_IsActive = 1;
    wmmeStreamData->framesPlayed = 0.0;
    wmmeStreamData->lastPosition = 0;
#if PA_TRACE_START_STOP
    AddTraceMessage( "PaHost_StartEngine: TimeSlice() returned ", result );
#endif
#if PA_USE_TIMER_CALLBACK
    /* Create timer that will wake us up so we can fill the DSound buffer. */
    bufsPerTimerCallback = wmmeStreamData->numHostBuffers/4;
    if( bufsPerTimerCallback < 1 ) bufsPerTimerCallback = 1;
    if( bufsPerTimerCallback < 1 ) bufsPerTimerCallback = 1;
    msecPerBuffer = (1000 * bufsPerTimerCallback *
                     wmmeStreamData->userBuffersPerHostBuffer *
                     internalStream->past_FramesPerUserBuffer ) / (int) internalStream->past_SampleRate;
    if( msecPerBuffer < 10 ) msecPerBuffer = 10;
    else if( msecPerBuffer > 100 ) msecPerBuffer = 100;
    resolution = msecPerBuffer/4;
    wmmeStreamData->timerID = timeSetEvent( msecPerBuffer, resolution,
                                         (LPTIMECALLBACK) Pa_TimerCallback,
                                         (DWORD) stream, TIME_PERIODIC );
    if( wmmeStreamData->timerID == 0 )
    {
        result = paHostError;
        sPaHostError = GetLastError();;
        goto error;
    }
#else /* PA_USE_TIMER_CALLBACK */
    ResetEvent( wmmeStreamData->abortEvent );
    /* Create thread that waits for audio buffers to be ready for processing. */
    wmmeStreamData->engineThread = CreateThread( 0, 0, WinMMPa_OutputThreadProc, stream, 0, &wmmeStreamData->engineThreadID );
    if( wmmeStreamData->engineThread == NULL )
    {
        result = paHostError;
        sPaHostError = GetLastError();;
        goto error;
    }
#if PA_TRACE_START_STOP
    AddTraceMessage( "PaHost_StartEngine: thread ", (int) wmmeStreamData->engineThread );
#endif
    /* I used to pass the thread which was failing. I now pass GetCurrentProcess().
     * This fix could improve latency for some applications. It could also result in CPU
     * starvation if the callback did too much processing.
     * I also added result checks, so we might see more failures at initialization.
     * Thanks to Alberto di Bene for spotting this.
     */
    if( !SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) ) /* PLB20010816 */
    {
        result = paHostError;
        sPaHostError = GetLastError();;
        goto error;
    }
    if( !SetThreadPriority( wmmeStreamData->engineThread, THREAD_PRIORITY_HIGHEST ) )
    {
        result = paHostError;
        sPaHostError = GetLastError();;
        goto error;
    }
#endif

error:
    return result;
}
/*************************************************************************/
PaError PaHost_StopEngine( internalPortAudioStream *internalStream, int abort )
{
    int timeOut;
    PaWMMEStreamData *wmmeStreamData = PaHost_GetWMMEStreamData( internalStream );

    if( wmmeStreamData == NULL ) return paNoError;

    /* Tell background thread to stop generating more data and to let current data play out. */
    internalStream->past_StopSoon = 1;
    /* If aborting, tell background thread to stop NOW! */
    if( abort ) internalStream->past_StopNow = 1;

    /* Calculate timeOut longer than longest time it could take to play all buffers. */
    timeOut = (DWORD) (1500.0 * PaHost_GetTotalBufferFrames( internalStream ) / internalStream->past_SampleRate);
    if( timeOut < MIN_TIMEOUT_MSEC ) timeOut = MIN_TIMEOUT_MSEC;

#if PA_USE_TIMER_CALLBACK
    if( (internalStream->past_OutputDeviceID != paNoDevice) &&
            internalStream->past_IsActive &&
            (wmmeStreamData->timerID != 0) )
    {
        /* Wait for IsActive to drop. */
        while( (internalStream->past_IsActive) && (timeOut > 0) )
        {
            Sleep(10);
            timeOut -= 10;
        }
        timeKillEvent( wmmeStreamData->timerID );  /* Stop callback timer. */
        wmmeStreamData->timerID = 0;
    }
#else /* PA_USE_TIMER_CALLBACK */
#if PA_TRACE_START_STOP
    AddTraceMessage( "PaHost_StopEngine: thread ", (int) wmmeStreamData->engineThread );
#endif
    if( (internalStream->past_OutputDeviceID != paNoDevice) &&
            (internalStream->past_IsActive) &&
            (wmmeStreamData->engineThread != NULL) )
    {
        DWORD got;
        /* Tell background thread to stop generating more data and to let current data play out. */
        DBUG(("PaHost_StopEngine: waiting for background thread.\n"));
        got = WaitForSingleObject( wmmeStreamData->engineThread, timeOut );
        if( got == WAIT_TIMEOUT )
        {
            ERR_RPT(("PaHost_StopEngine: timed out while waiting for background thread to finish.\n"));
            return paTimedOut;
        }
        CloseHandle( wmmeStreamData->engineThread );
        wmmeStreamData->engineThread = NULL;
    }
#endif /* PA_USE_TIMER_CALLBACK */

    internalStream->past_IsActive = 0;
    return paNoError;
}
/*************************************************************************/
PaError PaHost_StopInput( internalPortAudioStream *stream, int abort )
{
    MMRESULT mmresult;
    PaWMMEStreamData *wmmeStreamData = PaHost_GetWMMEStreamData( stream );

    if( wmmeStreamData == NULL ) return paNoError; /* FIXME: why return paNoError? */
    (void) abort; /* unused parameter */

    if( wmmeStreamData->hWaveIn != NULL )
    {
        mmresult = waveInReset( wmmeStreamData->hWaveIn );
        if( mmresult != MMSYSERR_NOERROR )
        {
            sPaHostError = mmresult;
            return paHostError;
        }
    }
    return paNoError;
}
/*************************************************************************/
PaError PaHost_StopOutput( internalPortAudioStream *internalStream, int abort )
{
    MMRESULT mmresult;
    PaWMMEStreamData *wmmeStreamData = PaHost_GetWMMEStreamData( internalStream );

    if( wmmeStreamData == NULL ) return paNoError;    /* FIXME: why return paNoError? */
    (void) abort;   /* unused parameter */

#if PA_TRACE_START_STOP
    AddTraceMessage( "PaHost_StopOutput: hWaveOut ", (int) wmmeStreamData->hWaveOut );
#endif
    if( wmmeStreamData->hWaveOut != NULL )
    {
        mmresult = waveOutReset( wmmeStreamData->hWaveOut );
        if( mmresult != MMSYSERR_NOERROR )
        {
            sPaHostError = mmresult;
            return paHostError;
        }
    }
    return paNoError;
}
/*******************************************************************/
PaError PaHost_CloseStream( internalPortAudioStream *stream )
{
    int i;
    PaWMMEStreamData *wmmeStreamData = PaHost_GetWMMEStreamData( stream );

    if( stream == NULL ) return paBadStreamPtr;
    if( wmmeStreamData == NULL ) return paNoError;   /* FIXME: why return no error? */

#if PA_TRACE_START_STOP
    AddTraceMessage( "PaHost_CloseStream: hWaveOut ", (int) wmmeStreamData->hWaveOut );
#endif
    /* Free data and device for output. */
    if( wmmeStreamData->hWaveOut )
    {
        if( wmmeStreamData->outputBuffers )
        {
            for( i=0; i<wmmeStreamData->numHostBuffers; i++ )
            {
                waveOutUnprepareHeader( wmmeStreamData->hWaveOut, &wmmeStreamData->outputBuffers[i], sizeof(WAVEHDR) );
                PaHost_FreeTrackedMemory( wmmeStreamData->outputBuffers[i].lpData ); /* MEM */
            }
            PaHost_FreeTrackedMemory( wmmeStreamData->outputBuffers ); /* MEM */
        }
        waveOutClose( wmmeStreamData->hWaveOut );
    }
    /* Free data and device for input. */
    if( wmmeStreamData->hWaveIn )
    {
        if( wmmeStreamData->inputBuffers )
        {
            for( i=0; i<wmmeStreamData->numHostBuffers; i++ )
            {
                waveInUnprepareHeader( wmmeStreamData->hWaveIn, &wmmeStreamData->inputBuffers[i], sizeof(WAVEHDR) );
                PaHost_FreeTrackedMemory( wmmeStreamData->inputBuffers[i].lpData ); /* MEM */
            }
            PaHost_FreeTrackedMemory( wmmeStreamData->inputBuffers ); /* MEM */
        }
        waveInClose( wmmeStreamData->hWaveIn );
    }
#if (PA_USE_TIMER_CALLBACK == 0)
    if( wmmeStreamData->abortEventInited ) CloseHandle( wmmeStreamData->abortEvent );
    if( wmmeStreamData->bufferEventInited ) CloseHandle( wmmeStreamData->bufferEvent );
#endif
    if( wmmeStreamData->streamLockInited )
        DeleteCriticalSection( &wmmeStreamData->streamLock );

    PaHost_FreeWMMEStreamData( stream );

    return paNoError;
}
/*************************************************************************
 * Determine minimum number of buffers required for this host based
 * on minimum latency. Latency can be optionally set by user by setting
 * an environment variable. For example, to set latency to 200 msec, put:
 *
 *    set PA_MIN_LATENCY_MSEC=200
 *
 * in the AUTOEXEC.BAT file and reboot.
 * If the environment variable is not set, then the latency will be determined
 * based on the OS. Windows NT has higher latency than Win95.
 */
#define PA_LATENCY_ENV_NAME  ("PA_MIN_LATENCY_MSEC")
int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate )
{
    char      envbuf[PA_ENV_BUF_SIZE];
    DWORD     hresult;
    int       minLatencyMsec = 0;
    double    msecPerBuffer = (1000.0 * framesPerBuffer) / sampleRate;
    int       minBuffers;

    /* Let user determine minimal latency by setting environment variable. */
    hresult = GetEnvironmentVariable( PA_LATENCY_ENV_NAME, envbuf, PA_ENV_BUF_SIZE );
    if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) )
    {
        minLatencyMsec = atoi( envbuf );   /* REVIEW: will we crash if the environment variable contains some nasty value? */
    }
    else
    {
        /* Set minimal latency based on whether NT or other OS.
         * NT has higher latency.
         */
        OSVERSIONINFO osvi;
		osvi.dwOSVersionInfoSize = sizeof( osvi );
		GetVersionEx( &osvi );
        DBUG(("PA - PlatformId = 0x%x\n", osvi.dwPlatformId ));
        DBUG(("PA - MajorVersion = 0x%x\n", osvi.dwMajorVersion ));
        DBUG(("PA - MinorVersion = 0x%x\n", osvi.dwMinorVersion ));
        /* Check for NT */
		if( (osvi.dwMajorVersion == 4) && (osvi.dwPlatformId == 2) )
		{
			minLatencyMsec = PA_WIN_NT_LATENCY;
		}
		else if(osvi.dwMajorVersion >= 5)
		{
			minLatencyMsec = PA_WIN_WDM_LATENCY;
		}
		else
		{
			minLatencyMsec = PA_WIN_9X_LATENCY;
		}
#if PA_USE_HIGH_LATENCY
        PRINT(("PA - Minimum Latency set to %d msec!\n", minLatencyMsec ));
#endif

    }
    DBUG(("PA - Minimum Latency set to %d msec!\n", minLatencyMsec ));
    minBuffers = (int) (1.0 + ((double)minLatencyMsec / msecPerBuffer));
    if( minBuffers < 2 ) minBuffers = 2;
    return minBuffers;
}
/*************************************************************************
 * Cleanup device info.
 */
PaError PaHost_Term( void )
{
    int i;

    if( sNumDevices > 0 )
    {
        if( sDevicePtrs != NULL )
        {
            for( i=0; i<sNumDevices; i++ )
            {
                if( sDevicePtrs[i] != NULL )
                {
                    PaHost_FreeTrackedMemory( (char*)sDevicePtrs[i]->name ); /* MEM */
                    PaHost_FreeTrackedMemory( (void*)sDevicePtrs[i]->sampleRates ); /* MEM */
                    PaHost_FreeTrackedMemory( sDevicePtrs[i] ); /* MEM */
                }
            }
            PaHost_FreeTrackedMemory( sDevicePtrs ); /* MEM */
            sDevicePtrs = NULL;
        }
        sNumDevices = 0;
    }

#if PA_TRACK_MEMORY
    PRINT(("PaHost_Term: sNumAllocations = %d\n", sNumAllocations ));
#endif

    return paNoError;
}
/*************************************************************************/
void Pa_Sleep( long msec )
{
    Sleep( msec );
}
/*************************************************************************
FIXME: the following memory allocation routines should not be declared here
 * Allocate memory that can be accessed in real-time.
 * This may need to be held in physical memory so that it is not
 * paged to virtual memory.
 * This call MUST be balanced with a call to PaHost_FreeFastMemory().
 * Memory will be set to zero.
 */
void *PaHost_AllocateFastMemory( long numBytes )
{
    return PaHost_AllocateTrackedMemory( numBytes ); /* FIXME - do we need physical memory? Use VirtualLock() */ /* MEM */
}
/*************************************************************************
 * Free memory that could be accessed in real-time.
 * This call MUST be 

⌨️ 快捷键说明

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