WebCamでtenorionぽくSiON鳴らす
SiONのソースの大部分は
http://wonderfl.net/c/qf4b
を参考にさせてもらってます。
※音量注意
/**
* Copyright mrhdms ( http://wonderfl.net/user/mrhdms )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/t6hp
*/
package
{
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.media.*;
import org.si.sion.events.SiONTrackEvent;
/**
* webCamでSiON鳴らす
* @author mrhdms
*/
public class Main extends Sprite
{
private var _camera:Camera;
private var _video:Video;
private var _canvas:BitmapData;
private var _rect:Rectangle;
private var _movieSize:uint = 350;
private var _col:uint = 16;//分割列数
private var _raw:uint = 16;//分割行数
private var _sc:SoundControll;
private var _sequences:Vector.<int> = new Vector.<int>(16);
private var _drawScale:Number = 1/4;//解析用画像の縮小率
private var _capMat:Matrix;
private var _circles:Circles;
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);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
//カメラの設定
try
{
_camera = Camera.getCamera();
_video = new Video(_movieSize, _movieSize);
_camera.setMode(_movieSize, _movieSize, 30);
_video.attachCamera(_camera);
}
catch (err:Error)
{
throw new Error("カメラ取得失敗");
}
//ビデオの反転(内向きカメラ用)
var mat:Matrix = new Matrix();
mat.scale( -1, 1);
mat.translate(_video.width, 0);
_video.transform.matrix = mat;
//キャプチャ用Matrix
_capMat = new Matrix();
_capMat.scale( -_drawScale, _drawScale);
_capMat.translate(_video.width * _drawScale, 0);
//書き込み用キャンバス
_canvas = new BitmapData(_camera.width*_drawScale, _camera.height*_drawScale, false, 0x000000);
var bmp:Bitmap = new Bitmap(_canvas);
//bmp.scaleX = bmp.scaleY = 2;
bmp.x = _movieSize;
//グラフィック表示
_circles = new Circles(_movieSize, _movieSize, _col, _raw);
//Sion制御
_sc = new SoundControll();
addChild(bmp);
addChild(_video);
addChild(_circles);
_sc.driver.addEventListener(SiONTrackEvent.BEAT, _onBeat);
_sc.driver.setTimerInterruption(1, _onTimerInterruption);
_sc.driver.play(null,false);
//var status:Stats = new Stats();
//addChild(status);
}
private function _onTimerInterruption():void
{
_canvas.lock();
_canvas.draw(_video,_capMat);
_canvas.threshold(_canvas, new Rectangle(0, 0, _canvas.width, _canvas.height), new Point(0, 0), "<", 0xFF888888);
_canvas.threshold(_canvas, new Rectangle(0, 0, _canvas.width, _canvas.height), new Point(0, 0), ">", 0xFF888888, 0xFFFFFFFF);
_canvas.unlock();
var beatIndex:uint = _sc.beatCounter & 15;
var cx:int = beatIndex * _canvas.width / _col;
cx += _canvas.width / _col / 2;
for (var i:int = 0; i < _raw; i++)
{
var cy:int = i * _canvas.height / _raw;
cy += _canvas.height / _raw / 2;
checkRGB(_canvas.getPixel(cx, cy),15-i,beatIndex);
if (_sequences[i] & (1 << beatIndex))
{
_sc.driver.noteOn(_sc.notes[i], _sc.voices[i], _sc.length[i]);
}
}
_sc.beatCounter++;
}
private function _onBeat(e:SiONTrackEvent):void
{
var beatIndex:uint = e.eventTriggerID & 15;
for (var i:int = 0; i < _raw; i++)
{
if (_sequences[i] & (1 << beatIndex))
{
_circles.move(beatIndex,15-i);
}
}
}
private function checkRGB(pixel:uint,track:uint,beat:uint):void
{
if (pixel > 0) { //2値化後の画像の白に反応
if (_sequences[track] & (1 << beat))
{
} else {
_sequences[track] ^= 1 << beat;
}
} else {
if (_sequences[track] & (1 << beat))
{
_sequences[track] ^= 1 << beat;
}
}
}
}
}
import org.si.sion.effector.SiEffectStereoReverb;
import org.si.sion.SiONDriver;
import org.si.sion.SiONVoice;
import org.si.sion.utils.SiONPresetVoice;
/**
* SiONを使って音鳴らすクラス
* ソースの大部分はSion Tenorion
* @see http://wonderfl.net/c/qf4b
*/
class SoundControll
{
// driver
public var driver:SiONDriver = new SiONDriver();
// preset voice
public var presetVoice:SiONPresetVoice = new SiONPresetVoice();
// voices, notes and tracks
public var voices:Vector.<SiONVoice> = new Vector.<SiONVoice>(16);
//public var notes :Vector.<int> = Vector.<int>([36,48,60,72, 43,48,55,60, 65,67,70,72, 77,79,82,84]);
public var notes :Vector.<int> = Vector.<int>([48,50,52,55, 60,62,64,67, 72,74,76,79, 84,86,88,91]);
public var length:Vector.<int> = Vector.<int>([ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
// beat counter
public var beatCounter:int;
public function SoundControll()
{
var i:int;
// set voices from preset
var percusVoices:Array = presetVoice["valsound.percus"];
voices[0] = percusVoices[0]; // bass drum
voices[1] = percusVoices[27]; // snare drum
voices[2] = percusVoices[16]; // close hihat
voices[3] = percusVoices[22]; // open hihat
//for (i=4; i<8; i++) voices[i] = presetVoice["valsound.bass18"]; // bass
for (i=4; i<16; i++) voices[i] = presetVoice["valsound.wind1"];
var reverb:SiEffectStereoReverb = new SiEffectStereoReverb(0.8,0.4,0.6,0.5);
driver.setBeatCallbackInterval();
driver.bpm = 80;
driver.volume = 0.5;
driver.effector.slot0 = [reverb];
beatCounter = 0;
}
}
import flash.display.BlendMode;
import flash.display.DisplayObject;
import flash.display.Sprite;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.tweens.ITween;
/**
* 丸を描く
* @author Hidemasa Mori
*/
class Circles extends Sprite
{
private var _circleAry:Array = new Array();
/**
* コンストラクタ
* @param capW 表示領域の幅
* @param capH 表示領域の高さ
* @param col 分割列数
* @param raw 分割行数
*/
public function Circles(capW:Number,capH:Number,col:uint,raw:uint)
{
for (var i:int = 0; i < raw; i++)
{
var cx:Number = capW / col * i;
for (var j:int = 0; j < col; j++)
{
var cy:Number = capH / raw * j;
var sp:Sprite = new Sprite();
sp.graphics.beginFill(0, 0);
sp.graphics.lineStyle(4, 0x666666);
sp.graphics.drawCircle( -8, -8, 16);
sp.graphics.endFill();
sp.blendMode = BlendMode.ADD;
sp.scaleX = sp.scaleY = 0;
sp.x = cx + capW / col / 2;
sp.y = cy + capH / raw / 2;
sp.visible = false;
if (_circleAry[i]) {
_circleAry[i][j] = sp;
} else {
_circleAry[i] = new Array();
_circleAry[i][j] = sp;
}
addChild(sp);
}
}
}
public function move(xIndex:int, yIndex:uint):void
{
var target:DisplayObject = _circleAry[xIndex][yIndex];
if (target)
{
target.visible = true;
target.alpha = 1;
var it:ITween = BetweenAS3.tween(target, { scaleX:1, scaleY:1, alpha:0 }, null, 0.5 );
it.onComplete = function():void { target.visible = false;target.scaleX = target.scaleY = 0 }
it.play();
}
}
}