見出し画像

$9 PT2399 clock sync delay - DIY Eurorack Modular Synthesizer

Delay IC PT2399とArduino nanoを使用してモジュラーシンセサイザー のClock sync delayを自作したので、その備忘録。

背景

自作モジュラーシンセの54作品目。
私のYoutubeチャンネルでアンケートを取ったところ、PT2399の要望が最も多かった。

PT2399 delay ICは、初心者向けのエフェクター電子工作の定番ICだ。ディレイサウンドには独特な歪みがあり、演奏中にディレイRATEを変更すると面白い音を作ることができる。

EurorackモジュラーシンセサイザーにもPT2399を使用したモジュールは多い。私もsynthrotekのECHOを組み立てたことがある。

今回、PT2399に新しい付加価値が付けられないか検討した。エフェクターとして使いやすいclock sync機能を追加したり、CVでディレイRATEを変更することで面白い音響効果が得られると面白いと思い、今回のモジュールを企画した。

設計コンセプトは
1. Clock syncによる東海岸的な統制の取れたサウンドを実現する。
2. PT2399を不安定な領域で使うことで、西海岸的な不安定なサウンドを実現する。

制作物のスペック

ユーロラック規格 3U 6HPサイズ
電源:50mA ( 12V )
12V単電源で動作可能。-12Vは使用しない。

モード選択

Clock syncモードと、No syncモードの2種類がある。

Clock syncモード
ディレイタイムを外部クロックにSYNCさせる。
ディレイタイムの分周は、/1~/6で選択できる。
外部クロックは常時監視しているため、途中でClock周期が変わっても追従できる。

No syncモード
Clock入力が3秒以上ないと、No syncモードになる。
ディレイタイムは正常動作範囲外で設定することができ、不安定な動作によるグリッチサウンドを出すことができる。

インターフェース

Feed Back POT:
ディレイエフェクトのフィードバック量を調整。
右に回し切ると過剰なフィードバックが発生し、ノイズサウンドになるよう調整している。

TIME POT:
Clock syncモードでは分周比率を選択。
No syncモードではディレイタイムを調整する。

MIX POT:
エフェクトのDRY:WETを調整する。

CLK IN:
Clock入力。0-5Vの信号を想定している。3秒以上入力がないと、No syncモードになる。

TIME CV IN:
TIMEと同じパラメータをCVで制御する。電圧範囲は0-5V。

WET SW:
スイッチを切り替えると、DRY出力を完全に遮断する。エフェクトサウンドだけが出力される。PT2399 をエフェクターとしてではなく、音声のモジュレーターとして使用することを想定している。

IN , OUT:
オーディオシグナルのIN/OUT。10Vp-pの信号を想定しており、10Vp-p以上の電圧を入力すると音が歪む。

5V駆動

入出力オペアンプの+端子をオフセットしているので、5Vでも動作可能。
5Vで動かす場合はIN,OUTのダイナミックレンジは小さくなる。
このモジュールはclock sync機能のためにArduino IDEのシリアルモニタを用いたキャリブレーションが必要だ。キャリブレーション時に12V電源を使わなくてもいいよう、5Vでも動く回路としてある。

製作費

総額約900円
---------------------------------
フロントパネル 100円
PT2399 IC 100円
Arduino nano 200円
トグルSW 20円
可変抵抗 30円*3pcs
オペアンプMPC6232 45円
他(汎用部品は下記リンク先参照)

PT2399はTayda electronicsから購入。様々な部品を安価に購入できるのでオススメ。送料も安い。

部品費は私が購入した時点での値段を記載している。2022年7月時点で、Arduino nano互換品はAliexpressで$4ドルとなっている。

ハードウェア

エフェクター回路
回路図の左上は外部入出力回路。ギターエフェクターのPT2399回路を参考にしているため、ハイインピーダンスに対応している。

右上は外部入出力回路のオペアンプバイアス電圧を作る回路。

右下はPT2399の一般的な回路。過激なサウンドが出るように、抵抗値を調整している。

「Rock音!アナログ系ギター・エフェクタ製作集」という本を参考にした。
PT2399に関する記事が豊富にあり、非常にわかりやすい。おすすめ!

デジタル制御回路
左下はArduino回路。D9pin回路によりPT2399のディレイタイムを調整している。オペアンプとトランジスタを使った電圧制御抵抗回路だ。
トランジスタに流れる電流をArduinoのPWMによって制御している。

トランジスタは2SC1815を使用しているが、ほかの汎用トランジスタでも代用できる。2SC1815を使用した理由は、日本で最も入手しやすく、最も安いからだ。

下記のTap tempo ギターペダルの回路を参考にしている。感謝!

ソフトウェア

キャリブレーション

トランジスタによる電圧制御抵抗回路は、トランジスタ特性や分圧抵抗誤差の影響を大きく受ける。
clock sync機能を使用するには、オシロスコープとArduino IDE シリアルモニタを使ったソフトウェアキャリブレーションが必要だ。

キャリブレーションに必要な道具
・オシロスコープ (1chでOK)
・Arduino IDEがインストールされたノートパソコン
・表計算ソフト、エクセルやLivreOffice Calc等
・適当な音源、ドラムのような1shot音だと良い

キャリブレーション手順
1,IN jackに音源を接続する。
2,Arduino nanoをPCに接続、Arduino IDEのシリアルモニタで”PWM”を監視する。
3,OUT jackの信号をオシロスコープに表示する。
4,CLK jackに信号は入力させず、no clock syncモードにする。

5,TIME POTを回し、シリアルモニタのPWM値が20になるよう調整する。
6,音声入力をして、オシロスコープでディレイタイムを計測する
7,表計算ソフトに計測したディレイタイムを記録する。

8, 5~7の作業を8回繰り返す。手順5のPWMは以下の通り調整する。
 PWM=30,40,50,60,70,90,110,130

9, 表計算ソフトの機能を使い、累乗近似曲線を作成する。

10,ソースコードのconstant[i]に累乗近似曲線の式を入力する。

  for (int i = 0; i <= 255; i++) {
    constant[i] = 11675 * pow(i, -0.9161);//prepare clock sync time table
  }

以上でキャリブレーション作業は終わり。

より詳細なキャリブレーション手順や、近似曲線による誤差とその考察、回路のチューニングポイントの記事はPatreonに投稿した。
オープンソースプロジェクトを継続するために、支援いただけると助かります。

https://www.patreon.com/posts/supplementary-69893870

ソースコード

粗末だが公開する。悪い点があれば指摘を貰えると嬉しい。
MsTimer2というライブラリを使用している。

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

int PWM = 0;
int constant[256];
bool clk_in, mode;
bool old_clk_in = 0;
unsigned long clk_count;
int clk_time1, clk_time2, clk_time_ave, buf_dt, search_dt, cmp1, cmp2,divide;

void setup() {
  TCCR1B &= B11111000;//fast pwm setting
  TCCR1B |= B00000001;//fast pwm setting

  pinMode(2, INPUT); //CLK IN
  pinMode(9, OUTPUT); //delay time control
  pinMode(13, OUTPUT);//LED

  for (int i = 0; i <= 255; i++) {
    constant[i] = 11675 * pow(i, -0.9161);//prepare clock sync time table
  }
  clk_count = 0;
  
  Serial.begin(9600);//for calibration
  
  MsTimer2::set(1, timer_count); // timer count per 1 msec
  MsTimer2::start();//
}

void timer_count() {
  clk_count ++;
}

void loop() {
  old_clk_in = clk_in;
  clk_in = digitalRead(2);//read external clock signal
  digitalWrite(13, clk_in);//LED light sync external clock signal
  
  if (old_clk_in == 0 && clk_in == 1) {
    clk_time2 = clk_time1;
    clk_time1 = clk_count;
    clk_time_ave = (clk_time2 + clk_time1) / 2;
    clk_count = 0;
  }

  if (clk_count < 3000) {
    mode = 0; //clock sync mode
    divide = map(min(1023, analogRead(1) + analogRead(5)), 0, 1023, 1, 6);
    buf_dt = clk_time_ave / divide;

    if (buf_dt > 80) {
      for ( search_dt = 255; search_dt >= 0 ; search_dt-- ) {// quantize
        if ( buf_dt < constant[search_dt] && buf_dt >= constant[search_dt + 1]) {
          cmp1 = constant[search_dt] - buf_dt; //Detect closest note
          cmp2 = buf_dt - constant[search_dt + 1];//Detect closest note
          break;
        }
      }
      if (cmp1 <= cmp2) {//Detect closest note
        PWM = max(5, search_dt + 1);
        PWM = min(PWM, 255);
      }
      else if (cmp2 < cmp1) {//Detect closest note
        PWM = max(5, search_dt);
        PWM = min(PWM, 255);
      }
    }
    else if (buf_dt <= 80) {//glitch noise countermeasure
      PWM = 255;
    }
  }

  else if (clk_count >= 3000) {// when no signal 3sec , no sync mode
    mode = 1; //no sync mode
    PWM = map(min(1023, analogRead(1) + analogRead(5)), 0, 1023, 1, 255);
  }
  analogWrite(9, PWM);
//  Serial.print(analogRead(1));// for calibration
//  Serial.print(",");// for calibration
  Serial.print(PWM);// for calibration
  Serial.println("");// for calibration
}

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