在 xaudio2 中集成 3D 音频
Posted
技术标签:
【中文标题】在 xaudio2 中集成 3D 音频【英文标题】:Integrating 3D audio in xaudio2 【发布时间】:2021-09-15 05:01:14 【问题描述】:我正在关注 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, 0, 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, sizeof(DWORD), &dwRead, NULL))
hr = HRESULT_FROM_WIN32(GetLastError());
switch (dwChunkType)
case fourccRIFF:
dwRIFFDataSize = dwChunkDataSize;
dwChunkDataSize = 4;
if (0 == ReadFile(hFile, &dwFileType, sizeof(DWORD), &dwRead, NULL))
hr = HRESULT_FROM_WIN32(GetLastError());
break;
default:
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, dwChunkDataSize, NULL, 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, NULL, FILE_BEGIN))
return HRESULT_FROM_WIN32(GetLastError());
DWORD dwRead;
if (0 == ReadFile(hFile, buffer, buffersize, &dwRead, 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, 0 ;
Emitter.OrientTop = 0, 1, 0 ;
Emitter.Position = 5, 2, 3 ;
Emitter.Velocity = 0, 0, 0 ;
Listener.OrientFront = 1, 0, 0 ;
Listener.OrientTop = 0, 1, 0 ;
Listener.Position = 0, 0, 0 ;
Listener.Velocity = 0, 0, 0 ;
HANDLE hFile = CreateFile(
(LPCSTR)"woodBreak.wav",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
SetFilePointer(hFile, 0, NULL, 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, sizeof(DWORD), dwChunkPosition);
FindChunk(hFile, fourccFMT, dwChunkSize, dwChunkPosition);
ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition);
//fill out the audio data buffer with the contents of the fourccDATA chunk
FindChunk(hFile, fourccDATA, dwChunkSize, dwChunkPosition);
BYTE* pDataBuffer = new BYTE[dwChunkSize];
ReadChunkData(hFile, pDataBuffer, dwChunkSize, 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, 1, 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
如果有人有任何想法,请告诉我。 提前谢谢你。
【问题讨论】:
您似乎正在使用 XAudio 2.8 (Windows 8.x) 或 XAudio 2.9 (Windows 10 & XAudio2Redist)。您应该提及您使用哪个操作系统来帮助诊断问题。 我使用的是 Windows 10 2.9 版本 顺便说一句,不要使用断言来检查失败。考虑类似ThrowIfFailed。 【参考方案1】:首先,您可能希望为 XAudio2 启用调试以帮助您跟踪问题。见Microsoft Docs。
您得到的 HRESULT (88960001) 是 XAUDIO2_E_INVALID_CALL
。
你的代码有两个问题(除了cmets中提到的assert
的滥用):
您的 HRESULT 失败可能是因为您的代码仅适用于单通道/单声道 wav 文件。
即使您解决了这个问题,您仍然会听到静音,因为您已将 Emitter.CurveDistanceScaler
设置为一个愚蠢的值。将其设置为 1 即可开始。
有关 Win32 桌面的最新 XAudio2 示例,请参阅GitHub。还有其他适用于通用 Windows 平台 (UWP) here 的示例。
您可能还想查看 DirectX Tool Kit 中的 DirectX Tool Kit for Audio DX11 / DX12。
【讨论】:
您好,我已经编辑了代码,以便可以将其复制粘贴到主文件中,并且在项目属性下应该使用多字节字符而不是 unicode。如果您评论 SetOutputMatrix 并将 wav 文件添加到项目中,它应该播放正常的 2d 音频。如果可以,请花时间尝试。 “woodbreak.wav”是什么音频格式?在您的代码中,您假设它是单声道(1 声道)声音。以上是关于在 xaudio2 中集成 3D 音频的主要内容,如果未能解决你的问题,请参考以下文章
Windows基础-使用XAudio2播放音频(本质是WASAPI)