Как предполагается реализовать WaitForSingleObjectEx при использовании исходных голосовых обратных вызовов с XAudio2 для компонентов среды выполнения Windows?

#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 , поэтому вам был предоставлен дескриптор без прав доступа.