電子楽器を自分で作れる「Ototo」

October 30, 2015

Ototoは、野菜や飲み物・金属の食器などを繋いで、電子楽器を簡単に作ることができるデバイスです。
http://www.ototo.fm

image-1760

入手方法

こちらの公式通販ショップから購入できます。注文してから1週間くらいで届きました。
>>オンラインショップ

オープンセサミ

外箱を開けるとこんな可愛らしい箱が。わくわくしてきます。

image-1759
image-1758
image-1757
image-1756

中身は、本体ボード1つ・ワニ口クリップたくさん・説明書1冊。

使ってみる

説明書をめくると、最初の使い方が書いてあります。単三電池2個をボードにセットし、右側の電源スイッチをON(目のアイコンがパチッと開いている方)にします。ボード手前のセンサー部分を触ると、中央のスピーカーから音が鳴ります。じゃじゃーん!

image-1755
image-1754

次に付属のワニ口クリップを使って、センサーと電気を通す物(しめじなど)を繋ぎます。スピーカー横の2つのボタンを同時押しすると、リセットがかかってチューニングされます。繋いだ物を触ると音が鳴ります。鳴らない場合は、電池を交換するかUSBケーブルを繋いでみてください。

こんな感じで、食べ物や液体、金属の食器など電気を通す物を鍵盤として使うことができました。簡単で楽しいです。

>>Processing.org

ProcessingでMidiを使うには、「MidiBus」というライブラリを使います。

Processingのメニューから、スケッチ - ライブラリのインポート - ライブラリの追加 を選択します。ライブラリ導入のウィンドウが開くので、検索窓に「midi」と入れると、「the MidiBus」という項目が表示されます。これを選択して右下のInstallボタンを押すと、ダウンロード・インストールが実行されます。

image-1753

使い方で注意するところは、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);
  }
}

Related Article