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

📄 pa_win_wmme.c

📁 一个任天堂掌上游戏机NDS的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    }
    return result;

error:
    return result;
}
/*******************************************************************/
PaError PaHost_OpenOutputStream( internalPortAudioStream *stream )
{
    PaError          result = paNoError;
    MMRESULT         mmresult;
    PaWMMEStreamData *wmmeStreamData;
    int              i;
    int              outputMmID;
    int              bytesPerOutputFrame;
    WAVEFORMATEX     wfx;
    const PaDeviceInfo *deviceInfo;

    wmmeStreamData = (PaWMMEStreamData *) stream->past_DeviceData;
    DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", stream->past_OutputDeviceID));

    deviceInfo = Pa_GetDeviceInfo( stream->past_OutputDeviceID );
    if( deviceInfo == NULL ) return paInternalError;

    switch( deviceInfo->nativeSampleFormats  )
    {
    case paInt32:
    case paFloat32:
        bytesPerOutputFrame = sizeof(float) * stream->past_NumOutputChannels;
        break;
    default:
        bytesPerOutputFrame = sizeof(short) * stream->past_NumOutputChannels;
        break;
    }
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nChannels = (WORD) stream->past_NumOutputChannels;
    wfx.nSamplesPerSec = (DWORD) stream->past_SampleRate;
    wfx.nAvgBytesPerSec = (DWORD)(bytesPerOutputFrame * stream->past_SampleRate);
    wfx.nBlockAlign = (WORD)bytesPerOutputFrame;
    wfx.wBitsPerSample = (WORD)((bytesPerOutputFrame/stream->past_NumOutputChannels) * 8);
    wfx.cbSize = 0;
    outputMmID = PaDeviceIdToWinId( stream->past_OutputDeviceID );
#if PA_USE_TIMER_CALLBACK
    mmresult = waveOutOpen( &wmmeStreamData->hWaveOut, outputMmID, &wfx,
                      0, 0, CALLBACK_NULL );
#else

    wmmeStreamData->abortEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
    if( wmmeStreamData->abortEvent == NULL )
    {
        result = paHostError;
        sPaHostError = GetLastError();
        goto error;
    }
    wmmeStreamData->abortEventInited = 1;
    mmresult = waveOutOpen( &wmmeStreamData->hWaveOut, outputMmID, &wfx,
                      (DWORD)wmmeStreamData->bufferEvent, (DWORD) stream, CALLBACK_EVENT );
#endif
    if( mmresult != MMSYSERR_NOERROR )
    {
        ERR_RPT(("PortAudio: PaHost_OpenOutputStream() failed!\n"));
        result = paHostError;
        sPaHostError = mmresult;
        goto error;
    }
    /* Allocate an array to hold the buffer pointers. */
    wmmeStreamData->outputBuffers = (WAVEHDR *) PaHost_AllocateTrackedMemory( sizeof(WAVEHDR)*wmmeStreamData->numHostBuffers ); /* MEM */
    if( wmmeStreamData->outputBuffers == NULL )
    {
        result = paInsufficientMemory;
        goto error;
    }
    /* Allocate each buffer. */
    for( i=0; i<wmmeStreamData->numHostBuffers; i++ )
    {
        wmmeStreamData->outputBuffers[i].lpData = (char *) PaHost_AllocateTrackedMemory( wmmeStreamData->bytesPerHostOutputBuffer ); /* MEM */
        if( wmmeStreamData->outputBuffers[i].lpData == NULL )
        {
            result = paInsufficientMemory;
            goto error;
        }
        wmmeStreamData->outputBuffers[i].dwBufferLength = wmmeStreamData->bytesPerHostOutputBuffer;
        wmmeStreamData->outputBuffers[i].dwUser = i;
        if( (mmresult = waveOutPrepareHeader( wmmeStreamData->hWaveOut, &wmmeStreamData->outputBuffers[i], sizeof(WAVEHDR) )) != MMSYSERR_NOERROR )
        {
            result = paHostError;
            sPaHostError = mmresult;
            goto error;
        }
    }
    return result;

error:
    return result;
}
/*******************************************************************/
PaError PaHost_GetTotalBufferFrames( internalPortAudioStream *stream )
{
    PaWMMEStreamData *wmmeStreamData = (PaWMMEStreamData *) stream->past_DeviceData;
    return wmmeStreamData->numHostBuffers * wmmeStreamData->framesPerHostBuffer;
}
/*******************************************************************
 * Determine number of WAVE Buffers
 * and how many User Buffers we can put into each WAVE buffer.
 */
static void PaHost_CalcNumHostBuffers( internalPortAudioStream *stream )
{
    PaWMMEStreamData *wmmeStreamData = (PaWMMEStreamData *) stream->past_DeviceData;
    unsigned int  minNumBuffers;
    int           minframesPerHostBuffer;
    int           maxframesPerHostBuffer;
    int           minTotalFrames;
    int           userBuffersPerHostBuffer;
    int           framesPerHostBuffer;
    int           numHostBuffers;

    /* Calculate minimum and maximum sizes based on timing and sample rate. */
    minframesPerHostBuffer = (int) (PA_MIN_MSEC_PER_HOST_BUFFER * stream->past_SampleRate * 0.001);
    minframesPerHostBuffer = (minframesPerHostBuffer + 7) & ~7;
    DBUG(("PaHost_CalcNumHostBuffers: minframesPerHostBuffer = %d\n", minframesPerHostBuffer ));
    maxframesPerHostBuffer = (int) (PA_MAX_MSEC_PER_HOST_BUFFER * stream->past_SampleRate * 0.001);
    maxframesPerHostBuffer = (maxframesPerHostBuffer + 7) & ~7;
    DBUG(("PaHost_CalcNumHostBuffers: maxframesPerHostBuffer = %d\n", maxframesPerHostBuffer ));
    /* Determine number of user buffers based on minimum latency. */
    minNumBuffers = Pa_GetMinNumBuffers( stream->past_FramesPerUserBuffer, stream->past_SampleRate );
    stream->past_NumUserBuffers = ( minNumBuffers > stream->past_NumUserBuffers ) ? minNumBuffers : stream->past_NumUserBuffers;
    DBUG(("PaHost_CalcNumHostBuffers: min past_NumUserBuffers = %d\n", stream->past_NumUserBuffers ));
    minTotalFrames = stream->past_NumUserBuffers * stream->past_FramesPerUserBuffer;
    /* We cannot make the WAVE buffers too small because they may not get serviced quickly enough. */
    if( (int) stream->past_FramesPerUserBuffer < minframesPerHostBuffer )
    {
        userBuffersPerHostBuffer =
            (minframesPerHostBuffer + stream->past_FramesPerUserBuffer - 1) /
            stream->past_FramesPerUserBuffer;
    }
    else
    {
        userBuffersPerHostBuffer = 1;
    }
    framesPerHostBuffer = stream->past_FramesPerUserBuffer * userBuffersPerHostBuffer;
    /* Calculate number of WAVE buffers needed. Round up to cover minTotalFrames. */
    numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer;
    /* Make sure we have anough WAVE buffers. */
    if( numHostBuffers < PA_MIN_NUM_HOST_BUFFERS)
    {
        numHostBuffers = PA_MIN_NUM_HOST_BUFFERS;
    }
    else if( (numHostBuffers > PA_MAX_NUM_HOST_BUFFERS) &&
             ((int) stream->past_FramesPerUserBuffer < (maxframesPerHostBuffer/2) ) )
    {
        /* If we have too many WAVE buffers, try to put more user buffers in a wave buffer. */
        while(numHostBuffers > PA_MAX_NUM_HOST_BUFFERS)
        {
            userBuffersPerHostBuffer += 1;
            framesPerHostBuffer = stream->past_FramesPerUserBuffer * userBuffersPerHostBuffer;
            numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer;
            /* If we have gone too far, back up one. */
            if( (framesPerHostBuffer > maxframesPerHostBuffer) ||
                    (numHostBuffers < PA_MAX_NUM_HOST_BUFFERS) )
            {
                userBuffersPerHostBuffer -= 1;
                framesPerHostBuffer = stream->past_FramesPerUserBuffer * userBuffersPerHostBuffer;
                numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer;
                break;
            }
        }
    }

    wmmeStreamData->userBuffersPerHostBuffer = userBuffersPerHostBuffer;
    wmmeStreamData->framesPerHostBuffer = framesPerHostBuffer;
    wmmeStreamData->numHostBuffers = numHostBuffers;
    DBUG(("PaHost_CalcNumHostBuffers: userBuffersPerHostBuffer = %d\n", wmmeStreamData->userBuffersPerHostBuffer ));
    DBUG(("PaHost_CalcNumHostBuffers: numHostBuffers = %d\n", wmmeStreamData->numHostBuffers ));
    DBUG(("PaHost_CalcNumHostBuffers: framesPerHostBuffer = %d\n", wmmeStreamData->framesPerHostBuffer ));
    DBUG(("PaHost_CalcNumHostBuffers: past_NumUserBuffers = %d\n", stream->past_NumUserBuffers ));
}
/*******************************************************************/
PaError PaHost_OpenStream( internalPortAudioStream *stream )
{
    PaError             result = paNoError;
    PaWMMEStreamData *wmmeStreamData;

    result = PaHost_AllocateWMMEStreamData( stream );
    if( result != paNoError ) return result;

    wmmeStreamData = PaHost_GetWMMEStreamData( stream );

    /* Figure out how user buffers fit into WAVE buffers. */
    PaHost_CalcNumHostBuffers( stream );
    {
        int msecLatency = (int) ((PaHost_GetTotalBufferFrames(stream) * 1000) / stream->past_SampleRate);
        DBUG(("PortAudio on WMME - Latency = %d frames, %d msec\n", PaHost_GetTotalBufferFrames(stream), msecLatency ));
    }
    InitializeCriticalSection( &wmmeStreamData->streamLock );
    wmmeStreamData->streamLockInited = 1;

#if (PA_USE_TIMER_CALLBACK == 0)
    wmmeStreamData->bufferEventInited = 0;
    wmmeStreamData->bufferEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
    if( wmmeStreamData->bufferEvent == NULL )
    {
        result = paHostError;
        sPaHostError = GetLastError();
        goto error;
    }
    wmmeStreamData->bufferEventInited = 1;
#endif /* (PA_USE_TIMER_CALLBACK == 0) */
    /* ------------------ OUTPUT */
    wmmeStreamData->bytesPerUserOutputBuffer = stream->past_FramesPerUserBuffer * stream->past_NumOutputChannels * sizeof(short);
    wmmeStreamData->bytesPerHostOutputBuffer = wmmeStreamData->userBuffersPerHostBuffer * wmmeStreamData->bytesPerUserOutputBuffer;
    if( (stream->past_OutputDeviceID != paNoDevice) && (stream->past_NumOutputChannels > 0) )
    {
        result = PaHost_OpenOutputStream( stream );
        if( result < 0 ) goto error;
    }
    /* ------------------ INPUT */
    wmmeStreamData->bytesPerUserInputBuffer = stream->past_FramesPerUserBuffer * stream->past_NumInputChannels * sizeof(short);
    wmmeStreamData->bytesPerHostInputBuffer = wmmeStreamData->userBuffersPerHostBuffer * wmmeStreamData->bytesPerUserInputBuffer;
    if( (stream->past_InputDeviceID != paNoDevice) && (stream->past_NumInputChannels > 0) )
    {
        result = PaHost_OpenInputStream( stream );
        if( result < 0 ) goto error;
    }

    Pa_InitializeCpuUsageScalar( stream );

    return result;

error:
    PaHost_CloseStream( stream );
    return result;
}
/*************************************************************************/
PaError PaHost_StartOutput( internalPortAudioStream *stream )
{
    PaError          result = paNoError;
    MMRESULT         mmresult;
    int              i;
    PaWMMEStreamData *wmmeStreamData = PaHost_GetWMMEStreamData( stream );

    if( wmmeStreamData == NULL ) return paInternalError;

    if( stream->past_OutputDeviceID != paNoDevice )
    {
        if( (mmresult = waveOutPause( wmmeStreamData->hWaveOut )) != MMSYSERR_NOERROR )
        {
            result = paHostError;
            sPaHostError = mmresult;
            goto error;
        }
        for( i=0; i<wmmeStreamData->numHostBuffers; i++ )
        {
            ZeroMemory( wmmeStreamData->outputBuffers[i].lpData, wmmeStreamData->outputBuffers[i].dwBufferLength );
            mmresult = waveOutWrite( wmmeStreamData->hWaveOut, &wmmeStreamData->outputBuffers[i], sizeof(WAVEHDR) );
            if( mmresult != MMSYSERR_NOERROR )
            {
                result = paHostError;
                sPaHostError = mmresult;
                goto error;
            }
            stream->past_FrameCount += wmmeStreamData->framesPerHostBuffer;
        }
        wmmeStreamData->currentOutputBuffer = 0;
        if( (mmresult = waveOutRestart( wmmeStreamData->hWaveOut )) != MMSYSERR_NOERROR )
        {
            result = paHostError;
            sPaHostError = mmresult;
            goto error;
        }
    }

error:
    DBUG(("PaHost_StartOutput: wave returned mmresult = 0x%X.\n", mmresult));
    return result;
}
/*************************************************************************/
PaError PaHost_StartInput( internalPortAudioStream *internalStream )
{
    PaError          result = paNoError;
    MMRESULT         mmresult;
    int              i;
    PaWMMEStreamData *wmmeStreamData = PaHost_GetWMMEStreamData( internalStream );

    if( wmmeStreamData == NULL ) return paInternalError;

    if( internalStream->past_InputDeviceID != paNoDevice )
    {
        for( i=0; i<wmmeStreamData->numHostBuffers; i++ )
        {
            mmresult = waveInAddBuffer( wmmeStreamData->hWaveIn, &wmmeStreamData->inputBuffers[i], sizeof(WAVEHDR) );
            if( mmresult != MMSYSERR_NOERROR )
            {
                result = paHostError;
                sPaHostError = mmresult;
                goto error;
            }
        }
        wmmeStreamData->currentInputBuffer = 0;
        mmresult = waveInStart( wmmeStreamData->hWaveIn );
        DBUG(("Pa_StartStream: waveInStart returned = 0x%X.\n", mmresult));
        if( mmresult != MMSYSERR_NOERROR )
        {
            result = paHostError;
            sPaHostError = mmresult;
            goto error;
        }
    }

error:
    return result;
}
/*************************************************************************/
PaError PaHost_StartEngine( internalPortAudioStream *stream )
{
    PaError             result = paNoError;
    PaWMMEStreamData *wmmeStreamData = PaHost_GetWMMEStreamData( stream );
#if PA_USE_TIMER_CALLBACK
    int                 resolution;
    int                 bufsPerTimerCallback;
    int                 msecPerBuffer;
#endif /* PA_USE_TIMER_CALLBACK */

    if( wmmeStreamData == NULL ) return paInternalError;

    stream->past_StopSoon = 0;

⌨️ 快捷键说明

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