Closed Flone-dnb closed 3 years ago
Where is the code that creates the audEngine
?
You are calling audEngine->Update()
in a loop somewhere, yes?
Clearly there's something unusual about your setup. I suggest you run through the tutorial on positional audio with DirectX Tool Kit for Audio.
Also, have you tried other wav files? Is the one you are using multi-channel?
I'm sorry I didn't include engine creation by mistake, here is the full code (I've referred to this wiki):
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr)) {}
std::unique_ptr<DirectX::AudioEngine> audEngine;
DirectX::AUDIO_ENGINE_FLAGS eflags = DirectX::AudioEngine_Default;
#ifdef _DEBUG
eflags |= DirectX::AudioEngine_Debug;
#endif
auto enumList = DirectX::AudioEngine::GetRendererDetails();
std::wstring deviceId = L"";
if (enumList.empty())
{
std::cout << "No audio devices\n";
system("pause");
return 1;
}
else
{
for (auto it = enumList.cbegin(); it != enumList.cend(); ++it)
{
// it->deviceId.c_str() - this is the device/end-point identifier you can
// pass as a parameter to AudioEngine
// it->description.c_str() - this is a textual description
}
}
if (deviceId == L"")
{
audEngine = std::make_unique<DirectX::AudioEngine>(eflags);
}
else
{
audEngine = std::make_unique<DirectX::AudioEngine>(eflags, nullptr, deviceId.c_str());
}
if (!audEngine->Update()) // Update returns false if no audio is actually playing or critical error
{
// No audio device is active
if (audEngine->IsCriticalError())
{
std::cout << "No audio device is active. Attempting to use another device.\n";
if (audEngine->Reset())
{
// OK.
}
else
{
system("pause");
return 1;
}
}
}
std::unique_ptr<DirectX::SoundEffect> soundEffect;
soundEffect = std::make_unique<DirectX::SoundEffect>(audEngine.get(), L"sound.wav");
auto effect = soundEffect->CreateInstance(DirectX::SoundEffectInstance_Use3D);
effect->SetVolume(0.5f);
effect->Play(false);
DirectX::AudioListener listener;
listener.SetPosition(DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f));
DirectX::AudioEmitter emitter;
emitter.SetPosition(DirectX::XMFLOAT3(0.0f, 0.0f, -3.0f));
effect->Apply3D(listener, emitter, false);
auto stats = audEngine->GetStatistics();
printf("\nPlaying: %zu / %zu; Instances %zu; Voices %zu / %zu / %zu / %zu;"
"%zu audio bytes, %zu streaming buffer bytes %\n",
stats.playingOneShots, stats.playingInstances,
stats.allocatedInstances, stats.allocatedVoices, stats.allocatedVoices3d,
stats.allocatedVoicesOneShot, stats.allocatedVoicesIdle,
stats.audioBytes, stats.streamingBytes);
The sound has 2 channels and the master voice also has 2 channels (I've checked). AFAIK Update() should not be necessary in this example, we only need the Apply3D (which calls the X3DAudioCalculate to set the output matrix). The weird part is. This code works on 1 machine but does not work as expected on another machine. On one machine it's resulting in only left speaker working, on other both are working. And as I've said my buddy checked the sound on his machine it's also not working (on his machine the sound is pure mono).
XAudio2 is a multi-threaded API, so all the calls are "non-blocking". You need to enter a loop somewhere to wait for the sound to finish playing... where do you do that?
For example, after you call Apply3D
you need to so something like this which waits until the sound finishes playing...
while ( effect->GetState() == PLAYING )
{
if (!audEngine->Update()) // Update returns false if no audio is actually playing or critical error
{
// No audio device is active
if (audEngine->IsCriticalError())
{
std::cout << "No audio device is active. Attempting to use another device.\n";
if (audEngine->Reset())
{
// OK.
}
else
{
system("pause");
return 1;
}
}
}
// Sleep for 1 second
Sleep(1000);
}
I have system("pause");
after GetStatistics
. I now added the above code after GetStatistics
and printf
and it didn't change anything. Still hearing the sound only in the left speaker.
If this is a non-mono .wav file, you need to set emitter.ChannelCount = 2;
.
If the ChannelCount
doesn't fix it, please try some other program using X3DAudio to see if that works on your system or not. Try the tutorial, XAudio2Sound3D, SimplePlay3DSoundUWP, or the Audio3DTest unit tester.
If this is a non-mono .wav file, you need to set
emitter.ChannelCount = 2;
.
With this, the sound is indeed using both speakers but the panning is not applied anymore. No matter how I position listener/emitter the only thing that is changing is the volume of the sound and it is applied equally to both speakers. So now it's pure mono.
I've converted my audio to mono sound (1 channel) and now it works as expected (emitter.ChannelCount = 1
was also changed back), the issue is resolved. But there is another question. Why does handling stereo 3D sounds is so weird?
It doesn't really make sense to apply 3D positioning to a sound source that is already stereo. There are other ways to adjust the mix, routing various amounts of each source audio channel to the available output channels, but "place the whole audio at this specific 3D position" is only a well defined operation for mono source data.
Makes sense. Glad to know it was the ChannelCount
after all. I've updated the wiki with more details on this issue...
DirectSound's 3D positioning only supported mono-channel sounds, and as @shawnhar notes those 'make the most sense'.
XAudio2/X3DAudio supports 3D positioning of multi-channel sounds for some specialized scenarios of groups of sounds, but you have to set the emitter.EmitterAzimuths
array values for each channel to get anything meaningful for panning. You may find this presentation from GameFest 2010 useful if you want to know more.
Thanks again for the issue report. It motivated me to address these two open issues for DirectX Tool Kit for Audio:
Hi. I've recently written a simple audio engine with 3D sound using XAudio2. The issue is that on this PC I only hear 3D sound coming from the left speaker (headphones). On my other PC with the same headphones, the result is correct. I've asked a buddy to try running my app and he said that the sound is pure mono no matter what the position of the listener/emitter. The issue only occurs when using 3D audio. 2D audio is ok, Windows sound is ok.
I might guess that the issue is not in the code, but how can I distribute such code that works this weirdly? So, any tips on why this may happen?
P.S. I've tried sample code from this repo's wiki - same result.