Problem implementing GameDev's beat detection algorithm

Started by
-1 comments, last by s4edev 10 years, 1 month ago

Hello, I'm new here so I don't really know if this should go to Game Programming or General Programming. Hopefully I'm in the right place.

I am currently having a problem implementing GameDev's beat detection algorithm in a Unity game to introduce rythm based elements (a la Audiosurf), more precisely Frequency selected sound energy algorithm #1. I'm pretty sure I've implemented the full algorithm, but I am doing it wrong somewhere. I put the print if a beat is found thanks to the last step, where I compare a subband's energy to the average of its history buffer multiplied by a threshold (250 as advised by the article), but nothing gets printed at all (and it should probably freeze Unity because of the billions of print that would occur if it did work, but anyway...)

I have included my implementation of the algorithm in the post. Note that Unity doesn't seem to let me separate the data between left and right channel with AudioClip.GetData but packs both together instead, so I'm only using the real part of the complex numbers since the imaginary part is empty.


audio.clip.GetData(samples, 0);
	
int i = 0;
while(i < samples.Length){ //navigate through the samples
	if(i%(1024 - 1) < 1){ //every 1024 samples...
		int k = 0;
		for(int j = i; j < i+1024; j++){
			if(j<samples.Length){
				data[k] = (double)samples[j]; //...fill a 1024 values array so we can FFT it
				k++;
			}
		}
		FFT.FFT(data, true); //FFT the data!
		
		for(int j = 0; j < data.Length; j++){
			buffer[j] = data[j]*data[j]; //we compute the square of our data to get frequency amplitudes
		}

		//divide the buffer in 32 subbands, compute the energy of these subbands and store them
		for(int j = 0; j < energySubband.Length; j++){
			double sum = 0;
			for(int l = j*32; l < (j+1)*32; l++){
				sum += buffer[l];
			}
			energySubband[j] = 32/1024 * sum;

			shift (energyHistoryBuffer, j); //shifts the history buffer
			
			energyHistoryBuffer[j,0] = energySubband[j]; //pile in the new energy of subband j

			//we compute the average of the current subband's history buffer
			double average = 0;
			for(int l = 0; l<43; l++){
				average += energyHistoryBuffer[j,l];
			}
			average *= 1/43;

			//For each subband 'i' if energySubband[j] > (C*<energyHistoryBuffer[j]>) we have a beat !
			//C == 250 here
			if(energySubband[j] > (250 * average))
				Debug.Log ("Beat! at subband number " + j);
		}
	}
	i++;
}

Thanks in advance

This topic is closed to new replies.

Advertisement