package
{
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.SampleDataEvent;
import flash.geom.Matrix;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.text.TextField;
import flash.text.TextFormat;
public class Main extends Sprite
{
private const PI2:Number = Math.PI * 2;
private const key:Array = [
[0, null], // F3=53
[1, null],
[0, null],
[1, "a"], // G#3=56
[0, "z"],
[1, "s"],
[0, "x"],
[0, "c"], // C4=60
[1, "f"],
[0, "v"],
[1, "g"],
[0, "b"],
[0, "n"],
[1, "j"],
[0, "m"],
[1, "k"],
[0, ","], // A4=69 440Hz
[1, "l"],
[0, "."],
[0, "/"], // C5=72
[1, ":"],
[0, "\\"],
[1, "]"],
[0, null],
];
private var hash:Object = new Object;
private var push:String = null;
private var mySound:Sound = new Sound;
private var soundChannel:SoundChannel;
private var freq:Number;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
var white_index:int = 0;
for (var i:int = 0; i < key.length; i++)
{
var color:int = key[i][0];
var char:String = key[i][1];
var obj:Object = new Object;
obj.color = color;
obj.noteno = 53 + i;
hash[char] = obj;
var sprite:Sprite = new Sprite;
var tf:TextField = new TextField;
if (char != null)
{
sprite.name = char;
}
if (color == 0)
{
sprite.x = white_index * 40;
sprite.y = 0;
white_index++;
drawRect(sprite.graphics, 0, 0, 40, 120, 0xffffff, 0xdddddd);
addChildAt(sprite, 0);
if (char != null)
{
tf.x = 10;
tf.y = 100;
tf.defaultTextFormat = new TextFormat(null, 14, 0x000000);
tf.text = char.toUpperCase();
sprite.addChild(tf);
}
}
else
{
sprite.x = white_index * 40 - 15;
sprite.y = 0;
drawRect(sprite.graphics, 0, 0, 30, 80, 0x000000, 0x888888);
addChild(sprite);
if (char != null)
{
tf.x = 10;
tf.y = 60;
tf.defaultTextFormat = new TextFormat(null, 14, 0xffffff);
tf.text = char.toUpperCase();
sprite.addChild(tf);
}
}
}
mySound.addEventListener(SampleDataEvent.SAMPLE_DATA, sineWaveGenerator);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
private function onKeyDown(e:KeyboardEvent):void
{
if (push != null) return;
var char:String = String.fromCharCode(e.charCode);
var sprite:Sprite = getChildByName(char) as Sprite;
if (sprite == null) return;
push = char;
sprite.graphics.clear();
if (hash[char].color == 0)
{
drawRect(sprite.graphics, 0, 0, 40, 120, 0x8888ff, 0xeeeeff);
}
else
{
drawRect(sprite.graphics, 0, 0, 30, 80, 0x000000, 0x8888ff);
}
//
var noteno:int = hash[push].noteno;
freq = 440 * Math.pow(Math.pow(2, noteno - 69), 1 / 12);
var st:SoundTransform = new SoundTransform;
st.volume = 0.3;
soundChannel = mySound.play(0, 0, st);
}
private function onKeyUp(e:KeyboardEvent):void
{
if (push == null) return;
var char:String = push;
var sprite:Sprite = getChildByName(char) as Sprite;
push = null;
sprite.graphics.clear();
if (hash[char].color == 0)
{
drawRect(sprite.graphics, 0, 0, 40, 120, 0xffffff, 0xdddddd);
}
else
{
drawRect(sprite.graphics, 0, 0, 30, 80, 0x000000, 0x888888);
}
//
soundChannel.stop();
}
private function drawRect(
g:Graphics, x:Number, y:Number, width:Number, height:Number,
colorLight:uint, colorDark:uint):void
{
var colors:Array = [colorLight, colorDark];
var alphas:Array = [1, 1];
var ratios:Array = [0, 255];
var matrix:Matrix = new Matrix;
matrix.createGradientBox(width, height, -Math.PI / 2, x, y);
g.lineStyle(1, 0x000000);
g.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix);
g.drawRect(x, y, width, height);
g.endFill();
}
private function sineWaveGenerator(e:SampleDataEvent):void
{
for (var i:int = 0; i < 8192; i++)
{
var t:Number = (e.position + i) * freq / 44100;
var n:Number = Math.sin(PI2 * t);
n = (0 <= n) ? 0.5 : -0.5;
e.data.writeFloat(n);
e.data.writeFloat(n);
}
}
}
}