見出し画像

$6 Vibrato_Bipolar LFO - DIY Eurorack Modular Synthesizer

背景

自作モジュラーシンセの67作品目。
ビブラート、すなわちLFOによる音色の変調は、楽器において非常に重要な要素だ。バイオリン、ギター、フルート等のアコースティック楽器。ハモンドオルガンのロータリースピーカー、テルミン、オンドマルトノ等の電子楽器も、ビブラートを加えるシステムになっている。

モジュラーシンセサイザーにおいても、ビブラートは重要な要素だ。オシレータモジュールの多くにはアッテネータ付きFM入力があり、簡単にビブラートができる。

ディレイビブラート

アナログシンセやモジュラーシンセでは「ディレイビブラート」を使うことがある。ディレイビブラートとは、発音から一定時間経過した後に徐々に大きくなるビブラートの事だ。

Isao Tomitaの「口笛と鐘」では、MOOGモジュラーシンセサイザーで口笛の音色を作成している。この口笛のビブラートにもディレイビブラートが使われている。

私が所有していたMS-20でも、ディレイビブラートを作るパッチングがマニュアルに書かれていた。RolandのいくつかSHシリーズにも、徐々にLFOが効かせるパラメータ(delay time , fade time など)が準備されている。

Eurorack モジュラーシンセでも、ディレイビブラートを作ることができる。LFO,EG,VCAを組み合わせたり、Doepfer A-147-2を使うことでも実現できる。
今回はこのディレイビブラートを作成すべく、企画をした。

制作物のスペック

ユーロラック規格 3U 6HPサイズ
電源:50mA ( +12V ) , 10mA ( -12V )

Arduinoベースのビブラート/バイポーラLFOモジュール。
Gate inのパッチケーブル入力状態(plugged/unplugged)でモードが切り替わる。

Vibratoモード(Gate in: plugged)

Gateのパッチケーブル入力がある場合、Vibratoモードとなる。ゲート入力中のみLFOを出力する。ゲート入力直後はLFOの振幅レベルは0で、徐々に増加する。

Frequency pot:LFO周波数
Level pot:LFO 振幅
Delay time pot:LFOが効くまでの時間
Rise time pot:LFO levelの増加速度
MOD in:CVによるlevel制御(0-5V)
Gate in:Gate入力、パッチケーブル挿抜状態を自動検出する
LED:Gate入力 Highの時に点灯する
Output:Vibrato CV出力(0-5Vp-p)

MOD inは、キーボードのモジュレーションホイールと組み合わせて使用することを想定した。CV入力に応じて、LFOの振幅が大きくなる。

CVのOutputは、0Vを基準としたバイポーラ出力だ。MAX -2.5V~2.5Vの出力。Vibratoモードでは波形はsin波固定。

バイポーラLFOモード(Gate in: unplugged)

Gateのパッチケーブル入力がない場合、バイポーラLFOモードとなる。常にLFOを出力する。

Frequency pot:LFO周波数
Level pot:LFO 振幅
Wave form pot:波形の選択(Saw , 逆Saw, sin , tri , squ)
Offset pot:出力のオフセット調整
MOD in:CVによるlevel制御(0-5V)
Gate in:使用不可
LED:出力波形に合わせて点滅する
Output:Vibrato CV出力

LFOのレンジは5Vp-pだが、-2.5~2.5の範囲でオフセットを設定できる。
-5V~0VのLFOや、0~5VのLFOが出力可能。

LevelはLFOの振幅の中央(オフセット電圧)を基準としている。0~5VのLFO出力状態でLevelを下げていくと、+2.5VのDC電圧出力になる。

製作費

総額約700円
---------------------------------
Arduino nano 250円
フロントパネル 100円
可変抵抗 30円*4pcs
ジャック 8円*3pcs
TL074 50円
他(汎用部品は下記リンク先参照)

ハードウェア

これまでArduinoを用いた多くのCV出力モジュールを作成してきたが、バイポーラ出力は今回が初である。ビブラートを作るには、バイポーラであることが必須だ。

CV出力回路

LFOの波と、オフセット電圧はArduinoのPWMをローパスフィルタで平滑することで作っている。
ローパスフィルタのインピーダンス影響を無くすために、オペアンプのボルテージフォロワを通過する。
最後に、オペアンプの加算回路でArduinoからの電圧を加算するが、加算回路では出力が反転しマイナス電位になる。この反転を打ち消すための電圧を、半固定抵抗を用いて作りだしている。

キャリブレーション
半固定抵抗はキャリブレーションが必要だ。ビブラート出力がない状態で、Outputが0Vになるよう調整する。

キャリブレーション方法
1.Gate inにパッチケーブルを挿入する。Gate信号入力はしない。
2.Output電圧をテスターで測定する。
3.Output電圧が0Vになるよう半固定抵抗を調整する。

Plug-in検出回路

Gate inへのパッチケーブルの挿入状態を検出する回路。
パッチケーブル入力がある場合、Arduino D7端子はオープンになる。D7はinternal-pullupに設定しているので、D7がHigh入力になる。
パッチケーブル入力がない場合、Arduino D7端子はGNDに接続される。D7はLow入力になる。
これにより、Arduinoで挿入状態を検出している。

D7端子の保護のため、ショットキーバリアダイオードの保護回路の位置を工夫している。

宣伝:オープンソースプロジェクトの支援をお願いします

DIYモジュラーシンセのオープンソースプロジェクトを継続するために、patreonというサービスでパトロンを募集しています。
コーヒー一杯の支援をいただけると嬉しいです。
また、パトロン限定のコンテンツも配信しています。

ソースコード

粗末だが公開する。

#include <avr/io.h>  //for fast PWM

int pot0, pot1, pot2, pot3, cv1, cv2, pwm1, pwm2, mode, level, lfo_freq;
int delay_count, rise_count, select_wave;
bool plug_in, gate;  //detect plug in cv1 and cv2 jack
long timer = 0;
float LFO_out;
const static byte wavetable[5][256] = {  //saw1,saw2,sin,tri,squ
  { 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 },
  { 127, 130, 133, 136, 139, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 181, 184, 187, 190, 192, 195, 198, 200, 203, 205, 208, 210, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236, 238, 239, 241, 242, 243, 245, 246, 247, 248, 249, 250, 250, 251, 252, 252, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 252, 251, 251, 250, 249, 248, 247, 246, 245, 244, 243, 241, 240, 239, 237, 235, 234, 232, 230, 228, 227, 225, 223, 220, 218, 216, 214, 212, 209, 207, 204, 202, 199, 197, 194, 191, 189, 186, 183, 180, 177, 174, 172, 169, 166, 163, 160, 157, 154, 151, 147, 144, 141, 138, 135, 132, 129, 126, 123, 119, 116, 113, 110, 107, 104, 101, 98, 95, 92, 89, 86, 83, 80, 77, 74, 71, 69, 66, 63, 60, 58, 55, 53, 50, 48, 45, 43, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 21, 23, 25, 26, 28, 30, 32, 35, 37, 39, 41, 44, 46, 48, 51, 53, 56, 59, 61, 64, 67, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 127 },
  { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 255, 253, 251, 249, 247, 245, 243, 241, 239, 237, 235, 233, 231, 229, 227, 225, 223, 221, 219, 217, 215, 213, 211, 209, 207, 205, 203, 201, 199, 197, 195, 193, 191, 189, 187, 185, 183, 181, 179, 177, 175, 173, 171, 169, 167, 165, 163, 161, 159, 157, 155, 153, 151, 149, 147, 145, 143, 141, 139, 137, 135, 133, 131, 129, 127, 125, 123, 121, 119, 117, 115, 113, 111, 109, 107, 105, 103, 101, 99, 97, 95, 93, 91, 89, 87, 85, 83, 81, 79, 77, 75, 73, 71, 69, 67, 65, 63, 61, 59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
};

void setup() {
  pinMode(3, OUTPUT);   //LED
  pinMode(10, OUTPUT);  //LFO output
  pinMode(9, OUTPUT);   //OFFSET output
  pinMode(7, INPUT_PULLUP);//plug_in detect

  TCCR1B &= B11111000;  //fast pwm setting
  TCCR1B |= B00000001;  //fast pwm setting

  timer = millis();
  delay(50);
}

void loop() {
  if (timer + 10 <= millis()) {
    timer = millis();
    pot0 = 1023 - analogRead(0);  //freq
    pot1 = analogRead(1);         //level
    pot2 = analogRead(2);         //delay , waveform
    pot3 = 1023 - analogRead(3);  //rise , offset
    cv1 = analogRead(4);          //gate in
    cv2 = analogRead(7);          //mod in
    level = constrain(pot1 + cv2, 0, 1023);

    plug_in = digitalRead(7);  //gate plug_in detect
    //------------------------LFO mode-----------------------------------
    if (plug_in == 0) {          //no plug in
      mode = 0;                  //LFO mode
      select_wave = pot2 / 203;  //select waveform
      select_wave = min(select_wave, 4);
      analogWrite(3, 255 - (byte)wavetable[select_wave][pwm1]);  //LED light
    }
    //------------------------vibrato mode-----------------------------
    else if (plug_in == 1) {  //plug in detect
      mode = 1;               //plug in
      if (cv1 > 60) {         // gate high
        gate = 1;
      } else if (cv1 <= 50) {  //gate low
        gate = 0;
        delay_count = 0;  //reset delay counter
        rise_count = 0;   //reset rise counter
      }
      if (gate == 1) {
        delay_count = delay_count + 1;
      }
      if (delay_count > pot2 / 8) {  //rise time setting
        if (pot3 < 1013) {
          rise_count = rise_count + (pot3 / 4) + 1;
        } else if (pot3 >= 1013) {  //if pot is max value , rise time is 0
          rise_count = 10000;
        }
        if (rise_count > 10000) {
          rise_count = 10000;
        }
      }
      digitalWrite(3, gate);  //LED light
    }
  }
  //----------------------------LFO wave output setting--------------
  pwm1++;            //wave table counter
  if (pwm1 > 255) {  //reset wavetable counter
    pwm1 = 0;
  }
  if (mode == 0) {  //LFO
    LFO_OUT();
    delayMicroseconds(100 + 15 * pot0);
  } else if (mode == 1) {  //vibrato
    VIB_OUT();
    delayMicroseconds(100 + 3 * pot0);
  }
}
//-------------PWM output-------------------
void LFO_OUT() {  //PWM duty setting
  LFO_out = constrain((wavetable[select_wave][pwm1] - 128) * (level / 64 * 0.0625) + 128, 0, 255);
  analogWrite(10, (byte)LFO_out);  //LFO wave output
  analogWrite(9, pot3 / 4);        //offset output
}

void VIB_OUT() {  //PWM duty setting
  LFO_out = (wavetable[2][pwm1] - 128) * (rise_count * 0.0001) * (level / 64 * 0.0625) + 128;
  analogWrite(10, (byte)LFO_out);  //LFO wave output
  analogWrite(9, 127);             // fixed offset output
}

この記事が気に入ったらサポートをしてみませんか?