juce-plugin について
JUCE でオーディオプラグインを開発する人向けのスキルです。プロジェクト構成、DSP、パラメーターと状態管理、UI、テストに加え、リアルタイムスレッドの安全性や JUCE 9 の WebView UI も扱います。
主な機能
- 01AudioProcessor とエディターの構成
- 02APVTS によるパラメーターと状態の管理
- 03DSP とリアルタイムスレッド安全性の案内
- 04各種プラグイン形式向け CMake ビルド
- 05JUCE 9 WebView UI の解説
活用シーン
- 01JUCE オーディオプラグインの新規作成
- 02シンセ、エフェクト、MIDI プラグインの実装
- 03オーディオスレッドの安全性や性能の調査
- 04プラグインへの WebView UI の追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ shortwavlabs/ agent-skills --skill juce-pluginインストール後、Claude Code で/juce-pluginを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlreferences/audio-thread-safety.mdcmake-reference.mddsp-patterns.mdparameter-management.mdperformance-investigation.mdplugin-lifecycle.mdproduction-plugin-practices.mdthreejs-webview-ui.mdui-patterns.mdwebview-ui.mdscripts/webview_gesture_check.cpp詳細
JUCE オーディオプラグイン開発
JUCE を使用したオーディオプラグインの構築を支援します。JUCE は、オーディオアプリケーションやプラグイン向けのクロスプラットフォーム C++ フレームワークです。単一のコードベースから、プラグインを VST3、AU、AAX、LV2、Standalone 形式にコンパイルできます。
JUCE プラグインの仕組み
JUCE プラグインは、常にペアで構成される2つのコアクラスを持ちます。
- AudioProcessor(エンジン) — DSP のコアです。パラメーターを管理し、
processBlock()でオーディオを処理し、状態の保存と読み込みを行います。リアルタイムオーディオスレッドで実行されます。 - AudioProcessorEditor(GUI) — ビジュアルインターフェースです。APVTS のアタッチメントを介してパラメーターに接続されます。メッセージスレッドで実行されます。
AudioProcessorValueTreeState(APVTS)が両者をつなぎます。オーディオスレッド向けのスレッドセーフなパラメーターアクセス、エディター向けの UI アタッチメント、プリセットや状態の XML シリアライズを提供します。
プロジェクト構成
MyPlugin/
CMakeLists.txt # Build configuration with juce_add_plugin()
Source/
PluginProcessor.h # AudioProcessor subclass declaration
PluginProcessor.cpp # AudioProcessor implementation
PluginEditor.h # AudioProcessorEditor subclass declaration
PluginEditor.cpp # Editor GUI implementation
dsp/ # Custom DSP classes (filters, oscillators, etc.)
components/ # Custom UI components (spectrum displays, etc.)
resources/ # Assets (images, impulse responses, fonts)
ワークフロー:新しいプラグインの作成
1. プロジェクトをセットアップする
JUCE の取り込み方法を決めます。
# Option A: JUCE as subdirectory (most common for plugins)
add_subdirectory(JUCE)
# Option B: System-installed JUCE
find_package(JUCE CONFIG REQUIRED)
2. CMakeLists.txt を作成する
cmake_minimum_required(VERSION 3.22)
project(MyPlugin VERSION 1.0.0)
add_subdirectory(JUCE)
juce_add_plugin(MyPlugin
COMPANY_NAME "YourCompany"
PLUGIN_MANUFACTURER_CODE Yco1 # 4 chars, at least 1 uppercase
PLUGIN_CODE Mp01 # 4 chars, exactly 1 uppercase
FORMATS VST3 AU Standalone # Build targets
PRODUCT_NAME "My Plugin"
IS_SYNTH FALSE
NEEDS_MIDI_INPUT FALSE
NEEDS_MIDI_OUTPUT FALSE
COPY_PLUGIN_AFTER_BUILD TRUE) # Auto-install on build
target_sources(MyPlugin PRIVATE
Source/PluginProcessor.cpp
Source/PluginEditor.cpp)
target_compile_definitions(MyPlugin PUBLIC
JUCE_WEB_BROWSER=0
JUCE_USE_CURL=0
JUCE_VST3_CAN_REPLACE_VST2=0)
target_link_libraries(MyPlugin
PRIVATE juce::juce_audio_utils
PUBLIC
juce::juce_recommended_config_flags
juce::juce_recommended_lto_flags
juce::juce_recommended_warning_flags)
CMake API の全容(SDK パス、バイナリデータ、バンドルリソース、iOS/macOS 固有の設定)については、references/cmake-reference.md をお読みください。
3. プロセッサーを作成する
AudioProcessor のサブクラスでは、特定のメソッドをオーバーライドする必要があります。必要な契約の全容については、references/plugin-lifecycle.md をお読みください。
最小限のプロセッサーのひな型:
// PluginProcessor.h
#pragma once
#include <juce_audio_processors/juce_audio_processors.h>
class MyPluginProcessor : public juce::AudioProcessor
{
public:
MyPluginProcessor();
~MyPluginProcessor() override;
// Audio processing
void prepareToPlay (double sampleRate, int samplesPerBlock) override;
void releaseResources() override;
void processBlock (juce::AudioBuffer<float>&, juce::MidiBuffer&) override;
// Editor
juce::AudioProcessorEditor* createEditor() override;
bool hasEditor() const override;
// Info
const juce::String getName() const override;
bool acceptsMidi() const override;
bool producesMidi() const override;
double getTailLengthSeconds() const override;
int getNumPrograms() override;
int getCurrentProgram() override;
void setCurrentProgram (int index) override;
const juce::String getProgramName (int index) override;
void changeProgramName (int index, const juce::String& newName) override;
// State
void getStateInformation (juce::MemoryBlock& destData) override;
void setStateInformation (const void* data, int sizeInBytes) override;
// Bus layout
bool isBusesLayoutSupported (const BusesLayout& layouts) const override;
// APVTS — the parameter manager
juce::AudioProcessorValueTreeState apvts;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyPluginProcessor)
};
4. APVTS でパラメーターを設定する
すべてのパラメーターをフリー関数内で静的に定義してから、コンストラクターで APVTS を初期化します。パターンの全容(アタッチメント、動的に近いパラメーター、パラメーター以外の状態)については、references/parameter-management.md をお読みください。
// In PluginProcessor.cpp
juce::AudioProcessorValueTreeState::ParameterLayout createParameterLayout()
{
return {
std::make_unique<juce::AudioParameterFloat>(
juce::ParameterID { "gain", 1 },
"Gain",
juce::NormalisableRange<float> (0.0f, 1.0f, 0.001f),
0.5f),
std::make_unique<juce::AudioParameterChoice>(
juce::ParameterID { "filterType", 1 },
"Filter Type",
juce::StringArray { "Low Pass", "High Pass", "Band Pass" },
0),
std::make_unique<juce::AudioParameterBool>(
juce::ParameterID { "bypass", 1 },
"Bypass",
false)
};
}
MyPluginProcessor::MyPluginProcessor()
: AudioProcessor (BusesProperties()
.withInput ("Input", juce::AudioChannelSet::stereo())
.withOutput ("Output", juce::AudioChannelSet::stereo())),
apvts (*this, nullptr, "Parameters", createParameterLayout())
{
}
5. processBlock を実装する
ここでオーディオ処理を行います。リアルタイムスレッドで実行されるため、厳格なルールに従ってください。安全性に関するガイドの全容については、references/audio-thread-safety.md をお読みください。
void MyPluginProcessor::processBlock (juce::AudioBuffer<float>& buffer,
juce::MidiBuffer& midiMessages)
{
juce::ScopedNoDenormals noDenormals;
// Read parameter values (thread-safe via atomics)
auto gainValue = apvts.getRawParameterValue("gain")->load();
for (int channel = 0; channel < buffer.getNumChannels(); ++channel)
{
auto* channelData = buffer.getWritePointer (channel);
for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
{
channelData[sample] *= gainValue;
}
}
}
DSP モジュールのパターン(フィルター、オシレーター、エフェクトチェーン、コンボリューション)については、references/dsp-patterns.md をお読みください。
6. 状態の保存と読み込みを実装する
void MyPluginProcessor::getStateInformation (juce::MemoryBlock& destData)
{
auto state = apvts.copyState();
if (auto xml = state.createXml())
copyXmlToBinary (*xml, destData);
}
void MyPluginProcessor::setStateInformation (const void* data, int sizeInBytes)
{
if (auto xml = getXmlFromBinary (data, sizeInBytes))
if (xml->hasTagName (apvts.state.getType()))
apvts.replaceState (juce::ValueTree::fromXml (*xml));
}
7. エディターを作成する
エディターはアタッチメントを介して UI コントロールを APVTS パラメーターに接続します。カスタムコンポーネント、レイアウト戦略、LookAndFeel のカスタマイズについては、references/ui-patterns.md をお読みください。
// PluginEditor.h
#pragma once
#include <juce_audio_processors/juce_audio_processors.h>
#include "PluginProcessor.h"
class MyPluginEditor : public juce::AudioProcessorEditor
{
public:
MyPluginEditor (MyPluginProcessor&);
~MyPluginEditor() override;
void paint (juce::Graphics&) override;
void resized() override;
private:
MyPluginProcessor& processorRef;
juce::Slider gainSlider;
juce::AudioProcessorValueTreeState::SliderAttachment gainAttachment;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyPluginEditor)
};
// PluginEditor.cpp
MyPluginEditor::MyPluginEditor (MyPluginProcessor& p)
: AudioProcessorEditor (&p),
processorRef (p),
gainAttachment (p.apvts, "gain", gainSlider)
{
addAndMakeVisible (gainSlider);
gainSlider.setSliderStyle (juce::Slider::RotaryHorizontalVerticalDrag);
gainSlider.setTextBoxStyle (juce::Slider::TextBoxBelow, false, 80, 20);
setResizeLimits (200, 150, 800, 600);
setResizable (true, true);
setSize (400, 300);
}
void MyPluginEditor::resized()
{
auto bounds = getLocalBounds().reduced (10);
gainSlider.setBounds (bounds.removeFromTop (100));
}
8. ビルドしてテストする
# Configure
cmake -B build -DCMAKE_BUILD_TYPE=Release
# Build all formats
cmake --build build --config Release
# On macOS, plugins are copied to:
# ~/Library/Audio/Plug-Ins/VST3/
# ~/Library/Audio/Plug-Ins/Components/ (AU)
# On Linux:
# ~/.vst3/
# ~/.lv2/ (if LV2 format enabled)
# On Windows:
# %APPDATA%/VST3/
クロスプラットフォームビルド、GitHub Actions による CI/CD、リリースについては、references/cmake-reference.md をお読みください。
プラグインの種類
JUCE は、CMake プロパティで設定できる複数のプラグインカテゴリーに対応しています。
| 種類 | CMake フラグ | 説明 |
|---|---|---|
| オーディオエフェクト | defaults | オーディオ入力を出力に処理します |
| シンセサイザー | IS_SYNTH TRUE, NEEDS_MIDI_INPUT TRUE | MIDI からオーディオを生成します |
| MIDI エフェクト | IS_MIDI_EFFECT TRUE | MIDI のみを処理します(オーディオなし) |
| シンセ + MIDI 出力 | NEEDS_MIDI_OUTPUT TRUE を追加 | MIDI も送信するシンセサイザーです |
JUCE モジュール
モジュールは構成要素です。最上位のモジュールをリンクすると、推移的な依存関係は自動的に解決されます。
| モジュール | 用途 | リンク |
|---|---|---|
juce_audio_utils | オーディオユーティリティ、MIDI キーボード | juce::juce_audio_utils |
juce_dsp | DSP:フィルター、オシレーター、コンボリューション、ProcessorChain | juce::juce_dsp |
juce_audio_processors | AudioProcessor、APVTS、プラグイン形式のホスティング | (自動的に含まれます) |
juce_graphics | グラフィックス、Colour、Path、Image | (自動的に含まれます) |
juce_gui_basics | Component、Slider、Button、Label | (自動的に含まれます) |
juce_gui_extra | CodeEditorComponent、WebBrowserComponent | juce::juce_gui_extra |
juce_opengl | プラグインでの OpenGL レンダリング | juce::juce_opengl |
juce_osc | Open Sound Control(OSC) | juce::juce_osc |
JUCE の 24 個のモジュールは次のとおりです:juce_analytics、juce_animation、juce_audio_basics、juce_audio_devices、juce_audio_formats、juce_audio_plugin_client、juce_audio_processors、juce_audio_processors_headless、juce_audio_utils、juce_box2d、juce_core、juce_cryptography、juce_data_structures、juce_dsp、juce_events、juce_graphics、juce_gui_basics、juce_gui_extra、juce_javascript、juce_midi_ci、juce_opengl、juce_osc、juce_product_unlocking、juce_video。
WebView UI(JUCE 9)
Web ベースのエディターでは、ブラウザモジュールを有効にし、CMake/WebView2、リレーのライフタイム、フロントエンドパッケージの互換性、オフラインリソース、ジェスチャーについては、最新のWebView 統合リファレンスを参照してください。ネイティブエディターの例にある JUCE_WEB_BROWSER=0 は 1 に変更する必要があります。API シグネチャがインストール済みの JUCE バージョンと一致することを確認してください。
Blender で作成したインタラクティブなアンプ、ペダル、またはラック機器については、Three.js/WebView UIを参照してください。段階的に進める Blender → セマンティック GLB → Three.js モック → JUCE WebView → APVTS のワークフロー、絶対値コントロールとプル/回転コントロール、スイッチ、入力ジャック、連動する表示状態、プラグイン専用のユーティリティ用 UI、オンデマンドレンダリング、ホストでの受け入れ確認について説明しています。APVTS を信頼できる情報源として維持し、ブラウザーより先にリレーを構築し、アタッチメントはブラウザーの後に構築してください。また、WebView に関する処理はすべてオーディオスレッド外で行ってください。
参照ファイル
実装内容に応じて、必要なファイルを参照してください。
references/plugin-lifecycle.md— AudioProcessor の完全な契約:すべてのオーバーライド、バス構成、倍精度、シンセサイザー向け Synthesiser フレームワークreferences/parameter-management.md— APVTS のパターン:パラメータレイアウト、アタッチメント、raw ポインター、パラメータ以外の状態、パラメータグループreferences/dsp-patterns.md— DSP の実践ガイド:ProcessorChain、フィルター、オシレーター、ウェーブシェイパー、コンボリューションリバーブ、ディレイライン、ウェーブテーブル合成、コントロールレートの LFO、2 層のチェーンアーキテクチャ、サンプル単位とブロック単位の処理references/ui-patterns.md— エディターのパターン:コンポーネントのレイアウト、カスタムウィジェット、LookAndFeel、メーター、FFT スペクトラムアナライザー、レスポンシブなサイズ変更、アセット用のバイナリデータreferences/webview-ui.md— JUCE 9 WebBrowserComponent、WebView2、ローカルリソース、ネイティブ関数、パラメータバインディング、フロントエンドフレームワーク、明示的な開発モード、ストリーミングするビジュアルデータ(メーターと再描画のコスト、アイドル状態の許容)references/threejs-webview-ui.md— インタラクティブなギター機材の GLB、モック/JUCE バインディング、物理コントロール、派生ビジュアル状態、要求時レンダリング、シャドウマップの無効化、再描画の頻度、ピクセル比、ドローコール、段階的なホスト検証references/audio-thread-safety.md— リアルタイム安全性のルール:processBlock で実行できること/できないこと、ロックフリーパターン、アトミック、オーディオのグリッチのデバッグreferences/cmake-reference.md— CMake API 全般:juce_add_plugin のすべてのプロパティ、SDK パス、バイナリデータ、CI/CD、プラットフォーム固有の設定references/performance-investigation.md— プラグインの「CPU 使用率が高すぎる」場合の調査:最適化の前にオーディオスレッド、メッセージスレッド、WebView のコストを特定する方法、ヘッドレス測定とライブコールバック測定の比較、テストマトリクス、段階ごとの内訳、ハーネスとライブホスト用ツール、ヌルテスト、複数インスタンスのスケーリング、パフォーマンスゲート、レポートreferences/production-plugin-practices.md— 製品としてのプラグイン開発の実践:CMake プリセット、テスト/測定ターゲット、アセット/モデルの読み込み、状態の復元、レイテンシ/テイルの更新、オーバーサンプリング対応の回路モデルプラグイン(レートポリシー、整数レイテンシ、バイパスパラメータ、モデルリビジョン)、ホスト検証、リリースゲート
よく使うパターン
シンセサイザープラグイン
Synthesiser フレームワークを使用します。ボイスごとの DSP には SynthesiserVoice::renderNextBlock() を、ノート/チャンネルのルーティングには SynthesiserSound をオーバーライドします。パターン全体については、references/plugin-lifecycle.md を参照してください。
サイドチェインエフェクト
コンストラクターにサイドチェインバスを追加します。
BusesProperties()
.withInput ("Input", juce::AudioChannelSet::stereo())
.withInput ("Sidechain", juce::AudioChannelSet::stereo())
.withOutput ("Output", juce::AudioChannelSet::stereo())
processBlock でアクセスします:auto sidechain = getBusBuffer (buffer, true, 1);
マルチバンド処理
juce::dsp::LinkwitzRileyFilter<> のクロスオーバーフィルターを使用してバンドに分割し、各バンドを個別に処理してから、再び合算します。
カスタムプリセットシステム
juce::File を使って XML ファイルとしてプリセットを保存して読み込むか、バイナリデータとして埋め込みます。読み込みには apvts.replaceState() を使用します。
ヒント
- 素早いプロトタイプには
GenericAudioProcessorEditorを使用します — パラメータから UI を自動生成します。createEditor()からnew GenericAudioProcessorEditor(*this)を返すだけです。 - 出荷前のプラグイン検証には
pluginvalを使用します — スレッド、状態、パラメータのバグを検出できます。 getRawParameterValue()のポインターはメンバーとしてキャッシュします —processBlock()内では決して呼び出さないでください。- すべてのバッファーは
prepareToPlay()で事前に確保します —processBlock()内では決して確保しないでください。 - 非正規化浮動小数点数によるパフォーマンスの低下を防ぐため、
processBlock()の先頭でjuce::ScopedNoDenormalsを使用します。 - 最適化の前に CPU 使用率の要因を特定します — ホストのパフォーマンスメーターが測定する対象はホストによって異なります。DSP と UI のどちらに問題があるか判断する前に、エディターを閉じた状態と開いた状態、さらにバイパスした状態で、オーディオコールバックを比較してください(
references/performance-investigation.md)。 - 反復作業を高速化するには、CMake で
COPY_PLUGIN_AFTER_BUILD TRUEを設定します — ビルドのたびにプラグインが自動インストールされます。 - 再ビルドする前に DAW を終了します — DAW はプラグインを読み込んでいる間、ファイルをロックします。