遊びと仕事のグラデーション by Yu Endo

電子楽器づくり大好き!遊びと仕事の間に生きる遠藤祐のブログ

【デジタルエフェクターを作ってみる】第8回 デジタルフィルターをプログラミングしてみる の巻

【デジタルエフェクターを作ってみる】第8回 デジタルフィルターをプログラミングしてみる の巻

今回はプログラミングで基本的なフィルターを作ってみます。

【前回までの記事はこちら】
第1回 デジタルエフェクターを作ってみる
第2回 何を作るか決めました の巻
第3回 オーディオ処理の心臓部はコイツ の巻
第4回 ソフトウェア内部構成を決める の巻
第5回 回路図を描いてみる の巻
第6回 基板ができたよ。プログラムで息を吹き込む準備 の巻
第7回 基板をケースに仮組みしてみる の巻

ちょっと専門的な話になってしましますが、デジタルエフェクターを作る際、オーディオを加工するための信号処理はソフトウェアで実装しますが、どのプログラミング言語で実現するのかが重要になります。

最近のスペックの高いDSP(デジタルシグナルプロセッサ)であればC言語でリアルタイムに信号処理することもできますが、ローコストなdsPICでは、C言語で沢山の処理を詰め込むのは難しいです。

そこで、ここでは、アセンブラで全部の処理をプログラミングしようと思います。
アセンブラとは、機械語とかマシン語とか呼ばれているものです。

私は25年くらい前からMSXのCPUであるザイログ社のZ80のマシン語に目覚めてしまったので、高級言語よりもアセンブラで組むほうが好きだったりします(^^)

dsPICのDSPエンジン

dsPICには、掛け算と足し算、つまり積和演算を1サイクルで行うための命令が搭載されています。

積和演算とは

アキュムレータ ← (16ビット×16ビット)+アキュムレータ
という積和演算を1サイクルで完了することができます。

演算結果を格納するアキュムレータは、40ビット幅なので、オーバーフローを起こさずにダイナミックレンジの広い演算が可能です。

また、dsPIC30にアキュムレータはACCA、ACCBの2個あります。

最終的な出力を16ビットのレジスタに格納する時に、「固定小数点位置をシフトさせてレジスタに格納」までの動作を1サイクルで行えます。

代表的なDSP命令

・MAC命令
    acc = acc + x * y
    acc = acc + x * x

・MPY命令
    acc = x * y
    acc = x * x

・MSC命令
    acc = acc - x * y
    acc = acc - x * x

x、yはレジスタ。accはアキュムレータ。

デジタルフィルタの設計

さて、今回のメインですが、デジタルフィルタを作ります。

歪み系のエフェクターの基本構成として、フィルターは欠かせません。

ampnaibu

ただ、デジタルフィルタといっても身構える必要はなく、簡単なレシピがあります。

RBJ Audio-EQ-CookbookというRobert B Johnson氏が作成した、オーディオ用2次フィルタの設計時に使う公式集を使うと、面倒な計算は不要でサクッとデジタルフィルタを設計することができます。

RBJ Audio-EQ-Cookbook を使ってIIRフィルタを設計

RBJ Audio-EQ-Cookbook

eq_cookbook

http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt

Robert B Johnson氏が作成した、オーディオ用2次フィルタの設計時に使う公式集。

EQクックブックで使用する信号処理実行部のフィルタの式は下記の通りです。

eq_koushiki

つまり、今回の入力音(AD値)と前回の入力音、前々回の入力音、前回の出力音、前々回の出力音さえあれば、あとは適切な係数knをそれぞれに掛け算してやり、合計を求めたものが今回の出音になるという式です。

重要なのは係数の求め方です。

係数の求め方

実は、これもさほど面倒ではありません。

基本的に、5つの係数を求めるための式は、下記の通り。

5つの係数:
  k0 = b0/a0
  k1 = b1/a0
  k2 = b2/a0
  k3 = -(a1/a0)
  k4 = -(a2/a0)

いきなり、axとかbxとか、出てきちゃいましたが、これらは6つの中間係数で、フィルタータイプ毎に異なります。

詳しくはEQクックブックに、公式がそのものズバリで掲載されていますので、ここでは割愛しますが、例えば低音を通して高音を落とすローパスフィルタの場合、

    b0 =  (1 – cos(ω0))/2
    b1 =   1 – cos(ω0)
    b2 =  (1 – cos(ω0))/2
    a0 =   1 + alpha
    a1 =  -2*cos(ω0)
    a2 =   1 – alpha

    ω0 = 2π×周波数/サンプリング周波数
    alpha = sin(ω0)/(2*Q)

これで、求めることができます。

フィルタータイプを決めたあと、フィルターを作用させる周波数とフィルターのQ値を決めれば係数を求めることができます。

ちなみに、HPFの場合は、

    b0 =  (1 + cos(ω0))/2
    b1 = -(1 + cos(ω0))
    b2 =  (1 + cos(ω0))/2
    a0 =   1 + alpha
    a1 =  -2*cos(ω0)
    a2 =   1 – alpha

LPFとはちょっと式が異なります。

けど、実行部で必要な信号処理の式は変わらずに、係数だけを入れ替えるだけで、LPFとHPFが切り替わるなんて、面白いですよね。

アセンブラで実際に記述

dsPICで実際にコーディングしてみるとどんな感じかご覧ください。

IMG_6876

もちろん、お手製のアセンブラのシートを手元にコーディングします。

 

係数メモリ確保

式で使っている入力音xと、出力音y、係数kのエリアを確保します。

.section    .xbss, bss, xmemory
    XY:       .space 10        ; x0, x1, x2, y1, y2の順に5個格納
.section    .ybss, bss, ymemory
    K:        .space 10        ; k0, k1, k2, k3, k4の順に係数5個格納

信号処理実行部

フィルタの信号処理はMPYから始まる5行です。

.section .text
    MOV    W0,        XY            ; x0格納
    MOV    #XY,       W8
    MOV    #K,        W10
    CLR    A,    [W8]+=2, W4, [W10]+=2, W5      ; アキュムレータをクリア
                                                ; アドレスW8が指すメモリの内容x0値をW4に格納
                                                ; アドレスW10が指すメモリの内容k0値をW5に格納
                                                ; アドレスW8をインクリメント
                                                ; アドレスW10をインクリメント

    MPY W4*W5, A, [W8]+=2, W4, [W10]+=2, W5
    MAC W4*W5, A, [W8]+=2, W4, [W10]+=2, W5
    MAC W4*W5, A, [W8]+=2, W4, [W10]+=2, W5
    MAC W4*W5, A, [W8]+=2, W4, [W10]+=2, W5
    MAC W4*W5, A, [W8]+=2, W4, [W10]+=2, W5

最後の5行が実際の実行部の数式です。

asmtoshiki

 

<出力データの取り出しとXYメモリのシフト>
    MOV [W8-#10],      W1                              ; X[1] -> X[2]
    MOV W1,            [W8-#8]
    MOV W0,            [W8-#10]                        ; X[0] -> X[1]
    MOV [W8-#6],       W0                              ; Y[1] -> Y[2]
    MOV W0,            [W8-#4]
    ; Qフォーマットに応じてシフト
    SAC.R A, #-1,      W0
    MOV W0,            [W8-#6]                         ; Y[0] -> Y[1]

coding1

おわりに

如何でしたか?

デジタルフィルタと言っても係数を設計するレシピがあるので、意外と簡単に作ることができると思います。

もちろんCで組めばもっと簡単に実現できると思います。

私は、フィルター以外にも様々な信号処理を組み込みたいと思っているからアセンブラでやっていますが、まずは作ってみることが何よりも重要と思いますので、Cでも別の言語でも試せるもので是非、フィルターで遊んでみてください。

面白いですよ!

zenkei

About The Author

株式会社ソニックウェアファウンダー / 代表取締役CEOYu Endo
SONICWARE inc. Founder & CEO / I can't help making instruments!! 三度の飯より楽器づくり!

Leave A Reply

*

Comment On Facebook