问题描述
我正在关注 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
):
-
您的 HRESULT 失败可能是因为您的代码仅适用于单声道/单声道 wav 文件。
-
即使您解决了这个问题,您仍然会听到静音,因为您将
Emitter.CurveDistanceScaler
设置为一个愚蠢的值。将其设置为 1 以开始。
有关 Win32 桌面的最新 XAudio2 示例,请参阅 GitHub。还有适用于通用 Windows 平台 (UWP) here 的其他示例。
您可能还想查看 DirectX Tool Kit DX11 / DX12 中的 DirectX Tool Kit for Audio。