Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】How I built my own set of audio plugins with JUCE

2026年09月05日に「Dev.to」が公開したITニュース「How I built my own set of audio plugins with JUCE」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

JUCEでオーディオプラグインを開発。自作シンセで音が「問題ない」と思いきや、詳細な計測でエイリアシング問題を発見した。客観的な計測の重要性や、UIとオーディオ処理を分ける開発ノウハウを解説する。

ITニュース解説

このニュース記事は、JUCEというC++オーディオフレームワークを使って独自のオーディオプラグインを開発した経験とその中で得られた教訓について解説している。システムエンジニアを目指す初心者にとって、実際の開発プロセスや直面する問題、そしてその解決策を知る上で貴重な内容だ。

JUCEは、オーディオアプリケーションやプラグインを構築するための強力なツールキットであり、開発者はこれを利用して、さまざまなオーディオ処理機能を実装できる。記事の筆者はJUCE 8を使用し、6つのVST3プラグインをC++で開発した。これらのプラグインは、独自のオンラインストアを通じて配布されている。

JUCEが提供する主要な機能の一つが、juce::dspモジュールだ。これは、オシレーター、フィルター、コンプレッサーといった基本的なDSP(デジタル信号処理)コンポーネントの骨格を提供する。例えば、Basic Oscilatorというシンプルなプラグインでは、JUCEのjuce::dsp::Oscillatorを利用してサイン波、ノコギリ波、矩形波といった波形を生成している。しかし、このモジュールはあくまで「骨格」であり、そのままでは完璧なオーディオ処理が実現できるわけではない。例えば、juce::dsp::Oscillatorは数学的に理想的な波形を生成するが、オーディオ処理において重要な「バンドリミッティング」(高周波成分が折り返してノイズとなるエイリアシング現象を防ぐ処理)は提供しない。これは、フレームワークが提供する範囲とその限界を理解し、残りの部分を開発者自身が実装する必要があるという重要な教訓を示している。

プラグイン開発において共通する重要な原則がいくつかある。一つは、すべてのパラメーター管理にAudioProcessorValueTreeState(APVTS)を使用することだ。これにより、パラメーターの自動化、ホストへの状態保存、プリセットのロードなどが容易になる。二つ目は、オーディオを処理する「プロセッサー」クラスと、ユーザーインターフェース(UI)を描画する「エディター」クラスを明確に分離することだ。これらはアトミック変数やFIFO(First-In, First-Out)バッファを介して安全に通信し、UIがオーディオ処理に影響を与えないようにする。三つ目は、オーディオスレッドでは決してブロックするような重い処理を行わないことだ。オーディオスレッドでの遅延は、いわゆる「クリック」ノイズやドロップアウトを引き起こす。そのため、FFT(高速フーリエ変換)のような計算量の多い処理やグラフィックの描画は、すべてUIスレッドで行い、オーディオスレッドはUIスレッドへのデータ転送に徹する。

個々のプラグインの実装には様々な工夫がある。コンプレッサーのVERTEXではjuce::dsp::Compressorを利用しつつ、その挙動を正確に視覚化する工夫に多くの時間を費やした。リミッターのESP-L1では、瞬時的なアタックタイム(立ち上がり時間)が求められる特性から、JUCEのコンプレッサー機能ではなく独自の検出器を実装している。MEGACRUSHERというディストーションプラグインでは、あえて「数学的に不正確」な処理(tanh、クランプ、折り返し)によって独特な歪み効果を生み出しており、エイリアシングが意図された効果の一部となっている。SPECTRUMというリアルタイムアナライザーでは、オーディオスレッドから送られたデータをUIスレッドでFFTし、多様な視覚化を可能にしている。

特にSYNTH/1というシンセサイザープラグインの開発は、フレームワークの限界を強く感じさせるとともに、オーディオDSP開発における最大の教訓をもたらした。当初、SYNTH/1のオシレーターは、64個のハーモニクス(倍音)を持つ固定の波形テーブルを使用していた。しかし、この設計は、特定の周波数(約344.5Hz、F4あたり)を超えると、本来聞こえないはずのエイリアシングノイズを大量に発生させていた。これは、ハーモニクスがナイキスト周波数(サンプリング周波数の半分)を超え、可聴帯域に折り返されてしまうためだ。筆者はこのバグを長らく認識していなかった。その音は「悪くない」と感じていたが、「音が良い」は測定の代わりにはならないということを痛感した。

このバグを発見し、解決するために筆者が行ったのは、プラグイン内部ではなく、独立した測定環境(「analysis/」フォルダー)を構築することだった。これは、製品版のオシレーターヘッダーを最小限のJUCEスタブでコンパイルし、様々なピッチで連続音をレンダリングして生データをダンプするプログラムと、そのデータをFFTにかけて、真のハーモニクス以外の成分(エイリアシング)を数値化するPythonスクリプトから成る。これにより、どのピッチでどれだけのエイリアシングが発生しているかを客観的に測定できるようになった。この測定の結果、F4より上の音域ではエイリアシングノイズが非常に大きく、出力の10%にも達することが明らかになった。

この問題の解決策として導入されたのが「ミップマッピング」だ。これは、音のピッチに応じて適切なハーモニクス数を持つ複数の波形テーブルを用意し、再生時に切り替える方式である。さらに、スムーズな音色変化のために隣接するミップレベル間をクロスフェードさせたり、補間方法を線形補間から三次エルミート補間に変更したりすることで、エイリアシングノイズを劇的に低減させた。この改善により、ある音域では以前より96dB、別の音域では139dBもエイリアシングが低減されたが、同時に一部の低音域ではわずかに性能が低下するというトレードオフも発生した。この「退行」(4dBの悪化)も隠さず公開していることは、開発における誠実な姿勢を示している。その他にも、フェーズアキュムレーターを倍精度浮動小数点数(double)にすることでより正確なピッチを実現したり、位相ワープ機能のエイリアシング問題が未解決であることを明記したりしている。

筆者は、自分で構築したReactベースのオンラインストアを通じてプラグインを配布している。これは、独自の配布方法を選ぶことで、ビルドステップをなくし、開発プロセスをシンプルにするという選択だ。

この開発経験全体を通して得られた主な教訓は、juce::dspが便利な足場を提供するものの、最終的なオーディオ品質は開発者自身の手に委ねられていること、オーディオスレッドの設計は非常に慎重に行うべきこと、「音が良い」という主観的な判断ではなく客観的な測定の重要性、そして測定結果が予想外の「退行」を示した場合でも、それを正直に公表することの重要性だ。また、問題の本質的な制約を代数的に導き出すことで、早期に問題を特定できる可能性があったことも強調されている。これらの教訓は、システムエンジニアとしてどのような分野に進むにしても、問題解決と品質保証における普遍的な原則として非常に役立つだろう。

関連コンテンツ

関連IT用語

関連ITニュース