テルミン
マウスのY軸をもとに1オクターブ分の音程をなめらかに
Y=0 のとき:ラ(441)
Y=stage.stageHeight のとき:1オクターブ上のラ
ずっと鳴らしっぱなしにすると遅れてきたりプツプツ鳴るから
gのY座標とマウスのY座標の差分が50p以上になったときに、
サウンドの再生を開始し、1秒後に自動的に止まる。
サウンドの再生開始時のgのY座標に対応する音程から、
実際のマウスのY座標に対応する音程まで音程を変化させる
// forked from kimu's Sound Test
// write as3 code here..
/*
マウスのY軸をもとに1オクターブ分の音程をなめらかに
Y=0 のとき:ラ(441)
Y=stage.stageHeight のとき:1オクターブ上のラ
ずっと鳴らしっぱなしにすると遅れてきたりプツプツ鳴るから
gのY座標とマウスのY座標の差分が50p以上になったときに、
サウンドの再生を開始し、1秒後に自動的に止まる。
サウンドの再生開始時のgのY座標に対応する音程から、
実際のマウスのY座標に対応する音程まで音程を変化させる
*/
package {
import flash.display.Sprite;
import flash.filters.BlurFilter;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.events.Event;
import flash.events.SampleDataEvent;
import flash.events.TimerEvent;
import flash.text.TextField;
import flash.utils.Timer;
import caurina.transitions.Tweener;
public class Main extends Sprite {
//鳴らすためのタイマー
public const timer:Timer = new Timer(500);
//Soundオブジェクト
public const snd:Sound = new Sound();
//描画オブジェクト用のラッパー
public const wrapper:Sprite = new Sprite();
//マウスおっかけるやつ
public const g:Sprite = new Sprite();
//まんなかのテキストフィールド
public const t:TextField = new TextField();
//SoundChannel
public var ch:SoundChannel;
//再生中フラグ
public var playing:Boolean = false;
//音の高さ( 0 <= tone < 1 )
public var tone:Number = 0;
public var toneTo:Number;
public var toneOffset:Number;
public function Main() {
//配置
addChild(wrapper);
wrapper.addChild(g);
wrapper.filters = [new BlurFilter(32,32,2)];
//Text
//addChild(t);
t.selectable = false;
t.width = 300;
t.height = 300;
t.htmlText = "<P ALIGN='CENTER'><FONT SIZE='128'>!</FONT></P>";
t.x = (stage.stageWidth-t.width)/2;
t.y = (stage.stageHeight-t.textHeight)/2;
//描画
g.graphics.beginFill(0);
g.graphics.drawCircle(0,0,10);
g.graphics.endFill();
//音
snd.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
//1秒たったらおと止める
timer.addEventListener(TimerEvent.TIMER,stopSound);
//
addEventListener(Event.ENTER_FRAME,onEnterFrame);
}
//gがマウスをおっかける+gの縦位置に合わせて音の高さを変える
private function onEnterFrame(e:Event):void {
if ( Math.abs(g.y-mouseY) > 50 || Math.abs(g.x-mouseX) > 50 ) startSound();
Tweener.addTween(g, {x:mouseX, y:mouseY, time:timer.delay/1000, transition:"easeOutSine"});
/*
g.x += ((mouseX - g.x)*0.1);
g.y += ((mouseY - g.y)*0.1);
*/
t.htmlText = "<P ALIGN='CENTER'><FONT SIZE='64'>"+((tone*1000)>>0)/1000+"</FONT></P>";
//マウスとの距離に合わせてちょっと●をおっきく
g.scaleX = g.scaleY = Math.abs(g.y-mouseY)/10;
}
//音ならす
private function startSound():void {
if ( playing ) return;
playing = true;
//音程の設定
tone = g.y/stage.stageHeight;//現在のgのY座標に対応した音程の値
toneTo = mouseY/stage.stageHeight;//現在のマウスのY座標に対応した音程の値
toneOffset = (toneTo-tone)/(44100*timer.delay/1000);
ch = snd.play();
timer.start();
//色をつける
g.graphics.clear();
g.graphics.beginFill(Math.random()*255*255*255);
g.graphics.drawCircle(0,0,10);
g.graphics.endFill();
}
//音とめる
private function stopSound(e:TimerEvent):void {
playing = false;
ch.stop();
//●をけす
g.graphics.clear();
}
//サンプルの生成
private function onSampleData(event:SampleDataEvent):void {
for (var c:int=0; c<8192; c++) {
tone += toneOffset;
var rad:Number = (Number(c+event.position)*(1+tone)/Math.PI);
var amp:Number = Math.sin(rad) / 4; // -1 から 1 の間の値なら OK
event.data.writeFloat(amp); // 左チャネルの音
event.data.writeFloat(amp); // 右チャネルの音
}
}
}
}