[resolved] Implementing a beat detection algorithm

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
Fang
Prole
Posts: 9
Joined: Sat Apr 13, 2013 4:31 pm

[resolved] Implementing a beat detection algorithm

Post by Fang »

Hey all,

I want to put beat detection into my game. It doesn't have to be super accurate, nothing fancy really, so I have settled for the simple sound energy algorithm, as outlined here.

That's all really cool, but to be honest I have no idea how to implement that in LÖVE. The maths behind it are doable for me, so I just need to know how to handle the sample history buffer, and the "do this every 1024 samples" thing. I know I can pass my audio file into love.sound.newSoundData, but I don't know how to proceed from there. Should I just store all samples beforehand? In my love.update, how would I know what sample position to use for the algorithm? How would I handle a looping background song?

As the end result, I want to be able to make the background of a screen flash whenever it detects a beat in the music that's playing.

If I could get code examples that'd be great, but I can make do with some pointers on how to do this as well. Thanks!
~ Fang
Last edited by Fang on Sun Jun 09, 2013 7:05 pm, edited 1 time in total.
~ Fang
User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Implementing a beat detection algorithm

Post by Boolsheet »

LÖVE is not designed to handle real time audio processing very efficiently. It requires you to load the whole song into memory with love.sound.newSoundData and then check the current offset of the playing source with Source:tell to get the right samples with SoundData:getSample. (Note that getSample returns the samples of a stereo track in an interleaved manner)

Here's an example.
Shallow indentations.
User avatar
Fang
Prole
Posts: 9
Joined: Sat Apr 13, 2013 4:31 pm

Re: Implementing a beat detection algorithm

Post by Fang »

Thanks Boolsheet, I got it working now! It's quite flawed still, only using the simple sound energy algorithm #1, but it runs fine, so that's great!

When instantiating:

Code: Select all

self.soundData = love.sound.newSoundData( "filename.mp3" )
self.source = love.audio.newSource( self.soundData )
self.lastChecked = 0
self.beat = false
love.audio.play( self.source )
In the update function:

Code: Select all

local curSample = self.source:tell( "samples" )
if curSample-1024 > self.lastChecked then
	
	local instantEnergy = 0
	for i=curSample, curSample+1024 do
		instantEnergy = instantEnergy + self.soundData:getSample(i)^2
	end
	local localAverageEnergy = 0
	for i=curSample-44032, curSample do
		localAverageEnergy = localAverageEnergy + self.soundData:getSample(i)^2
	end
	localAverageEnergy = localAverageEnergy * (1024/44100)
	
	if instantEnergy > localAverageEnergy*1.8 then
		self.beat = true
	else
		self.beat = false
	end
	
	self.lastChecked = curSample
	
end
Sure, this could use a lot of optimization, but I'm happy to have it running this easily. Thanks again!
~ Fang
Post Reply

Who is online

Users browsing this forum: No registered users and 13 guests