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

📄 pa_win_wmme.c

📁 一个任天堂掌上游戏机NDS的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    {
#if PA_SIMULATE_UNDERFLOW
        if(gUnderCallbackCounter++ == UNDER_SLEEP_AT)
        {
            Sleep(UNDER_SLEEP_FOR);
        }
#endif

        /* If we are using output, then we need an empty output buffer. */
        gotOutput = 0;
        outBufPtr = NULL;
        if( stream->past_NumOutputChannels > 0 )
        {
            if((wmmeStreamData->outputBuffers[ wmmeStreamData->currentOutputBuffer ].dwFlags & WHDR_DONE) == 0)
            {
                break;  /* If none empty then bail and try again later. */
            }
            else
            {
                outBufPtr = wmmeStreamData->outputBuffers[ wmmeStreamData->currentOutputBuffer ].lpData;
                gotOutput = 1;
            }
        }
        /* Use an input buffer if one is available. */
        gotInput = 0;
        inBufPtr = NULL;
        if( ( stream->past_NumInputChannels > 0 ) &&
                (wmmeStreamData->inputBuffers[ wmmeStreamData->currentInputBuffer ].dwFlags & WHDR_DONE) )
        {
            inBufPtr = wmmeStreamData->inputBuffers[ wmmeStreamData->currentInputBuffer ].lpData;
            gotInput = 1;
#if PA_TRACE_RUN
            AddTraceMessage("Pa_TimeSlice: got input buffer at ", (int)inBufPtr );
            AddTraceMessage("Pa_TimeSlice: got input buffer # ", wmmeStreamData->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( stream );
        for( i=0; i<wmmeStreamData->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, wmmeStreamData->bytesPerUserOutputBuffer );
                }
            }
            else
            {
                /* Convert 16 bit native data to user data and call user routine. */
                result = Pa_CallConvertInt16( stream, (short *) inBufPtr, (short *) outBufPtr );
                if( result != 0) done = 1;
            }
            if( gotInput ) inBufPtr += wmmeStreamData->bytesPerUserInputBuffer;
            if( gotOutput) outBufPtr += wmmeStreamData->bytesPerUserOutputBuffer;
        }
        Pa_EndUsageCalculation( stream );
        /* Send WAVE buffer to Wave Device to be refilled. */
        if( gotInput )
        {
            mmresult = waveInAddBuffer( wmmeStreamData->hWaveIn,
                                       &wmmeStreamData->inputBuffers[ wmmeStreamData->currentInputBuffer ],
                                       sizeof(WAVEHDR) );
            if( mmresult != MMSYSERR_NOERROR )
            {
                sPaHostError = mmresult;
                result = paHostError;
                break;
            }
            wmmeStreamData->currentInputBuffer = (wmmeStreamData->currentInputBuffer+1 >= wmmeStreamData->numHostBuffers) ?
                                              0 : wmmeStreamData->currentInputBuffer+1;
        }
        /* Write WAVE buffer to Wave Device. */
        if( gotOutput )
        {
#if PA_TRACE_START_STOP
            AddTraceMessage( "Pa_TimeSlice: writing buffer ", wmmeStreamData->currentOutputBuffer );
#endif
            mmresult = waveOutWrite( wmmeStreamData->hWaveOut,
                                    &wmmeStreamData->outputBuffers[ wmmeStreamData->currentOutputBuffer ],
                                    sizeof(WAVEHDR) );
            if( mmresult != MMSYSERR_NOERROR )
            {
                sPaHostError = mmresult;
                result = paHostError;
                break;
            }
            wmmeStreamData->currentOutputBuffer = (wmmeStreamData->currentOutputBuffer+1 >= wmmeStreamData->numHostBuffers) ?
                                               0 : wmmeStreamData->currentOutputBuffer+1;
        }

    }

#if PA_TRACE_RUN
    AddTraceMessage("Pa_TimeSlice: buffersProcessed ", buffersProcessed );
#endif
    return (result != 0) ? result : done;
}

/*******************************************************************/
static PaError PaHost_BackgroundManager( internalPortAudioStream *stream )
{
    PaError      result = paNoError;
    int          i;
    int          numQueuedoutputBuffers = 0;
    PaWMMEStreamData *wmmeStreamData = (PaWMMEStreamData *) stream->past_DeviceData;

    /* Has someone asked us to abort by calling Pa_AbortStream()? */
    if( stream->past_StopNow )
    {
        stream->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( stream->past_StopSoon )
    {
        /* Poll buffer and when all have played then exit thread. */
        /* Count how many output buffers are queued. */
        numQueuedoutputBuffers = 0;
        if( stream->past_NumOutputChannels > 0 )
        {
            for( i=0; i<wmmeStreamData->numHostBuffers; i++ )
            {
                if( !( wmmeStreamData->outputBuffers[ i ].dwFlags & WHDR_DONE) )
                {
#if PA_TRACE_START_STOP
                    AddTraceMessage( "PaHost_BackgroundManager: waiting for buffer ", i );
#endif
                    numQueuedoutputBuffers++;
                }
            }
        }
#if PA_TRACE_START_STOP
        AddTraceMessage( "PaHost_BackgroundManager: numQueuedoutputBuffers ", numQueuedoutputBuffers );
#endif
        if( numQueuedoutputBuffers == 0 )
        {
            stream->past_IsActive = 0; /* Will cause thread to return. */
        }
    }
    else
    {
        /* Process full input buffer and fill up empty output buffers. */
        if( (result = Pa_TimeSlice( stream )) != 0)
        {
            /* User callback has asked us to stop. */
#if PA_TRACE_START_STOP
            AddTraceMessage( "PaHost_BackgroundManager: TimeSlice() returned ", result );
#endif
            stream->past_StopSoon = 1; /* Request that audio play out then stop. */
            result = paNoError;
        }
    }

    PaHost_UpdateStreamTime( wmmeStreamData );
    return result;
}

#if PA_USE_TIMER_CALLBACK
/*******************************************************************/
static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
    internalPortAudioStream   *stream;
    PaWMMEStreamData        *wmmeStreamData;
    PaError                    result;

    stream = (internalPortAudioStream *) dwUser;
    if( stream == NULL ) return;
    wmmeStreamData = (PaWMMEStreamData *) stream->past_DeviceData;
    if( wmmeStreamData == NULL ) return;
    if( wmmeStreamData->ifInsideCallback )
    {
        if( wmmeStreamData->timerID != 0 )
        {
            timeKillEvent(wmmeStreamData->timerID);  /* Stop callback timer. */
            wmmeStreamData->timerID = 0;
        }
        return;
    }
    wmmeStreamData->ifInsideCallback = 1;
    /* Manage flags and audio processing. */
    result = PaHost_BackgroundManager( stream );
    if( result != paNoError )
    {
        stream->past_IsActive = 0;
    }
    wmmeStreamData->ifInsideCallback = 0;
}
#else /* PA_USE_TIMER_CALLBACK */
/*******************************************************************/
static DWORD WINAPI WinMMPa_OutputThreadProc( void *pArg )
{
    internalPortAudioStream *stream;
    PaWMMEStreamData      *wmmeStreamData;
    HANDLE       events[2];
    int          numEvents = 0;
    DWORD        result = 0;
    DWORD        waitResult;
    DWORD        numTimeouts = 0;
    DWORD        timeOut;
    stream = (internalPortAudioStream *) pArg;
    wmmeStreamData = (PaWMMEStreamData *) stream->past_DeviceData;
#if PA_TRACE_START_STOP
    AddTraceMessage( "WinMMPa_OutputThreadProc: timeoutPeriod", timeoutPeriod );
    AddTraceMessage( "WinMMPa_OutputThreadProc: past_NumUserBuffers", stream->past_NumUserBuffers );
#endif
    /* Calculate timeOut as half the time it would take to play all buffers. */
    timeOut = (DWORD) (500.0 * PaHost_GetTotalBufferFrames( stream ) / stream->past_SampleRate);
    /* Get event(s) ready for wait. */
    events[numEvents++] = wmmeStreamData->bufferEvent;
    if( wmmeStreamData->abortEventInited ) events[numEvents++] = wmmeStreamData->abortEvent;
    /* Stay in this thread as long as we are "active". */
    while( stream->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;
            stream->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( stream );
        if( result != paNoError )
        {
            stream->past_IsActive = 0;
        }
    }
    return result;
}
#endif

/*******************************************************************/
PaError PaHost_OpenInputStream( internalPortAudioStream   *stream )
{
    PaError          result = paNoError;
    MMRESULT         mmresult;
    PaWMMEStreamData *wmmeStreamData;
    int              i;
    int              inputMmId;
    int              bytesPerInputFrame;
    WAVEFORMATEX     wfx;
    const PaDeviceInfo  *deviceInfo;

    wmmeStreamData = (PaWMMEStreamData *) stream->past_DeviceData;
    DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", stream->past_InputDeviceID));
    deviceInfo = Pa_GetDeviceInfo( stream->past_InputDeviceID );
    if( deviceInfo == NULL ) return paInternalError;

    switch( deviceInfo->nativeSampleFormats  )
    {
    case paInt32:
    case paFloat32:
        bytesPerInputFrame = sizeof(float) * stream->past_NumInputChannels;
        break;
    default:
        bytesPerInputFrame = sizeof(short) * stream->past_NumInputChannels;
        break;
    }
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nChannels = (WORD) stream->past_NumInputChannels;
    wfx.nSamplesPerSec = (DWORD) stream->past_SampleRate;
    wfx.nAvgBytesPerSec = (DWORD)(bytesPerInputFrame * stream->past_SampleRate);
    wfx.nBlockAlign = (WORD)bytesPerInputFrame;
    wfx.wBitsPerSample = (WORD)((bytesPerInputFrame/stream->past_NumInputChannels) * 8);
    wfx.cbSize = 0;
    inputMmId = PaDeviceIdToWinId( stream->past_InputDeviceID );
#if PA_USE_TIMER_CALLBACK
    mmresult = waveInOpen( &wmmeStreamData->hWaveIn, inputMmId, &wfx,
                     0, 0, CALLBACK_NULL );
#else
    mmresult = waveInOpen( &wmmeStreamData->hWaveIn, inputMmId, &wfx,
                     (DWORD)wmmeStreamData->bufferEvent, (DWORD) stream, CALLBACK_EVENT );
#endif
    if( mmresult != MMSYSERR_NOERROR )
    {
        ERR_RPT(("PortAudio: PaHost_OpenInputStream() failed!\n"));
        result = paHostError;
        sPaHostError = mmresult;
        goto error;
    }
    /* Allocate an array to hold the buffer pointers. */
    wmmeStreamData->inputBuffers = (WAVEHDR *) PaHost_AllocateTrackedMemory( sizeof(WAVEHDR)*wmmeStreamData->numHostBuffers ); /* MEM */
    if( wmmeStreamData->inputBuffers == NULL )
    {
        result = paInsufficientMemory;
        goto error;
    }
    /* Allocate each buffer. */
    for( i=0; i<wmmeStreamData->numHostBuffers; i++ )
    {
        wmmeStreamData->inputBuffers[i].lpData = (char *)PaHost_AllocateTrackedMemory( wmmeStreamData->bytesPerHostInputBuffer ); /* MEM */
        if( wmmeStreamData->inputBuffers[i].lpData == NULL )
        {
            result = paInsufficientMemory;
            goto error;
        }
        wmmeStreamData->inputBuffers[i].dwBufferLength = wmmeStreamData->bytesPerHostInputBuffer;
        wmmeStreamData->inputBuffers[i].dwUser = i;
        if( ( mmresult = waveInPrepareHeader( wmmeStreamData->hWaveIn, &wmmeStreamData->inputBuffers[i], sizeof(WAVEHDR) )) != MMSYSERR_NOERROR )
        {
            result = paHostError;
            sPaHostError = mmresult;
            goto error;
        }

⌨️ 快捷键说明

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