2

我在我的研究实验室中使用 C++ 编写神经科学实验。我们正在研究触觉感知,我们使用并行端口来触发我们的大脑刺激设备。时机非常重要。我们最近开始使用 xaudio2 播放非常简单的 WAV 文件,这些文件用于触发我们的振动触觉刺激器(例如,我们的“触觉”刺激是 100 和 200 Hz 的声音,持续时间为 100 ms,它移动压电刺激器放在手上)。我们的问题是,我们需要通过并行端口向大脑刺激器发送 3 个命令:在触觉刺激前 40 毫秒一次,在刺激开始后 10 毫秒一次,在刺激开始后 60 毫秒第三次。请记住,触觉刺激持续 100 毫秒。但是,xaudio2 触发声音的方式是它播放波形并阻塞直到完成。结果,程序忽略了应该在激励期间发送的两个并行端口命令。有谁知道我如何确保在整个 100 毫秒的持续时间内仍然触发触觉刺激,而且在此期间还发送并行端口命令?我使用 MSDN XAudio2Samples 作为播放 wav 文件的基本结构,而 PlayWave 功能是在播放 Wav 文件时“阻止”任何其他输入的功能 - 但我不知道如何修改它所以在播放声音时,它还将接受我的并行端口命令(即 Out32(888,1))。谢谢!有谁知道我如何确保在整个 100 毫秒的持续时间内仍然触发触觉刺激,而且在此期间还发送并行端口命令?我使用 MSDN XAudio2Samples 作为播放 wav 文件的基本结构,而 PlayWave 功能是在播放 Wav 文件时“阻止”任何其他输入的功能 - 但我不知道如何修改它所以在播放声音时,它还将接受我的并行端口命令(即 Out32(888,1))。谢谢!有谁知道我如何确保在整个 100 毫秒的持续时间内仍然触发触觉刺激,而且在此期间还发送并行端口命令?我使用 MSDN XAudio2Samples 作为播放 wav 文件的基本结构,而 PlayWave 功能是在播放 Wav 文件时“阻止”任何其他输入的功能 - 但我不知道如何修改它所以在播放声音时,它还将接受我的并行端口命令(即 Out32(888,1))。谢谢!t 弄清楚如何修改它,以便在播放声音时它也会接受我的并行端口命令(即 Out32(888,1))。谢谢!t 弄清楚如何修改它,以便在播放声音时它也会接受我的并行端口命令(即 Out32(888,1))。谢谢!

这是 PlayWave 函数的代码:

    //--------------------------------------------------------------------------------------
// Name: PlayWave
// Desc: Plays a wave and blocks until the wave finishes playing
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT PlayWave( IXAudio2* pXaudio2, LPCWSTR szFilename )
{
    //
    // Locate the wave file
    //
    WCHAR strFilePath[MAX_PATH];
    HRESULT hr = FindMediaFileCch( strFilePath, MAX_PATH, szFilename );
    if( FAILED( hr ) )
    {
        wprintf( L"Failed to find media file: %s\n", szFilename );
        return hr;
    }

    //
    // Read in the wave file
    //
    std::unique_ptr<uint8_t[]> waveFile;
    DirectX::WAVData waveData;
    if ( FAILED( hr = DirectX::LoadWAVAudioFromFileEx( strFilePath, waveFile, waveData ) ) )
    {
        wprintf( L"Failed reading WAV file: %#X (%s)\n", hr, strFilePath );
        return hr;
    }

    //
    // Play the wave using a XAudio2SourceVoice
    //

    // Create the source voice
    IXAudio2SourceVoice* pSourceVoice;
    if( FAILED( hr = pXaudio2->CreateSourceVoice( &pSourceVoice, waveData.wfx ) ) )
    {
        wprintf( L"Error %#X creating source voice\n", hr );
        return hr;
    }

    // Submit the wave sample data using an XAUDIO2_BUFFER structure
    XAUDIO2_BUFFER buffer = {0};
    buffer.pAudioData = waveData.startAudio;
    buffer.Flags = XAUDIO2_END_OF_STREAM;  // tell the source voice not to expect any data after this buffer
    buffer.AudioBytes = waveData.audioBytes;

    if ( waveData.loopLength > 0 )
    {
        buffer.LoopBegin = waveData.loopStart;
        buffer.LoopLength = waveData.loopLength;
        buffer.LoopCount = 1; // We'll just assume we play the loop twice
    }

#if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/)
    if ( waveData.seek )
    {
        XAUDIO2_BUFFER_WMA xwmaBuffer = {0};
        xwmaBuffer.pDecodedPacketCumulativeBytes = waveData.seek;
        xwmaBuffer.PacketCount = waveData.seekCount;
        if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer, &xwmaBuffer ) ) )
        {
            wprintf( L"Error %#X submitting source buffer (xWMA)\n", hr );
            pSourceVoice->DestroyVoice();
            return hr;
        }
    }
#else
    if ( waveData.seek )
    {
        wprintf( L"This platform does not support xWMA or XMA2\n" );
        pSourceVoice->DestroyVoice();
        return hr;
    }
#endif
    else if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) )
    {
        wprintf( L"Error %#X submitting source buffer\n", hr );
        pSourceVoice->DestroyVoice();
        return hr;
    }

    hr = pSourceVoice->Start( 0 );

    // Let the sound play
    BOOL isRunning = TRUE;
    while( SUCCEEDED( hr ) && isRunning )
    {
        XAUDIO2_VOICE_STATE state;
        pSourceVoice->GetState( &state );
        isRunning = ( state.BuffersQueued > 0 ) != 0;

        // Wait till the escape key is pressed
        if( GetAsyncKeyState( VK_ESCAPE ) )
            break;

        Sleep( 10 );
    }

    // Wait till the escape key is released
    while( GetAsyncKeyState( VK_ESCAPE ) )
        Sleep( 10 );

    pSourceVoice->DestroyVoice();

    return hr;
}
4

0 回答 0