Digital Classical Metronome

Content on this page requires a newer version of Adobe Flash Player.

Get Adobe Flash player

Double click the cover to begin.


For this project, I first bought a vintage Seth Thomas metronome from eBay and observed how it works. I then used a microphone to capture the tick sound as well as a flatbed scanner to get high resolution images. I used photoshop to chop the images into the metronome individual components (hand, weight, body). Lastly, Adobe Flash AS3 & trigonometry was used to produce a realistic effect.

hand.visible = false;
hand.buttonMode = true;
hand.wei.doubleClickEnabled = true;

var tempo:Number;
var twtempo:Number;
var weiOffset:Number;
var goto:Number;

var snd:Sound = new Sound();
	//snd.length = 6000000;
	
snd.addEventListener(SampleDataEvent.SAMPLE_DATA, sineWave);
function sineWave(e:SampleDataEvent):void {
for (var i:int=0; i<2048; i++) {
        e.data.writeFloat(Math.sin((i+e.position) * 2*Math.PI/44100 * 440) * 0);
        e.data.writeFloat(Math.sin((i+e.position) * 2*Math.PI/44100 * 440) * 0);}}
snd.play();

var vx:Number;
var oldx:Number;
var newx:Number;

var tick:Sound = new Sound(new URLRequest("tick.mp3"));
	//tick.play();
var tickRight:Boolean = false;

var thisAng:Number;
var lastAng:Number;

var thisTick:Boolean;

var a:Number = 3;
//var timesmorz:Number = 1;
var maxang:Number = 25;
//var n_osc:Number = .5;

function loop(e:Event):void{
	trace(a);
	//trace(hand.rotation);
	
	a += .00088 * tempo;
	
	lastAng = thisAng;
	hand.rotation = Math.sin(a)*maxang;
	thisAng = hand.rotation;
	
	if(thisAng - lastAng >= 0){
		tickRight = true;
	}else{tickRight = false;}
	
	if(thisTick != tickRight){
		playTick();
	}
	thisTick = tickRight;
}

top.doubleClickEnabled = true;
top.addEventListener(MouseEvent.DOUBLE_CLICK, openM);

function openM(e:MouseEvent):void{
	top.nextFrame();
	hand.visible = true;
	
	//hand.addEventListener(MouseEvent.MOUSE_DOWN, handclick);
	//hand.wei.addEventListener(MouseEvent.MOUSE_DOWN, weiclick);
	//hand.wei.addEventListener(MouseEvent.DOUBLE_CLICK, dblclk);
	stage.addEventListener(MouseEvent.MOUSE_DOWN, stgclick);
}

function stgclick(e:MouseEvent):void{
	removeEventListener(Event.ENTER_FRAME, loop);
	
	addEventListener(Event.ENTER_FRAME, dragloop);
	stage.addEventListener(MouseEvent.MOUSE_UP, mouseup);
}
/*
function handclick(e:MouseEvent):void{
	hand.removeEventListener(MouseEvent.MOUSE_DOWN, handclick);
	removeEventListener(Event.ENTER_FRAME, loop);
	
	addEventListener(Event.ENTER_FRAME, dragloop);
	stage.addEventListener(MouseEvent.MOUSE_UP, mouseup);
}

function weiclick(e:MouseEvent):void{
	weiOffset = hand.wei.mouseY;
	
	hand.wei.removeEventListener(MouseEvent.MOUSE_DOWN, weiclick);
	hand.wei.addEventListener(Event.ENTER_FRAME, weiloop);
	
}*/
function dblclk(e:MouseEvent):void{
	//trace("dblclik" );
	
	top.prevFrame();
	hand.visible = false;
	hand.rotation = 1;
	//hand.removeEventListener(MouseEvent.MOUSE_DOWN, handclick);
	//hand.wei.removeEventListener(MouseEvent.MOUSE_DOWN, weiclick);
	hand.wei.removeEventListener(MouseEvent.DOUBLE_CLICK, dblclk);
}



function dragloop (e:Event):void{

	hand.rotation = getAngle(hand.x, hand.y, mouseX, mouseY) + 90;

	if(hand.rotation > maxang){
		hand.rotation = maxang;
	}
	if(hand.rotation < -maxang){
		hand.rotation = -maxang;
	}
	
	oldx = newx;
	newx = stage.mouseX;
	
	weiloop();

}


function mouseup(e:MouseEvent):void{
	removeEventListener(Event.ENTER_FRAME, dragloop);
	//hand.wei.removeEventListener (Event.ENTER_FRAME, weiloop);
	stage.removeEventListener(MouseEvent.MOUSE_UP, mouseup);
	
	stage.addEventListener(MouseEvent.MOUSE_DOWN, stgclick);
	//hand.wei.addEventListener(MouseEvent.MOUSE_DOWN, weiclick);
	addEventListener(Event.ENTER_FRAME, loop);

	vx =  (newx-oldx)/20;
	
	tempo = ( 300 - ((hand.wei.y*-1)/1.5));
	twtempo = 60/tempo;
	
	a = 3;
}


function weiloop ():void{
	hand.wei.y =  hand.wei.parent.mouseY + 71;
	
	  if(hand.wei.y <= -315){hand.wei.y = -315;}
	  if(hand.wei.y >= 0){hand.wei.y = 0;}
	 
	 tempo = ( 300 - ((hand.wei.y*-1)/1.5));
	 twtempo = 60/tempo;
	
	//trace(tempo);
    // trace(e.currentTarget.y);
}


function getAngle(x1:Number, y1:Number, x2:Number, y2:Number):Number{
	var radians:Number = Math.atan2(y2-y1, x2-x1);
	var rad:Number = radians * (180 / Math.PI);
	return rad;
}

function playTick(){

	tick.play(1);

}