forked from: あの楽器っぽいスクリプト(鍵盤にしてみました)
あの楽器っぽいスクリプトのセルフフォーク
鍵盤にしてみましたが、タッチパネルならではのシームレスな音程のつなぎ方ができなくて落ち込み中。
多分「あの楽器」的には前のバージョンのほうがよかったんだろうなぁ。
白鍵黒鍵関係なくX軸でシームレスにすることはできますけど、EとF、BとCの半音間がどう計算すればいいのやら。
強引にやればできなくもないんでしょうけど・・・。もうちょっとあがいてみます。
あと、writeFloatの説明ありがとうございます。
試しに片方の数値を0にしてみたら、もう片方からしか聞こえてきませんでした。
必ず2つ書いていないとだめなんですね。そこらへんの仕組みがわからない・・・。
そもそもByteArrayすらわからない・・・。
あと、知人からエフェクトがワンパターンなのを指摘されたんで、そこもどうしようか悩み中。
いろいろ使ってないメンバとかありますが、気にしないでください。試行錯誤の名残です。
package
{
/*
* あの楽器っぽいスクリプトのセルフフォーク
*
* 鍵盤にしてみましたが、タッチパネルならではのシームレスな音程のつなぎ方ができなくて落ち込み中。
* 多分「あの楽器」的には前のバージョンのほうがよかったんだろうなぁ。
*
* 白鍵黒鍵関係なくX軸でシームレスにすることはできますけど、EとF、BとCの半音間がどう計算すればいいのやら。
* 強引にやればできなくもないんでしょうけど・・・。もうちょっとあがいてみます。
*
* あと、writeFloatの説明ありがとうございます。
* 試しに片方の数値を0にしてみたら、もう片方からしか聞こえてきませんでした。
* 必ず2つ書いていないとだめなんですね。そこらへんの仕組みがわからない・・・。
* そもそもByteArrayすらわからない・・・。
*
* あと、知人からエフェクトがワンパターンなのを指摘されたんで、そこもどうしようか悩み中。
*
* いろいろ使ってないメンバとかありますが、気にしないでください。試行錯誤の名残です。
*/
import flash.display.MovieClip;
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.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
[SWF(width="465", height="465", frameRate="30", backgroundColor="#ffffff")]
public class Main extends Sprite
{
//ステージ上描画関連
private var _baseSp:Sprite;
private var _baseSpGrid:Sprite;
private var _blackKeyArray:Array = new Array();
private var tF:TextField;
private var button:Sprite;
private var buttonText:TextField;
private var _dragFlag:Boolean;
//サウンドオブジェクト関連
private var _soundCh:SoundChannel;
private var _soundObj:Sound;
//音関連
private var _phase:Number = 0;
private var _buffSize:Number = 4096
private var _targetFreq:Number;
private var _freq:Number = 0;
private var _baseFreq:Number = 440;
private const PI2:Number = Math.PI * 2;
private var _mouseX:Number;
private var _mouseY:Number;
private var keyArray:Array = [130.8,146.8,164.8,174.6,196.0,220.0,246.9,261.6, 293.7, 329.6, 349.2, 392.0, 440, 493.9,523.3];
private var _keyBaseFreq:uint;
private var _movCnt:uint; //図形を出すためのカウント変数
private const POWER:Number = Math.pow(2, 1 / 13); //X軸で音階を変えるのに必要
private var num:uint = 24; //音階の数
private var _flag:int; //現在の図形の種類
private var _waveTone:uint = 0; //現在の音の種類
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);
//ステージ上の描画
_baseSp = new Sprite();
_baseSp.x = _baseSp.y = 0;
_baseSp.graphics.beginFill(0x000000, 1);
_baseSp.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
_baseSp.graphics.endFill();
addChild(_baseSp);
//鍵盤描画(縦線)
_baseSp.graphics.lineStyle(0.5, 0x222222);
for (var i:uint = 0; i <= 16; i++) {
_baseSp.graphics.moveTo(i * 31, 0);
_baseSp.graphics.lineTo(i * 31, 465);
}
//鍵盤描画(黒鍵)
for (var j:uint = 0; j < 4; j++) {
_blackKeyArray[j] = new Array();
drawBlackKey(21, j * 116, 138.6,_blackKeyArray[j]);
drawBlackKey(52, j * 116, 155.5,_blackKeyArray[j]);
drawBlackKey(114, j * 116, 185,_blackKeyArray[j]);
drawBlackKey(145, j * 116, 207.7,_blackKeyArray[j]);
drawBlackKey(176, j * 116, 233.1,_blackKeyArray[j]);
drawBlackKey(238, j * 116, 277.2,_blackKeyArray[j]);
drawBlackKey(269, j * 116, 311.2,_blackKeyArray[j]);
drawBlackKey(331, j * 116, 370,_blackKeyArray[j]);
drawBlackKey(362, j * 116, 415.3,_blackKeyArray[j]);
drawBlackKey(393, j * 116, 466.2,_blackKeyArray[j]);
}
//鍵盤描画(横線)
_baseSpGrid = new Sprite();
_baseSpGrid.graphics.lineStyle(0.5, 0x333333);
_baseSpGrid.graphics.moveTo(0, 0);
_baseSpGrid.graphics.lineTo(465, 0);
_baseSpGrid.graphics.moveTo(0, 116);
_baseSpGrid.graphics.lineTo(465, 116);
_baseSpGrid.graphics.moveTo(0, 232);
_baseSpGrid.graphics.lineTo(465, 232);
_baseSpGrid.graphics.moveTo(0, 348);
_baseSpGrid.graphics.lineTo(465, 348);
_baseSpGrid.graphics.moveTo(0, 465);
_baseSpGrid.graphics.lineTo(465, 465);
addChild(_baseSpGrid);
//波形情報表示関連
tF = new TextField();
tF.autoSize = TextFieldAutoSize.LEFT;
tF.defaultTextFormat = new TextFormat(null, 40, 0xFFFFFF);
tF.text = "SineWave";
_baseSp.addChild(tF);
button = new Sprite();
button.buttonMode = true;
button.mouseChildren = false;
button.graphics.beginFill(0x6666FF);
button.graphics.drawRoundRect(0, 0, 100, 30,10);
button.graphics.endFill();
button.x = 10;
button.y = 50;
addChild(button);
buttonText = new TextField();
buttonText.autoSize = TextFieldAutoSize.CENTER;
buttonText.defaultTextFormat = new TextFormat(null, 20, 0xFFFFFF);
buttonText.text = "Change";
buttonText.selectable = false;
button.addChild(buttonText);
button.addEventListener(MouseEvent.CLICK, onButtonClick);
//サウンド関連
_soundCh = new SoundChannel();
_soundObj = new Sound();
//いろいろ
_dragFlag = false;
_baseSp.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
_baseSp.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
_baseSp.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
_baseSp.mouseChildren = false;
_mouseX = stage.mouseX;
_mouseY = stage.mouseY;
}
//Draw系Function
private function drawBlackKey(tx:Number,ty:Number,hz:Number,arr:Array):void
{
var sp:Sprite = new Sprite();
sp.graphics.beginFill(0x000000);
sp.graphics.lineStyle(0.5,0x222222);
sp.graphics.moveTo(0, 0);
sp.graphics.lineTo(20, 0);
sp.graphics.lineTo(20, 70);
sp.graphics.lineTo(0, 70);
sp.graphics.lineTo(0, 0);
sp.graphics.endFill();
sp.name = hz.toString();
sp.x = tx;
sp.y = ty;
_baseSp.addChild(sp);
arr.push(sp);
}
private function onButtonClick(e:MouseEvent = null):void
{
_waveTone += 1;
if (_waveTone > 5) _waveTone = 0;
switch (_waveTone)
{
case 0:
tF.text = "SineWave";
break;
case 1:
tF.text = "SquareWave(50:50)?";
break;
case 2:
tF.text = "SquareWave(25:75)?";
break;
case 3:
tF.text = "TriangleWave";
break;
case 4:
tF.text = "Saw Wave";
break;
case 5:
tF.text = "Noise";
break;
}
}
private function drawBitmap(flagNum:int,e:MouseEvent):void
{
var drawSp:MovieClip = new MovieClip();
if (flagNum == -1) _flag = Math.floor(Math.random() * 5);
else _flag = flagNum;
drawSp.graphics.beginFill(0x66FF66);
switch (_flag)
{
case 0:
drawSp.graphics.drawCircle( 0, 0, 50);
drawSp.graphics.drawCircle( 0, 0, 47.5);
break;
case 1:
drawStar(drawSp,0, 0, 50);
drawStar(drawSp,0, 0, 45);
break;
case 2:
drawSp.graphics.drawRect(-50,-50,100,100);
drawSp.graphics.drawRect( -47.5, -47.5, 95, 95);
break;
case 3:
drawLineBmp();
break;
case 4:
drawTriangle(drawSp);
}
drawSp.graphics.endFill();
drawSp.x = e.stageX;
drawSp.y = e.stageY;
drawSp.rotation = Math.random() * 360;
_baseSp.addChild(drawSp);
drawSp.addEventListener(Event.ENTER_FRAME, bmpFadeOut);
}
private function drawLineBmp():void
{
var drawLineSp:MovieClip = new MovieClip();
drawLineSp.x = _mouseX;
drawLineSp.y = _mouseY;
drawLineSp.graphics.lineStyle(Math.random() * 30 + 5, 0x66FF66);
drawLineSp.graphics.moveTo(-657, 0);
drawLineSp.graphics.lineTo(657, 0);
drawLineSp.rotation = Math.random() * 360;
_baseSp.addChild(drawLineSp);
drawLineSp.addEventListener(Event.ENTER_FRAME, bmpFadeOutNoRotation);
}
private function drawTriangle(drawSp:Sprite):void
{
drawSp.graphics.beginFill(0x66FF66);
drawSp.graphics.moveTo(0, -43.4);
drawSp.graphics.lineTo(50, 43.4);
drawSp.graphics.lineTo(-50, 43.4);
drawSp.graphics.lineTo(0, -43);
drawSp.graphics.moveTo(0, -39.05);
drawSp.graphics.lineTo(45, 41);
drawSp.graphics.lineTo(-45, 41);
drawSp.graphics.lineTo(0, -39.05);
}
private function drawStar(sp:Sprite,drawX:Number = 0,drawY:Number = 0,drawScale:Number = 50):void
{
var scale:Number = drawScale / 50;
sp.graphics.lineStyle(0.5,0x66FF66,0.5);
sp.graphics.moveTo(0.3*scale , -47.65*scale);
sp.graphics.lineTo(12.5*scale, -12.2*scale);
sp.graphics.lineTo(50*scale, -10.95*scale);
sp.graphics.lineTo(20.05*scale, 11.6*scale);
sp.graphics.lineTo(30.45*scale, 47.65*scale);
sp.graphics.lineTo( -0.3*scale , 26.15*scale);
sp.graphics.lineTo( -31.35*scale , 47.15*scale);
sp.graphics.lineTo( -20.4*scale , 11.3*scale);
sp.graphics.lineTo(-50*scale, -11.75*scale);
sp.graphics.lineTo( -12.45*scale , -12.4*scale);
sp.graphics.lineTo(0.3*scale, -47.65*scale);
}
private function bmpFadeOutNoRotation(e:Event):void
{
var mc:MovieClip = e.target as MovieClip;
mc.alpha -= 0.08;
if (mc.alpha <= 0) {
mc.removeEventListener(Event.ENTER_FRAME, bmpFadeOutNoRotation);
_baseSp.removeChild(mc);
}
}
private function bmpFadeOut(e:Event):void
{
var mc:MovieClip = e.target as MovieClip;
mc.alpha -= 0.08;
mc.rotation += 10;
mc.scaleX = mc.scaleY += 0.4;
if (mc.alpha <= 0) {
mc.removeEventListener(Event.ENTER_FRAME, bmpFadeOut);
_baseSp.removeChild(mc);
}
}
//Intaractive系Function
private function mouseDownHandler(e:MouseEvent):void
{
_dragFlag = true;
_mouseX = stage.mouseX;
_mouseY = stage.mouseY;
changeFreqency();
_soundObj.addEventListener(SampleDataEvent.SAMPLE_DATA, toneGenerate);
_soundCh = _soundObj.play();
drawBitmap( -1, e);
stage.addEventListener(Event.ENTER_FRAME, changeFreqency);
}
private function mouseUpHandler(e:MouseEvent):void
{
_dragFlag = false;
_movCnt = 0;
_soundObj.removeEventListener(SampleDataEvent.SAMPLE_DATA, toneGenerate);
_soundCh.stop();
_flag = -1;
stage.removeEventListener(Event.ENTER_FRAME, changeFreqency);
}
private function mouseMoveHandler(e:MouseEvent):void
{
if (_dragFlag) {
_movCnt++;
if (_movCnt >= 20) {
_movCnt = 0;
//drawLine();
drawBitmap(_flag,e);
}
//changeFreqency();
}
}
//sound系Function
private function changeFreqency(e:Event = null):void
{
_mouseX = stage.mouseX;
_mouseY = stage.mouseY;
if (_mouseX < 0) _mouseX = 0;
else if (_mouseX > 465) _mouseX = 465;
if (_mouseY < 0) _mouseY = 0;
else if (_mouseY > 465) _mouseY = 465;
var position:uint = Math.floor(stage.mouseX / 31);
var centerPoint:Number = 31 * position + 16;
_keyBaseFreq = 0;
var posY:uint = Math.floor(_mouseY / 116);
_blackKeyArray[posY].forEach(blackKeyCheck);
if (_keyBaseFreq == 0) {
_keyBaseFreq = keyArray[position];
}
if (_mouseY < 116) {
_targetFreq = _keyBaseFreq * 4;
} else if (_mouseY < 232) {
_targetFreq = _keyBaseFreq * 2;
} else if (_mouseY < 348) {
_targetFreq = _keyBaseFreq;
} else {
_targetFreq = _keyBaseFreq / 2;
}
_freq = _targetFreq;
//_freq += (_targetFreq - _freq) / 10;
}
private function blackKeyCheck(element:*,i:int,arr:Array):void
{
if (element.hitTestPoint(_mouseX, _mouseY, true)) {
_keyBaseFreq = Number(element.name);
}
}
private function toneGenerate(e:SampleDataEvent):void
{
for (var i:int = 0; i < 2048; ++i) {
var smpl:Number;
var w:Number = PI2 * _freq / 44100;
_phase += w;
if (_phase > PI2) {
_phase -= PI2;
}
switch (_waveTone)
{
case 0:
smpl = Math.sin(_phase);
break;
case 1:
smpl = (_phase < Math.PI) ? 1 : -1;
break;
case 2:
smpl = (Math.sin(_phase) > 0.5) ? 1 : -1;
break;
case 3:
smpl = (_phase < Math.PI) ? -2 / Math.PI * _phase + 1 : 2 / Math.PI * _phase - 3;
break;
case 4:
smpl = - _phase / Math.PI + 1;
break;
case 5:
smpl = Math.random() * 2 - 1;
break;
}
if (smpl >= 1) smpl = 1;
else if (smpl <= -1) smpl = -1;
e.data.writeFloat(smpl);
e.data.writeFloat(smpl);
}
}
}
}