Audio Playback Delay Bug?

windows

#1

Has anyone noticed sometimes audio playback using AudioTransportSource will be delayed ~1 second before it actually starts to play? 4 out of 5 times there is no delay it plays instantly, but randomly it will occur if you keep restarting the software.

This happens in my personal application as well as the Juce File Playback demo, the Latency Detector demo, and The Synthesizers demo. I was able to reproduce this issue on both Windows 7 and 10 and on separate systems so it appears to be a bug, I have not yet tested it on other platforms.

You can test it yourself by restarting the JuceDemo until it occurs. Just play any audio file and eventually you will notice the delay if you listen closely or look closely at the waveform. This bug was present in older versions of Juce so I updated today hoping it would be fixed but it is still present in this version.

It doesn’t matter if I use DirectSound, Windows Audio or ASIO, the result is always the same. I tried to detect the delay in code with no success, getCurrentPosition() and getNextReadPosition() always increments as if there was no delay. It can only be heard audibly.

It seems consistant its always around 1 second when it happens but I have no idea how to compensate for it. I thought maybe AudioTransportSource.setSource was causing the problem, so I tried changing the readAheadBufferSize and the sourceSampleRateToCorrectFor, and using no background thread but to no avail.

I can’t be the only one experiencing this, someone must know a solution but I can’t find anything in the forums. The only thread I could find is 5 years old and seems unrelated: Slight delay in looping audio files using AudioSource

Hopefully someone can offer some advice. Tom


#2

I don’t think you get more answers by reposting this… You can always bump a thread by adding further information or rephrasing the question.

You are talking about delay, what delay? You will need a better understanding about timing. Your mouse click happens on the message (GUI) thread vs. audio happens on the audio thread. The audio thread will not wait for things on the gui thread. So if e.g. some heavy painting or something else blocks the message thread, it takes some time until the audio thread knows, that there is something to play.

But this happens somewhere deep in your code and not at all in processBlock or similar places. It is impossible for anybody to know, hence no reply to your topic so far.

HTH


#3

I reposted because I was not very clear in my original post, and now I’m sure its a bug in Juce not in my software because it also occurs in the demos, and on multiple PCs. I’m just surprised I’m the only one experiencing this. It is fairly easy to reproduce on Windows.

The delay is not related to mouse clicks or painting, it is related to AudioTransportSource and it is seemingly random. The Synthesizers demo will randomly have a delay when you press the keys, and the Latency Detector Demo will randomly have a delay before you can hear the audio. Same thing with the File Playback demo.


#4

There may be some delay as buffers have to fill, it’s not an instantaneous process from my understanding.


#5

You mention mp3 files specifically but what about other audio file formats?

Do you have some kind of hard drive sleep feature enabled on your systems?


#6

If you don’t manage to fill the buffers in time and return, you are blocking the audio thread and probably will hear noise or other garbage. This is different from “a delay”. (unless you use a BufferingAudioSource, that will just send silence, if it didn’t read enough).


#7

I just tested both wav and flac files and the delay still occurs with both. I always disable the sleep feature on Windows I don’t trust it.

According to the docs setting a non-zero value for readAheadBufferSize it will use a BufferingAudioSource, otherwise it won’t. The delay occurs regardless if I use a value of 32768 (from the demo), 44100, or 0. Changing sourceSampleRateToCorrectFor doesn’t seem to make a difference either.

Can someone at least confirm I’m not crazy? Just launch the JuceDemo from Visual Studio and try it for yourself.


#8

I think you’re probably just seeing the OS taking a moment to open the audio driver sometimes. I’m guessing that because you say it happens on startup.

It’s not unusual for the audio device to take a second to start, often when your app asks for a sample rate that differs from the hardware’s current rate, in which case the driver may choose to change the hardware rate before continuing.

I’d have thought it’d be easy enough for you to step through things in the debugger and quickly narrow-in on the place where this happens, which I suspect will turn out to be a call to an audio device API function.


#9

In that case I would expect it to correct itself after the audio device starts. Technically it doesn’t happen on startup, the delay is still present after stopping and playing the file again. The demo also doesn’t stop playing until ~1 sec after I press the Stop button. Restarting the app is the only way to correct it that I am aware of. It doesn’t happen every time its only every 4th or 5th time I launch it. Its just very strange how consistant it seems to be.


#10

Correct after what? An atomic watch? space time?

The audio stream is considered the clock master, hence the world has to correct after the audio thread, not vice versa…


#11

How do I correct after the audio thread when the audio thread is reporting an invalid currentPosition/nextReadPosition? AudioTransportSource reports as if it plays instantly, but I can hear the delay before it starts playing. I tried everything I can think of to correct this issue but nothing has worked thus far.


#12

What about trying something like the synth demo? Does that have 1 sec latency when you press a key?


#13

I am sorry, I think we are misunderstanding each other. Most of it might be a result that I am riddling about how your actual implementation looks like.

The thing is, the audio thread is agnostic to any time or stream position. The main entry point is the AudioIODeviceCallback::audioDeviceIOCallback(). You see, it is simply pulling sample blocks one after each other. You can set at any point a time zero, but that is completely arbitrary.

The first point, where a time comes into play is your AudioTransportSource. I assume, because you mention it, but didn’t show any implementation details, that this is connected directly to the AudioIODeviceCallback, maybe the derived class AudioSourcePlayer.

The AudioTransportSource has several features, that you can turn on or off. Each has potential an influence to the timing variations you observe:

  • play/stop: This just sets a flag, to either feed the source’s samples into the audio thread, or to send zeroes instead. How you call play or stop is again unknown. If it is from a button, it is a result from the gui thread, where I pointed out, it is not designed to deliver in real time.
  • BufferingAudioThread: If you set a read ahead, and you call setPosition at the same time as play, the buffering thread is just starting to fill the buffer. This means, if the machine is busy otherwise, be it updating Spotlight database or playing a youtube tutorial, the buffering thread didn’t read anything and delivers zeroes.

Maybe I just don’t get it or it is just anything completely different, then I have no idea…

Good luck


#14

Yes this delay is present in the Synth demo, File Playback demo, and in the Latency Detector demo. It seems to occur randomly according to my tests, but its always the 4th or 5th time I launch the software and the delay is always the same when it happens (roughly 1 second). It happens on both my Win 7 and 10 machines, and my friend said it occurs on his system as well. I spent weeks trying to debug my code until I realized this delay was present in the demos too.

My implementation is almost identical to the File Playback and Recording demos, besides the fact that I’m using a MixerAudioSource and OpenGL for graphics. That’s why I didn’t provide any source code. I’m using the same LoadFileIntoTransport function from the demo.

I tried every available option in AudioTransportSource, none of them seem to make a difference. The demos are using a TimeSliceThread for buffering, but this issue doesn’t occur when the PC is busy it also happens when idle. Removing the TimeSliceThread and using 0 for readAheadBufferSize didn’t make much of a difference either.


#15

Well, if there’s really a 1 sec delay between pressing a note in the synth demo and hearing the sound, then the only possible culprit is your audio driver.

There’s simply nothing else in the juce codebase that introduces a delay in that signal chain, and when opening an audio device, you can see the latency it asks the driver for, which will never be more than about 1024 samples.

If the actual latency is longer than that, then it MUST be the OS or driver itself adding some extra internal processing delay for reasons only known to itself. Try a different audio device, or if it has settings, try messing around with them.