I was following the tutorial on msdn for xaudio2. 2D audio is working fine, but when I tried integrating 3D audio, it just wasnt working.
#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;
}
The problem lies when I try to apply the 3d audio, but when I run the code the assert triggers with code 88960001 https://learn.microsoft.com/en-us/windows/win32/xaudio2/xaudio2-error-codes
If anybody has any idea please let me know. I thank you in advance.
First of all, you may want to enable debugging for XAudio2 to help you track down problems. See Microsoft Docs.
The HRESULT you are getting (88960001) is XAUDIO2_E_INVALID_CALL
.
There are two problems with your code (besides the abuse of assert
mentioned in the comments):
Your HRESULT failure is likely because your code only works with single-channel / mono wav files.
Even if you fix this, you still hear silence because you have set Emitter.CurveDistanceScaler
to a silly value. Set it to 1 to start out.
For the latest XAudio2 samples for Win32 desktop, see GitHub. There are additional samples for Universal Windows Platform (UWP) here.
You may also want to look at the DirectX Tool Kit for Audio in the DirectX Tool Kit DX11 / DX12.