PICマイコンを使ったMIDIシンセサイザーの製作 2015.10.18


    1.はじめに

     トランジスタ技術2015年8月号の特集記事「楽器エフェクタ製作集」では、アナログシンセサイザーの製作が紹介されていました。これを読んでいて俄然シンセサイザーを作ってみたくなりました。

     アナログシンセサイザーは、その昔、「TEISCO-100F」というキーボード付きのシンセサイザーを所有していたことがあります。パネルに整然とならんだボリュームのつまみ類などがカッコ良かったです。色々いじくって楽しんでいましたが、自宅を新築した際にオーディオ装置とともに廃棄してしまいました。


    TEISCO-100F
    マニュアルは残っていました
    音の作り方が書いてあります
    100Fの規格

     トラ技で紹介されているアナログシンセサイザーも原理的には、このS-100Fと同じものです。あの当時の思い出を蘇らすべくアナログシセサイザーの製作に挑戦しようと思ったのですが、製作には、それなりに電子部品を揃えなければなりません。また部品の数も結構あります。

     そこで、製作記事をトレースするのではなく、PICマイコンを使ったシンセサイザーを作ってみることにしました。手元には、これまた随分昔に購入したMIDIのキーボードがありますので、MIDIのシンセサイザー音源として製作してみました。

    QUICK-SHOT製MIDIキーボード
    音源は内蔵されていません


    2.ハードウェア

    2−1.外観

     完成したシンセサイザーは、次の写真のとおりです。


    上部パネルのつまみ類です。エンベロープの4つのボリューム、ビブラートとエコーのボリュームを設けました。
    前部にRS-232C、MIDI-INコネクタとRCAピンを取り付けました。RCAピンは、左と右の2つありますが、どちらも同じ出力です。 左側面には、DC(+5V〜+9V)入力ジャックと電源SWを設けています。


    上部パネルはフラットケーブルで接続しています。
    本体マイコン基板です。中央がPICです。右上の回路はMIDI入力部で、右下は、RS232Cのレベル変換ICです。左上が3V3電源です。左下は、サウンド出力のローパスフィルタです。 パネルやケースはプラ板で作成しました。

    2−2.操作方法

     +5V〜+9VのACアダプターをDC入力ジャックに接続します。MIDIキーボードのMIDI-OUTコネクタと本機のMID-INコネクタをMIDIケーブルで接続します。次にサウンド出力のRCAピンをオーディオアンプのAUX入力端子などに接続します。

     ケーブルの接続が間違いなければ、本機、キーボード、オーディオアンプの順に電源を投入します。

     attack, decay, release のつまみを右に4分の一程度、sustain を右に半分程度廻しておきます。vib.depth など他のつまみは、左に絞りきっておきます。fmchorus の2つのスィッチは、ともに off にしておきます。

     次に、osc select で発振波形を選択します。左から、正弦波三角波鋸歯状波矩形波PWM付き矩形波、の5種類から選べます。

     オーディオアンプの音量を適当に調整し、MIDIキーボードの鍵盤を押下します。アンプのスピーカーから音が出れば本機は正常に動作しています。

     本機は、10音同時発音が可能なポリフォニックシンセサイザーとなっています。鍵盤でドミソなどのキーを同時に押して和音がきちんと出力されるか確認して見てください。

    正弦波 sine.mp3(166kb)
    三角波 triangle.mp3(174kb)
    鋸歯状波 sawtooth.mp3(184kb)
    sawtooth_doremi.mp3(215kb)
    (ビブラート、エコーあり)
    矩形波 pulse.mp3(185kb)


    2−3.つまみ類の設定範囲

     各つまみを廻して音色変化や音量変化を楽しむことができます。各種つまみは、右に廻すと値が大きくなるようになっています。

     各つまみの設定範囲は次のとおりです。

      attack time1 - 2000 msec
      decay time1 - 3000 msec
      sustain level0 - 100 %
      release time1 - 3000 msec
      vibrato depth0 - 2 %
      vibrato frequncy0 - 20Hz
      echo delay time0 - 500 msec
      echo level0 - 100 %
      fm on/offon: FM音源を使う off: FM音源を使わない
      chorus on/offon: コーラス効果有り off: コーラス効果なし
      osc select波形選択、 fm on の時はFM音源5種類を切替


    2−4.FM音源

     本機では、2オペレータによるFM音源を備えています。fm on にすると、オシレータの選択は、正弦波 や 三角波からの選択ではなく、FM音源の切替になります。osc select の5つの位置によって切り替わります。

     本気で実現しているFM音源の変調パターンは、次の式のとおり簡易なものです。

      sin(x + A * sin( n * x )) n=2,4,6,8,10 A=1.0〜0.7

     n は、セレクタの位置によって変わります。右回りに 2, 4, 6, 8, 10 と変化します。A は、変調の深さです。decay time の間に、 1.0から0.7へと浅くなって行きます。

    sine(x+sine(2*x)) fm1.mp3(178kb)
    sine(x+sine(4*x)) fm2.mp3(166kb)
    sine(x+sine(6*x)) fm3.mp3(175kb)

    sine(x+sine(8*x)) fm4.mp3(177kb)
    sine(x+sine(10*x)) fm5.mp3(173kb)
    fm5_doremi.mp3(217kb)
    (ビブラート、エコーあり)

    2−5.MIDIシーケンサによる演奏

     パソコンにUSB-MIDIやシリアルMIDIインタフェースがあれば、そのMIDI-OUTを本機のMIDI-INに接続することにより、パソコンのシーケンサーソフトを使って本機を演奏することができます。

     パソコンのMIDIシーケンサーを使って自動演奏してみたのが次の2曲です。どちらもFM音源を使っています。ビブラートやエコーをかけています。



    2−6.回路説明

    図1マイコン基板
    図2パネルパーツ

     図1にマイコン基板回路を、図2にパネル部回路を示します。使用したPICは、DIPタイプのPIC32MX250F128B(ROM128KB、RAM32KB)です。クロックは内蔵のRCオシレータを使っています。

     操作用のボリュームは、PICのAD入力に接続しています。PIC32MX250F128Bでは、アナログ入力は最大9入力使えます。ボリュームx8、セレクタx1で9入力全てを使っています。

     オシレータのセレクタスィッチは、PICにデジタル入力ピンの余裕がありませんので、抵抗分圧によるアナログ入力で行うようにしました。

     MIDIキーボードからのMIDI信号は、フォトカプラ(TLP521)で受けて、その出力をトランジスタ(C1815)を通して、UART1で受信しています。UART1のRX端子は、RPA4(RA4)にマップしています。UART1は、MIDI信号の伝送規格である31.25kbpsで動作させています。

     サウンド出力は、OC2によるPWMでDA変換を行って出力しています。OC2の出力は、RPB5(RB5)にマップしています。1.2Kの抵抗と0.1uFのコンデンサによる簡単なフィルタを通した後、4.7uFの電解コンデンサで直流カットした後、RCAピンに出力しています。

     RS-232Cコネクタは、デバッグ出力用です。UART2を使っています。RPB10(RB10)/RPB11(RB11)をUART2のTX、RXにそれぞれマップしています。RS-232Cのレベル変換ICを通してコネクタに接続しています。

     RB10/RB11は、プログラム書き込み用のPGED/PGECと兼用していますので、ジャンパー端子によりプログラム書き込み時には回路を切り離せるようにしました。

     UART2の出力をTTLレベルで済ませられれば、ICはPICだけの簡単な回路になります。ブレッドボードでも確認できる簡単な回路です。


    3.ソフトウェア

    3−1.オシレータ

     オシレータの発振は、DDS方式を採用しました。正弦波、三角波などの波形データを予め配列変数に格納しておき、データを順次読み出してPWMに出力しています。

     配列変数には1周期分1024点の波形データを格納しています。データの読み出しは、タイマー4による20KHz(50usec)インターバルタイマーの割り込みで行っています。

     発振周波数毎のデータを読み出す間隔は次の式となります。

      read_out_step = 1024 * midi_note_frequency / 20000

     例えば、440Hzの周波数を発振する場合には、割り込みの都度、1024x440/20000=22.53 の間隔で配列のデータを読み出して行くことになります。

     読み出したデータの値は、最大値が1、最小値が −1の範囲にありますので、これに、別途エンベロープ処理で計算された波高値を掛け算して出力します。


    3−2.MIDIの受信

     MIDI信号は、UARTの受信割り込みにより受信バッファに格納されます。これを順次読み出して、ノートオンなら発音開始処理をノートオフなら発音停止処理を行います。これ以外の信号は、リセット信号を除き全て読み捨てています。

     ノート・オン信号は、ノート番号とベロシティがパラメータとしてキーボードから送信されてきます。ノート番号により発振周波数を、ベロシティにより出力の大きさ(最大波高値)を設定します。


    3−3.エンベロープ処理

    attack=25m,decay=50m,release=70m,sustain=50%
     出力の大きさを制御するエンベロープの処理は、タイマー3による1KHz(1msec)インターバルタイマーの割り込みで行っています。ボリュームで設定された、attack Time、decay Time、sustainlevel、release Time の指示に従って出力の波高値を1msec間隔で計算して行きます。

     アタックやディケイ、リリースの増減衰パターンは、エキスポネンシャルカーブでは無く、計算が簡単な線形カーブを採用しました。

     アタックタイムやサステインレベルなどを設定するボリュームの値は、5msec間隔でA/D変換して読み取っています。スィッチの状態の読み取りも同様です。

     タイマー3の割り込み処理の中では、ビブラート周波数の計算や、FM音源の変調の深さ制御、LPFの制御なども行っています。


    3−4.LPF

     発音の持続とともに倍音成分を徐々に減衰させるために、ローパスフィルタを設けました。その処理は、単純に、今回値と前回値、前々回値、前前々回値 ... と過去の値との和を求め、それの平均を取るだけの簡単なものです。どこまで過去に遡って平均を取るかをエンベロープ処理の中で制御しています。

     具体的には、鳴り始めのアタックでは、今回値だけをそのまま出力します。ディケイの時間経過とともに、「前回値との平均を出力する」、「前々回値も含めた平均を出力する」、更に「前前々回値も含めた平均を出力する」、と順次平均を取る範囲を増やして行きます。これによりフィルタ特性に時間変化を持たせています。

     なお、FM音源を選択している時は、LPFは使いません。代わりに、変調の深さを順次浅くして行くことで、LPFと同様の効果を出しています。


    3−5.ビブラート、エコーの処理

    遅延125msec, 減衰レベル65%のエコーです。最初の波が源音で、125msecで繰り返しながら減衰します。
     ビブラートは、発振周波数を次の式で1msec毎に変化させ、波形データを読み出す間隔を再計算します。

      out_frequency = midi_note_frequency * ( 1 + vibratoDepth * sine[ (1024 * vibratoFreq / 1000) * n ])
      read_out_step = 1024 * out_frequency / 20000

     エコーは、500msec分の出力値を保持できるリングバッファを使って、現在値と、バッファ内の echo delay Time 分離れた位置のデータとを加算して出力するとともに、出力値に echo level を乗じたデータを新たにバッファに格納して行く事で行っています。

     時間的に離れた複数の位置のデータを加算することで、エコーではなくリバーブを実現できますが、やって見たところ、エコーとの差があまり感じられなかったので実装からは外しました。


    3−6.ポリフォニック(複数音同時発音)

     複数の音を同時発音させるために、一つの発音に関する各変数群を一つの構造体変数に収めて、それを配列変数とすることで実現しています。

     1msec や 50usecの各割り込み処理では、この構造体変数の配列を順次処理します。配列の大きさが、同時発音数であり、割り込み処理では、発音数に応じて処理時間が増大します。そのため、50usec以内で完結出来る処理数が実現可能な同時発音数となります。

     本機の製作では、左右の指10本での同時打鍵を最大発音数となるようにしました。


    デバッグウィンドウの表示
    3−7.デバッグ表示

     RS-232Cケーブルでパソコンに接続するとテラターム等の端末ウインドウに、MIDI−INから受信したノート番号とベロシティの値をリアルタイムに表示します。

     パソコンのキーボードで、pを打鍵しますと、エンベロープやビブラート、エコーの各ボリュームの現在の設定値を表示します。

     配列変数の使用状態も表示します。本作では、配列要素は10個になります。
     ノート番号が、255と表示されている要素は現在未使用であることを示します。


    3−8.PICプログラム

     シンセサイザープログラムのバイナリーです。PICKit3で書き込んでください。