微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 xaudio2 中集成 3D 音频

如何解决在 xaudio2 中集成 3D 音频

我正在关注 msdn 上的 xaudio2 教程。 2D 音频工作正常,但当我尝试集成 3D 音频时,它无法正常工作。

#include <xaudio2.h>
#include <x3daudio.h>
#include <assert.h>
#include <iostream>
#pragma comment(lib,"xaudio2.lib") 

#ifdef _XBox //Big-Endian
#define fourccRIFF 'RIFF'
#define fourccDATA 'data'
#define fourccFMT 'fmt '
#define fourccwAVE 'WAVE'
#define fourccXWMA 'XWMA'
#define fourccDPDS 'dpds'
#endif

#ifndef _XBox //Little-Endian
#define fourccRIFF 'FFIR'
#define fourccDATA 'atad'
#define fourccFMT ' tmf'
#define fourccwAVE 'EVAW'
#define fourccXWMA 'AMWX'
#define fourccDPDS 'sdpd'
#endif

HRESULT FindChunk(HANDLE hFile,DWORD fourcc,DWORD& dwChunkSize,DWORD& dwChunkDataPosition)
{
    HRESULT hr = S_OK;
    if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile,NULL,FILE_BEGIN))
        return HRESULT_FROM_WIN32(GetLastError());

    DWORD dwChunkType;
    DWORD dwChunkDataSize;
    DWORD dwRIFFDataSize = 0;
    DWORD dwFileType;
    DWORD bytesRead = 0;
    DWORD dwOffset = 0;

    while (hr == S_OK)
    {
        DWORD dwRead;
        if (0 == ReadFile(hFile,&dwChunkType,sizeof(DWORD),&dwRead,NULL))
            hr = HRESULT_FROM_WIN32(GetLastError());

        if (0 == ReadFile(hFile,&dwChunkDataSize,NULL))
            hr = HRESULT_FROM_WIN32(GetLastError());

        switch (dwChunkType)
        {
        case fourccRIFF:
            dwRIFFDataSize = dwChunkDataSize;
            dwChunkDataSize = 4;
            if (0 == ReadFile(hFile,&dwFileType,NULL))
                hr = HRESULT_FROM_WIN32(GetLastError());
            break;

        default:
            if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile,dwChunkDataSize,FILE_CURRENT))
                return HRESULT_FROM_WIN32(GetLastError());
        }

        dwOffset += sizeof(DWORD) * 2;

        if (dwChunkType == fourcc)
        {
            dwChunkSize = dwChunkDataSize;
            dwChunkDataPosition = dwOffset;
            return S_OK;
        }

        dwOffset += dwChunkDataSize;

        if (bytesRead >= dwRIFFDataSize) return S_FALSE;

    }

    return S_OK;

}

HRESULT ReadChunkData(HANDLE hFile,void* buffer,DWORD buffersize,DWORD bufferoffset)
{
    HRESULT hr = S_OK;
    if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile,bufferoffset,FILE_BEGIN))
        return HRESULT_FROM_WIN32(GetLastError());
    DWORD dwRead;
    if (0 == ReadFile(hFile,buffer,buffersize,NULL))
        hr = HRESULT_FROM_WIN32(GetLastError());
    return hr;
}

int main()
{
    Ixaudio2* pxaudio2;
    Ixaudio2MasteringVoice* pMasterVoice;
    Ixaudio2SourceVoice* pSource;
    X3DAUdio_HANDLE X3DInstance;
    WAVEFORMATEXTENSIBLE wfx = { 0 };
    xaudio2_BUFFER buffer = { 0 };

    HRESULT hr;

    assert(SUCCEEDED(hr = CoInitializeEx(nullptr,COINIT_MULTITHREADED)));

    assert(SUCCEEDED(hr = xaudio2Create(&pxaudio2,xaudio2_DEBUG_ENGINE,xaudio2_DEFAULT_PROCESSOR)));

    assert(SUCCEEDED(hr = pxaudio2->CreateMasteringVoice(&pMasterVoice)));

    //xaudio2_DEBUG_CONfigURATION debug;
    //pxaudio2->SetDebugConfiguration(&debug);

    DWORD dwChannelMask;
    pMasterVoice->GetChannelMask(&dwChannelMask);

    assert(SUCCEEDED(hr = X3DAudioInitialize(dwChannelMask,X3DAUdio_SPEED_OF_SOUND,X3DInstance)));

    X3DAUdio_LISTENER Listener = {};
    X3DAUdio_EMITTER Emitter = {};
    Emitter.ChannelCount = 1;
    Emitter.CurvedistanceScaler = FLT_MIN;

    xaudio2_VOICE_DETAILS details;
    pMasterVoice->GetVoiceDetails(&details);

    X3DAUdio_DSP_SETTINGS DSPSettings = { 0 };
    FLOAT32* matrix = new FLOAT32[details.InputChannels];
    DSPSettings.SrcChannelCount = 1;
    DSPSettings.DstChannelCount = details.InputChannels;
    DSPSettings.pMatrixCoefficients = matrix;


    Emitter.OrientFront = { -1,0 };
    Emitter.OrientTop = { 0,1,0 };
    Emitter.Position = { 5,2,3 };
    Emitter.VeLocity = { 0,0 };
    Listener.OrientFront = { 1,0 };
    Listener.OrientTop = { 0,0 };
    Listener.Position = { 0,0 };
    Listener.VeLocity = { 0,0 };

    HANDLE hFile = CreateFile(
        (LPCSTR)"woodBreak.wav",GENERIC_READ,FILE_SHARE_READ,OPEN_EXISTING,NULL);


    SetFilePointer(hFile,FILE_BEGIN);

    DWORD dwChunkSize;
    DWORD dwChunkPosition;
    //check the file type,should be fourccwAVE or 'XWMA'
    FindChunk(hFile,fourccRIFF,dwChunkSize,dwChunkPosition);
    DWORD filetype;
    ReadChunkData(hFile,&filetype,dwChunkPosition);

    FindChunk(hFile,fourccFMT,dwChunkPosition);
    ReadChunkData(hFile,&wfx,dwChunkPosition);

    //fill out the audio data buffer with the contents of the fourccDATA chunk
    FindChunk(hFile,fourccDATA,dwChunkPosition);
    BYTE* pDataBuffer = new BYTE[dwChunkSize];
    ReadChunkData(hFile,pDataBuffer,dwChunkPosition);

    buffer.AudioBytes = dwChunkSize;
    buffer.pAudioData = pDataBuffer;
    buffer.Flags = xaudio2_END_OF_STREAM;
    buffer.LoopCount = xaudio2_LOOP_INFINITE;

    
    assert(SUCCEEDED(hr = pxaudio2->CreateSourceVoice(&pSource,(WAVEFORMATEX*)&wfx)));
    assert(SUCCEEDED(hr = pSource->SubmitSourceBuffer(&buffer)));

    X3DAudioCalculate(X3DInstance,&Listener,&Emitter,X3DAUdio_CALculaTE_MATRIX | X3DAUdio_CALculaTE_DOPPLER | X3DAUdio_CALculaTE_LPF_DIRECT | X3DAUdio_CALculaTE_REVERB,&DSPSettings);

    assert(SUCCEEDED(hr = pSource->SetFrequencyRatio(DSPSettings.DopplerFactor)));
    assert(SUCCEEDED(hr = pSource->SetoutputMatrix(pMasterVoice,details.InputChannels,DSPSettings.pMatrixCoefficients)));

    pSource->Start();

    int i;
    std::cin >> i;

    return 0;
}

问题在于当我尝试应用 3d 音频时,但是当我运行代码时,断言会触发代码 88960001 https://docs.microsoft.com/en-us/windows/win32/xaudio2/xaudio2-error-codes

如果有人有任何想法,请告诉我。 我先谢谢你。

解决方法

首先,您可能希望为 XAudio2 启用调试以帮助您跟踪问题。见Microsoft Docs

您得到的 HRESULT (88960001) 是 XAUDIO2_E_INVALID_CALL

您的代码有两个问题(除了评论中提到的滥用 assert):

  1. 您的 HRESULT 失败可能是因为您的代码仅适用于单声道/单声道 wav 文件。

  2. 即使您解决了这个问题,您仍然会听到静音,因为您将 Emitter.CurveDistanceScaler 设置为一个愚蠢的值。将其设置为 1 以开始。

有关 Win32 桌面的最新 XAudio2 示例,请参阅 GitHub。还有适用于通用 Windows 平台 (UWP) here 的其他示例。

您可能还想查看 DirectX Tool Kit DX11 / DX12 中的 DirectX Tool Kit for Audio

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。