« Van Damme - Zero Gravity Split | ホーム | 新ゴジラにホワイト先生が出てる! »

March 19, 2014

オンド・マルトノMIDIコントローラの制作(3)Ondes Martenot MIDI controller project (3)








注:このエントリ、以前(2012年)のものを修正してたら間違って新規アップになってしまいました。消すのもアレなのでそのまま置いておきます。すみません〜。以前のものはこちらへ>/ 1 / 2 / 3 /



今年の5月から7月にかけて、幻のフランス製電子楽器『オンド・マルトノ』の発想をベースに『オンド・マルトノMIDIコントローラ』を制作した。その過程について3回に分けて記録する。最終回は組み立て後の仕上げ・プログラミング作業と今後の展開について。Arduinoスケッチも公開します。


完成したオンド・マルトノMIDIコントローラの試奏ビデオ


最近出たMiniNovaが気になってます。

Novation UltraNova
Novation UltraNova
posted with amazlet at 12.09.02
Novation
売り上げランキング: 9452

2の続き)

やっとテストベッドがカタチになったのだが、音を出す前にすべき事はまだまだある。

まずは音程をコントロールするために、リング位置に応じたピッチベンド数値を出力する計算式が必要だ。最初にArduinoがリング位置をどのように認識しているかを確かめてみる。準備としてArduinoアプリの『ファイル/スケッチの例/01.Basics/』にある『AnalogReadSerialスケッチ』を使用し、Arduinoと精密ポテンショメータを接続、読み込んだ数値をシリアルモニタ上に表示させておく。次に真鍮製の小さな釘を半音部分に打ち込んだ『音程ボード』をテストベッド上に仮固定し、リングに人差し指を入れ、一番低い『ド』の位置まで指先を左にスライドさせる。シリアルモニタ上に表示された数値は『335(精密ポテンショメータの位置によって異なる)』。次に指先を3オクターブ分右にスライドし、一番高い『ド』の位置まで移動させる。このときの数値は『804』。この結果、3オクターブの数値の差は『469』となった。この数字を用いて計算式を作成する。(注:Arduinoは電源の状態によってアナログ読み込み数値に差が生じる。上記の値はUSB給電の場合であり、電源の電圧などにより数値が変わってくるので注意。またMIDIのピッチベンドは本来『16383』というかなり細かい解像度でコントロールできるのだが、Arduinoから得られる精密ポテンショメータの分解能は1024しかない。ただし469を3オクターブ分の音数36で割ると半音あたりの解像度は『約13』となり、聴覚上段差を感じる事はほぼ無いと予測される。本当はあと数倍の解像度が欲しいところなのだが。)

音程ボードとリングのディテール。上の鍵盤は原寸大のカラーコピー。
IMG 4096

ここまでの文章でお気づきの方もいるだろうが、このオンド・マルトノMIDIコントローラ、要は大きなピッチベンドホイールである。ノートのオンオフMIDI情報はシンセサイザーの『特定の高さのキー』をオンオフするだけで、音程は全てピッチベンドの数値で決まってくる。たとえばリングに通した指先が『特定の高さのキー』の位置にある時は、ピッチベンド数値はゼロである。その位置から指先を右に動かすと数値がプラス方向に拡大し、音程が上がっていく。左に動かせば数値が徐々にマイナスとなり、音程が下がる。この変化は一定で直線的なので、計算式は単純だ。今回のテストベッドでは3オクターブ幅のうち『左端から2つめのド』を『特定の高さのキー』と設定し、ピッチベンド数値がゼロになる位置として計算式を作成した。

x=(y-z)/0.03815

x=求めるべきピッチベンド量
y=精密ポテンショメータの現在の数値
z=『左端から2つ目のド』位置の精密ポテンショメータの数値
0.03815≒(469/3*4)/16383 精密ポテンショメータ数値とピッチベンド数値の比例定数

数式のための計算メモ

計算式

ところで上の式を用いて4オクターブをコントロールするためには、使用するソフトシンセのピッチベンド幅が±24であることが必要である。この幅を備えているソフトシンセの中から、私はKORG Legacy CollectionのMono/Polyを選択した。高校時代にMono/Polyの実機を所有していた事が選択の理由だが、ピッチベンド幅を±24に設定できるシンセサイザーであれば何でも構わない。

KORG Mono/Poly
スクリーンショット 2012 09 02 10 34 04

音程コントロールのための計算式は完成した。次は音量コントロール部分の作業を進めよう。組み上げたテストベッドには暫定的にスライドボリュームを取り付けていたが、エア演奏から迅速な音量コントロールが出来ない事が判明したため、オリジナルオンド・マルトノのトゥッシュ部分の様に指の圧力でコントロールする仕様に変更した。マイクロスイッチに前述小型圧力センサを接着し、マイクロスイッチでノートのオンオフを、指先にかける圧力の大小で音量をコントロールする事にした。こちらも先ほど使用した『AnalogReadSerialスケッチ』を使って圧力センサからの数値を読み込み、簡単な数式を作成した。

トウッシュ部分アップ
IMG 4344

ここまでの計算式などを元にして初期のスケッチが完成、YAMAHA USB-MIDIインターフェース UX-16を通じてソフトシンセに接続し動作をテストしてみた。すると…音が…鳴った! 音程ボードに合わせて気持ちよく演奏ができる!しかもレーザーテルミンの時のような音程の誤差が無い!(1参照)ビブラートもリアルタイムでばっちり!念願の、楽器として演奏できるレベルである。単に計算した通りに動いただけなのだが、私はすっかり感動してしまった。この『実働した』という瞬間が電子工作の一番の醍醐味である。

しかしMake:の世界は甘くなく、すぐに新たな問題が出現した。しばらく演奏しているとチューニングがズレてくるのだ。原因はタコ糸の『滑り』である。演奏中にリングを左右に素早く動かすとタコ糸とプーリー位置にズレが生じ、その蓄積によって段々とチューニングがズレてくるのだ。これではとてもじゃないが楽器とは呼べない。さっきの喜びはどこへやら。そこでさらなる試行錯誤を繰り返し、プーリーにヤスリでギザギザの滑り止め加工を施す事と、任意のリング位置を瞬時にピッチベンド量ゼロ位置に設定できるチューニングボタン(下の完成画像参照)を追加することで問題を解決した。演奏の合間にチューニングするというのはなかなかアナログな行為であり、楽器っぽくて気に入っている。

プーリーの滑り止め加工
IMG 4097


ここで仮組みしていた部品などを固定し、オンド・マルトノMIDIコントローラの基本的な部分が完成した。

完成画像
20120706title

いったん完成の後も、様々なモディファイを行なっている。まずはオリジナルオンド・マルトノにもあるような、演奏中に音の表情を変えるためのカットオフスライダを装備した。これがなかなか具合が良い(上写真及び演奏ビデオ参照)。また、ピッチベンド幅調整用ボリュームも追加し、ソフトシンセの音色作成の際に利用している。音色については前述したMono/Polyでオンド・マルトノに近い音を数種類作成した。しかしこれはMIDIコントローラなのでオリジナルの音色にこだわる必要はなく、楽曲に合わせて幅を広げて行きたいと思っている。将来的な予定としては、4オクターブ以上の演奏に対応できるようオクターブUP/DOWNボタンを追加する予定である。その他にも音色変更用のボタンを追加したいと考えており、丸裸のデザインもなんとかしたい。コントローラの進化は当分続きそうだ。

制作に要した期間は約2ヶ月、金額は約15000円。内訳は、Arduino2760円、プーリーが4つで3360円、精密ポテンショメータが約1500円、圧力センサが800円程度、あとは各種スイッチ、抵抗類、ブレッドボード、配線、板、ネジなどである。

配線図
配線図

さてお待ちかねの演奏である(といっても冒頭と同じ映像なのだが)。最初はテルミン定番の『白鳥(サン・サーンス)』からということで、GarageBandでカラオケを作成し、演奏してみた。かなり良いところまできていると思うのだが、いかがだろうか。この先、トリ音さんが演奏していた『亜麻色の髪の乙女』や『月の光(ドビュッシー)』など、レパートリーを広げたいと思っている。呼ばれれば演奏もします(笑)。

演奏してみました(アンコール)

3回連載『オンド・マルトノMIDIコントローラの制作』は以上である。実物を見たこともないオンド・マルトノを、「出来るような気がする」という思いだけでなんとか制作することができたのは、やはりArduinoの存在が大きい。ハードウェア(工作)とソフトウェア(プログラミング)を組み合わせて問題を解決するプロセスはパズルで遊んでいる感覚に近く、とても楽しいものだ。ビバ、フィジカルコンピューティング! このエントリをきっかけに一人でも多くの人がArduinoを触るようになれば望外の幸せである。

 

/ 1 / 2 / 3 /

スケッチ (MIDIライブラリ4.2用に修正 2015.9.20)
Sketch (Modified 2015.9.20 for MIDI Library 4.2)

////////////////////////////////////////////////////////////
// Ondes Martenot MIDI controller for Arduino UNO 9V v0.0
// Mitsushi "Galliano" Abe 2012.9.1
// Modified 2015.9.20 for MIDI Library 4.2
// http://gam.boo.jp/blog/archives/2012/07/midi.html
////////////////////////////////////////////////////////////
// Connect the pressure sensor (volume) to A0, the micro switch (note on) to D7
// Connect the center pin of 10-turn potentiometer (pitchbend) to A1
// Connect the push switch (tuning adjust) to D8
// Connect the center pin of slide potentiometer (cut off, not must) to A3
// Connect the center pin of potentiometer (to control pitchbend range, not must) to A2
// Connect Mac>>USB-MIDI(IN)>>Arduino
// The software synthesizer must have +- 24 pitch bend range for 4 octave control
////////////////////////////////////////////////////////////

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define SWITCH 7 // connect the micro switch to D7
#define PITCHADJUST 8 // connect the push switch to D8
int PITCHADJUST_RANGE = 0;
int PITCH_RANGE = 24;

#define PITCHINPUT 1 // connect the center pin of 10-turn potentiometer to A1

int sensorPin = 0; // connect the pressure sensor to A0
int sensorValue;
int midiValue = 0; // volume Value
int old_midiValue;
int cc = 7; // main volume for MIDI control change

int bendPin = 2; // connect the potentiometer to A2
int bendValue;
int midibendValue = 0; // bend Value
int old_midibendValue;
int br = 58; // MIDI bendrange change (depends on user's difinition)

int cutoffPin = 3; // connect the slide pot to A3
int cutoffValue;
int midicutoffValue = 0; // cutoff Value
int old_midicutoffValue;
int cu = 74; // MIDI cutoff change

int midiCh = 1;
int notecounter = 0; // Counter used to avoid refrainig note on
int val1 = 0;
int val2 = 0;
int data3 = 0;

int MIDI_ROOT_NOTE = 60;
byte lowerBits; // Pitchbend value LSB
byte upperBits; // Pitchbend value MSB
int iCounter = 0; // Counter used to reduce the sample rate
byte noteOnToggle = HIGH; // Used to hold the state of the beam

float MIDIPITCHSCALE = 0.03785;

void SendMIDI(char cmd, char data1, char data2)
{
Serial.write(byte(cmd));
Serial.write(byte(data1));
Serial.write(byte(data2));
}

void control(){


val1 = digitalRead(SWITCH);

if(val1 == HIGH)
{
notecounter = notecounter + 1;
if(notecounter == 1)
{
SendMIDI(0x90, MIDI_ROOT_NOTE, 127); // Send the root note
}
}
else
{
// NOTE OFF
SendMIDI(0x80, MIDI_ROOT_NOTE, 127); // Silence the note
notecounter = 0; // Reset the counter
}
}

void volume(){

sensorValue = analogRead(sensorPin);
midiValue = sensorValue / 7.6;
if(midiValue>127){midiValue=127;}

if(midiValue != old_midiValue)
{
SendMIDI(0xB0, cc, midiValue);
}

old_midiValue = midiValue;

}

void bendrange(){
// connect the potentiometer to A2
// this pot controls pitchbend range
// this is not mandatory
bendValue = analogRead(bendPin);
midibendValue = bendValue / 8;
if(midibendValue>127){midibendValue=127;}

if(midibendValue != old_midibendValue)
{
SendMIDI(0xB0, br, midibendValue);
}

old_midibendValue = midibendValue;

}

void cutoff(){

cutoffValue = analogRead(cutoffPin);
midicutoffValue = cutoffValue / 8;
if(midicutoffValue>127){midicutoffValue=127;}

if(midicutoffValue != old_midicutoffValue)
{
SendMIDI(0xB0, cu, midicutoffValue);
}

old_midicutoffValue = midicutoffValue;

}

void ProcessAnalogValue(byte i)
{
// get a value for the GP sensor on pin i
float _x = Z(i);

val2 = digitalRead(PITCHADJUST);

if(val2 == HIGH)
{
data3 = analogRead(1);
PITCHADJUST_RANGE = 608-data3; // 608 is the middlepoint of pitchbend plus 1
}


// 0 - 16383 is the full 14 bit pitchbend range
int _converted = (int)((_x-297+PITCHADJUST_RANGE)/ MIDIPITCHSCALE);

if (_converted > 16383)
{_converted = 16383;}

if (_converted < 0)
{_converted = 0;}

// Convert this 14 bit range value to LSB and MSB bytes
lowerBits = (byte)(_converted & 0x7F);
_converted >>= 7;
upperBits = (byte)(_converted & 0x7F);

// Now output the message
SendMIDI(0xe0, lowerBits, upperBits);

}

float Z(byte pin)
{
int tmp;
int data1 = 0;
int data2 = 0;
int summary = 0; // summary of input data
int h;

// get average data from analogpin0
for(h=0;h<10;h++){
data1 = analogRead(pin);
summary = summary + (data1);
}
tmp = summary/10;
return (float)tmp;
}

void setup(){

MIDI.begin(1);
Serial.begin(31250); // Set MIDI baud rate:

SendMIDI(0xB0, 0x65, 0);
SendMIDI(0xB0, 0x64, 0);
SendMIDI(0xB0, 0x06, PITCH_RANGE); // Set pitchbend range

pinMode(SWITCH, INPUT);
pinMode(PITCHADJUST, INPUT);

}

void loop(){

volume();
bendrange();
cutoff();
control();
ProcessAnalogValue(PITCHINPUT);
delay(1);

}

 

/ 1 / 2 / 3 /


Arduinoを始めるにはこの本から。

Arduinoをはじめよう 第2版 (Make:PROJECTS)
Arduinoをはじめよう 第2版 (Make:PROJECTS)
posted with amazlet at 12.09.02
Massimo Banzi
オライリージャパン
売り上げランキング: 4978








« Van Damme - Zero Gravity Split | ホーム | 新ゴジラにホワイト先生が出てる! »

[blog]
 wrote by galliano




Related Posts Plugin for WordPress, Blogger...