Ototoは、野菜や飲み物・金属の食器などを繋いで、電子楽器を簡単に作ることができるデバイスです。
http://www.ototo.fm
入手方法
こちらの公式通販ショップから購入できます。注文してから1週間くらいで届きました。
>>オンラインショップ
オープンセサミ
外箱を開けるとこんな可愛らしい箱が。わくわくしてきます。
中身は、本体ボード1つ・ワニ口クリップたくさん・説明書1冊。
使ってみる
説明書をめくると、最初の使い方が書いてあります。単三電池2個をボードにセットし、右側の電源スイッチをON(目のアイコンがパチッと開いている方)にします。ボード手前のセンサー部分を触ると、中央のスピーカーから音が鳴ります。じゃじゃーん!
次に付属のワニ口クリップを使って、センサーと電気を通す物(しめじなど)を繋ぎます。スピーカー横の2つのボタンを同時押しすると、リセットがかかってチューニングされます。繋いだ物を触ると音が鳴ります。鳴らない場合は、電池を交換するかUSBケーブルを繋いでみてください。
こんな感じで、食べ物や液体、金属の食器など電気を通す物を鍵盤として使うことができました。簡単で楽しいです。
>>Processing.orgProcessingでMidiを使うには、「MidiBus」というライブラリを使います。
Processingのメニューから、スケッチ - ライブラリのインポート - ライブラリの追加 を選択します。ライブラリ導入のウィンドウが開くので、検索窓に「midi」と入れると、「the MidiBus」という項目が表示されます。これを選択して右下のInstallボタンを押すと、ダウンロード・インストールが実行されます。
使い方で注意するところは、MidiBusオブジェクトを実体化する時に、入出力のMIDI機器を名前で指定する必要があります。Ototoの場合は"Unknown name"と指定します。他のデバイスと重複した場合にどうなるかは不明。今回は出力機器を使わないので、3つ目のパラメータは-1としています。
noteOn()で押された瞬間、noteOff()で離された瞬間を取得できます。パラメータとして渡される「pitch」で押された鍵盤を判断しています。
import themidibus.*; //Import the libraryMidiBus myBus; // The MidiBusfloat spring = 0.05;float gravity = 0.1;float friction = -0.9;int id = 0;ArrayList balls = new ArrayList();void setup() { //fullScreen(); size(displayWidth, displayHeight ); noStroke(); MidiBus.list(); myBus = new MidiBus(this, "Unknown name", -1 ); //ototo is "Unknown name"}void draw() { background(0); int numBalls = balls.size(); for (int i = 0; i < numBalls; i++) { balls.get(i).collide(); balls.get(i).move(); balls.get(i).display(); }}void addBall(float _x, float _y, color _color) { Ball b = new Ball( _x, _y, random(100, 200), 0, balls, _color ); balls.add( b );}// MIDI Event --------------------------------------void noteOn(int channel, int pitch, int velocity) { // Receive a noteOn println(); println("Note On:"); println("--------"); println("Channel:"+channel); println("Pitch:"+pitch); println("Velocity:"+velocity); switch( pitch ) { case 61 : addBall( random(width), 0, color( 127, 127, 127 ) ); break; case 63 : addBall( random(width), 0, color( 255, 255, 0 )); break; case 66 : addBall( random(width), 0, color( 255, 127, 0 )); break; case 68 : addBall( random(width), 0, color( 255, 255, 255 )); break; case 70 : addBall( random(width), 0, color( 0, 255, 0 )); break; }}void noteOff(int channel, int pitch, int velocity) { // Receive a noteOff println(); println("Note Off:"); println("--------"); println("Channel:"+channel); println("Pitch:"+pitch); println("Velocity:"+velocity);}void controllerChange(int channel, int number, int value) { // Receive a controllerChange println(); println("Controller Change:"); println("--------"); println("Channel:"+channel); println("Number:"+number); println("Value:"+value);}class Ball { float x, y; float diameter; float vx = 0; float vy = 0; int id; ArrayList others; color ballColor; Ball(float xin, float yin, float din, int idin, ArrayList oin, color _color ) { x = xin; y = yin; diameter = din; id = idin; others = oin; ballColor = _color; id++; } void collide() { int numBalls = balls.size(); for (int i = id + 1; i < numBalls; i++) { float dx = others.get(i).x - x; float dy = others.get(i).y - y; float distance = sqrt(dx*dx + dy*dy); float minDist = others.get(i).diameter/2 + diameter/2; if (distance < minDist) { float angle = atan2(dy, dx); float targetX = x + cos(angle) * minDist; float targetY = y + sin(angle) * minDist; float ax = (targetX - others.get(i).x) * spring; float ay = (targetY - others.get(i).y) * spring; vx -= ax; vy -= ay; others.get(i).vx += ax; others.get(i).vy += ay; } } } void move() { vy += gravity; x += vx; y += vy; if (x + diameter/2 > width) { x = width - diameter/2; vx *= friction; } else if (x - diameter/2 < 0) { x = diameter/2; vx *= friction; } if (y + diameter/2 > height) { y = height - diameter/2; vy *= friction; } else if (y - diameter/2 < 0) { y = diameter/2; vy *= friction; } } void display() { fill( ballColor ); ellipse(x, y, diameter, diameter); } }