In very optimistic cases the main thread can freeze for >50 ms. Imagine game full of sounds on AMD
To avoid title thread interruptions
from a blocking DestroyVoice call, the
application can destroy voices on a
separate non-critical thread, or the
application can use voice pooling
strategies to reuse voices rather than
destroying them. Note that voices can
only be reused with audio that has the
same data format and the same number
of channels the voice was created
As you see from the official documentation, DestroyVoice blocks the whole thread.
I confirm having poor performance too, even freeze, on the exact same part of code.
When the UE4 editor window loses focus, when I try to get back in, the function Source->DestroyVoice() often takes more than 30 seconds to finish. This result of the IDE being non resumable, and I need to restart it.
I’m using an AMD 8120 @ 3.1Ghz.
Not sure what is really causing that.
Sorry for the delay in responding to this post. I have managed to get my hands on a machine that has an AMD CPU. Unfortunately, it does not have Visual Studio or UE4 on it, so I am in the process of getting those items installed in order to take a look at this.
I had a to run this test today, and noticed that the cycle times do appear to be higher on the AMD machine than what I was seeing on my own machine. However, the AMD machine that I was testing on is not quite comparable in terms of capabilities so I am going to see if I can get a co-worker to run the same test on his machine which has an AMD processor and is more comparable to my own.
Thank you for reporting this issue to us. While testing this issue, we were not able to see anything conclusive. When I tested on my Intel processor, I was seeing cycle times between 41 and 51 (with an occasional spike). When my co-worker tested on his AMD processor, he saw cycle times that were actually very slightly lower than mine on average. The computer I had used initially was actually a laptop with significantly lower specs than the computers we ended up testing on, and with that the cycle times averaged between 55 and 75 (with occasional spikes that were a little more frequent than with the desktop computers).
I did get in touch with the audio engineer for the Engine, and he mentioned that he did not have any additional insight into this issue. He mentioned that this isn’t something we would be able to fix since the audio engine is currently running in the main thread, and moving it out, or using voice pools, would be a major project. We do have a long-term plan to re-write the audio engine, and this is most likely something that will be taken into consideration whenever that happens.
Thanks for your time on this, but as you did not reproduce it, it seems it is related to something else than simply an AMD processor. Maybe the sound card or its drivers are incriminated ?
I’m using an ASUS M5A99X EVO with it integrated soundcard, with latest drivers which are from 2012, on win 7 64 bits. Pierdek what’s yours ?
@: average cycle times aren’t problem here, the lag spikes are the problem, because the DestroyVoice is freezeing main thread - the whole game is destabilized. I’ve implemented simple pool IXAudio2Voice and the problem dissapear. I don’t want to make a pull request on GIT, my code is HACK on HACK I just want to let you know about the problem.
@CodingMarmot: Nope, definitely this is not problem in the drivers, I have gathered some data from the users:
As you see they have different operating systems, different audio devices and drivers, the common denominator is AMD CPU.
Is there any possibility that you could run your test again using the ShooterGame sample project? That project has a great deal more sounds than in my original test project. I saw quite a few more spikes in ShooterGame, but no noticeable lag when playing. Most of the log entries were in the 50-70 range, but there were some spikes that went up to 4 or 5 digits.
That’s not a problem. I’ll mark this as resolved for now, and whenever you have a to do some more looking into this issue just add a new comment and it will re-open the post. I appreciate your help with this.
Hey guys, we just had another licensee reporting this exact issue so I went ahead and came up with a solution that is pretty simple that I think should avoid the hitching. I’d like to ask you guys to grab the CL and see if it works for you guys.
I’d prefer not to use pools since I think our XAudio2 sources are not guaranteed to all be the same source format (e.g. num channels, sample rate, etc) which means we’d have to juggle different sets of pools for different formats and because I think that’d constitute a bit more of an invasive change, I’d prefer not to do that if we can avoid it. We’ve already recently leveraged the UE4 task API for async on-the-fly ogg decoding so there’s already precedence in the audio engine for using tasks for little jobs like this.
The original post here was specifically about the IXAudio2Source->DestroyVoice call being slow on AMD.
The tech i implemented for voice pools is to specifically solve that problem. Voices are no longer being created/destroyed for every sound. DestroyVoice is only called when the audio device shuts down in the ~FXAudioDeviceProperties() destructor:
// Destroy all the xaudio2 voices allocated in our pools
for (int32 i = 0; i < VoicePool.Num(); ++i)
for (int32 j = 0; j < VoicePool[i]->FreeVoices.Num(); ++j)
IXAudio2SourceVoice* Voice = VoicePool[i]->FreeVoices[j];
I did not realize this was posted by the same people having issues we’ve heard about with Squad and VOIP streaming. I suspect the performance issue is related to VOIP/Procedural buffers. I’ve seen some videos and the audio issues only occur when somebody is using VOIP. Otherwise, the audio sounds like its working fine but most of the videos I’ve seen have about 90% of the video with people using VOIP so it’s hard to tell.
Have you guys done any special code with VOIP and procedural voices? There were a few people on UDN/Answerhub that were doing some experimental stuff with VOIP streams – like supporting 3d spatialization and VOIP (which I believe we don’t officially support) and if I recall there was some threading/critical section code that looked like it may be non-performant. Indeed, this might make sense in conjunction with your original post about DestroyVoice. DestroyVoice will block the main thread until the voice processing thread finishes, which if there’s blocking code in the procedural voice callback functions, would cause DestroyVoice to be very slow.
Can you guys confirm that its indeed VOIP stuff causing the issues by playing your game without VOIP on AMD and seeing if audio is stuttering?
As far as we can tell. (and I will let a coder chime in here)
There are two issues we are seeing.
General low performance on AMD compared to similar spec Nvidia / Intel systems (as you can imagine results vary wildly depending on the specific config)
Very specific massive frame lag / stutter only when voip is active and only on AMD systems.
We did a bunch of specific profiling and may have narrowed #2 down to EQ being used in a specific filter. (this filter seems to exclusively cause the lag in testing) where the normal voip channels do not. (In fact some people have simply deleted the uasset containing the EQ enabled filter and the problem has completely disappeared)
Any leads on why EQ might cause massive frame spikes or stuttering?
We will report back any success with EQ adjustments.
And if you want to look at how we set it up, check out XAudio2Effects.cpp. Basically, it creates a pre-master submix voice with the EQEffectChain and routes audio to it if enabled.
The issue I found was in:
Where there’s hard-coded params for the 4th band – i.e. the 4th band can never have anything but a fc of 10k. My “fix” is to just to expose all the params of the EQ effect. I haven’t checked it in yet because we’re doing testing/stabilization from our internal dev branch. I’ll send you a CL once I check that fix in.
As I said, my suspicion is AMD audio devices are doing something that other devices aren’t and is requiring more CPU time per audio block.
It’s likely that the EQ effect is just the “feather” on the back of the CPU camel that is pushing your stuff over the edge and causing buffer underruns.
Have you guys written custom audio code to get VOIP 3D-spatialization? Are there any thread synchronization issues between the main thread in your VOIP procedural voice (either in audio capture side or rendering)? If so, I’d suggest removing any critical sections or other blocking synchronization mechanisms and use a lockless queue or some other lockless mechanism to get any main-thread data (e.g. position information) to any of your custom code.