■自作デジタルエフェクター

■RasPd2 プログラミング編

参考になるかわかりませんが、とりあえずRasPd2に入っているファイルをアップロードしておきます。(直リンクできないようなのでこちらの別ページにダウンロードリンクを載せています。)

▽コントロール割り当て
左スイッチ: エフェクト切替、切替時に右LEDが点滅
中央スイッチ: 特殊機能(ブースト機能等)オン・オフ、オン時中央LED点灯
右スイッチ: 長押しでシャットダウン
各ポット: エフェクトパラメータ
フットスイッチ: エフェクトオン・オフ、オン時左LED点灯

今回の内部プログラムはRasPd1のプログラムを単に移植しただけのものです。エフェクトを3種類入れているものの、エフェクトを切り替えた後いちいち各ポットを設定しなおさなければいけない仕様なので、現実的な運用は面倒だと思います。もちろん中身は自由に変更できるので、今後いろいろと発展させていきたいです。変態的なエフェクトをプログラムするのもいいし、スマートフォンと連携してエフェクトを操作するなんてこともできるかもしれません。



<スイッチ・LED>
RasPd1と同様、GPIOピンによるスイッチやLEDの制御を行っています。
こちらで丁寧に解説されています。→RaspberryPi電子工作入門

<可変抵抗>
エフェクトパラメータ設定は、ポットで分圧した電圧値をADコンバータMCP3008で読み取るという方式です。
こちらのページのプログラムを改変して利用しました。→Raspberry PiのPythonからTMP36のアナログ温度センサとMCP3008のADコンバータを使う
値の取得は0.3秒ごとにしています。取得した値が前回の値から変化していたとき、RasPd1と同様pdsendでPdへデータ送信しています。ポットを回したとき反応が遅く雑音が発生しますが、ワウペダルではないので実用上問題ないでしょう。

<データ保存>
RasPd1からの名残でパラメータ保存機能は一応残っています。しかしすぐにパラメータが上書きされてしまうため、意味がない状態です。工夫次第ではプリセット保存・呼び出しといった機能をつけることも可能だと思います。



ハードウェア編へ  ソフトウェア編

■RasPd2 ソフトウェア編

Pure Dataやオーディオを優先的に動かすため、下準備をしていきます(太字表記はコマンド)。
Raspberry Pi zeroの基本設定はこちら

通信に使うUSBケーブルは5V給電できないよう加工しています(外部から5V給電しているため)。さらに、うまく挿し込めるように角度を変えています。
03_188_1raspd2u.jpg



<CPU周波数スケーリング>
CPUのクロック周波数を常に1000MHzで動作するよう設定変更します。
$ sudo nano /boot/config.txt
#arm_freq=800 を arm_freq=1000 に変更
$ sudo apt-get install cpufrequtils(cpufrequtilsインストール)
$ sudo nano /etc/init.d/cpufrequtils
43行目あたり GOVERNOR="performance"



<不要なプログラムを停止>
RasPd1 ソフトウェア編その1と同じです。



<オーディオ設定>
WM8731のドライバを有効化します。
$ sudo nano /boot/config.txt
#dtparam=audio=on (コメントアウトしてオンボードのオーディオをオフに)
dtoverlay=rpi-proto (追加記載)

再起動後、オーディオ設定プログラムを起動します。
$ alsamixer
F5で全表示、スペースキー・↑↓キー・mキーで機能オン(OO)・オフ(MM)や機能切替です。設定は自動で保存されます。
Master 56 [dB gain: -9.00, -9.00]
Master Playback ZC [Off, Off]
Sidetone 0 [dB gain: -15.00]
Line CAPTURE
Mic [Off]
Mic Boost 0 [dB gain: 0.00]
Mic Boost 0 [dB gain: 0.00]
Playback Deemphasis [Off]
Capture 87 [dB gain: 9.00, 9.00]
ADC High Pass Filter オフ
Input Mux [Line In]
Output Mixer HiFi オン
Output Mixer Line Bypass [Off]
Output Mixer Mic Sidetone [Off]
Store DC Offset [Off]



<Pure Data(Pd)設定>
RasPd1 ソフトウェア編その2と同じですが、さらに低レイテンシー設定が可能です。また、44.1kHzには対応していませんので注意が必要です。Pd設定ファイルの下記該当箇所を変更しました。
$ nano .pdsettings
audiobuf: 5
rate: 48000



<自動起動設定>
RasPd1 ソフトウェア編その2と同じです。
今回のメインプログラム名は main2.py です。



<ADコンバータ MCP3008用設定>
$ sudo nano /boot/config.txt
dtparam=spi=on (#を外してSPI通信をオンに)
$ sudo apt-get install python-spidev(SPI通信に必要なPythonライブラリをインストール)



ハードウェア編へ  プログラミング編

■RasPd2 ハードウェア編

03_187_1raspd2p.jpg
Raspberry Pi Zeroを使い、コンパクトなデジタルエフェクターを作りました。今回はLCDがなく、単機能エフェクターとして使うことを想定しています。オーディオインターフェイスはUSBではなくI2Sで通信するとレイテンシーが低減できるようで、WM8731というICを使用しました。レイテンシー実測値は7msとほとんどリアルタイムに近いレベルとなりました。

WM8731については、別記事に記載しています。
WM8731 設定メモ
Raspberry Pi Zeroでもほとんど設定は同じですが、ADC High Pass Filterはオンにするとノイズが増えたためオフにしました。音量は Master 56(-9dB) Capture 87(+9dB) です。

SN比を稼ぐため、RasPd1のときには外部回路で入力前増幅→出力後減衰を行っていました。WM8731のデータシートを見てみると、IC内部でアナログな増幅・減衰ができるため外部回路は入力バッファのみとしました。電源電圧が3.3Vと低いですが、+9dB(2.8倍)程度までは歪まないだろうと思います。

▽回路図
03_187_2raspd2s.gif
出力のコンデンサが100uFと大きい値なのはイヤホンを直接繋ぐためでしたが、誤って大出力になったとき危険なのでイヤホンでのテストはしない方がいいでしょう。各スイッチには少し面倒ですがチャタリング防止の抵抗やコンデンサを入れています。とりあえずたくさんコントロールを準備したという感じで、割り当てをどうするかは未定です。WM8731への接続に入っている抵抗(ダンピング抵抗)はありあわせの22Ωにしましたが、役割はあまり理解していません。

ノイズ対策のため、電源・GNDは4系統に分かれています。
 [アナログ9V電源・GND(バッファ用)]
   ↓
 [デジタル5V電源・GND(Raspberry Pi用)] → [アナログ3.3V電源・GND(WM8731用)]
   ↓
 [デジタル3.3V電源・GND(WM8731用)]

▽レイアウト
03_187_3raspd2l.png
▽PCB(横111.8mm縦73.7mm)
03_187_4raspd2lp.png
あまり見慣れない水晶振動子というパーツがありますが、ケースが金属なので基板から少し浮かせて取り付けています。周波数の値はそんなに高精度のものでなくていいようです。WM8731には、シングルタイプのピンソケットを使うことでICの下にパーツを配置できるようにしています。レイアウト上部の基板間の配線は、着脱式にして後からの修正をしやすくしました。また、GND等のいくつかのジャンパーは基板の裏側(半田面)で配線しています。

今回もノイズには悩まされました。まずサーというホワイトノイズがRasPd1より多く出ていました。Raspberry Pi自体から電磁波的ノイズが出ているのかと思いアルミホイルでシールドしてみましたが効果なしでした。pedalSHIELD DUEのようにRチャネルに位相反転した入力を入れて、ノイズキャンセルしようとしましたがこれもダメでした(LとRでノイズの乗り方が違うようです)。結局電源を分離すると解決したため、ノイズ源はWM8731用アナログ電源だったようです。

その他にもギターを繋いだときに少しキーン&プツプツというノイズが出ていました。RasPd2内蔵のバッファを一旦外し、別電源のバッファを前段に繋いだ場合はほとんどノイズが消えたため、電源とGNDの取り方が原因と考えました。試行錯誤の結果、絶縁型のDC-DCコンバータを使用し、その出力部に各GNDを集めるというレイアウトになっています。

下写真のように基板を2枚重ねにしています。
03_187_5raspd2g.jpg
ケースは高さがあるHAMMOND1590BSです。発熱が心配ですが、裏フタをあけた状態ではCPU温度50℃程度で安定しているようです。そのうち無線接続可能なRaspberry Pi Zero Wに変更し、改めて長時間使用時の安定性を調べようと思います。



ソフトウェア編へ  プログラミング編

■RasPd1 プログラミング編

プログラミングはかなり昔にお遊び程度にしていたレベルで、全く自信がありません。参考になるかわかりませんが、とりあえずRasPd1に入っているファイルをアップロードしておきます。(直リンクできないようなのでこちらの別ページにダウンロードリンクを載せています。)
Pythonというプログラミング言語を使っています。記事にしてみると思ったよりたいしたことはしていませんでした。エフェクトは3種類入っていますが、取り急ぎ適当に作ったものになります。



<スイッチ・LED>
Raspberry PiではGPIOピンという端子によりデジタル信号の入出力を行うことができます。スイッチやLEDの制御は比較的簡単です。こちらで丁寧に解説されています。→RaspberryPi電子工作入門

<液晶ディスプレイ>
秋月電子の超小型LCDキャラクタディスプレイを使用しています。HD44780互換ということで、下記ページのプログラムをほぼそのままモジュールとしてインポートしています。
16×2 LCD Module Control Using Python
ただし、3番ピンはGNDではなく10kΩトリマーで5Vを抵抗分圧して接続しています。トリマーを回すことでコントラスト調整ができます。

<ロータリーエンコーダ>
こちらのページのプログラムを改変して利用しました。→RaspberryPi + Python でロータリエンコーダを制御してみた
主な変更は、ロータリーエンコーダを回し始めたときにGPIO監視を開始するようにした点、速く動かしたとき値が3倍増減するようにした点です。いまいちコントロールしにくいときがあるので、まだまだ改善が必要だと思います。

<Pure Data(Pd)連携>
pdsendというコマンドを使って、ロータリーエンコーダやスイッチからPythonを介してPdへデータ送信しています。例えば「$ echo '50;' | pdsend 3010」というコマンドで、開いているPdのパッチの[netreceive 3010]オブジェクトにセミコロンが除かれた50というデータが送られます。数字データの場合は、Pdが文字ではなく数値と認識してくれるようなので、そのまま計算等に使うことができます。pdreceiveというコマンドで逆にデータ受信もできると思いますが、現状では必要なかったため試していません。

<データ保存>
起動時・終了時やエフェクト切り替え時に、各エフェクトの状態をテキストファイルに保存しています。エフェクトのパラメータはfx_pというリストデータになっています。いちいち整数と文字を切り替えなければいけないのが少し面倒でした。



ハードウェア編へ  ソフトウェア編その1へ  ソフトウェア編その2

■RasPd1 ソフトウェア編その2

Pure Data(Pd)の設定等をしていきます(太字表記はコマンド)。



<Pd設定>
Pdと外部オブジェクト(Externals)をインストールします。
$ sudo apt-get install puredata
$ sudo apt-get install pd-libdir pd-cyclone pd-unauthorized pd-ggee pd-zexy
作るエフェクトによっては、もっとたくさんの外部オブジェクトが必要となるかもしれません。

設定ファイルを作成します。
$ nano .pdsettings (新規作成)
以下の内容です。パス(path)は念のため全ての外部オブジェクトを入れています。
audioapi: 1
noaudioin: False
audioindev1: 0 2
noaudioout: False
audiooutdev1: 0 2
audiobuf: 6
rate: 44100
callback: 0
blocksize: 64
nomidiin: True
nomidiout: True
path1: /usr/lib/pd/extra
path2: /usr/lib/pd/extra/cyclone
path3: /usr/lib/pd/extra/ggee
path4: /usr/lib/pd/extra/libdir
path5: /usr/lib/pd/extra/pddp
path6: /usr/lib/pd/extra/unauthorized
path7: /usr/lib/pd/extra/zexy
npath: 7
standardpath: 1
verbose: 0
nloadlib: 0
defeatrt: 0
flags: -nogui -rt -alsa

flagsにコマンドラインオプションを入れることができます。-realtime(-rt)を入れるとPdをリアルタイム優先度で実行できますが、通常のpiユーザーでは権限が弱いためこのオプションが使えずエラーが出ます。こちらのページを参考に設定変更しています。
$ sudo nano /etc/security/limits.conf
以下の2行を追加で記載します。
* - rtprio 99
* - memlock unlimited
※「audio」ユーザーグループだけに設定してもよいのですが、面倒なので全てのユーザーで優先度を上げて実行可能にしています。

設定ファイルのaudiobufとblocksizeを少なくするほど低レイテンシーとなります。しかし少なくしすぎると処理が追いつかず波形が途切れ途切れの状態になり、ノイズが発生します。ですので波形が途切れない限界の値を探っていくことになります。レイテンシーについては別の記事にも記載しています。

-nosleepオプションを入れると「audiobuf 5 blocksize 64」が限界値で、レイテンシーは11msとなりました。しかしエフェクトを切り替えた際にハングアップしてしまうことがあるため、このオプションは入れないことにしました。その場合「audiobuf 6 blocksize 64」が限界値で、レイテンシーは14msでした。聴感上は遅延を感じませんが、複数のエフェクトを処理する場合はもっと遅くなると思われるので、現在はI2S接続のオーディオインターフェイスの使用を検討中です。

※ちなみにclass4のmicroSDカードを使ったときclass10のものよりレイテンシーが約0.7ms増加していたので、ハイスピードのmicroSDカードはわずかに効果がありそうです。



<自動起動設定>
電源を入れたときにメインプログラム(私の場合はmain.pyというPythonスクリプトファイル)が自動起動されるように設定します。
$ crontab -e
最後に追加 @reboot python /home/pi/main.py
※私はメインプログラム等の使うファイルはすべて/home/pi/フォルダに入れています。

自動起動しているプログラムを終了したいときは下記コマンドを使います。
$ killall python ; killall pd



<リアルタイムカーネル>
下記ページに載っている方法が最も簡単にリアルタイムカーネルを導入できると思われます。
Raspberry Pi 3とリアルタイムカーネル(3)[自前ビルド無し導入編(おまけ)]
しかしながらはっきりとはわかりませんが、Pdで「tried but couldn't sync A/D/A」というエラーが発生する原因になる可能性があります。また、私の環境ではレイテンシーがほとんど変わらなかったので、特に導入する必要はないと思います。

<JACK Audio Connection Kit>
いろいろなサイトでふれられているJACKですが、私はどう設定してもうまくいきません。何とか起動できてもレイテンシー24msぐらいだったため、導入をあきらめました。



ハードウェア編へ  ソフトウェア編その1へ  プログラミング編

管理人

ブログ内検索

メールフォーム

当ブログに関するお問い合わせはこちらからお願いします。 ※FAQ(よくある質問)もお読みください。

お名前
メールアドレス
件名
本文

アクセスカウンター