Tweet + forked from: SiON Tenorion
SiON TENORION
/**
* Copyright bkzen ( http://wonderfl.net/user/bkzen )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/hEMO
*/
// forked from keim_at_Si's SiON Tenorion
// SiON TENORION
package {
import com.bit101.components.Label;
import com.bit101.components.Panel;
import com.bit101.components.PushButton;
import com.bit101.components.Window;
import flash.display.Sprite;
import flash.events.*;
import flash.net.navigateToURL;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.utils.escapeMultiByte;
import org.si.sion.*;
import org.si.sion.events.*;
import org.si.sion.sequencer.SiMMLTrack;
import org.si.sion.utils.SiONPresetVoice;
/**
* いい音ができたら友達に Twitter で知らせる機能つけた。
* デバッグプレイヤーのみ対応。
*/
[SWF(width = "465", height = "465", backgroundColor = "#ffffff", frameRate = 30)]
public class Tenorion extends Sprite {
// driver
public var driver:SiONDriver = new SiONDriver();
// preset voice
public var presetVoice:SiONPresetVoice = new SiONPresetVoice();
// voices, notes and tracks
public var tracks:Vector.<SiMMLTrack> = new Vector.<SiMMLTrack>(16);
public var voices:Vector.<int> = Vector.<int>([ 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]);
public var notes:Vector.<int> = Vector.<int>([36,48,60,72, 43,48,55,60, 65,67,70,72, 77,79,82,84]);
// beat counter
public var beatCounter:int;
// control pad
public var matrixPad:MatrixPad;
private var bit:Bit;
private var label:Label;
private var panel:Panel;
private var cnt: uint;
private var waitCnt: uint;
private var sendBtn:PushButton;
// constructor
function Tenorion() {
driver.setVoice(0, presetVoice["valsound.percus1"]); // bass drum
driver.setVoice(1, presetVoice["valsound.percus28"]); // snare drum
driver.setVoice(2, presetVoice["valsound.percus17"]); // close hihat
driver.setVoice(3, presetVoice["valsound.percus23"]); // open hihat
driver.setVoice(4, presetVoice["valsound.bass18"]);
// listen click
driver.setTimerInterruption(1, _onTimerInterruption);
driver.setBeatCallbackInterval(1);
driver.addEventListener(SiONTrackEvent.BEAT, _onBeat);
driver.addEventListener(SiONEvent.STREAM_START, _onStreamStart);
// control pad
matrixPad = new MatrixPad(stage);
matrixPad.x = 72;
matrixPad.y = 72;
addChild(matrixPad);
// start streaming
driver.play();
var btn: PushButton = new PushButton(this);
btn.label = "Tweet";
btn.x = (465 - btn.width) / 2;
btn.y = 465 - btn.height;
btn.buttonMode = true;
btn.addEventListener(MouseEvent.CLICK, onClick);
bit = new Bit("http://wonderfl.net/c/hEMO"); // めんどくさくて手打ち
bit.addEventListener(Event.COMPLETE, onBitComp);
bit.addEventListener(IOErrorEvent.IO_ERROR, onBitIOError);
panel = new Panel(this);
panel.width = panel.height = 465;
panel.visible = false;
panel.alpha = 0.5;
label = new Label(this);
label.scaleX = label.scaleY = 3;
label.visible = false;
sendBtn = new PushButton(this);
sendBtn.label = "send";
sendBtn.buttonMode = true;
sendBtn.x = (465 - btn.width) / 2;
sendBtn.y = (465 - btn.height) / 2;
sendBtn.visible = false;
sendBtn.addEventListener(MouseEvent.CLICK, onClickSend);
if (WQuery.available)
{
var q: String = WQuery.getQuery("seq");
if (q == "") return;
var qs: Array = q.split("_");
for (var i:int = 0; i < qs.length; i++)
{
matrixPad.add(i, parseInt(qs[i], 36));
}
}
}
private function onBitIOError(e: IOErrorEvent ): void
{
label.text = "ERROR...";
waitCnt = cnt + 90;
}
private function onBitComp(e: Event): void
{
label.text = "COMPLETE!!";
waitCnt = cnt + 90;
}
private function onClick(e: MouseEvent ): void
{
var seq: Vector.<int> = matrixPad.sequences;
var n: int = seq.length;
var query: String = "?seq=";
for (var i:int = 0; i < n; i++)
{
query += seq[i].toString(36);
if (i < n - 1) query += "_";
}
waitCnt = uint(-1);
label.text = "NOW COMPRESSING...";
panel.visible = label.visible = true;
matrixPad.enabled = false;
bit.getURL(query);
addEventListener(Event.ENTER_FRAME, loop);
}
private function loop(e: Event ): void
{
label.x = (465 - label.width * label.scaleX) / 2;
label.y = (465 - label.height * label.scaleY) / 2;
label.alpha = (cnt % 8);
cnt ++;
if (waitCnt < cnt)
{
removeEventListener(Event.ENTER_FRAME, loop);
label.visible = false;
cnt = 0;
if (bit.result == "")
{
panel.visible = false;
matrixPad.enabled = true;
}
else
{
sendBtn.visible = true;
}
}
}
private function onClickSend(e: MouseEvent ): void
{
sendBtn.visible = panel.visible = false;
matrixPad.enabled = true;
var url: String = "http://twitter.com/home/?status=" + escapeMultiByte("いい音できた。") + bit.result;
navigateToURL(new URLRequest(url), "_blank");
}
// _onStreamStart (SiONEvent.STREAM_START) is called back first of all after SiONDriver.play().
private function _onStreamStart(e:SiONEvent) : void
{
// create new controlable tracks and set voice
for (var i:int=0; i<16; i++) {
tracks[i] = driver.sequencer.newControlableTrack();
tracks[i].setChannelModuleType(6, 0, voices[i]);
tracks[i].velocity = 64;
}
beatCounter = 0;
}
// _onBeat (SiONTrackEvent.BEAT) is called back in each beat at the sound timing.
private function _onBeat(e:SiONTrackEvent) : void
{
matrixPad.beat(e.eventTriggerID & 15);
}
// _onTimerInterruption (SiONDriver.setTimerInterruption) is called back in each beat at the buffering timing.
private function _onTimerInterruption() : void
{
var beatIndex:int = beatCounter & 15;
for (var i:int=0; i<16; i++) {
if (matrixPad.sequences[i] & (1<<beatIndex)) tracks[i].keyOn(notes[i]);
}
beatCounter++;
}
}
}
import flash.display.*;
import flash.events.*;
import flash.geom.*;
class MatrixPad extends Bitmap {
public var sequences:Vector.<int> = new Vector.<int>(16);
private var canvas:Shape = new Shape();
private var buffer:BitmapData = new BitmapData(320, 320, true, 0);
private var padOn:BitmapData = _pad(0x303050, 0x6060a0);
private var padOff:BitmapData = _pad(0x303050, 0x202040);
private var pt:Point = new Point();
private var colt:ColorTransform = new ColorTransform(1,1,1,0.1)
private var _enabled: Boolean = true;
function MatrixPad(stage:Stage) {
super(new BitmapData(320, 320, false, 0));
var i:int;
for (i=0; i<256; i++) {
pt.x = (i&15)*20;
pt.y = (i&240)*1.25;
buffer.copyPixels(padOff, padOff.rect, pt);
bitmapData.copyPixels(padOff, padOff.rect, pt);
}
for (i=0; i<16; i++) sequences[i] = 0;
addEventListener("enterFrame", _onEnterFrame);
stage.addEventListener("click", _onClick);
}
public function add(track: int, value: uint): void
{
for (var i:int = 0; i < 16; i++)
{
if (value >> i & 1)
{
pt.x = i * 20;
pt.y = (15 - track) * 20;
buffer.copyPixels(padOn, padOn.rect, pt);
}
}
trace(value);
sequences[track] = value;
}
private function _pad(border:int, face:int) : BitmapData {
var pix:BitmapData = new BitmapData(20, 20, false, 0);
canvas.graphics.clear();
canvas.graphics.lineStyle(1, border);
canvas.graphics.beginFill(face);
canvas.graphics.drawRect(1, 1, 17, 17);
canvas.graphics.endFill();
pix.draw(canvas);
return pix;
}
private function _onEnterFrame(e:Event) : void {
bitmapData.draw(buffer, null, colt);
}
private function _onClick(e:Event) : void
{
if (!_enabled) return;
if (mouseX>=0 && mouseX<320 && mouseY>=0 && mouseY<320) {
var track:int = 15-int(mouseY*0.05), beat:int = int(mouseX*0.05);
sequences[track] ^= 1<<beat;
pt.x = beat*20;
pt.y = (15-track)*20;
if (sequences[track] & (1<<beat)) buffer.copyPixels(padOn, padOn.rect, pt);
else buffer.copyPixels(padOff, padOff.rect, pt);
}
}
public function set enabled(value: Boolean): void
{
_enabled = value;
}
public function beat(beat16th:int) : void {
for (pt.x=beat16th*20, pt.y=0; pt.y<320; pt.y+=20) bitmapData.copyPixels(padOn, padOn.rect, pt);
}
}
/**
* URL 圧縮するやつ。
*/
class Bit extends EventDispatcher
{
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
private const BASE: String = "http://api.bit.ly/shorten?version=2.0.1&apiKey=R_608e24fd300e458016ef6ea805c6ecd6&login=bkwon&format=xml&longUrl=";
private var loader:URLLoader;
private var _result: String = "";
private var wonderflUrl: String;
public function Bit(wonderflURL: String)
{
wonderflUrl = wonderflURL;
loader = new URLLoader();
loader.addEventListener(Event.COMPLETE, comp);
loader.addEventListener(IOErrorEvent.IO_ERROR, ioerror);
}
public function getURL(query: String): void
{
var url: String = BASE + wonderflUrl + query;
_result = "";
loader.load(new URLRequest(url));
}
private function ioerror(e: IOErrorEvent ): void
{
dispatchEvent(e.clone());
}
private function comp(e: Event ): void
{
var res: XML = new XML(loader.data);
_result = res.results.nodeKeyVal.shortUrl;
dispatchEvent(e.clone());
}
public function get result(): String { return _result; }
}
/**
* 無理やり URL を取得する。(デバッグプレイヤーオンリー)
* http://wonderfl.net/code/854d4b5fed8c905e98aee6da935a496d79ea6213
*/
class WQuery
{
import flash.external.ExternalInterface;
import flash.system.Capabilities;
private static var _qString: String = "///";
public static function get available(): Boolean { return ExternalInterface.available && Capabilities.isDebugger; }
public static function getQuery(key: String): String
{
if (qString == "" ) return "";
var s: int = _qString.indexOf(key + "=");
if (s < 0) return "";
var e: int = _qString.indexOf("&", s);
if (e < 0) e = _qString.length;
return _qString.substring(s + key.length + 1, e);
}
public static function get qString():String
{
if (!available) return "";
try
{
if (_qString == "///") _qString = ExternalInterface.call("function() { return window.location.search; }");
}
catch (error: Error)
{
if (error.errorID == 2060)
{
var msg: String = error.message;
msg = msg.split(" は ").pop().split(" ").shift();
if (msg.indexOf("?") < 0) _qString = "";
else _qString = msg.substr(msg.indexOf("?"));
}
}
return _qString;
}
}