開発環境 |
Apache Flex SDK 4.12.1 |
|
FlashDevelop 4.6.1 |
実行環境 |
Microsoft Windows 8.1 (64bit) |
プロジェクトの種類 |
ActionScript 3/AS3 Project |
プロジェクト名 |
EzPlay |
Main.as
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.SampleDataEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
public class Main extends Sprite
{
private var input:TextField = new TextField;
private var mml:String;
private var pos:int;
private var waveform:Vector.<Number>;
private const PI2:Number = Math.PI * 2;
private const scale:Object = { A:9, B:11, C:0, D:2, E:4, F:5, G:7 };
private const timebase:int = 960;
private var q:int = 7; // 音の長さの割合
private var tempo:int;
private var octave:int;
private var deflen:int;
private var sound:Sound = new Sound;
private var soundChannel:SoundChannel = null;
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
input.type = TextFieldType.INPUT;
input.multiline = true;
input.defaultTextFormat = new TextFormat(null, 16);
input.text = "t100 l4 o4\n" +
"ccgg aag2 ffee ddc2\n" + // Twinkle, twinkle, little star, How I wonder what you are!
"ggff eed2 ggff eed2\n" + // Up above the world so high, Like a diamond in the sky.
"ccgg aag2 ffee ddc2\n"; // Twinkle, twinkle, little star, How I wonder what you are!
input.border = true;
input.x = 10;
input.y = 10;
input.width = 400;
input.height = 200;
addChild(input);
var tf:TextFormat = new TextFormat;
tf.size = 24;
tf.align = TextFormatAlign.CENTER;
var play:TextField = new TextField;
play.defaultTextFormat = tf;
play.border = true;
play.selectable = false;
play.text = "Play";
play.x = 100;
play.y = 220;
play.width = 80;
play.height = 30;
addChild(play);
var stop:TextField = new TextField;
stop.defaultTextFormat = tf;
stop.border = true;
stop.selectable = false;
stop.text = "Stop";
stop.x = 200;
stop.y = 220;
stop.width = 80;
stop.height = 30;
addChild(stop);
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
play.addEventListener(MouseEvent.CLICK, onPlay);
stop.addEventListener(MouseEvent.CLICK, onStop);
}
// 再生ボタン
private function onPlay(e:MouseEvent):void
{
mml = input.text.toUpperCase();
waveform = new Vector.<Number>;
tempo = 120;
octave = 4;
deflen = 4;
for (pos = 0; pos < mml.length; )
{
var cmd:String = mml.charAt(pos++);
switch (cmd)
{
case "<":
octave--;
break;
case ">":
octave++;
break;
case "A": case "B": case "C": case "D": case "E": case "F": case "G":
note(cmd);
break;
case "L":
deflen = getValue();
break;
case "O":
octave = getValue();
break;
case "T":
tempo = getValue();
break;
case "R":
rest();
break;
default:
}
}
var st:SoundTransform = new SoundTransform;
st.volume = 0.3;
soundChannel = sound.play(0, 0, st);
}
// 音符
private function note(cmd:String):void
{
var acci:int = getAccidental();
var len:int = getValue();
var dot:int = getDot();
var tie:Boolean = getTie();
var noteno:int = (octave + 1) * 12 + scale[cmd] + acci;
var tick:int = calcTick(len, dot);
var qtick:int = tie ? tick : tick * q / 8;
generateNote(qtick, noteno);
generateRest(tick - qtick);
}
// 休符
private function rest():void
{
var len:int = getValue();
var dot:int = getDot();
var tick:int = calcTick(len, dot);
generateRest(tick);
}
// tick計算
private function calcTick(len:int, dot:int):int
{
if (len == 0) len = deflen;
var tick:int = timebase * 4 / len;
var n:int = Math.pow(2, dot);
tick += tick * (n - 1) / n;
return tick;
}
// 音符生成
private function generateNote(tick:int, noteno:int):void
{
var freq:Number = 440 * Math.pow(Math.pow(2, noteno - 69), 1 / 12);
var n:int = Math.round(tick * 44100 * 60 / (timebase * tempo));
for (var i:int = 0; i < n; i++)
{
var t:Number = (i * freq / 44100) % 1;
var h:Number;
//h = Math.sin(PI2 * t);
h = (t < 0.25) ? 0.5 : -0.5;
waveform.push(h);
}
}
// 休符生成
private function generateRest(tick:int):void
{
var n:int = Math.round(tick * 44100 * 60 / (timebase * tempo));
for (var i:int = 0; i < n; i++)
{
waveform.push(0);
}
trace("r" + n);
}
// 変化記号
private function getAccidental():int
{
var acci:int = 0;
for ( ; pos < mml.length; pos++)
{
switch (mml.charAt(pos))
{
case "+": case "#":
acci++;
break;
case "-":
acci--;
break;
default:
return acci;
}
}
return acci;
}
// 値
private function getValue():int
{
var value:int = 0;
for ( ; pos < mml.length; pos++)
{
var num:int = mml.charCodeAt(pos) - 0x30;
if (num < 0 || 9 < num) break;
value = value * 10 + num;
}
return value;
}
// 付点
private function getDot():int
{
var dot:int = 0;
for ( ; pos < mml.length; pos++)
{
if (mml.charAt(pos) != ".") break;
dot++;
}
return dot;
}
// タイ
private function getTie():Boolean
{
if (mml.charAt(pos) == "&")
{
pos++;
return true;
}
return false;
}
// 停止ボタン
private function onStop(e:MouseEvent):void
{
if (soundChannel == null) return;
soundChannel.stop();
soundChannel = null;
}
// サンプルデータ要求
private function onSampleData(e:SampleDataEvent):void
{
var len:int = Math.min(waveform.length - e.position, 8192);
for (var i:int = 0; i < len; i++)
{
var value:Number = waveform[e.position + i];
e.data.writeFloat(value);
e.data.writeFloat(value);
}
}
}
}
最終更新:2014年06月23日 17:54