Okay, so first off, i do wanted to apologize, because i wrote that reply on the bus home from a ~32 hour work shift + training session, so it was a bit terse and i didn't elaborate on what i meant; and then i fell asleep, waking up just a few minutes ago.
You have
artefactsissues with looping mp3 and similar formats, because they aren't exactly stored in a per-samplepoint fashion, hence in most cases the end of those bitstreams will contain some hiccups. mp3 artefacting usually refers more to the bubbling quality that arises from low bitrates not containing the higher frequencies correctly, thanks to the encoding scheme the format uses (filtering out information based on a psycho-acoustic model).
(Also, i just noticed you actually stating this, i was under the impression you meant artefacting as bad looping, and not the bubbling thing; this is moot then since we agree )
If you wanted to loop an mp3 with QSources (do permit me not to write out the silent vowels in that word), then you could do a similar thing to what you are doing with music:tell() and music:seek() in your project's source that you posted, but a bit differently:
(This is what i was referring to when i previously wrote that you'd need to do some things "manually")
Code: Select all
mSource = love.sound.newDecoder('path/to/music/song.mp3', 2048) -- Default, but this should be smaller, imo.
qSource = love.audio.newQueueableSource(mSource:getSampleRate(), mSource:getBitDepth(), mSource:getChannelCount(), 8) -- default
smpCounter = 0
yourLoopPoint = 6942804
-- in update
if qSource:getFreeBufferCount() then
local Buffer = mSource:decode() -- You'll get a 2048 (by default) sized SoundData
if yourLoopPoint == smpCounter + Buffer:getSampleCount() then
-- queue and seek
qSource:queue(Buffer)
mSource:seek(0) -- or whatever your starting point would be
smpCounter = 0
if yourLoopPoint > smpCounter+Buffer:getSampleCount() then
-- just queue the whole buffer
qSource:queue(Buffer)
smpCounter = smpCounter + Buffer:getSampleCount()
elseif yourLoopPoint > smpCounter then
-- only queue part of the buffer, and then seek to the starting point (or to the loop start if you have such a thing) with the Decoder.
local temp = love.sound.newSoundData(yourLoopPoint - smpCounter, mSource:getSampleRate(), mSource:getBitDepth(),
mSource:getChannelCount())
for i=0, (yourLoopPoint - smpCounter - 1) do
temp:setSample(i, Buffer:getSample(i))
end
qSource:queue(temp)
mSource:seek(0) -- or whatever your starting point would be
smpCounter = 0
end
end
Fair note, Decoders have decode and seek methods, but they aren't mentioned in the changelogs, much less have entries on the wiki.
Also, i'm not 100% sure what unit :seek uses, if it's seconds, then anything other than seek(0) won't be samplepoint-accurate.
Also also, not sure whether :decode creates a new SoundData each time it's called or not, if they do, that's both sad and unoptimized, hence this kind of thing may cost a fair amount of cycles more than it should. (the temp buffer thing is amortized though, since it's only done when the loop end point is reached... then again, it still bumps up the processing time when it happens)