Page 1 of 2
Streaming audio from memory
Posted: Sun Apr 27, 2014 10:39 am
by foo0
Keep in mind that, if you pass love.audio.newSource "static" as a second argument, the sound file will be expanded into memory, so if you load a 5MB compressed .ogg file that way, it would consume ~50MB RAM when fully decompressed. Consider not using "static" in such cases.
Why not load that 5MB file into memory as it is, and stream from there, instead of hard drive? Or is it doable already? That would seem like an optimal way of doing it, as opposed to "stream from disk" (disk reads in the main loop) or "uncompress to memory" (excessive memory usage).
Re: Streaming audio from memory
Posted: Sun Apr 27, 2014 2:38 pm
by slime
That's what love.audio.newSource(filename, "stream") does right now.
Re: Streaming audio from memory
Posted: Sun Apr 27, 2014 4:34 pm
by foo0
Ah, my bad then for not checking it more thoroughly. The wiki is kind of misleading, it gives the impression that with "stream" parameter audio is streamed from disk, not loaded to memory and streamed from there.
Re: Streaming audio from memory
Posted: Sun Apr 27, 2014 4:59 pm
by slime
Yeah, I guess one reason it's ambiguously defined is so that can be added in the future if it's proven to be useful, without affecting the API.
One way to guarantee that it will always be streamed from RAM rather than the disk (although the internal implementation always does this right now anyway) is to load the file as FileData first. Something like this:
Code: Select all
local filedata = love.filesystem.newFileData("myaudio.ogg") -- Loads the whole file into memory.
source = love.audio.newSource(filedata, "stream")
Re: Streaming audio from memory
Posted: Sun May 04, 2014 11:15 am
by jjmafiae
Is this for avoiding drive bottlenecking ?
Re: Streaming audio from memory
Posted: Sun May 04, 2014 4:27 pm
by foo0
@jjmafiae: In my case it's about avoiding HDD reads, analogically to why you don't usually read textures from HDD in main game loop.
Just to clarify things already said in
this thread:
To play the same sound file multiple times simultaneously, each play needs its own copy of the file? E.g.:
Code: Select all
-- This will result in one time read of "myaudio.ogg" from disk, and 4 copies in memory?
local filedata = love.filesystem.newFileData("myaudio.ogg")
source1 = love.audio.newSource(filedata, "stream")
source2 = love.audio.newSource(filedata, "stream")
source3 = love.audio.newSource(filedata, "stream")
-- This will result in 3 times read of "myaudio.ogg" from disk, and 3 copies in memory?
source1 = love.audio.newSource("myaudio.ogg", "stream")
source2 = love.audio.newSource("myaudio.ogg", "stream")
source3 = love.audio.newSource("myaudio.ogg", "stream")
-- Example use:
love.audio.play(source1)
-- wait 1 sec
love.audio.play(source2)
-- wait 1 sec
love.audio.play(source3)
Re: Streaming audio from memory
Posted: Sun May 04, 2014 5:21 pm
by slime
If you do this, you will have 3 copies of the mp3 data loaded in RAM, 3 decoders (which only reference the mp3 data and allocate a small buffer of their own when streaming), and 3 unique Sources:
Code: Select all
source1 = love.audio.newSource("myaudio.ogg", "stream")
source2 = love.audio.newSource("myaudio.ogg", "stream")
source3 = love.audio.newSource("myaudio.ogg", "stream")
If you do this, you will have 1 copy of the mp3 data loaded in RAM, 3 decoders (which all reference the same un-decoded mp3 data), and 3 unique sources:
Code: Select all
local filedata = love.filesystem.newFileData("myaudio.ogg")
source1 = love.audio.newSource(filedata, "stream")
source2 = love.audio.newSource(filedata, "stream")
source3 = love.audio.newSource(filedata, "stream")
In general there aren't a lot of reasons to have multiple copies of the same
streaming source. If you have a short sound file that will be played many times, you should create a static source. Static sources only decode the audio once per source (when it's initially loaded), whereas streaming sources will decode the same thing every time, if you play it back several times.
As of LÖVE 0.9.1, you can use [wiki]Source:clone[/wiki], which will be as efficient as method #2 above for streaming sources, and more efficient than that for static sources - it won't create a separate copy of the decoded (raw PCM) data with static sources, so it uses less RAM.
Code: Select all
source1 = love.audio.newSource("myaudio.ogg", "static")
source2 = source1:clone()
source3 = source1:clone()
Re: Streaming audio from memory
Posted: Sun May 04, 2014 5:38 pm
by jjmafiae
can textures be streamed from memory too ?
Re: Streaming audio from memory
Posted: Sun May 04, 2014 5:46 pm
by slime
You can use
Image:getData to get the ImageData which was used to create the Image. If you modify that ImageData, you can use
Image:refresh to apply the changes.
Re: Streaming audio from memory
Posted: Sun May 04, 2014 6:41 pm
by foo0
Thanks for detailed explanation. This clone() mechanics seems to be the way.
Is it possible to check the length (duration) of a sound source (either stream or static)?