Mono output when using X3DAudio

222 Views Asked by At

I'm making a simple audio engine, the audio works well in 2D, now I want to use X3DAudio to have a sound that is positioned in 3D space. I've followed the docs and now can play sound using X3DAudio but for some reason, it's outputting mono sound although my master has 2 channels and the sound also has 2 channels.
What I'm doing wrong?

First, I initialize X3DAudio:

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

X3DAudioInitialize(dwChannelMask, X3DAUDIO_SPEED_OF_SOUND, hX3dAudio);

Then, I initialize listener stuff (and convert vectors from my coordinate system to coordinate system X3DAudio uses):

x3dAudioListener.pCone = NULL;

listenerProps.position = X3DAUDIO_VECTOR(-listenerProps.position.x, listenerProps.position.z, listenerProps.position.y);
listenerProps.velocity = X3DAUDIO_VECTOR(-listenerProps.velocity.x, listenerProps.velocity.z, listenerProps.velocity.y);
listenerProps.topVector = X3DAUDIO_VECTOR(-listenerProps.topVector.x, listenerProps.topVector.z, listenerProps.topVector.y);
listenerProps.forwardVector = X3DAUDIO_VECTOR(-listenerProps.forwardVector.x, listenerProps.forwardVector.z, listenerProps.forwardVector.y);

x3dAudioListener.OrientFront = listenerProps.forwardVector;
x3dAudioListener.OrientTop = listenerProps.topVector;
x3dAudioListener.Position = listenerProps.position;
x3dAudioListener.Velocity = listenerProps.velocity;

Then, I initialize DSP settings:

XAUDIO2_VOICE_DETAILS masterVoiceDetails;
pAudioEngine->pMasteringVoice->GetVoiceDetails(&masterVoiceDetails);

XAUDIO2_VOICE_DETAILS sourceVoiceDetails;
pSourceVoice->GetVoiceDetails(&sourceVoiceDetails);

p3dAudioMatrix = new float[sourceVoiceDetails.InputChannels * masterVoiceDetails.InputChannels];
memset(p3dAudioMatrix, 0, sizeof(float) * sourceVoiceDetails.InputChannels * masterVoiceDetails.InputChannels);

x3dAudioDSPSettings.SrcChannelCount = sourceVoiceDetails.InputChannels;
x3dAudioDSPSettings.DstChannelCount = masterVoiceDetails.InputChannels;
x3dAudioDSPSettings.pMatrixCoefficients = p3dAudioMatrix;
x3dAudioDSPSettings.pDelayTimes = NULL;

And then apply the sound position:

emitterProps.position = X3DAUDIO_VECTOR(-emitterProps.position.x, emitterProps.position.z, emitterProps.position.y);
emitterProps.velocity = X3DAUDIO_VECTOR(-emitterProps.velocity.x, emitterProps.velocity.z, emitterProps.velocity.y);
emitterProps.topVector = X3DAUDIO_VECTOR(-emitterProps.topVector.x, emitterProps.topVector.z, emitterProps.topVector.y);
emitterProps.forwardVector = X3DAUDIO_VECTOR(-emitterProps.forwardVector.x, emitterProps.forwardVector.z, emitterProps.forwardVector.y);

x3dAudioEmitter = {0};
x3dAudioEmitter.pCone = NULL;
x3dAudioEmitter.pLFECurve = NULL;
x3dAudioEmitter.pLPFDirectCurve = NULL;
x3dAudioEmitter.pLPFReverbCurve = NULL;
x3dAudioEmitter.pVolumeCurve = NULL;
x3dAudioEmitter.pReverbCurve = NULL;
x3dAudioEmitter.OrientFront = emitterProps.forwardVector;
x3dAudioEmitter.OrientTop = emitterProps.topVector;
x3dAudioEmitter.Position = emitterProps.position;
x3dAudioEmitter.Velocity = emitterProps.velocity;
x3dAudioEmitter.InnerRadius = 2.0f;
x3dAudioEmitter.InnerRadiusAngle = X3DAUDIO_PI/4.0f;
x3dAudioEmitter.ChannelCount = soundInfo.iChannels;
x3dAudioEmitter.ChannelRadius = 10.0f;
x3dAudioEmitter.CurveDistanceScaler = 1.0f;
x3dAudioEmitter.DopplerScaler = 1.0f;
float* pEmitterAzimuths = new float[x3dAudioEmitter.ChannelCount];
memset(pEmitterAzimuths, 0, x3dAudioEmitter.ChannelCount * sizeof(float));
x3dAudioEmitter.pChannelAzimuths = pEmitterAzimuths;


UINT32 iFlags = X3DAUDIO_CALCULATE_MATRIX;
if (bCalcDopplerEffect) iFlags |= X3DAUDIO_CALCULATE_DOPPLER;


X3DAudioCalculate(pAudioEngine->hX3dAudio, &pAudioEngine->x3dAudioListener, &x3dAudioEmitter, iFlags, &x3dAudioDSPSettings);

XAUDIO2_VOICE_DETAILS masterVoiceDetails;
pAudioEngine->pMasteringVoice->GetVoiceDetails(&masterVoiceDetails);

delete[] pEmitterAzimuths;

HRESULT hr = pSourceVoice->SetOutputMatrix(pAudioEngine->pMasteringVoice, soundInfo.iChannels, masterVoiceDetails.InputChannels, x3dAudioDSPSettings.pMatrixCoefficients);
if (FAILED(hr))
{
    // error handling
}

if (bCalcDopplerEffect)
{
    hr = pSourceVoice->SetFrequencyRatio(x3dAudioDSPSettings.DopplerFactor);
    if (FAILED(hr))
    {
        // error handling
    }
}

The debug layer is enabled and I see no errors. I've checked soundInfo.iChannels is == 2 and master channel count is also 2. I apply listener/emitter properties like this:

listenerProps.position = X3DAUDIO_VECTOR(0.0f, 0.0f, 0.0f);
listenerProps.velocity = X3DAUDIO_VECTOR(0.0f, 0.0f, 0.0f);
listenerProps.forwardVector = X3DAUDIO_VECTOR(0.0f, 1.0f, 0.0f);
listenerProps.topVector = X3DAUDIO_VECTOR(0.0f, 0.0f, 1.0f);

SEmitterProps props;
props.position = X3DAUDIO_VECTOR(-5.0f, 0.0f, 0.0f);
props.velocity = X3DAUDIO_VECTOR(fSoundSpeed, 0.0f, 0.0f);
props.forwardVector = X3DAUDIO_VECTOR(-1.0f, 0.0f, 0.0f);
props.topVector = X3DAUDIO_VECTOR(0.0f, 0.0f, 1.0f);

In my coordinate system x is from right to left, up is z, and y is near to far.

2

There are 2 best solutions below

1
Chuck Walbourn On

There are a lot of parameters and steps to properly using X3DAudio, and I can't really tell from the code above if you have properly zero'd and set all the values in X3DAUDIO_LISTENER, X3DAUDIO_EMITTER, and X3DAUDIO_DSP_SETTINGS so check those first. Any uninitialized values will cause problems.

The most recent versions of the XAudio2 samples that originally shipped in the legacy DirectX SDK can be found on GitHub. In particular, look at XAudio2Sound3D. You should try hard-coding all the emitter/listener values to something trivial to test and make sure that works before hooking it up to your coordinate system.

In addition to the XAudio2 samples from the legacy DirectX SDK, you should take a look at DirectX Tool Kit for Audio which is part of the DirectX Tool Kit for DX11 / DX12.

0
VoidRune On

I had the same problem and what I found out is that when building for 64 bit version the second and third value in matrix were calculated flipped for some reason. This does not apply for 1 channel (mono) audio.

after X3DAudioCalculate() function try

float f = p3dAudioMatrix [1];
p3dAudioMatrix [1] = p3dAudioMatrix [2];
p3dAudioMatrix [2] = f;