FeliCaでDJもどき forked from: FeliCa Flash Contest - FeliCa Search sample
FeliCaでDJもどき
@created by Hiiragi
コードがどんどん汚くなっていく・・・。
使い方
FeliCaリーダー/ライターにFeliCa搭載端末を置いて、
Melo1とかのボタンを押すとIDmの読み込みを開始します。
その情報に従ってフレーズを構築して音を鳴らす感じです。
あと、idmによって音が変わるようにしました。
発音時に左側が光るようになってますが、たまに光らないです。
帯もたまに出ない感じです。
指標にもならないので、「光ってるなー」くらいに見てください。
新機能として、キーボードパッドをつけてみました。
左の波形スイッチで波形を切り替えて、右のパッドをグリグリやると音が鳴ります。
赤色がキーの主音、緑色が全体の音と合わせても絶対に外れない音です。
これらのマークのところを目標にしてグリグリすれば、必ず音が外れない仕組みになってます。
残念ながら、FlashPlayerの特性上、発音の遅延は避けられません。
駅とかのポスターとかに、みんながタッチして音楽を奏でたら素敵ですよね。
FlashDevelopで開発してたんですが、デバッグ用プロジェクタがめちゃくちゃ重くてげんなりです。
読み込めなくなったら、おそらくFeliCaリーダーが占有されている状態なので、
しばらく待った後に再読み込みしてください。
// forked from felicacontest2010's FeliCa Flash Contest - FeliCa Search sample
package
{
/*
* FeliCaでDJもどき
* @created by Hiiragi
*
* コードがどんどん汚くなっていく・・・。
*
* 使い方
* FeliCaリーダー/ライターにFeliCa搭載端末を置いて、
* Melo1とかのボタンを押すとIDmの読み込みを開始します。
* その情報に従ってフレーズを構築して音を鳴らす感じです。
*
* あと、idmによって音が変わるようにしました。
*
* 発音時に左側が光るようになってますが、たまに光らないです。
* 帯もたまに出ない感じです。
* 指標にもならないので、「光ってるなー」くらいに見てください。
*
* 新機能として、キーボードパッドをつけてみました。
* 左の波形スイッチで波形を切り替えて、右のパッドをグリグリやると音が鳴ります。
* 赤色がキーの主音、緑色が全体の音と合わせても絶対に外れない音です。
* これらのマークのところを目標にしてグリグリすれば、必ず音が外れない仕組みになってます。
* 残念ながら、FlashPlayerの特性上、発音の遅延は避けられません。
*
*
*
* 駅とかのポスターとかに、みんながタッチして音楽を奏でたら素敵ですよね。
*
* FlashDevelopで開発してたんですが、デバッグ用プロジェクタがめちゃくちゃ重くてげんなりです。
* 読み込めなくなったら、おそらくFeliCaリーダーが占有されている状態なので、
* しばらく待った後に再読み込みしてください。
*/
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.media.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
import flash.utils.*;
import net.hires.debug.Stats;
import org.si.sion.*;
import org.si.sion.events.*;
import org.si.sion.utils.*;
import org.si.sion.sequencer.*;
import org.si.sion.module.*;
import com.sony.jp.felica.*;
import com.sony.jp.felica.event.*;
import com.sony.jp.felica.error.*;
import mx.controls.Button;
[SWF(width = 465, height = 465, frameRate = 60, backgroundColor = 0x222222)]
public class FeliCa extends Sprite
{
private var _felicaPhraseVec:Vector.<FelicaPhrase> = new Vector.<FelicaPhrase>(3);
private var _note:Vector.<int> = Vector.<int>([60, 62, 64, 67, 69, 72, 74, 76, 79, 81,
48, 50, 52, 55, 57, 60, 62, 64, 67, 69,
45, 52, 57,
60, 61, 62, 63, 64]);
private var _score:Vector.<int> = new Vector.<int>();
private var _voice:Vector.<SiONVoice> = new Vector.<SiONVoice>();
private var _drumScorePattern:Vector.<Vector.<int>> = new Vector.<Vector.<int>>;
private var _percusVoiceArray:Vector.<SiONVoice> = new Vector.<SiONVoice>;
private var _beatCounter:int = 0;
private var _sionDriver:SiONDriver = new SiONDriver();
private var _timer:Timer = new Timer(3000, 1);
private var _loader:Loader = new Loader();
private var _urlRequest:URLRequest;
private var _soundPartsArray:Array = [];
private var _statusSp:Sprite = new Sprite();
private var _statusTextField:TextField = new TextField();
private var _soundAnalyzer:SoundAnalyzer;
private var _wavesCanvas:BitmapData;
private var _wavesCanvasRect:Rectangle;
private var _wavesCanvasCtf:ColorTransform;
private var _attackLightArray:Vector.<AttackLight>;
private var _colorArray:Array = [];
//現在選択しているパート
private var _selectedPart:int = 1;
private var _selectedDrumPart:int = 0;
// FeliCaProxy との通信を行うコントロールクラス
private var fc:FeliCaControl = new FeliCaControl();
public function FeliCa()
{
_statusTextField.defaultTextFormat = new TextFormat(null, 30, 0xFFFFFF, FontStyle.BOLD);
_statusTextField.autoSize = TextFieldAutoSize.LEFT;
_statusTextField.y = this.stage.stageHeight / 2 - 25;
statusTextSet("FeliCa Proxy Holding now");
_statusSp.addChild(_statusTextField);
_statusSp.graphics.beginFill(0x000000, .3);
_statusSp.graphics.drawRect(0, 0, this.stage.stageWidth, this.stage.stageHeight);
_statusSp.graphics.endFill();
_statusSp.graphics.beginFill(0x000000, .8);
_statusSp.graphics.drawRect(0, this.stage.stageHeight / 2 - 25, this.stage.stageWidth, 50);
_statusSp.graphics.endFill();
_wavesCanvas = new BitmapData(465, 465, true, 0);
//soundLoadStart();
init();
}
private function statusTextSet(txt:String):void
{
_statusTextField.text = txt;
_statusTextField.x = this.stage.stageWidth / 2 - _statusTextField.width / 2;
}
//private function soundLoadStart():void
//{
//_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, soundLoadComplete);
//_urlRequest = new URLRequest("FeliCaAssets.swf");
//var context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
//_loader.load(_urlRequest, context);
//}
//
//private function soundLoadComplete(e:Event):void
//{
//_soundPartsArray[0] = new (_loader.contentLoaderInfo.applicationDomain.getDefinition("kick") as Class)();
//_soundPartsArray[1] = new (_loader.contentLoaderInfo.applicationDomain.getDefinition("snare") as Class)();
//_soundPartsArray[2] = new (_loader.contentLoaderInfo.applicationDomain.getDefinition("ch") as Class)();
//_soundPartsArray[3] = new (_loader.contentLoaderInfo.applicationDomain.getDefinition("oh") as Class)();
//_soundPartsArray[4] = new (_loader.contentLoaderInfo.applicationDomain.getDefinition("crash") as Class)();
//init();
//}
public function init():void
{
//SiON
//_felicaPhraseVec[0] = new FelicaPhrase("011721103f08972b", false);
//_felicaPhraseVec[1] = new FelicaPhrase("01010701360dd007", false);
_felicaPhraseVec[0] = new FelicaPhrase(null, false);
_felicaPhraseVec[1] = new FelicaPhrase(null, false);
_felicaPhraseVec[2] = new FelicaPhrase(null, false);
_drumScorePattern[0] = Vector.<int>([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0
]);
//_drumScorePattern[1] = Vector.<int>([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
//0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
//1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1,
//0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1,
//1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0
//]);
//
//_drumScorePattern[2] = Vector.<int>([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
//0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
//0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0,
//0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
//1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0
//]);
_drumScorePattern = convertDrumPattern(_drumScorePattern);
_soundAnalyzer = new SoundAnalyzer();
createSionScoreAndVoice();
_sionDriver.setBeatCallbackInterval(1);
_sionDriver.addEventListener(SiONTrackEvent.BEAT, beatListner);
_sionDriver.setTimerInterruption(1, timerInterruption);
var preset:SiONPresetVoice = new SiONPresetVoice();
_percusVoiceArray[0] = preset["valsound.percus10"]; //CC
_percusVoiceArray[1] = preset["valsound.percus23"]; //OH
_percusVoiceArray[2] = preset["valsound.percus18"]; //CH
_percusVoiceArray[3] = preset["valsound.percus29"]; //snare
_percusVoiceArray[4] = preset["valsound.percus2"]; //bass
//_sionDriver.setSamplerSound(64, _soundPartsArray[0]);
//_sionDriver.setSamplerSound(63, _soundPartsArray[1]);
//_sionDriver.setSamplerSound(62, _soundPartsArray[2]);
//_sionDriver.setSamplerSound(61, _soundPartsArray[3]);
//_sionDriver.setSamplerSound(60, _soundPartsArray[4]);
var tFormat:TextFormat = new TextFormat("_serif", 16, 0xFFFFFF);
var btn1:ControllerButton = new ControllerButton("Melo1", "btn1",60, 30, 3, tFormat,0, 0x222222);
var btn2:ControllerButton = new ControllerButton("Melo2", "btn2",60, 30, 3, tFormat,0, 0x222222);
var btn3:ControllerButton = new ControllerButton("Bass", "btn3",60, 30, 3, tFormat,0, 0x222222);
//var btn4:ControllerButton = new ControllerButton("Drum", "btn4", 100, 40, 5, tFormat);
btn1.y = btn2.y = btn3.y = 430;
btn1.x = 10;
btn2.x = 70;
btn3.x = 130;
//btn4.x = 350;
btn1.addEventListener(MouseEvent.CLICK, cardReadStart);
btn2.addEventListener(MouseEvent.CLICK, cardReadStart);
btn3.addEventListener(MouseEvent.CLICK, cardReadStart);
//btn4.addEventListener(MouseEvent.CLICK, drumPatternEdit);
var wavesCanvasBmp:Bitmap = new Bitmap(_wavesCanvas);
_wavesCanvasRect = _wavesCanvas.rect;
_wavesCanvasCtf = new ColorTransform(0.995, 0.995, 0.995, 0.995);
this.addChild(wavesCanvasBmp);
_attackLightArray = new Vector.<AttackLight>();
var verticalGridLine:Sprite = new Sprite();
this.addChild(verticalGridLine);
var h:int = 400 / _note.length;
this.graphics.beginFill(0x200000);
this.graphics.drawRect(0, 0, 465, h * 10);
this.graphics.endFill();
this.graphics.beginFill(0x002000);
this.graphics.drawRect(0, h * 10, 465, h * 10);
this.graphics.endFill();
this.graphics.beginFill(0x000020);
this.graphics.drawRect(0, h * 20, 465, h * 3);
this.graphics.endFill();
//グリッド描画と色設定とAttackLight設置
this.graphics.lineStyle(1, 0x666666);
verticalGridLine.graphics.lineStyle(1, 0x666666);
for (var i:int = 0; i < 16; i++)
{
this.graphics.moveTo(465 / 16 * i, 0);
this.graphics.lineTo(465 / 16 * i, 400 - 9);
_colorArray[i] = HSVtoRGB(360 / 16 * i);
}
this.graphics.moveTo(465, 0);
this.graphics.lineTo(465, 465);
for (i = 0; i < _note.length ; i++)
{
verticalGridLine.graphics.moveTo(0, h * i + 400 / + h / 2 -1);
verticalGridLine.graphics.lineTo(465, h * i + 400 / + h / 2 -1);
var al:AttackLight = new AttackLight();
al.y = h * i - 10;
verticalGridLine.addChild(al);
_attackLightArray[i] = al;
}
this.addChild(btn1);
this.addChild(btn2);
this.addChild(btn3);
//this.addChild(btn4);
var keyboard:Keyboard = new Keyboard(465);
keyboard.y = 390;
this.addChild(keyboard);
_soundAnalyzer.x = 465 - 256;
_soundAnalyzer.y = 423;
this.addChild(_soundAnalyzer);
//this.addChild(new Stats());
this.addEventListener(Event.ENTER_FRAME, canvasScroller);
_timer.addEventListener(TimerEvent.TIMER, connectionCloser);
// リスナー登録
fc.addEventListener(OpenStatusEvent.OPEN_COMPLETE, onOpenComplete);
fc.addEventListener(OpenStatusEvent.OPEN_FAILURE, onOpenFailure);
fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_COMPLETE, onFeliCaAccessComplete);
fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_FAILURE, onFeliCaAccessFailure);
fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_PARAMETER_ERROR, onFeliCaAccessParameterError);
tracer("FeliCaProxy との認証を開始します。");
//fc.open(10250);
fc.open(10250,"__FELICA_STANDARD_KEY__", "");
_sionDriver.play();
}
private function HSVtoRGB(hue:Number, saturation:Number=1, value:Number=1):uint {
var Hi:int = Math.floor(hue / 60) % 6;
var f:Number = hue / 60 - Hi;
var p:Number = value * (1 - saturation);
var q:Number = value * (1 - f * saturation);
var t:Number = value * (1 - (1 - f) * saturation);
var r:Number = 0;
var g:Number = 0;
var b:Number = 0;
switch (Hi) {
case 0:
r=value; g=t; b=p;
break;
case 1:
r=q; g=value; b=p;
break;
case 2:
r=p; g=value; b=t;
case 3:
r=p; g=q; b=value;
break;
case 4:
r=t; g=p; b=value;
break;
case 5:
r=value; g=p; b=q;
break;
}
r = Math.floor(r*255);
g = Math.floor(g*255);
b = Math.floor(b*255);
return r << 16 | g << 8 | b;
}
private var _ctfCnt:int = 0;
private function canvasScroller(e:Event):void
{
_wavesCanvas.lock();
_wavesCanvas.scroll(5, 0);
_ctfCnt++;
if (_ctfCnt >= 3)
{
_wavesCanvas.colorTransform(_wavesCanvasRect, _wavesCanvasCtf);
_ctfCnt = 0;
}
_wavesCanvas.unlock();
}
private var feliCaReadFlag:Boolean = false;
private function connectionCloser(e:TimerEvent):void
{
tracer("制限時間により読み取りを終了します。");
feliCaReadFlag = false;
}
private function cardReadStart(e:MouseEvent):void
{
if (feliCaReadFlag)
{
tracer("現在FeliCa読み取り中です。");
}
else
{
switch (e.target.name)
{
case "btn1":
_selectedPart = 0;
break;
case "btn2":
_selectedPart = 1;
break;
case "btn3":
_selectedPart = 2;
break;
}
RwLock();
feliCaReadFlag = true;
_timer.reset();
_timer.start();
this.addChild(_statusSp);
}
}
private function drumPatternEdit(e:MouseEvent):void
{
}
private function onOpenComplete(e:OpenStatusEvent):void
{
tracer("FeliCaProxy との認証に成功しました。");
//RwLock();
}
private function onOpenFailure(e:OpenStatusEvent):void
{
var error:Error = e.object as Error;
tracer( "FeliCaProxy との相互認証に失敗しました。\n" +
" ERROR : (" + error.errorID + ") " + error.message);
}
private function onFeliCaAccessComplete(e:FeliCaStatusEvent):void
{
if (e.object is FeliCaSessionResponse)
{
var session:FeliCaSessionResponse = e.object as FeliCaSessionResponse;
// リーダ/ライタの専有
if (session.type == FeliCaSessionResponse.HOLD)
{
statusTextSet("R/W Hold Complete");
tracer("リーダ/ライタの専有をしました。");
// リーダ/ライタのオープンを実行
RwOpen();
}
// リーダ/ライタの開放
else
{
tracer("リーダ/ライタの専有を開放しました。");
this.removeChild(_statusSp);
// FeliCaProxy の切断
//FeliCaProxyClose();
}
}
else if (e.object is FeliCaOpenReaderWriterAutoResponse)
{
tracer("リーダ/ライタのオープンに成功しました。");
statusTextSet("R/W Open Complete");
// FeliCa を検出するために、Polling の実行
Polling();
}
else if (e.object is FeliCaPollingAndGetCardInformationResponse)
{
var response:FeliCaPollingAndGetCardInformationResponse = e.object as FeliCaPollingAndGetCardInformationResponse;
statusTextSet("set FeliCa idm = " + response.idm);
// 検出した FeliCa の情報を表示
tracer( "FeliCa を検出しました。\n" +
" idm = " + response.idm + "\n" +
" pmm = " + response.pmm);
if (_selectedPart != -1 && _felicaPhraseVec[_selectedPart].idm != response.idm)
{
trace("_selectedPart = " + _selectedPart + " , idm = " + response.idm);
_felicaPhraseVec[_selectedPart] = new FelicaPhrase(response.idm, true);
createSionScoreAndVoice();
}
// リーダ/ライタのクローズを実行
if (feliCaReadFlag)
{
Polling();
}
else
{
RwClose();
}
}
else if (e.object is FeliCaCloseReaderWriterResponse)
{
tracer("リーダ/ライタのクローズに成功しました。");
// リーダ/ライタ専有の開放
RwUnlock();
}
}
private function onFeliCaAccessFailure(e:FeliCaStatusEvent):void
{
var errorMsg:String;
if (e.object is FeliCaAccessError)
{
var error1:FeliCaAccessError =e.object as FeliCaAccessError;
errorMsg = " ERROR: (" + error1.errorID + ")" + error1.message + "\n" +
" FeliCa Error Code (" + error1.felicaError + ")\n" +
" RW Error Code (" + error1.rwError + ")\n" +
" FeliCaProxy Error Code (" + error1.felicaProxyError + ")";
}
else if (e.object is Error)
{
var error2:Error =e.object as Error;
errorMsg = " ERROR : (" + error2.errorID + ") " + error2.message;
}
tracer("FeliCa アクセスに失敗しました\n" + errorMsg);
// FeliCaProxy の切断
if (feliCaReadFlag)
{
Polling();
}
else
{
RwUnlock();
//FeliCaProxyClose();
}
}
private function onFeliCaAccessParameterError(e:FeliCaStatusEvent):void
{
var error:Error = e.object as Error;
tracer( "FeliCa アクセスでパラメータエラーが発生しました。\n" +
" ERROR: (" + error.errorID + ")" + error.message);
// FeliCaProxy の切断
FeliCaProxyClose();
}
// リーダ/ライタの専有を実行
private function RwLock():void
{
// リーダ/ライタを専有する為の情報の設定
var request:FeliCaSessionRequest = new FeliCaSessionRequest();
request.type = FeliCaSessionRequest.HOLD; // リーダ・ライタ専有要求
request.lockTimeout = 10; // 専有(Lock)するまでのタイムアウト時間(秒)
request.unlockTimeout = 60; // 専有(Lock)してから開放(Unlock)するまでの見込み時間(秒)
// FeliCaProxyは、このunlockTimeout時間経過した場合自動でR/W開放を行う。
// リーダ/ライタ専有を実行
tracer("リーダ/ライタ専有を実行します。");
fc.access(request);
}
// リーダ/ライタ専有の開放を実行
private function RwUnlock():void
{
// リーダ/ライタ専有を開放する為の情報の設定
var request:FeliCaSessionRequest = new FeliCaSessionRequest();
request.type = FeliCaSessionRequest.RELEASE; // リーダ・ライタ開放要求
// リーダ/ライタ専有開放を実行
fc.access(request);
}
// リーダ/ライタのオープンを実行
private function RwOpen():void
{
// [open_reader_writer_auto] コマンドを実行
fc.access(new FeliCaOpenReaderWriterAutoRequest());
}
// リーダ/ライタのクローズを実行
private function RwClose():void
{
// [close_reader_writer] コマンドを実行
fc.access(new FeliCaCloseReaderWriterRequest());
}
// FeliCa を検出するために、Polling の実行
private function Polling():void
{
// [polling_and_get_card_information] コマンドを実行する為の情報の設定
var request:FeliCaPollingAndGetCardInformationRequest = new FeliCaPollingAndGetCardInformationRequest();
request.systemCode = "FFFF"; // ポーリングするシステムコード
// [polling_and_get_card_information] コマンドを実行
fc.access(request);
}
// FeliCaProxy の切断
private function FeliCaProxyClose():void
{
if (fc.close() == true)
{
tracer("FeliCaProxy との接続を切断しました。");
}
else
{
tracer("FeliCaProxy との接続を切断に失敗しました。");
}
}
////////////////////////以下、SiON用ファンクション
//DrumPatternを変換
private function convertDrumPattern(vec:Vector.<Vector.<int>>):Vector.<Vector.<int>>
{
var tempVec:Vector.<Vector.<int>> = vec.concat();
var len:int = tempVec.length;
for (var i:int = 0; i < len ; i++)
{
var tempVec2:Vector.<int> = new Vector.<int>(5);
var len2:int = tempVec[i].length;
for (var j:int = 0 ; j < len2; j++)
{
if (tempVec[i][j] == 1) tempVec2[(j / 16) >> 0] |= 1 << (j % 16);
}
tempVec[i] = tempVec2;
}
return tempVec;
}
//Create
private function createSionScoreAndVoice():void
{
_score = new Vector.<int>();
_score = _score.concat(_drumScorePattern[_selectedDrumPart], _felicaPhraseVec[2].baseScore, _felicaPhraseVec[1].melo2Score, _felicaPhraseVec[0].melo1Score);
//trace(_score);
_voice = Vector.<SiONVoice>([_felicaPhraseVec[0].melo1Voice, _felicaPhraseVec[1].melo2Voice, _felicaPhraseVec[2].baseVoice]);
//_soundAnalyzer.barRedColor = _felicaPhraseVec[0]color;
//_soundAnalyzer.barGreenColor = _felicaPhraseVec[1].color;
//_soundAnalyzer.barBlueColor = _felicaPhraseVec[2].color;
_soundAnalyzer.color = _felicaPhraseVec[_selectedPart].colors[0];
}
//描画
private function beatListner(e:SiONTrackEvent):void
{
_wavesCanvas.lock();
var beatIndex:int = _beatCounter & 15;
var height:int = 400;
var len:int = _score.length;
var diffHeight:int = height / len;
var color:uint;
for (var i:int = 0; i < len ; i++)
{
if (_score[i] & (1 << beatIndex))
{
if (i < 10) color = 0xFF << 24 | _felicaPhraseVec[0].colors[i];
else if (i < 20) color = 0xFF << 24 | _felicaPhraseVec[1].colors[i % 10];
else if (i < 23) color = 0xFF << 24 | _felicaPhraseVec[2].colors[i % 20];
else color = 0xFF << 24 | _colorArray[beatIndex];
_wavesCanvas.fillRect(new Rectangle(0, diffHeight * i, 5, diffHeight), color);
_attackLightArray[i].lightUp();
//trace(_attackLightArray[i]);
//_wavesCanvas.setPixel32(0, diffHeight * i, 0xFFFFFFFF);
}
}
_wavesCanvas.unlock();
}
//音
private function timerInterruption():void
{
var beatIndex:int = _beatCounter & 15;
var len:int = _score.length;
var st:SiMMLTrack;
for (var i:int = 0; i < len ; i++)
{
if (_score[i] & (1 << beatIndex))
{
if (i < 10) _sionDriver.noteOn(_note[i], _voice[0], 1);
else if (i < 20) _sionDriver.noteOn(_note[i], _voice[1], 1);
else if (i < 23) _sionDriver.noteOn(_note[i], _voice[2], 1);
else
{
//var preset:SiONPresetVoice = new SiONPresetVoice();
//var voice:SiONVoice = preset["valsound.percus1"];
//st = _sionDriver.playSound(_note[i], 1);
//trace(i - 23);
st = _sionDriver.noteOn(40, _percusVoiceArray[i - 23], 1);
//st.velocity = 255;
}
}
}
//Drum
//if (_beatCounter % 4 == 0)
//{
//_sionDriver.noteOn(40, _percusVoiceArray[0], 4);
//st = _sionDriver.playSound(60, 10);
//st.velocity = 255;
//
//if (_beatCounter % 16 == 4 || _beatCounter % 16 == 12)
//{
//_sionDriver.noteOn(36, _percusVoiceArray[2], 4);
//}
//}
_beatCounter++;
}
private function tracer(str:String):void
{
//trace(str);
}
}
}
import flash.display.*;
import flash.filters.BlurFilter;
import flash.filters.GlowFilter;
import flash.media.*;
import flash.events.*;
import flash.geom.*;
import flash.text.*;
import flash.utils.*;
import org.si.sion.*;
import org.si.sion.utils.*;
class FelicaPhrase extends Object
{
private var _idm:String = "";
private var _melo1Voice:SiONVoice;
private var _melo2Voice:SiONVoice;
private var _baseVoice:SiONVoice;
private var _melo1Score:Vector.<int> = new Vector.<int>(10);
private var _melo2Score:Vector.<int> = new Vector.<int>(10);
private var _baseScore:Vector.<int> = new Vector.<int>(3);
private var _colors:Array;
public function FelicaPhrase(idm:String, doDispatch:Boolean = true)
{
var sionPreset:SiONPresetVoice = new SiONPresetVoice();
_idm = (idm == null) ? "0000000000000000" : idm;
////初期情報設定 検証用idm = 011721103f08972b
//音符
var notesStr:String = _idm.substr(6, 10);
//休符情報(0は休符・1は音符)(1110110110001110)
//var restNum:int = int("0x" + _idm.substr(5, 1) + _idm.substr(4, 1) + _idm.substr(3, 1) + _idm.substr(2, 1));
//if (restNum != 0) restNum ^= 0xFFFF;
//trace(restNum.toString(2));
trace("idm = " + _idm);
//melo1ScoreCreate
var pos:int;
//trace("notesStr = " + notesStr);
for (var i:int = 0; i < notesStr.length; i++)
{
pos = 15 - int("0x" + notesStr.substr(i, 1));
_melo1Score[i] = (int("0x" + notesStr) == 0) ? 0 : 1 << int("0x" + notesStr.substr(i, 1));
}
_melo1Score = redundancyDelete(_melo1Score, 16);
trace("_melo1Score = " + _melo1Score);
//melo2ScoreCreate
var notesStr2:String = ("0000000000" + parseInt(int("0x" + notesStr).toString(2).split("").reverse().join(""), 2).toString(16)).substr(-10, 10);
for (i = 0; i < notesStr2.length; i++)
{
pos = 15 - int("0x" + notesStr2.substr(i, 1));
_melo2Score[i] = (int("0x" + notesStr2) == 0) ? 0 : 1 << int("0x" + notesStr2.substr(i, 1));
}
_melo2Score = redundancyDelete(_melo2Score, 16);
trace("_melo2Score = " + _melo2Score);
//baseScoreCreate
var notesStrBass:String = "";
for (i = 1; i <= 8 ; i++)
{
notesStrBass += ("0000" + int("0x" + notesStr.substr( -i, 1)).toString(2)).substr(-4, 4);
}
var index:int;
for (i = 0; i < 16; i++)
{
index = parseInt(notesStrBass.substr(i * 2, 2), 2);
if (index != 0)
{
_baseScore[index - 1] += 1 << i;
}
}
trace("_baseScore = " + _baseScore);
//voiceSet
_melo1Voice = sionPreset["valsound.lead" + (int("0x" + notesStr.substr(-2, 2)) % 42 + 1)];
_melo2Voice = sionPreset["valsound.piano" + (int("0x" + notesStr.substr(-4, 2)) % 19 + 1)];
_baseVoice = sionPreset["valsound.bass" + (int("0x" + notesStr.substr( -6, 2)) % 53 + 1)];
//_melo1Voice = sionPreset["valsound.lead1"];
//_melo2Voice = sionPreset["valsound.piano2"];
//_baseVoice = sionPreset["valsound.bass3"];
_colors = [];
var colorStr:String = _idm.substr( -8, 8);
_colors.push(parseInt(colorStr.substr( 0, 6), 16));
_colors.push(parseInt(colorStr.substr( 1, 6), 16));
_colors.push(parseInt(colorStr.substr( 2, 6), 16));
_colors.push(parseInt(colorStr.substr( 1, 5) + colorStr.substr(0, 1), 16));
_colors.push(parseInt(colorStr.substr( 2, 5) + colorStr.substr(1, 1), 16));
_colors.push(parseInt(colorStr.substr( 3, 5) + colorStr.substr(2, 1), 16));
_colors.push(parseInt(colorStr.substr( 2, 1) + colorStr.substr( 5, 1) + colorStr.substr( 3, 1) + colorStr.substr( 1, 1) + colorStr.substr( 0, 1) + colorStr.substr( 4, 1), 16));
_colors.push(parseInt(colorStr.substr( 3, 1) + colorStr.substr( 6, 1) + colorStr.substr( 4, 1) + colorStr.substr( 2, 1) + colorStr.substr( 1, 1) + colorStr.substr( 5, 1), 16));
_colors.push(parseInt(colorStr.substr( 4, 1) + colorStr.substr( 7, 1) + colorStr.substr( 5, 1) + colorStr.substr( 3, 1) + colorStr.substr( 2, 1) + colorStr.substr( 6, 1), 16));
_colors.push(parseInt(colorStr.substr( 3, 1) + colorStr.substr( 0, 1) + colorStr.substr( 5, 1) + colorStr.substr( 4, 1) + colorStr.substr( 1, 1) + colorStr.substr( 2, 1), 16));
_colors.push(parseInt(colorStr.substr( 4, 1) + colorStr.substr( 1, 1) + colorStr.substr( 6, 1) + colorStr.substr( 5, 1) + colorStr.substr( 2, 1) + colorStr.substr( 3, 1), 16));
_colors.push(parseInt(colorStr.substr( 5, 1) + colorStr.substr( 2, 1) + colorStr.substr( 7, 1) + colorStr.substr( 6, 1) + colorStr.substr( 3, 1) + colorStr.substr( 4, 1), 16));
_colors.push(parseInt(colorStr.substr( 5, 1) + colorStr.substr( 4, 1) + colorStr.substr( 2, 1) + colorStr.substr( 0, 1) + colorStr.substr( 3, 1) + colorStr.substr( 1, 1), 16));
_colors.push(parseInt(colorStr.substr( 6, 1) + colorStr.substr( 5, 1) + colorStr.substr( 3, 1) + colorStr.substr( 1, 1) + colorStr.substr( 4, 1) + colorStr.substr( 2, 1), 16));
_colors.push(parseInt(colorStr.substr( 7, 1) + colorStr.substr( 6, 1) + colorStr.substr( 4, 1) + colorStr.substr( 2, 1) + colorStr.substr( 5, 1) + colorStr.substr( 3, 1), 16));
_colors.push(parseInt(colorStr.substr( 4, 1) + colorStr.substr( 2, 1) + colorStr.substr( 5, 1) + colorStr.substr( 1, 1) + colorStr.substr( 7, 1) + colorStr.substr( 0, 1), 16));
var colorPetternArray:Array = [["r", "g", "b"], ["g", "b", "r"],["b", "r" , "g"], ["r", "b", "g"]];
var colorPetternIndex:int = parseInt(parseInt(_idm, 16).toString(16).substr( -2, 2), 2);
for (i = 0; i < _colors.length; i++)
{
_colors[i] = intLimiter(_colors[i], colorPetternArray[colorPetternIndex][i % 3]);
}
trace("colors = " + _colors);
}
private function intLimiter(value:int, pettern:String):int
{
const MIN_LIMIT:int = 0x55;
const MAX_LIMIT:int = 0xFF;
var r:int = value >> 16;
var g:int = value >> 8 & 0xFF;
var b:int = value & 0xFF;
if (r < MIN_LIMIT) r = (pettern == "r") ? MAX_LIMIT : MIN_LIMIT;
if (g < MIN_LIMIT) g = (pettern == "g") ? MAX_LIMIT : MIN_LIMIT;
if (b < MIN_LIMIT) b = (pettern == "b") ? MAX_LIMIT : MIN_LIMIT;
return r << 16 | g << 8 | b;
}
private function redundancyDelete(vec:Vector.<int>, num:int):Vector.<int>
{
var len:int = vec.length;
var flag:Boolean = false;
for (var i:int; i < num; i++)
{
for (var j:int = 0; j < len; j++)
{
if (vec[j] & 1 << i)
{
if (!flag) flag = true;
else vec[j] = 0;
}
}
flag = false;
}
return vec;
}
public function get melo1Score():Vector.<int> { return _melo1Score; }
public function get melo2Score():Vector.<int> { return _melo2Score; }
public function get baseScore():Vector.<int> { return _baseScore; }
public function get melo1Voice():SiONVoice { return _melo1Voice; }
public function get melo2Voice():SiONVoice { return _melo2Voice; }
public function get baseVoice():SiONVoice { return _baseVoice; }
public function get idm():String { return _idm; }
public function get colors():Array { return _colors; }
}
class SoundAnalyzer extends Bitmap
{
private var _byteArray:ByteArray;
private var _canvas:BitmapData;
private var _ctf:ColorTransform;
private var _rect:Rectangle;
private var _plotHeight:int;
private var _barRedColor:int = 0;
private var _barGreenColor:int = 0;
private var _barBlueColor:int = 0;
private var _color:int = 0x666666;
public function SoundAnalyzer()
{
_plotHeight = 40;
_byteArray = new ByteArray();
_canvas = new BitmapData(256, _plotHeight, false, 0x0);
_ctf = new ColorTransform(.9, .9, .9);
_rect = new Rectangle(0, 0, 256, 50);
this.bitmapData = _canvas;
this.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
private var _leftByteArray:ByteArray;
private var _rightByteArray:ByteArray;
private function onEnterFrameHandler(e:Event):void
{
SoundMixer.computeSpectrum(_byteArray, true, 0);
_canvas.colorTransform(_rect, _ctf);
//var color:int = 0x44 << 16 | _barRedColor << 16 | 0x44 << 8 | _barGreenColor << 8 | 0x44 | _barBlueColor;
var x:int = 0;
var h:int = 0;
_leftByteArray = new ByteArray();
_rightByteArray = new ByteArray();
for (var i:int = 0; i < 512; i++)
{
if (i < 256) _leftByteArray.writeFloat(_byteArray.readFloat());
else _rightByteArray.writeFloat(_byteArray.readFloat());
}
_leftByteArray.position = 0;
_rightByteArray.position = 0;
_canvas.lock();
for (i = 0; i < 250; i++)
{
h = (_leftByteArray.readFloat() + _rightByteArray.readFloat()) / 2 * _plotHeight;
for (var j:int = 0; j < h; j++)
{
_canvas.setPixel(x, _plotHeight - j, _color);
}
x++;
}
_canvas.unlock();
}
public function get color():int { return _color; }
public function set color(value:int):void
{
_color = value;
}
//public function get barRedColor():int { return _barRedColor; }
//
//public function set barRedColor(value:int):void
//{
//_barRedColor = multiplierLimiter(value);
//}
//
//public function get barGreenColor():int { return _barGreenColor; }
//
//public function set barGreenColor(value:int):void
//{
//_barGreenColor = multiplierLimiter(value);
//}
//
//public function get barBlueColor():int { return _barBlueColor; }
//
//public function set barBlueColor(value:int):void
//{
//_barBlueColor = multiplierLimiter(value);
//}
//
//private function multiplierLimiter(value:int):Number
//{
//if (value > 0xbb)
//{
//value /= Math.ceil(value / 0xbb);
//}
//else if (value < 0)
//{
//value = 0;
//}
//
//return value;
//}
}
class AttackLight extends Bitmap
{
//private var _canvas:BitmapData;
private var _sourceSp:Sprite;
private var _ctf:ColorTransform;
private var _timer:Timer;
public function AttackLight()
{
this.bitmapData = new BitmapData(150, 25, true, 0);
//_canvas = new BitmapData(100, 80, true, 0);
_ctf = new ColorTransform(0.8, 0.8, 0.8, 0.8);
_timer = new Timer(16, 120);
_timer.addEventListener(TimerEvent.TIMER, update);
_sourceSp = new Sprite();
var g:Graphics = _sourceSp.graphics;
//var mtx:Matrix = new Matrix();
//mtx.createGradientBox(25, 25, 0, 0, 0);
//g.beginGradientFill(GradientType.RADIAL, [0xDDDDFF, 0xFFFFFF], [1, 1], [0, 255], mtx);
g.beginFill(0xFFFFFF);
g.drawCircle(0, 8, 8);
//g.drawRoundRect(0, 0, 50, 25, 5);
g.endFill();
_sourceSp.filters = [new GlowFilter(0xFFFFFFFF, 1, 96, 16, 20, 2), new BlurFilter(8,4,2)];
//this.addChild(_sourceSp);
//this.addChild(new Bitmap(_canvas));
//this.stage.addEventListener(MouseEvent.CLICK, lightUp);
}
public function lightUp(e:MouseEvent = null):void
{
this.bitmapData.draw(_sourceSp, new Matrix(1, 0, 0, 1, 0, 8));
_timer.reset();
_timer.start();
}
private function update(e:TimerEvent):void
{
this.bitmapData.colorTransform(this.bitmapData.rect, _ctf);
}
}
class ControllerButton extends Sprite
{
private var _backSp:Sprite;
private var _rollOverSp:Sprite;
private var _mouseDownSp:Sprite;
private var _tf:TextField;
private var _tFormat:TextFormat;
private var _labelText:String;
private var _id:String;
private var _width:Number;
private var _height:Number;
private var _color1:int;
private var _color2:int;
private var _roundRadius:Number;
public function ControllerButton(labelText:String, name:String = null, width:Number = 80, height:Number = 20, roundRadius:Number = 5, tFormat:TextFormat = null, color1:int = 0x000000, color2:int = 0x333333)
{
//引数の取得・設定
_labelText = labelText;
if (name != null) this.name = name;
_width = width;
_height = height;
_tFormat = tFormat;
_roundRadius = roundRadius;
_color1 = color1;
_color2 = color2;
//テキスト設定
_tf = new TextField();
_tf.autoSize = TextFieldAutoSize.LEFT;
_tf.antiAliasType = AntiAliasType.ADVANCED;
if (tFormat == null) _tf.defaultTextFormat = new TextFormat(null, null, 0xFFFFFF);
else _tf.defaultTextFormat = tFormat;
//初期化、表示リスト追加、リスナー追加
_backSp = new Sprite();
_rollOverSp = new Sprite();
_mouseDownSp = new Sprite();
addChild(_backSp);
addChild(_mouseDownSp);
addChild(_rollOverSp);
addChild(_tf);
this.addEventListener(MouseEvent.ROLL_OVER, onRollOverHandler);
this.addEventListener(MouseEvent.ROLL_OUT, onRollOutHandler);
this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler);
this.addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);
createBtn();
}
//ボタン形状の描画
private function createBtn():void
{
_tf.text = _labelText;
_width = (_width >= _tf.width) ? _width : _tf.width;
backSpDraw();
rollOverSpDraw();
mouseDownDraw();
_tf.x = _width / 2 - _tf.width / 2;
_tf.y = _height / 2 - _tf.height / 2;
this.mouseChildren = false;
this.buttonMode = true;
_rollOverSp.visible = false;
_mouseDownSp.visible = false;
}
//平常時のボタングラフィック
private function backSpDraw():void
{
var _mtx:Matrix = new Matrix();
_mtx.createGradientBox(_width, _height, Math.PI / 2);
_backSp.graphics.beginGradientFill(GradientType.LINEAR,[_color1, _color2, _color1], [1,1,1],[0,126,255],_mtx);
_backSp.graphics.drawRoundRect(0, 0, _width, _height, _roundRadius, _roundRadius);
_backSp.graphics.endFill();
}
//ロールオーバ-したとき時のボタングラフィック
private function rollOverSpDraw():void
{
_rollOverSp.graphics.beginFill(0xFFFFFF, .3);
_rollOverSp.graphics.drawRoundRect(0, 0, _width, _height, _roundRadius, _roundRadius);
_rollOverSp.graphics.endFill();
}
//ボタンを押した時のボタングラフィック
private function mouseDownDraw():void
{
var _mtx:Matrix = new Matrix();
_mtx.createGradientBox(_width, _height, Math.PI / 2);
_mouseDownSp.graphics.beginGradientFill(GradientType.LINEAR,[_color2, _color1, _color2], [1,1,1],[0,126,255],_mtx);
_mouseDownSp.graphics.drawRoundRect(0, 0, _width, _height, _roundRadius, _roundRadius);
_mouseDownSp.graphics.endFill();
}
//MouseEvent.ROLL_OVER時の描画変更
private function onRollOverHandler(e:MouseEvent):void
{
_rollOverSp.visible = true;
}
//MouseEvent.ROLL_OUT時の描画変更
private function onRollOutHandler(e:MouseEvent):void
{
_rollOverSp.visible = false;
_mouseDownSp.visible = false;
}
//MouseEvent.MOUSE_DOWN時の描画変更
private function onMouseDownHandler(e:MouseEvent):void
{
_mouseDownSp.visible = true;
}
//MouseEvent.MOUSE_UP時の描画変更
private function onMouseUpHandler(e:MouseEvent):void
{
_mouseDownSp.visible = false;
}
//getter/setter
public function get labelText():String { return _labelText; }
public function set labelText(value:String):void
{
_labelText = value;
createBtn();
}
public function get id():String { return _id; }
public function set id(value:String):void
{
_id = value;
}
}
class Keyboard extends Sprite
{
private const SINE:String = "sineWave";
private const TRIANGLE:String = "triangleWave";
private const SQUARE_50:String = "square50Wave";
private const SQUARE_25:String = "square25Wave";
private const SQUARE_12_5:String = "square12.5Wave";
private const SAW:String = "sawWave";
private var _waveTypeArray:Array = [SINE,
TRIANGLE,
SQUARE_50,
SQUARE_25,
SQUARE_12_5,
SAW];
private var _waveType:String = SINE;
private var _w:int;
private var _padding:int;
private var _menuIconSp:Sprite;
private var _menuIconFilmSp:Sprite;
private var _keyboardSp:Sprite;
private var _imageSoundWave:ASMovieClip;
private var _keyboardWidth:int;
private var _sound:Sound;
private var _sc:SoundChannel;
private var _baseFreq:Number = 220;
private var _phase:Number = 0;
private var _frequency:Number = 0;
private var _keyDiffX:Number = 0;
private var _PI2:Number = Math.PI * 2;
private var _stf:SoundTransform;
public function Keyboard(w:int, h:int = 30)
{
_w = w;
_padding = 2;
var keyboardNoteNum:int = 25;
var pentaTonic:Array = [1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1];
var g:Graphics = this.graphics;
g.lineStyle(1, 0x666666);
g.beginFill(0);
g.drawRect(0, 0, w, h);
g.endFill();
_menuIconSp = new Sprite();
_menuIconSp.mouseChildren = false;
g = _menuIconSp.graphics;
g.lineStyle(1,0x999999);
g.beginFill(0x0, 1);
g.drawRect(_padding, _padding, h - _padding * 2, h - _padding * 2);
g.endFill();
_menuIconSp.addEventListener(MouseEvent.CLICK, changeWave);
_menuIconSp.addEventListener(MouseEvent.ROLL_OVER, iconRollOverOut);
_menuIconSp.addEventListener(MouseEvent.ROLL_OUT, iconRollOverOut);
this.addChild(_menuIconSp);
_imageSoundWave = new ASMovieClip();
_imageSoundWave.isLoop = true;
_menuIconSp.addChild(_imageSoundWave);
//iconDraw
var len:int = _waveTypeArray.length;
var drawMaxCnt:int = 360;
var cy:Number = h / 2;
var dx:Number = 20 / drawMaxCnt;
for (var i:int = 0; i < len; i++)
{
var sp:Sprite = new Sprite();
sp.graphics.lineStyle(0.25, 0xFFFFFF);
switch (_waveTypeArray[i])
{
case SINE:
var degree:Number = 0;
sp.graphics.moveTo(5, cy);
for (var ii:int = 0; ii < 360; ii++ )
{
degree++;
sp.graphics.lineTo(degree * dx + 5, cy + 10 * Math.sin(degree * Math.PI / 180));
}
break;
case TRIANGLE:
sp.graphics.moveTo(5, cy + 6);
sp.graphics.lineTo(15, cy - 6);
sp.graphics.lineTo(25, cy + 6);
break;
case SQUARE_50:
sp.graphics.moveTo(5, cy + 6);
sp.graphics.lineTo(5, cy - 6);
sp.graphics.lineTo(15, cy - 6);
sp.graphics.lineTo(15, cy + 6);
sp.graphics.lineTo(25, cy + 6);
break;
case SQUARE_25:
sp.graphics.moveTo(5, cy + 6);
sp.graphics.lineTo(5, cy - 6);
sp.graphics.lineTo(10, cy - 6);
sp.graphics.lineTo(10, cy + 6);
sp.graphics.lineTo(25, cy + 6);
break;
case SQUARE_12_5:
sp.graphics.moveTo(5, cy + 6);
sp.graphics.lineTo(5, cy - 6);
sp.graphics.lineTo(7.5, cy - 6);
sp.graphics.lineTo(7.5, cy + 6);
sp.graphics.lineTo(25, cy + 6);
break;
case SAW:
sp.graphics.moveTo(5, cy);
sp.graphics.lineTo(10, cy - 10);
sp.graphics.lineTo(10, cy + 10);
sp.graphics.lineTo(20, cy - 10);
sp.graphics.lineTo(20, cy + 10);
sp.graphics.lineTo(25, cy);
break;
}
sp.graphics.endFill();
_imageSoundWave.addFrame(sp);
}
_menuIconFilmSp = new Sprite();
g = _menuIconFilmSp.graphics;
g.beginFill(0xFFFFFF, .3);
g.drawRect(_padding, _padding, h - _padding * 2, h - _padding * 2);
g.endFill();
_menuIconFilmSp.visible = false;
_menuIconSp.addChild(_menuIconFilmSp);
_keyboardSp = new Sprite();
g = _keyboardSp.graphics;
_keyboardWidth = w - _padding * 2 -_menuIconSp.width - _padding;
var keyboardHeight:int = h - _padding * 2;
_keyDiffX = _keyboardWidth / keyboardNoteNum;
g.beginFill(0);
g.lineStyle(1, 0x999999);
g.drawRect(0, 0, _keyboardWidth, keyboardHeight);
g.lineStyle();
for (i = 0; i < keyboardNoteNum; i++)
{
if (pentaTonic[i] == 1)
{
if (i % 12 == 0)
{
g.beginFill(0x220000);
}
else
{
g.beginFill(0x001100);
}
g.drawRect(_keyDiffX * i, 1, _keyDiffX, keyboardHeight - 2);
}
}
g.endFill();
_keyboardSp.x = _padding + _menuIconSp.width + _padding;
_keyboardSp.y = _padding;
_keyboardSp.addEventListener(MouseEvent.MOUSE_UP, waveStop);
_keyboardSp.addEventListener(MouseEvent.MOUSE_DOWN, waveStart);
_keyboardSp.addEventListener(MouseEvent.ROLL_OUT, waveStop);
//_keyboardSp.addEventListener(MouseEvent.MOUSE_MOVE, waveNoteSearch);
g.beginFill(0, 0);
g.lineStyle(1, 0x999999);
g.drawRect(0, 0, _keyboardWidth, keyboardHeight);
this.addChild(_keyboardSp);
//Sound
_sc = new SoundChannel();
_sound = new Sound();
_sound.addEventListener(SampleDataEvent.SAMPLE_DATA, waveCreate);
_stf = new SoundTransform(.2);
}
private function waveCreate(e:SampleDataEvent):void
{
var smpl:Number;
var w:Number = _PI2 * _frequency / 44100;
var buffer:int = 2048;
var PI:Number = Math.PI;
for (var i:int = 0; i < buffer; i++)
{
switch (_waveType)
{
case SINE:
smpl = Math.sin(_phase);
break;
case TRIANGLE:
smpl = (_phase < PI) ? -2 / PI * _phase + 1 : 2 / PI * _phase - 3;
break;
case SQUARE_50:
smpl = (_phase < PI) ? 1 : -1;
break;
case SQUARE_25:
smpl = (_phase > PI/4 && _phase < PI/2) ? 1 : -1;
break;
case SQUARE_12_5:
smpl = (_phase > PI/8 && _phase < PI/4) ? 1 : -1;
break;
case SAW:
smpl = - _phase / PI + 1;
break;
}
if (smpl >= 1) smpl = 1;
else if (smpl <= -1) smpl = -1;
e.data.writeFloat(smpl);
e.data.writeFloat(smpl);
_phase = (_phase >= _PI2) ? _phase - _PI2 : _phase;
_phase += w;
}
}
private function iconRollOverOut(e:MouseEvent):void
{
_menuIconFilmSp.visible = !_menuIconFilmSp.visible;
}
private function changeWave(e:MouseEvent):void
{
_imageSoundWave.nextFrame();
_waveType = _waveTypeArray[_imageSoundWave.currentFrame - 1];
}
private function waveNoteSearch(e:Event = null):void
{
var posX:Number = mouseX - _keyboardSp.x;
_frequency = _baseFreq * Math.pow(2, Math.floor(posX / _keyDiffX) / 12);
}
private function waveStart(e:MouseEvent):void
{
waveNoteSearch();
if (_waveType == SQUARE_50 || _waveType == SQUARE_25)
{
_stf.volume = .15;
}
else if (_waveType == SQUARE_12_5 || _waveType == SAW)
{
_stf.volume = .20;
}
else
{
_stf.volume = .3;
}
_sc.stop();
_sc = _sound.play(0, 0, _stf);
this.addEventListener(Event.ENTER_FRAME, waveNoteSearch);
}
private function waveStop(e:MouseEvent):void
{
_sc.stop();
this.removeEventListener(Event.ENTER_FRAME, waveNoteSearch);
}
}
class ASMovieClip extends Sprite
{
private const PLAY:String = "play";
private const REVERSE_PLAY:String = "reversePlay";
private var _frames:Array;
private var _frameObject:Sprite;
private var _timer:Timer;
private var _enterFrameDelayTime:int;
private var _playDirectionFlag:String;
private var _startUpFlag:Boolean;
private var _currentFrame:int;
private var _isLoop:Boolean;
public function ASMovieClip()
{
_enterFrameDelayTime = 33;
_timer = new Timer(_enterFrameDelayTime);
_frameObject = new Sprite();
_timer.addEventListener(TimerEvent.TIMER, timerEventHandler);
init();
}
private function init():void
{
if (this.contains(_frameObject)) this.removeChild(_frameObject);
_frames = [];
_frameObject = new Sprite();
_startUpFlag = false;
_currentFrame = 1;
_isLoop = false;
}
//////////////////////////////////////////////////
////////// Public
//////////////////////////////////////////////////
public function addFrame(displayObject:DisplayObject, displayNow:Boolean = false):void
{
_frames.push(displayObject);
if (displayNow || _frames.length == 1)
{
gotoAndStop(_frames.length);
}
}
public function addFrameAt(displayObject:DisplayObject, frameNumber:uint, displayNow:Boolean = false):void
{
if (frameCheck(frameNumber, true))
{
_frames.splice(frameNumber - 1, 0, displayObject);
if (displayNow || _frames.length == 1)
{
gotoAndStop(frameNumber);
}
}
}
public function removeFrameAt(frameNumber:uint):void
{
if (frameCheck(frameNumber))
{
_frames.splice(frameNumber - 1, 1);
if (_frames.length > 0)
{
var position:int = (frameNumber > _frames.length) ? _frames.length : frameNumber;
gotoAndStop(position);
}
else
{
init();
return;
}
}
}
public function removeAllFrames():void
{
init();
}
//Movie系ファンクション
public function gotoAndPlay(frameNumber:uint = 1, enterFrameDelayTime:uint = 33, isLoop:Boolean = false):void
{
_playDirectionFlag = PLAY;
gotoAndStop(frameNumber);
playBaseFunction(frameNumber, enterFrameDelayTime, isLoop);
}
public function gotoAndReversePlay(frameNumber:uint = 1, enterFrameDelayTime:uint = 33, isLoop:Boolean = false):void
{
_playDirectionFlag = REVERSE_PLAY;
gotoAndStop(frameNumber);
playBaseFunction(frameNumber, enterFrameDelayTime, isLoop);
}
public function gotoAndStop(frameNumber:uint):void
{
if (frameCheck(frameNumber))
{
if (this.contains(_frameObject)) this.removeChild(_frameObject);
_frameObject = _frames[frameNumber - 1];
_currentFrame = frameNumber;
this.addChildAt(_frameObject, 0);
if (_startUpFlag) frameMoveEventDispatcher();
_startUpFlag = true;
}
}
public function play(enterFrameDelayTime:uint = 33, isLoop:Boolean = false):void
{
_playDirectionFlag = PLAY;
gotoAndStop(_currentFrame);
playBaseFunction(_currentFrame, enterFrameDelayTime, isLoop);
}
public function stop():void
{
timerStop();
stopEventDispatcher();
}
public function nextFrame():void
{
if (_currentFrame == _frames.length)
{
if (_isLoop)
{
gotoAndStop(1);
loopCompleteEventDispatcher();
}
else
{
timerStop();
stopEventDispatcher();
return;
}
}
else if (_currentFrame < _frames.length)
{
_currentFrame++;
gotoAndStop(_currentFrame);
}
}
public function prevFrame():void
{
if (_currentFrame == 1)
{
if (_isLoop)
{
gotoAndStop(_frames.length - 1);
loopCompleteEventDispatcher();
}
else
{
timerStop();
stopEventDispatcher();
return;
}
}
else if (_currentFrame > 1)
{
_currentFrame--;
gotoAndStop(_currentFrame);
}
}
//////////////////////////////////////////////////
////////// Private
//////////////////////////////////////////////////
private function playBaseFunction(frameNumber:uint, enterFrameDelayTime:uint, isLoop:Boolean):void
{
var isLoop_temp:Boolean = _isLoop; //一時的保存
_isLoop = isLoop;
if (frameCheck(frameNumber))
{
if (loopCheck())
{
_isLoop = isLoop;
_enterFrameDelayTime = enterFrameDelayTime;
_timer.delay = _enterFrameDelayTime;
_timer.start();
playStartEventDispatcher();
}
else
{
_isLoop = isLoop_temp;
return;
}
}
}
private function timerEventHandler(e:TimerEvent):void
{
if (loopCheck())
{
switch (_playDirectionFlag)
{
case PLAY:
if (_isLoop && _currentFrame == _frames.length)
{
gotoAndStop(1);
loopCompleteEventDispatcher();
}
else
{
nextFrame();
}
break;
case REVERSE_PLAY:
if (_isLoop && _currentFrame == 1)
{
gotoAndStop(_frames.length);
loopCompleteEventDispatcher();
}
else
{
prevFrame();
}
break;
default:
timerStop();
throw new Error("再生用のフラグが規定の定数ではありません。");
break;
}
}
else
{
timerStop();
stopEventDispatcher();
}
}
//EventDispatch
private function playStartEventDispatcher():void
{
this.dispatchEvent(new FrameEvent(FrameEvent.PLAY_START));
}
private function frameMoveEventDispatcher():void
{
this.dispatchEvent(new FrameEvent(FrameEvent.FRAME_MOVE));
}
private function loopCompleteEventDispatcher():void
{
this.dispatchEvent(new FrameEvent(FrameEvent.LOOP_COMPLETE));
}
private function stopEventDispatcher():void
{
this.dispatchEvent(new FrameEvent(FrameEvent.STOP));
}
private function timerStop():void
{
if (_timer.running) _timer.stop();
}
private function loopCheck():Boolean
{
//最後のフレームにいるときに、ループしない設定でplayしても意味ない。
//同様に、最初のフレームにいるのに、ループしない設定でreversePlayしても意味ない。
if ((_currentFrame == _frames.length && _playDirectionFlag == PLAY && !isLoop) ||
(_currentFrame == 1 && _playDirectionFlag == REVERSE_PLAY && !isLoop))
{
return false;
}
else
{
return true;
}
}
private function frameCheck(frameNumber:uint, addToArray:Boolean = false):Boolean
{
if (framesEmptyCheck())
{
if (framesFrameNumberLengthCheck(frameNumber,addToArray))
{
return true;
}
}
return false;
}
private function framesEmptyCheck():Boolean
{
if (_frames.length > 0)
{
return true;
}
else
{
throw new Error("シーンの登録数が0です。");
}
}
private function framesFrameNumberLengthCheck(frameNumber:uint, addToArray:Boolean):Boolean
{
frameNumber--;
if (_frames.length > frameNumber || (addToArray && _frames.length >= frameNumber))
{
if (frameNumber + 1 > 0)
{
return true;
}
else
{
throw new Error("フレームは1から始まります。 : \n\t指定されたフレーム : " + frameNumber + ")");
}
}
else
{
throw new Error("指定されたインデックスは範囲外です。\n\t現在登録されているフレーム数 : " + _frames.length + "\n\t指定されたフレーム : " + (frameNumber + 1));
}
}
//getter / setter
public function get currentFrame():int { return _currentFrame; }
public function set currentFrame(index:int):void
{
gotoAndStop(index);
}
public function get isLoop():Boolean { return _isLoop; }
public function set isLoop(value:Boolean):void
{
_isLoop = value;
}
public function get frames():Array { return _frames; }
public function set frames(value:Array):void
{
_frames = value;
}
public function get frameObject():Sprite { return _frameObject; }
public function set frameObject(value:Sprite):void
{
_frameObject = value;
}
public function get enterFrameDelayTime():int { return _enterFrameDelayTime; }
public function set enterFrameDelayTime(value:int):void
{
_enterFrameDelayTime = value;
_timer.delay = _enterFrameDelayTime;
}
}
class FrameEvent extends Event
{
public static const PLAY_START:String = "framePlayStart";
public static const STOP:String = "frameStop";
public static const FRAME_MOVE:String = "frameMove";
public static const LOOP_COMPLETE:String = "frameLooComplete";
public function FrameEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false)
{
super(type, bubbles, cancelable);
}
}