mcpField
J
juce-plugin

juce-plugin

github.com/shortwavlabs開発699 回インストール3 週間前に更新
リポジトリ

juce-plugin について

JUCE でオーディオプラグインを開発する人向けのスキルです。プロジェクト構成、DSP、パラメーターと状態管理、UI、テストに加え、リアルタイムスレッドの安全性や JUCE 9 の WebView UI も扱います。

主な機能

  1. 01AudioProcessor とエディターの構成
  2. 02APVTS によるパラメーターと状態の管理
  3. 03DSP とリアルタイムスレッド安全性の案内
  4. 04各種プラグイン形式向け CMake ビルド
  5. 05JUCE 9 WebView UI の解説

活用シーン

  1. 01JUCE オーディオプラグインの新規作成
  2. 02シンセ、エフェクト、MIDI プラグインの実装
  3. 03オーディオスレッドの安全性や性能の調査
  4. 04プラグインへの WebView UI の追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/shortwavlabs/agent-skills --skill juce-plugin

インストール後、Claude Code で/juce-pluginを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
references/
audio-thread-safety.md
cmake-reference.md
dsp-patterns.md
parameter-management.md
performance-investigation.md
plugin-lifecycle.md
production-plugin-practices.md
threejs-webview-ui.md
ui-patterns.md
webview-ui.md
scripts/
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 TRUEMIDI からオーディオを生成します
MIDI エフェクトIS_MIDI_EFFECT TRUEMIDI のみを処理します(オーディオなし)
シンセ + MIDI 出力NEEDS_MIDI_OUTPUT TRUE を追加MIDI も送信するシンセサイザーです

JUCE モジュール

モジュールは構成要素です。最上位のモジュールをリンクすると、推移的な依存関係は自動的に解決されます。

モジュール用途リンク
juce_audio_utilsオーディオユーティリティ、MIDI キーボードjuce::juce_audio_utils
juce_dspDSP:フィルター、オシレーター、コンボリューション、ProcessorChainjuce::juce_dsp
juce_audio_processorsAudioProcessor、APVTS、プラグイン形式のホスティング(自動的に含まれます)
juce_graphicsグラフィックス、Colour、Path、Image(自動的に含まれます)
juce_gui_basicsComponent、Slider、Button、Label(自動的に含まれます)
juce_gui_extraCodeEditorComponent、WebBrowserComponentjuce::juce_gui_extra
juce_openglプラグインでの OpenGL レンダリングjuce::juce_opengl
juce_oscOpen 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 はプラグインを読み込んでいる間、ファイルをロックします。

コメント