How to change audio playback speed at runtime?

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
User avatar
ddabrahim
Party member
Posts: 185
Joined: Mon May 17, 2021 8:05 pm
Contact:

How to change audio playback speed at runtime?

Post by ddabrahim »

Hi everyone!

Just would like to ask if is there any way in LÖVE to change playback speed of audio files such as mp3, wav, ogg at runtime?
I did search the forum and it seems the short answer is NO, the audio library in LÖVE does not support this.
But it was a discussion from 2016 and could not find any more recent info about it.

So I am just wondering if by any chance, is there any Lua library one could use to change audio playback speed at runtime?

Thank you.
User avatar
darkfrei
Party member
Posts: 1186
Joined: Sat Feb 08, 2020 11:09 pm

Re: How to change audio playback speed at runtime?

Post by darkfrei »

:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
ddabrahim
Party member
Posts: 185
Joined: Mon May 17, 2021 8:05 pm
Contact:

Re: How to change audio playback speed at runtime?

Post by ddabrahim »

Thank you for the tip but setDopplerScale doesn't seems to do anything at all.

This is what I tried

Code: Select all

local fireSound

function love.load()
    love.audio.setDopplerScale(0.1)
    fireSound = love.audio.newSource("fire.ogg", "stream")
    fireSound:setLooping(true)
    love.audio.play(fireSound)
end
Tried with all 3 audio formats.

In case it is supposed to work, here is a project including the sound in mp3, wav and ogg format
doppler test.zip
(69.66 KiB) Downloaded 83 times
Regarding what am I trying to do, I would like to play the sound in a slow pace.

Tried to set the pitch of the sound but I don't get the result I want. It sounds different, but not exactly what I want.

Thank you.
User avatar
zorg
Party member
Posts: 3449
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: How to change audio playback speed at runtime?

Post by zorg »

You can use setPitch to basically change the playback rate (the sampling rate, that is), so if it's 0.5, it will play half as fast, but also lower in pitch; 2.0 will play twice as fast but also higher in pitch.

I do have a library that can separately change the pitch and/or the speed of audio though, among other things: https://github.com/zorggn/love-asl
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.
User avatar
ddabrahim
Party member
Posts: 185
Joined: Mon May 17, 2021 8:05 pm
Contact:

Re: How to change audio playback speed at runtime?

Post by ddabrahim »

I have tried setPitch but I am not happy with the result. I would like to change the speed only but not the pitch.

Not sure how to use your library do you have any API reference guide? I tried this:

Code: Select all

love.audio.newAdvancedSource = require "asl"
fireSound = love.audio.newAdvancedSource("fire.ogg", "stream")
But it throw me this error message:

Code: Select all

Error: asl.lua:276: /asl-thread.lua:710: Can't yet create streaming or queue type sources!
stack traceback:
        [C]: in function 'error'
        /asl-thread.lua:710: in function 'new'
        /asl-thread.lua:1876: in main chunk
But even if I did not get any error, by just looking at the source, I am uncertain which method to use to change playback speed only.
Do you have any idea why do I get this error and which method to use to set speed only?

Thank you in advance.
User avatar
zorg
Party member
Posts: 3449
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: How to change audio playback speed at runtime?

Post by zorg »

The guide is the readme.md file, or what you can read on the github page.

As the error message says, for now, it only supports static type sources... although that just means that it'll load in the entirety of the sound into a SoundData; internally it uses queueable sources.

For the most part, API is the same as regular löve sources, except for the new stuff; you want source:setTimeStretch(ratio) to stretch the sound without modifying the pitch.

One caveat though is that it's a damn hard task to do this (along with changing pitch but not the length of the sound), considering this is not how waveforms were designed to work in reality, so there's a ton of concessions you need to look out for.

Source:setBufferSize(amount, unit) and Source:setBufferVariance(amount, unit) would be two things you'd probably need to play with to get a result you'd deem acceptable.

A complete example that might be fine:

Code: Select all

function love.load()
    love.audio.newAdvancedSource = require "asl"
    fireSound = love.audio.newAdvancedSource("fire.ogg", "static", 2) -- 2 is how many internal buffers the qsource has; less means less delay.
    fireSound:setTimeStretch(0.1) -- this means it'll play at 10% speed.
    fireSound:setLooping(true)
    fireSound:setBufferSize(35, 'milliseconds') -- longer buffer means more echo-y overlapping segments when magic is happening
    fireSound:setBufferVariance(15, 'milliseconds') -- for shorter buffer sizes, fixes the thing sounding "metallic", which can be annoying
    love.audio.play(fireSound)
end
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.
User avatar
ddabrahim
Party member
Posts: 185
Joined: Mon May 17, 2021 8:05 pm
Contact:

Re: How to change audio playback speed at runtime?

Post by ddabrahim »

Thanks a lot. Really appreciate it!
I don't expect the library to be perfectly optimal but the playback sounds very similar to what I was trying to achieve. Happy with the result :)
kuinashi101
Prole
Posts: 7
Joined: Tue Feb 21, 2023 9:47 am

Re: How to change audio playback speed at runtime?

Post by kuinashi101 »

@zorg:
I'm making a module that generating melodies in runtime, the setTimeStretch() helps a tons for sync BPM with audio length! however, there's still a crucial step here: to play the time stretched audio / soundData multiple times in short period.
I've noticed there are something about "clone" in both 'asl' and 'asl-thread', but have no idea how to deal with it.

Could I done that with love-asl ? Thanks in advance.
User avatar
zorg
Party member
Posts: 3449
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: How to change audio playback speed at runtime?

Post by zorg »

kuinashi101 wrote: Tue Mar 07, 2023 3:01 am @zorg:
I'm making a module that generating melodies in runtime, the setTimeStretch() helps a tons for sync BPM with audio length! however, there's still a crucial step here: to play the time stretched audio / soundData multiple times in short period.
I've noticed there are something about "clone" in both 'asl' and 'asl-thread', but have no idea how to deal with it.

Could I done that with love-asl ? Thanks in advance.
clone is analogous to regular Source:clone, it creates a new advanced source object based on the one you're cloning from; and yes, that should work how you want it to. Since i read you using SLAM or whatever, i don't know if that'd be compatible with this library or not; i already know that Ripple has issues that i can't really fix.
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.
kuinashi101
Prole
Posts: 7
Joined: Tue Feb 21, 2023 9:47 am

Re: How to change audio playback speed at runtime?

Post by kuinashi101 »

messing up love-asl and SLAM was my first idea popped up and did so, but they aren't work along with each other. the good thing is the "clone" works pretty well as expected! I've also test the performance by the code below:

Code: Select all

local _snd = love_asl( "3MB.mp3", "static", 2) 	-- MP3 file that has size: 3MB
_snd:setTimeStretch(4)
for i=1,100 do
    HumpTimer.after(i*0.1, function() 
        _snd:clone():play()
    end)
end
the FPS did't drop at all and MEM usage is quite stable at range between 2000 ~ 4000 bytes which was amazing!

Again, thank for your help and the awesome module you made! really appreciated it! :awesome:
Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests