Prototyping Lab: Recipe 27.3
/**
* Copyright kotobuki ( http://wonderfl.net/user/kotobuki )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/7l3D
*/
package {
import flash.display.Sprite;
import flash.text.TextField;
import funnel.*;
import org.si.sion.SiONDriver;
public class PatternMatching extends Sprite {
// オカリナの穴の代わりのスイッチの状態とデジタル入力の状態の対応
private static const CLOSED:int = 1;
private static const OPENED:int = 0;
// 指使いとパターンの対応表
private static const FINGERING_TABLE:Array = new Array();
FINGERING_TABLE[0] = [CLOSED, CLOSED, CLOSED, CLOSED];
FINGERING_TABLE[1] = [CLOSED, OPENED, CLOSED, CLOSED];
FINGERING_TABLE[2] = [CLOSED, CLOSED, CLOSED, OPENED];
FINGERING_TABLE[3] = [CLOSED, OPENED, CLOSED, CLOSED];
FINGERING_TABLE[4] = [OPENED, OPENED, CLOSED, CLOSED];
FINGERING_TABLE[5] = [OPENED, OPENED, CLOSED, OPENED];
FINGERING_TABLE[6] = [OPENED, CLOSED, OPENED, OPENED];
FINGERING_TABLE[7] = [OPENED, OPENED, OPENED, OPENED];
// パターンが見つからなかった時を表す値
private static const NOT_FOUND:int = -1;
// パターンとノート番号の対応
private static const NOTE_NUMBER:Array
= [60, 62, 64, 65, 67, 69, 71, 72];
// パターンと音名を表す文字列の対応
private static const NOTE_NAME:Array
= ["C4", "D4", "E4", "F4", "G4", "A4", "B4", "C5"];
// Arduino
private var arduino:Arduino;
// 各タクトスイッチに接続したピン
private var button0Pin:Pin;
private var button1Pin:Pin;
private var button2Pin:Pin;
private var button3Pin:Pin;
// 感圧センサに接続したアナログピン
private var sensorPin:Pin;
// 現在のタクトスイッチの状態を収める配列
private var buttonState:Array
= [OPENED, OPENED, OPENED, OPENED];
// 現在選択されているパターン
private var index:int = 7;
// SiONドライバ
private var driver:SiONDriver;
// 状態やキャリブレーション結果を表示するためのテキストフィールド
private var textField:TextField;
public function PatternMatching() {
// タクトスイッチに接続したピンのモードを入力にセット
var config:Configuration = Arduino.FIRMATA;
config.setDigitalPinMode(2, IN);
config.setDigitalPinMode(3, IN);
config.setDigitalPinMode(4, IN);
config.setDigitalPinMode(5, IN);
arduino = new Arduino(config);
// 各タクトスイッチを表す変数を初期化
button0Pin = arduino.digitalPin(2);
button1Pin = arduino.digitalPin(3);
button2Pin = arduino.digitalPin(4);
button3Pin = arduino.digitalPin(5);
// 各タクトスイッチに接続したピンにイベントリスナをセット
button0Pin.addEventListener(PinEvent.CHANGE,
onButtonPinChange);
button1Pin.addEventListener(PinEvent.CHANGE,
onButtonPinChange);
button2Pin.addEventListener(PinEvent.CHANGE,
onButtonPinChange);
button3Pin.addEventListener(PinEvent.CHANGE,
onButtonPinChange);
// 感圧センサに接続したピンの変数を初期化してフィルタとリスナをセット
sensorPin = arduino.analogPin(0);
sensorPin.addFilter(new SetPoint([0.2, 0.05]));
sensorPin.addEventListener(PinEvent.CHANGE,
onSensorPinChange);
// テキストフィールドを生成してセット
textField = new TextField();
addChild(textField);
// SiONドライバのインスタンスを生成して音声ストリーミングを開始
driver = new SiONDriver();
driver.play();
}
// 各タクトスイッチに接続したピンで変化が起きたら
private function onButtonPinChange(e:PinEvent):void {
// イベントが発生したピンの番号からスイッチのインデックスを求め、値を更新
var buttonIndex:int
= e.target.number - button0Pin.number;
buttonState[buttonIndex]
= (e.target.value == 0) ? OPENED : CLOSED;
// 現在のスイッチの状態に対応したパターンを検索
index = findPattern(buttonState);
// 検索結果をテキストフィールドに表示
textField.text = "Note: ";
if (index != NOT_FOUND) {
// パターンが見つかっていたら対応する音名を表示
textField.appendText(NOTE_NAME[index]);
} else {
// 見つかっていなければNot Foundを表示
textField.appendText("Not found");
}
}
// 感圧センサに接続したピンで変化が起きたら
private function onSensorPinChange(e:PinEvent):void {
// 感圧センサが押されたら
if (e.target.value == 1) {
// パターンが見つかっていたら
if (index != NOT_FOUND) {
// パターンに対応したノート番号で発音
driver.noteOn(NOTE_NUMBER[index]);
}
} else {
// そうでなければ発音を停止
driver.noteOff(-1);
}
}
// パターンを検索
private function findPattern(pattern:Array):int {
// 指使いのテーブルと与えられたパターンを順次比較
for (var i:int = 0; i < FINGERING_TABLE.length; i++) {
// 一致するパターンが見つかったら
if (pattern.join() == FINGERING_TABLE[i].join()) {
// 現在のインデックスを返す
return i;
}
}
// 最後まで見つからなかったらNOT_FOUNDを返す
return NOT_FOUND;
}
}
}