Created
May 7, 2010 23:16
-
-
Save koyachi/394133 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 2010-05-08 koyachi | |
// Frequency selected sound energy algorithm 1 | |
// http://www.gamedev.net/reference/programming/features/beatdetection/ | |
package { | |
import flash.display.*; | |
import flash.text.*; | |
import flash.net.*; | |
import flash.media.*; | |
import flash.events.*; | |
import flash.utils.*; | |
public class Sketch20100506 extends Sprite { | |
private var tf:TextField; | |
private var textFormat:TextFormat; | |
private var sound:Sound = new Sound(); | |
private var playSound:Sound = new Sound(); | |
private var sprite:Sprite = new Sprite(); | |
private var samplesL:Array = []; | |
private var samplesR:Array = []; | |
private var energyHistory:Array = []; | |
private var beatDetected:Boolean = false; | |
[SWF(background=0xFFFFFF,width=800,height=600,frameRate=30)] | |
public function Sketch20100506() { | |
// var url:URLRequest = new URLRequest('./renai_circulation.mp3'); | |
var url:URLRequest = new URLRequest('./f.x.n.c..mp3.ab160.mp3'); | |
sound.load(url); | |
sound.addEventListener(Event.COMPLETE, onLoaded); | |
tf = new TextField(); | |
tf.width = 800; | |
tf.height = 600; | |
tf.text = '2010-05-06, hello.'; | |
textFormat = new TextFormat(); | |
textFormat.size = 8; | |
tf.defaultTextFormat = textFormat; | |
addChild(tf); | |
addChild(sprite); | |
addEventListener(Event.ENTER_FRAME, processSamples); | |
} | |
public function onLoaded(event:Event):void { | |
playSound.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound); | |
playSound.play(); | |
} | |
public function processSound(event:SampleDataEvent):void { | |
var resultBuffer:ByteArray = new ByteArray(); | |
var sourceBuffer:ByteArray = new ByteArray(); | |
var len:Number = 4096; | |
var samples:Number = sound.extract(sourceBuffer, len); | |
var str:String = samples + '.\nhohoho\n'; | |
sourceBuffer.position = 0; | |
samplesL = []; | |
samplesR = []; | |
var energy:Number = 0; | |
var count:uint=0; | |
while (sourceBuffer.bytesAvailable > 0) { | |
count++; | |
var l:Number = sourceBuffer.readFloat(); | |
var r:Number = sourceBuffer.readFloat(); | |
samplesL.push(l); | |
samplesR.push(r); | |
resultBuffer.writeFloat(l); | |
resultBuffer.writeFloat(r); | |
energy += l*l + r*r; | |
// change pitch | |
// if (sourceBuffer.bytesAvailable > 0) { | |
// sourceBuffer.position += 4; | |
// } | |
} | |
event.data.writeBytes(resultBuffer); | |
var optimizedE:Number = 0.0; | |
for(var i:uint=0; i < energyHistory.length; i++) { | |
// 2乗だとほとんど検出しない | |
//optimizedE += energyHistory[i] * energyHistory[i]; | |
optimizedE += energyHistory[i]; | |
} | |
optimizedE *= (1.0 / 43); | |
// beatDetected = isBeat(energy, optimizedE); | |
var v:Number = 0; | |
for(i=0; i < energyHistory.length; i++) { | |
v += energyHistory[i] - optimizedE; | |
} | |
v *= (1.0 / 43); | |
beatDetected = isBeat2(energy, optimizedE, v); | |
energyHistory.push(energy); | |
if (energyHistory.length > (44032 / 1024)) { // 43 | |
energyHistory.shift(); | |
} | |
str = [str, count,energy, optimizedE, (beatDetected ? 'BEAT' : '...'), ''].join('\n'); | |
str += energyHistory.map(function(eh:Number, index:int, list:Array):String{return '[' + eh + ']'}).join('\n'); | |
tf.text = str; | |
} | |
public function isBeat(currentEnergy:Number, optimizedE:Number):Boolean { | |
var C:Number = 1.3; | |
// var C:Number = 1.0; | |
return (currentEnergy > C * optimizedE) ? true : false; | |
} | |
public function isBeat2(currentEnergy:Number, optimizedE:Number, v:Number):Boolean { | |
var C:Number = (-0.0025714 * v) + 1.5142857; | |
return (currentEnergy > C * optimizedE) ? true : false; | |
} | |
public function processSamples(event:Event):void { | |
var g:Graphics = sprite.graphics; | |
g.clear(); | |
var w:uint = 800; | |
var h:uint = 600; | |
var prev_lx:uint = 0; | |
var prev_ly:uint = h/2; | |
var cur_lx:uint = 0; | |
var cur_ly:uint = 0; | |
/* | |
var prev_rx:uint = 0; | |
var prev_ry:uint = h/2; | |
var cur_rx:uint = 0; | |
var cur_ry:uint = 0; | |
*/ | |
if (beatDetected) { | |
g.lineStyle(2, 0x0000ff); | |
} | |
else { | |
g.lineStyle(1, 0x8080ff); | |
} | |
g.moveTo(prev_lx, prev_ly); | |
for (var i:uint=0; i < samplesL.length; i++) { | |
// g.lineStyle(1, 0xff0000ff, 1.0); | |
// g.moveTo(prev_lx, prev_ly); | |
cur_lx = w * i / samplesL.length; | |
cur_ly = samplesL[i] * (h / 2) + (h / 2); | |
// g.lineStyle(1, 0xff0000ff, 1.0); | |
g.lineTo(cur_lx, cur_ly); | |
// prev_lx = cur_lx; | |
// prev_ly = cur_ly; | |
/* | |
g.lineStyle(1, 0x00ff00ff, 1.0); | |
g.moveTo(prev_rx, prev_ry); | |
cur_rx = w * i / samplesR.length; | |
cur_ry = samplesR[i] * (h / 2) + (h / 2); | |
g.lineStyle(1, 0xff0000ff, 1.0); | |
g.lineTo(cur_rx, cur_ry); | |
prev_rx = cur_rx; | |
prev_ry = cur_ry; | |
*/ | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment