我已经非常彻底地寻找了一个类似的问题,但还没有真正找到我所拥有的确切情况。
我有一个用于创建线程并等待来自声卡的事件来填充输出缓冲区的音频应用程序的非托管 dll。
该应用程序在板载声卡上运行良好,但如果我切换到任何 USB 音频设备,线程就会挂起。
这是主要代码位:我在我的 Initialize 函数中初始化我的事件
::Initialize()
{
_AudioSamplesReadyEvent = CreateEventEx(NULL, L"InputReady", 0, EVENT_MODIFY_STATE | SYNCHRONIZE);
}
并在初始化后将其传递给声音设备
::InitiAudioEngine()
{
hr = _AudioClient->SetEventHandle(_AudioSamplesReadyEvent);
}
这是线程
//HRESULT hr = CoInitializeEx(NULL, COINIT_SPEED_OVER_MEMORY); //gets called in the constructor of my renderthread class
DWORD DoRenderThread()
{
HANDLE waitArray[2] = {_ShutdownEvent, _AudioSamplesReadyEvent};
HANDLE mmcssHandle = NULL;
DWORD mmcssTaskIndex = 0;
mmcssHandle = AvSetMmThreadCharacteristics(L"Audio", &mmcssTaskIndex);
while (_StillPlaying)
{
HRESULT hr;
DWORD waitResult = WaitForMultipleObjects(2, waitArray, FALSE, INFINITE);
switch (waitResult)
{
case WAIT_OBJECT_0 + 0: // _ShutdownEvent
_StillPlaying = false; // We're done, exit the loop.
break;
case WAIT_OBJECT_0 + 1: // _AudioSamplesReadyEvent
// We need to provide the next buffer of samples to the audio renderer.
BYTE *pData;
//invoke the callback to the managed app to fill our buffer
_Handler(NULL, 0);
hr = _RenderClient->GetBuffer(_BufferSizePerPeriod, &pData);
if (SUCCEEDED(hr))
{
// Copy data from the render buffer to the output buffer and bump our render pointer.
if(_FrameSize == QUAD_FRAME)
{
//we have to remux the stream data in to an L,R,LR,RR frame
//inserting silence for the rear channels
const int bufmuxsz = FIXED_FRAME_SIZE * QUAD_FRAME;
BYTE muxarray[bufmuxsz] = {0};
BYTE tempbuffer[FIXED_FRAME_SIZE * STEREO_FRAME];
CopyMemory(tempbuffer, _Buffer, FIXED_FRAME_SIZE * STEREO_FRAME);
int i = 0;
for(int x = 0; x < bufmuxsz; ++x)
{
muxarray[x++] = tempbuffer[i++];
muxarray[x++] = tempbuffer[i++];
muxarray[x++] = tempbuffer[i++];
muxarray[x++] = tempbuffer[i++];
x += 3; //the array is initialized to '0' so skip the assignments
}
CopyMemory(pData, muxarray, _BufferSizePerPeriod*_FrameSize);
}
else
{
CopyMemory(pData, _Buffer, _BufferSizePerPeriod * _FrameSize);
}
hr = _RenderClient->ReleaseBuffer(_BufferSizePerPeriod, 0);
if (!SUCCEEDED(hr))
{
printf("Playback Failed!!\n");
_StillPlaying = false;
}
}
else
{
_StillPlaying = false;
}
break;
}
}
AvRevertMmThreadCharacteristics(mmcssHandle);
CoUninitialize();
return 0;
}
我等待的两个事件是关闭事件和来自声卡的 samplesready 事件。它总是命中一次,然后挂起。同样,这仅适用于 USB 音频接口。