#windows-runtime #c -cx #xaudio2
#windows-среда выполнения #c -cx #xaudio2
Вопрос:
Я получаю код системной ошибки x05 error_access_denied при попытке использовать функцию WaitForSingleObjectEx для сигнализации о том, что исходный голос Xaudio2 завершил обработку всех данных в своем буфере.
Я хочу использовать это как обработчик событий, чтобы знать, когда отправлять другой буфер аудиоданных исходному голосу, чтобы он мог продолжать воспроизведение до тех пор, пока не будет вызвана моя функция / метод 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(amp;pXAudio2,0,XAUDIO2_DEFAULT_PROCESSOR);
pXAudio2->CreateMasteringVoice(amp;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(amp;buffer);
getSourceVoiceCallbacks(vcb, pSourceVoice, amp;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(amp;pSourceVoice,amp;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) { }
Комментарии:
1. Кажется маловероятным, что вторая строка в getSourceVoiceCallbacks будет даже скомпилирована; это ошибка копирования-вставки?
2. Вы установили
dwDesiredAccess
значение нуляCreateEventEx
, поэтому вам был предоставлен дескриптор без прав доступа.