モノフォニックシンセサイザーとしては完成、次は…

 しばらくは開発が順調に(?)進み、何とか単音であればシンセサイザーの音を出せるようになりました。しかし同時発音数が一つ程度であれば、これはマイコンでも実現できる処理です。ここからがFPGA実装の本領発揮で、多ボイス化を行い、同時発音数を増やします。ここで問題が発生しました。

 当初の予定では、1ボイス分のモジュールを作成したら、あとはたくさん並べるだけのはずでした。ところが、回路規模の制約があり、それが難しくなってしまったのです。

 多ボイス化を行うとき、ソフトウエア実装では、インスタンスをボイス分作成すればよいのでした。ところが、回路実装では、モジュールはFPGA上の実際の回路構造になるので、回路規模を消費します。FPGA上に載っている乗算器が、仮に80個だとしましょう。一つの発音モジュールで乗算器を10個消費していたとすれば、この発音モジュールは最大8個しか、FPGA上に載せられません。

 では、一つのモジュールで、1ボイスずつ順番に処理をしていく方法ではどうでしょうか。この場合、FPGA実装の利点は失われてしまいます。出力する1サンプルの値を決定するためには、何クロックかにわたって計算を行う必要があります。1ボイス分の処理が終わってから次のボイスの処理を行う、という形にすると、すべてのボイス分の処理が終わるまでたくさんの時間がかかってしまいます。すべてのボイス分の処理にかかる時間が出力サンプルの間隔を超えてしまうと、この回路は音声を出力できません。

回路のスループットを最大にするには?

 上の問題を、工場のラインを例に考えてみます。

 一つの製品を作り終わってから次の製品を作る…という形は効率が悪く、時間がかかってしまいます。一方でラインを並列にたくさん配置するのも、工場の敷地面積の都合上、限界があります。

 限られた敷地面積と従業員で、最大の作業を行うためには、従業員が休んでいる時間を最小化することが必要です。そう、流れ作業です。これをパイプライン化と呼びます。

 一つのラインに、別々の作業をする従業員を配置し、その上にデータを流しながら計算をしていきます。ラインが1本であれば流れは簡単ですが、実際には複数のモジュールに分かれており、互いに処理結果に依存しているので、それぞれの部品がどこで合流するか、各部品が完成するまで何クロックかかるかによって、適宜遅延を挟む作業が必要となります。タイミングが複雑にはなりますが、これが回路リソースを低遅延で一番効率的に使う方法になります。パイプライン化によるスループット向上はCPUでも使われている一般的な方法ですが、実際に回路として実装してみると、やはり効率的であることが実感できました。

 最終的に、1ボイス分の発音を、すべてパイプライン化することにしました。従って今までパイプライン化を考えずに作成していたモジュールをすべてパイプライン用に書き換えることになりました。こうして完成したシンセサイザーは、

・最大同時発音数:256ボイス
・レイテンシー:5サンプル程度(理論値)
・モジュール:VCO、VCF、VCA、エンベロープ・ジェネレーター(VCO・VCA・VCF用3基)

という性能のものになりました。遅延を感じることなく両手でスムーズに演奏できるほか、ペダルやキーボード上のツマミを使って,演奏者の意図通りのリアルタイムな音色変化を施し、シンセサイザーチックな表現を行うことができます。また、波形テーブルやLFOのパラメーターを変えることで、音作りも行えます。256ボイスまで音を重ねられるので、分厚い音も出すことができます。

 成果発表では得票結果は富田くんに1番を譲りましたが、たくさんの人に試奏していただけました。