Queueable sources don't always free buffers

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
myQwil
Prole
Posts: 13
Joined: Mon Nov 23, 2020 7:19 pm

Queueable sources don't always free buffers

Post by myQwil »

I'm looking to create a queueable audio source with the least amount of delay that I can possibly get away with before stuttering occurs.
This is my main.lua:

Code: Select all

size ,samplerate ,bitdepth ,channels ,buffers =
128  ,48000      ,16       ,1        ,8

bufs_per_ms = (samplerate / 1000) / size

function love.load()
	sdata  = love.sound.newSoundData(size, samplerate, bitdepth, channels)
	source = love.audio.newQueueableSource(samplerate, bitdepth, channels, buffers)
end

function love.update(dt)
	dt = dt * 1000
	local bufs  = dt * bufs_per_ms
	local count = source:getFreeBufferCount()
	print(
		string.format('%.2f', dt)..' ms'
		..'   expected: '..string.format('%.2f', bufs)
		..'   got: '..(count>0 and count or 'none')
	)
	for _=1,count do
		source:queue(sdata)
		source:play()
	end
end
And this is an excerpt from the print output:

Code: Select all

17.00 ms   expected: 6.37   got: 8
16.43 ms   expected: 6.16   got: 8
16.60 ms   expected: 6.22   got: none
16.67 ms   expected: 6.25   got: 8
16.83 ms   expected: 6.31   got: 8
16.62 ms   expected: 6.23   got: 8
16.66 ms   expected: 6.25   got: none
16.63 ms   expected: 6.24   got: 8
16.40 ms   expected: 6.15   got: 8
16.98 ms   expected: 6.37   got: 8
16.60 ms   expected: 6.22   got: none
16.48 ms   expected: 6.18   got: 8
Assuming I haven't screwed up the math, there should be, according to the delta time, roughly 6 or 7 buffers used and freed up at any given update call, but what we see instead is that either all of the buffers are free or none of them are. Can anyone explain to me what the reason is behind that behavior? Also, is there any way to have it distribute the work more evenly between update calls?
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: Queueable sources don't always free buffers

Post by ReFreezed »

I'm just guessing here, but I think this is just an effect caused by multiple audio-related things simply not being in sync. Your code always prints either 7, 8 or none for me. Disabling vsync or increasing 'buffers' doesn't make any difference - it seems that the buffers in the source get "freed" in chunks of 7 or 8. With vsync off, I increased 'buffers' to 32 and wrapped the loop in 'if count == buffers then ... end' and got this:

Code: Select all

0.99 ms   expected: 0.37   got: 15
1.02 ms   expected: 0.38   got: 22
(... lots of "got: 22" ...)
0.99 ms   expected: 0.37   got: 22
1.04 ms   expected: 0.39   got: 30
(... lots of "got: 30" ...)
1.02 ms   expected: 0.38   got: 30
1.00 ms   expected: 0.38   got: 32
0.98 ms   expected: 0.37   got: none
1.01 ms   expected: 0.38   got: none
Increasing 'size' does seem to decrease the amount of buffers in each freed "chunk". Setting 'size' to 512 made the chunk size 1 or 2 for me, so maybe the size you're using is just too small for things to work properly.
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
myQwil
Prole
Posts: 13
Joined: Mon Nov 23, 2020 7:19 pm

Re: Queueable sources don't always free buffers

Post by myQwil »

One thing I hadn't taken into account was my JACK audio server. It was running at 1024 frames/period with 2 buffers, resulting in an additional 42.7 ms of delay, so I was able to lower that to 16 ms, which makes a considerable difference.
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Queueable sources don't always free buffers

Post by zorg »

OpenALSoft allegedly has a horrid internal latency as well (50ms iirc - by default), but i did manage to get about a (3x)11ms calculated latency with only 3 "internal" buffers (that you set for the Qsource, as opposed to using multiple SoundData objects), 44100 Hz sampling rate, mono and a buffer size of 512 samplepoints where my ad-hoc sine signal still sounded good... caveat: on my machine, might not sound good on yours. :3

I modified the OP's posted script a bit, gonna attach the love file; it also actually plays sound so one can hear if it underruns or not.
test.love
(167.67 KiB) Downloaded 137 times

Oh, i also took vsync out, i prefer it that way when rendering audio. (do it in another thread also, less chance of interference from the scheduler or anything)

Still, i do feel like comparing the audio time offset with deltatime is not that useful, since you shouldn't rely on that anyway; just queue up the data if there are free buffers, the backend/soundcard will do its job at the correct pace.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 66 guests