0

当我尝试使用 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) { }
4

0 回答 0