Struggling with Actionscript computeSpectrum and beat detection

153 views Asked by At

I am trying to understand the values given back to me from the computeSpectrum method. I want to work with the lower frequencies pick out the bass drum of a track. The numbers I am getting back from the byteArray make no sense. For example, it says that the value is 0 when there is clearly a sound playing. What am I missing here...I do know beat detection is not easy and have looked at most of the posts here on the subject...It's just that the numbers that are returned to me make no sense, can somebody explain them to me? Thanks in advance.

My Code:

import flash.display.Graphics;
import flash.events.Event;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundMixer;
import flash.net.URLRequest;
import flash.display.MovieClip;

var snd: Sound = new Sound();
var req: URLRequest = new URLRequest("mySong.mp3");
snd.load(req);

var channel: SoundChannel;
channel = snd.play();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
snd.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete);

const CHANNEL_LENGTH: int = 256;
const BUFFER_LENGTH: int = 512;

var bytes:ByteArray = new ByteArray();

function onEnterFrame(event: Event): void 
{

  SoundMixer.computeSpectrum(bytes, true, 0);


  for (var i:int = 0; i < CHANNEL_LENGTH; i++) // channel_length = 256
  {


      var sampleValue:Number = bytes.readFloat() * 200;
      var byteArrayIndex = bytes.position;
      trace(byteArrayIndex, sampleValue);

  }
}

function onPlaybackComplete(e:Event):void
{
    removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
1

There are 1 answers

0
Jacky Lau On

Nice to meet you again, I think I'm more understand your mind this time.

If you are going to check whether there exist a 'beat' at a specific time of the song; I may suggest this method for reference:

import flash.events.Event;

var snd: Sound = new Sound();
var req: URLRequest = new URLRequest("mySong.mp3");
snd.load(req);

var channel: SoundChannel;
channel = snd.play();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
snd.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete);


// I want to specify which region of byteData is passing to my check function.
// this two value help me to extract the sample I need.
var checkLength:int = 20; 
var checkStart:int = 0; 
var theshold:Number = 0.5; // How big the value should I determine it is the 'beat'.

const CHANNEL_LENGTH: int = 256;
const BUFFER_LENGTH: int = 512;

var myArray:Array;
var bytes:ByteArray = new ByteArray();

function onEnterFrame(event: Event): void 
{

    SoundMixer.computeSpectrum(bytes, true, 0);

    myArray = [];
   for (var i:int = checkStart; i < checkLength; i+=8) // extract the sample
   {
     var sampleValue:Number = bytes.readFloat();
       myArray.push(sampleValue);
   }
   if( CheckBeat( myArray ))
   {
       trace("here maybe a beat!!", getTimer());
   }
}

function CheckBeat(valueArray:Array):Boolean  // check the whether 'beat' exist
{
    var meanValue:Number = valueArray[0];
    for(var i:int = 1; i < valueArray.length; i++)
    {
        meanValue = (meanValue + valueArray[i])/2;
    }
    return meanValue > theshold;
}

function onPlaybackComplete(e:Event):void
{
    removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}

But this method is just an Estimation, and not accurate enough at all.