我目前正在努力用XAudio2库实现3D定位声音。当监听器和源的位置在所有轴上正好是0.0f时,我设法让它工作起来。当我稍微移动听众或音源时,声音就不再被听到,但仍在播放。我在这里错过了什么?谢谢:(
uint32_t sourceInputChannels = 2;
uint32_t masterInputChannels = 8;
float* outputMatrix = new float[masterInputChannels * sourceInputChannels];
// Listener
X3DAUDIO_LISTENER listener{};
listener.Position = { 0.0f, 0.0f, 0.0f };
listener.Velocity = { 0.0f, 0.0f, 0.0f };
listener.OrientFront = { 1.0f, 0.0f, 0.0f };
listener.OrientTop = { 0.0f, 0.0f, 1.0f };
// Emitter
X3DAUDIO_EMITTER sourceEmitter{};
sourceEmitter.ChannelCount = 1;
sourceEmitter.CurveDistanceScaler = FLT_MIN;
sourceEmitter.Position = { 0.0f, 0.0f, 0.0f };
sourceEmitter.Velocity = { 0.0f, 0.0f, 0.0f };
sourceEmitter.OrientFront = { 1.0f, 0.0f, 0.0f };
sourceEmitter.OrientTop = { 0.0f, 0.0f, 1.0f };
sourceEmitter.ChannelRadius = 2.0f;
sourceEmitter.InnerRadius = 2.0f;
sourceEmitter.InnerRadiusAngle = X3DAUDIO_PI / 4.0f;
X3DAUDIO_DSP_SETTINGS dspSettings{};
dspSettings.SrcChannelCount = sourceEmitter.ChannelCount; // 1
// 8 * 2, OUTPUT_CHANNELS is also present in CreateMasteringVoice
dspSettings.DstChannelCount = OUTPUT_CHANNELS * sourceVoiceDetails.InputChannels;
dspSettings.pMatrixCoefficients = outputMatrix;
// Calculating
X3DAudioCalculate(g_CealContext->X3DInstance, &listener, &sourceEmitter, X3DAUDIO_CALCULATE_MATRIX |
X3DAUDIO_CALCULATE_DOPPLER | X3DAUDIO_CALCULATE_LPF_DIRECT | X3DAUDIO_CALCULATE_REVERB, &dspSettings);
sourceVoice->SetOutputMatrix(g_CealContext->XMasterVoice, sourceInputChannels, masterInputChannels, outputMatrix);
delete[] outputMatrix;
X3DAudio有很多参数,但我猜问题是您有立体声(2声道(源语音,并且试图使用1声道DSP设置。您还传递了许多X3DAUDIO_CALCULATE_
标志,这些标志需要比您提供的更多的数据。
您应该看看托管在GitHub上的原始遗留DirectX SDK XAudio2示例。特别请参见XAudio2Sound3D。
您还应该看看DirectX音频工具包。
此外,sourceEmitter.CurveDistanceScaler
和sourceEmitter.DopplerScaler
通常应为1.0。
更新
:如果SrcChannelCount大于1,则必须提供发射器方位角。我在DirectX音频工具包AudioEmitter::EnableDefaultMultiChannel
中有一个助手方法,它基于简单的扬声器几何结构来设置这些功能——这就是传统XACT处理它们的方式。
// **Note these constants came from xact3d3.h in the legacy DirectX SDK**
//
// Supported speaker positions, represented as azimuth angles.
//
// Here's a picture of the azimuth angles for the 8 cardinal points,
// seen from above. The emitter's base position is at the origin 0.
//
// FRONT
// | 0 <-- azimuth
// |
// 7pi/4 | / pi/4
// | /
// LEFT |/ RIGHT
// 3pi/2-------0-------pi/2
// /|
// / |
// 5pi/4 / | 3pi/4
// |
// | pi
// BACK
//
constexpr float LEFT_AZIMUTH = 3 * X3DAUDIO_PI / 2;
constexpr float RIGHT_AZIMUTH = X3DAUDIO_PI / 2;
constexpr float FRONT_LEFT_AZIMUTH = 7 * X3DAUDIO_PI / 4;
constexpr float FRONT_RIGHT_AZIMUTH = X3DAUDIO_PI / 4;
constexpr float FRONT_CENTER_AZIMUTH = 0.0f;
constexpr float LOW_FREQUENCY_AZIMUTH = X3DAUDIO_2PI;
constexpr float BACK_LEFT_AZIMUTH = 5 * X3DAUDIO_PI / 4;
constexpr float BACK_RIGHT_AZIMUTH = 3 * X3DAUDIO_PI / 4;
constexpr float BACK_CENTER_AZIMUTH = X3DAUDIO_PI;
constexpr float c_channelAzimuths[9][8] =
{
/* 0 */ { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
/* 1 */ { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
/* 2 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
/* 2.1 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, LOW_FREQUENCY_AZIMUTH, 0.f, 0.f, 0.f, 0.f, 0.f },
/* 4.0 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, BACK_LEFT_AZIMUTH, BACK_RIGHT_AZIMUTH, 0.f, 0.f, 0.f, 0.f },
/* 4.1 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, LOW_FREQUENCY_AZIMUTH, BACK_LEFT_AZIMUTH, BACK_RIGHT_AZIMUTH, 0.f, 0.f, 0.f },
/* 5.1 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, FRONT_CENTER_AZIMUTH, LOW_FREQUENCY_AZIMUTH, BACK_LEFT_AZIMUTH, BACK_RIGHT_AZIMUTH, 0.f, 0.f },
/* 6.1 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, FRONT_CENTER_AZIMUTH, LOW_FREQUENCY_AZIMUTH, BACK_LEFT_AZIMUTH, BACK_RIGHT_AZIMUTH, BACK_CENTER_AZIMUTH, 0.f },
/* 7.1 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, FRONT_CENTER_AZIMUTH, LOW_FREQUENCY_AZIMUTH, BACK_LEFT_AZIMUTH, BACK_RIGHT_AZIMUTH, LEFT_AZIMUTH, RIGHT_AZIMUTH }
};
...
emitter.ChannelCount = channels;
emitter.ChannelRadius = 1.f;
emitter.pChannelAzimuths = (channels <= 8)
? &c_channelAzimuths[channels] : nullptr;
好吧,多亏了@chuck walbourn,我成功地让它工作了
问题是X3DAUDIO_EMITTER
的成员CurveDistanceScaler
被设置为FLT_MIN,而不是某个不太小的值
奇怪的是,我正在关注微软的官方文档《如何将X3DAudio与XAudio2集成》,示例代码使用FLT_MIN,所以我真的不明白发生了什么。