当我尝试使用WaitForSingleObjectEx函数发出Xaudio2源语音处理完缓冲区中所有数据的信号时,我收到系统错误代码x05 error_access_denied。
我想用它作为事件处理程序来知道何时向源语音提交另一个音频数据缓冲区,这样它就可以继续播放,直到我的stop()函数/方法被调用。
如何正确实现WaitForSingleObjectEx函数,以便我不会收到error_access_denied系统错误代码?
这适用于Windows Phone 8 C ++ / CX Windows运行时组件......
TestTone.h文件:
#pragma once
#include <client.h> /* ComPtr */
#include <winnt.h> /* HRESULT */
#include <xaudio2.h> /* IXAudio2 */
#include <ppltasks.h> /* task .then */
#include "XAudio2VoiceBufferCallback.h"
namespace PhoneDirect3DXamlAppComponent
{
public ref class TestTone sealed
{
public:
void Initialize();
void Play();
void Stop();
private:
Microsoft::WRL::ComPtr<IXAudio2> pXAudio2;
IXAudio2MasteringVoice *pMasteringVoice;
IXAudio2SourceVoice * pSourceVoice;
byte soundData[2*44100];
XAUDIO2_BUFFER buffer;
WAVEFORMATEX waveformat;
VoiceCallback *vcb;
void CreateSourceVoice();
void FillSoundArrayWithData();
void getSourceVoiceCallbacks(VoiceCallback *vcb,IXAudio2SourceVoice *pSourceVoice,XAUDIO2_BUFFER *buffer);
};
}
TestTone.cpp文件:
// TestTone.cpp
#include "pch.h"
#include "TestTone.h"
#include "XAudio2VoiceBufferCallback.h"
#include <client.h> /* ComPtr */
#include <winnt.h> /* HRESULT */
#include <XAudio2.h> /* IXAudio2 */
#include <ppltasks.h> /* task .then */
#include <math.h> /* sine */
#define PI 3.14159265
using namespace PhoneDirect3DXamlAppComponent;
using namespace concurrency; // tasks
void TestTone::Initialize()
{
XAudio2Create(&pXAudio2,0,XAUDIO2_DEFAULT_PROCESSOR);
pXAudio2->CreateMasteringVoice(&pMasteringVoice);
vcb = new VoiceCallback();
CreateSourceVoice();
buffer.AudioBytes = 2 * 44100;
buffer.pAudioData = soundData;
buffer.PlayBegin = 0;
buffer.PlayLength = 44100;
}
void TestTone::Play()
{
pSourceVoice->Start();
FillSoundArrayWithData();
buffer.pAudioData = soundData;
pSourceVoice->SubmitSourceBuffer(&buffer);
getSourceVoiceCallbacks(vcb, pSourceVoice, &buffer);
}
void TestTone::Stop()
{
pSourceVoice->Stop();
CreateSourceVoice();
}
void TestTone::CreateSourceVoice()
{
waveformat.wFormatTag = WAVE_FORMAT_PCM;
waveformat.nChannels = 1;
waveformat.nSamplesPerSec = 44100;
waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nChannels;
waveformat.nBlockAlign = waveformat.nChannels;
waveformat.wBitsPerSample = 8;
waveformat.cbSize = 0;
hrXAudio2Create = pXAudio2->CreateSourceVoice(&pSourceVoice,&waveformat,0,XAUDIO2_DEFAULT_FREQ_RATIO,vcb,NULL,NULL);
}
void TestTone::FillSoundArrayWithData()
{
for (int index = 0, second = 0; second < 1; second++)
{
for (int sample = 0; sample < waveformat.nSamplesPerSec; sample++)
{
soundData[index++] = 128+(127*sin((500*sample*PI)/(waveformat.nSamplesPerSec)));
}
}
}
void TestTone::getSourceVoiceCallbacks(VoiceCallback *vcb,IXAudio2SourceVoice *pSourceVoice,XAUDIO2_BUFFER *buffer)
{
DWORD dw = NULL;
dw = WaitForSingleObjectEx( vcb->hBufferEndEvent,0,//INFINITE,TRUE );
DWORD err = NULL;
err = GetLastError();
while (WAIT_OBJECT_0 == (WaitForSingleObjectEx(vcb->hBufferEndEvent,INFINITE,TRUE)))
{
pSourceVoice->SubmitSourceBuffer(buffer);
}
return;
}
XAudio2VoiceBufferCallback.h文件:
#pragma once
#include <client.h> /* ComPtr */
#include <winnt.h> /* HRESULT */
#include <xaudio2.h> /* IXAudio2 */
namespace PhoneDirect3DXamlAppComponent
{
class VoiceCallback : public IXAudio2VoiceCallback
{
public:
HANDLE hBufferEndEvent;
VoiceCallback();//: hBufferEndEvent( CreateEventEx( NULL, FALSE, FALSE, NULL ) ){};
~VoiceCallback();//{ CloseHandle( hBufferEndEvent ); }
//Called when the voice has just finished playing a contiguous audio stream.
virtual void __stdcall OnStreamEnd(); //{ SetEvent( hBufferEndEvent ); }
//Unused methods are stubs
void __stdcall OnVoiceProcessingPassEnd();
void __stdcall OnVoiceProcessingPassStart(UINT32 SamplesRequired);
void __stdcall OnBufferEnd(void * pBufferContext);
void __stdcall OnBufferStart(void * pBufferContext);
void __stdcall OnLoopEnd(void * pBufferContext);
void __stdcall OnVoiceError(void * pBufferContext, HRESULT Error);
};
}
XAudio2VoiceBufferCallback.cpp文件:
// XAudio2VoiceBufferCallback.cpp
#include "pch.h"
#include "XAudio2VoiceBufferCallback.h"
#include <client.h> /* ComPtr */
#include <winnt.h> /* HRESULT */
#include <XAudio2.h> /* IXAudio2 */
using namespace PhoneDirect3DXamlAppComponent;
VoiceCallback::VoiceCallback()//:hBufferEndEvent( CreateEventEx( NULL, FALSE, FALSE, NULL ) )
{
hBufferEndEvent = (CreateEventEx(NULL,FALSE,FALSE,NULL));
}
VoiceCallback::~VoiceCallback()
{
CloseHandle( hBufferEndEvent );
}
void VoiceCallback::OnStreamEnd()
{
SetEvent( hBufferEndEvent );
}
void VoiceCallback::OnVoiceProcessingPassEnd() { }
void VoiceCallback::OnVoiceProcessingPassStart(UINT32 SamplesRequired) { }
void VoiceCallback::OnBufferEnd(void * pBufferContext) { }
void VoiceCallback::OnBufferStart(void * pBufferContext) { }
void VoiceCallback::OnLoopEnd(void * pBufferContext) { }
void VoiceCallback::OnVoiceError(void * pBufferContext, HRESULT Error) { }