我正在学习xaudio2的msdn教程。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音频时,但当我运行代码时,assert会触发代码88960001https://learn.microsoft.com/en-us/windows/win32/xaudio2/xaudio2-error-codes
如果有人有任何想法,请告诉我。我提前感谢你。
首先,您可能希望启用XAudio2的调试功能,以帮助您跟踪问题。请参阅Microsoft文档。
您得到的HRESULT(88960001(是XAUDIO2_E_INVALID_CALL
。
你的代码有两个问题(除了评论中提到的assert
的滥用(:
-
您的HRESULT失败可能是因为您的代码仅适用于单通道/单声道wav文件。
-
即使您修复了这个问题,您仍然会听到静音,因为您已经将
Emitter.CurveDistanceScaler
设置为一个愚蠢的值。将其设置为1即可开始。
有关Win32桌面的最新XAudio2示例,请参阅GitHub。这里还有通用Windows平台(UWP(的其他示例。
您可能还想查看DirectX工具包DX11/DX12中的DirectX音频工具包。