JUCEのバス関連クラスや関数がいろいろと存在して、わかりにくいので、調べてまとめてみました。
対象のソースは、現在のリリース版である、5.2.0です。
まとめ方が雑なのはご容赦ください。また、網羅的に解説しているわけではなく、ある程度自明な関数や、あまりに内部的な関数や、ややこしくて目を背けた関数やなんかは含めていません。
それと、勘違いしている部分や正しくない書き方になっている箇所があるかもしれないです。気づいた方はぜひお知らせください。
AudioProcessor::BusesProperties
https://juce.com/doc/structAudioProcessor_1_1BusesProperties
-
AudioProcessor
に設定するバス情報を構築するためのヘルパークラス。 -
withInput()
/withOutput()
メンバ関数によって、メソッドチェーン方式で入力用/出力用それぞれのバス情報を構築できる。 - このオブジェクトでバス情報を構築して、それを
AudioProcessor
クラスのコンストラクタに渡すと、それに従ってAudioProcessor
のバスが設定される。
class MyAudioPlugin :
{
MyAudioPlugin()
: AudioProcessor(BusesProperties()
.withInput ("Input", AudioChannelSet::stereo(), true)
.withInput ("Side Chain", AudioChannelSet::mono(), true)
.withOutput ("Output", AudioChannelSet::stereo(), true)
)
// ステレオ入力/ステレオ出力と
// サイドチェイン入力(モノラル)をもつプラグインになる
{}
/* ... */
};
AudioProcessor::BusProperties
https://juce.com/doc/structAudioProcessor_1_1BusProperties
-
BusesProperties
が保持する、入力用あるいは出力用のバスひとつの情報を表すクラス。 - 以下の3つのプロパティを持つ。(
BusesProperties
のwithInput()
/withOutput()
メンバ関数に渡されたものがここに設定される。)- バス名
- デフォルトのチャンネル情報(c.f.
AudioChannelSet
) - デフォルトで有効かどうかのフラグ
- 具体的には、下記の
Bus
クラスの初期時に、デフォルトのチャンネル情報が、getCurrentLayout()
メンバ関数の値として最初からセットされるかどうかを表す
- 具体的には、下記の
AudioChannelSet
https://juce.com/doc/classAudioChannelSet
- チャンネル情報のコンテナ。
- 複数のチャンネルを保持し、どのチャンネルがどのスピーカーに対応するかの情報も持つ。
isDisabled() constメンバ関数
- 自身のチャンネル情報が有効か/無効かを判定する。
- デフォルトコンストラクタによる構築後など、チャンネル情報が一つも設定されてない状態のときは
true
を返し、そうでないときはfalse
を返す。
AudioProcessor::Bus
https://juce.com/doc/classAudioProcessor_1_1Bus
-
AudioProcessor
が持つバス本体のクラス。このクラスのオブジェクトひとつでバスひとつ分を表す。 - このクラスは、
AudioProcessor
クラスのコンストラクタの中で、引数として渡されたBusesProperties
の情報をもとにして初期化される。 -
Bus
が表すチャンネル情報は、プラグインがサポートしていればBusesProperties
で指定したもの以外に変更できる。-
Bus
は、そのBus
デフォルト値としてのチャンネル情報と、現在のチャンネル情報、最後に有効な値がセットされたときのチャンネル情報の3つのチャンネル情報を持つ。
-
const AudioChannelSet& getDefaultLayout() constメンバ関数
-
BusesProperties
で指定した、デフォルト値としてのAudioChannelSet
を返す。
const AudioChannelSet& getCurrentLayout() constメンバ関数
- 現在
Bus
に設定されているAudioChannelSet
を返す。 -
Bus
には無効なAudioChannelSet
が設定されている可能性がある、その時は、この戻り値も無効なAudioChannelSet
となる。
const AudioChannelSet& getLastEnabledLayout() constメンバ関数
- 有効なチャンネル表現を持っていて最後にBusに設定された
AudioChannelSet
を返す。 -
AudioProcessor
のコンストラクタ呼び出し直後は、getDefaultLayout()
メンバ関数と同じものが返る。
bool isEnabled() constメンバ関数
-
Bus
の有効/無効状態を返す。 - 実際には、
Bus
の現在のチャンネル情報(つまりgetCurrentLayout()
メンバ関数で返るAudioChannelSet
)の有効/無効状態を返す。
bool setCurrentLayout(const AudioChannelSet&)メンバ関数
- この
Bus
の現在のチャンネル情報を、指定したAudioChannelSet
に変更する。 - 内部的には、この
Bus
を保持しているAudioProcessor
のsetChannelLayoutOfBus()
メンバ関数を呼び出すだけ。
bool setCurrentLayoutWithoutEnabling(const AudioChannelSet& layout)メンバ関数
-
setCurrentLayout()
と同じように、Bus
のチャンネル情報を、指定したAudioChannelSet
に変更するが、Bus
の有効/無効状態は変化させない。 - もし
Bus
が有効なら、Bus
のsetCurrentLayout()
を呼び出して、指定したAudioChannelSet
をBus
の現在のチャンネル情報として設定する。 - もし
Bus
が無効なら、指定したAudioChannelSet
がこのBus
によってサポートされているものかどうかを判定した上で、最後に有効だったAudioChannelSet
(つまりgetLastEnabledLayout()
で返るもの)として、チャンネル情報を保持する。
bool setNumberOfChannels(int channels)メンバ関数
- 指定したチャンネル数を持つように、
Bus
のチャンネル情報を設定する。 - 実質的には、指定したチャンネル数に適合する
AudioChannelSet
を作成し、setCurrentLayout()
の処理と同じように、AudioProcessor
のsetChannelLayoutOfBus()
を呼び出す
bool isLayoutSupported(const AudioChannelSet& set, BusesLayout* currentLayout = nullptr) constメンバ関数
- 指定した
AudioChannelSet
をBus
に設定可能かどうかを返す -
currentLayout
がnullptr
でない場合は、AudioProcessor
のバス全体が、そのスナップショットの状態であるとみなして、処理を行う。そして、関数から抜ける際に、指定されたAudioChannelSet
を適用した場合に、AudioProcessor
のバス全体の状態がどうなるかを、currentLayout
に設定する。- 一つの
Bus
に対するチャンネル情報の変更によって、他のBus
の状態も変更されてしまう可能性がある。そのため、このようにして、変更後の状態を確認できるようになっている。
- 一つの
bool isNumberOfChannelsSupported (int channels) constメンバ関数
- 指定したチャンネル数を持つようにこの
Bus
のチャンネル設定を変更できるかどうかを返す。
AudioChannelSet supportedLayoutWithChannels(int channels) constメンバ関数
- この
Bus
が、指定したチャンネル数のチャンネル設定をサポートしている場合に、そのチャンネル設定を返す。
BusesLayout getBusesLayoutForLayoutChangeOfBus(const AudioChannelSet&) constメンバ関数
- 指定した
AudioChannelSet
をこのBus
に適用しようとした場合に、バス全体の状態がどのようになるかを、BusesLayout
で返す。
AudioProcessor::BusesLayout
https://juce.com/doc/structAudioProcessor_1_1BusesLayout
-
AudioProcessor
が保持しているバス全体のスナップショットを表すクラス。 - 入力用/出力用それぞれのバスのチャンネル情報を、2つの
AudioChannelSet
の配列に保持する。 -
AudioProcessor
の現在のバス状態を表すだけではなく、「AudioProcessor
のバスひとつのチャンネル情報を変更した場合に、バス全体のチャンネル状態がどうなるか」というような、仮のバス状態を表すためにも使用される。
AudioProcessor
https://juce.com/doc/classAudioProcessor
- プラグイン本体。
-
Bus
クラスを、入力用/出力用の2つの配列に保持して、複数のバスを扱う。
virtual bool canAddBus(bool isInput) const/virtual bool canRemoveBus(bool isInput) constメンバ関数
- プラグインのバスを動的に追加/削除できるかどうかを判定する関数。
- このメンバ関数をオーバーライドすると、自身のプラグインでバスを動的に追加/削除できるかどうかを指定できる。
- ただし、VST/VST3ではこの仕組みはサポートされていないので、このメンバ関数をオーバーライドしてもバスを追加/削除可能にはできない。コンストラクタで最初にバスを設定しておく必要がある。
- AudioUnitではこの仕組みがサポートされているので、オーバーライドによって、バスの追加/削除を可能にできる。(https://github.com/WeAreROLI/JUCE/blob/9f6126779c63cbe2e07719d9453c0d506b562a25/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm#L295)
bool addBus(bool isInput)メンバ関数
- この
AudioProcessor
にバスを一つ追加する。canAddBus()
やcanApplyBusCountChange()
でfalse
を返した場合には、バスは追加されずに、false
が返る。
bool removeBus(bool isInput)メンバ関数
- この
AudioProcessor
の末尾のバスを一つ削除する。canRemoveBus()
やcanApplyBusCountChange()
でfalse
を返した場合には、バスは追加されずに、false
が返る。
bool setBusesLayout(const BusesLayout&)メンバ関数
- 指定した
BusesLayout
が保持する状態を、すべてのBus
の現在のチャンネル情報として適用する - 内部的に
canApplyBusesLayout()
を呼び出して、このレイアウトが適用可能かどうかを判定する。その呼び出しでfalse
が返された場合には、レイアウトを適用しない。
bool setBusesLayoutWithoutEnabling(const BusesLayout&)メンバ関数
-
setBusesLayout()
と同じように、指定したBusesLayout
が保持する状態を、すべてのBus
に適用する - ただし、
setBusesLayout()
と異なり、各Bus
の有効/無効状態は変化させない。- 有効な
Bus
に対して有効なAudioChannelSet
が適用されようとした場合は、setBusesLayout()
と同様に、Bus
の現在のチャンネル情報が更新される。 - 無効な
Bus
に対して有効なAudioChannelSet
が適用されようとした場合は、そのBus
の最後に有効だったチャンネル情報が更新される。
- 有効な
virtual bool isBusesLayoutSupported(const BusesLayout&) const
- 渡されたレイアウトが、このプラグインでサポートされているものかどうかをbool値で返す。
- 開発しているプラグインで、特定のレイアウトをサポートするかどうかをカスタマイズしたいときは、このメンバ関数をオーバーライドして、挙動を変更する。
- 例えば、ある
Bus
では5.1chサラウンドのチャンネル設定を許可したいとき、渡されたレイアウトで、このBus
に対するAudioChannelSet
がステレオのようなチャンネル数が異なるものになっていたり、チャンネルの構成が"6.0ch"や"hexagonal"のようなチャンネル数は合っていてもチャンネルの構成が期待通りでない場合にfalse
を返すと、そのレイアウトを拒否できる。
virtual bool canApplyBusesLayout(const BusesLayout&) const
- 渡されたレイアウトを、この
AudioProcessor
に実際に適用できるかどうかを返す -
isBusesLayoutSupported()
がtrue
を返す場合でも、レイアウトの適用を拒否したい状況のために、このメンバ関数が用意されている。- 例えば、
isBusesLayoutSupported()
がtrue
を返したとしても、実際にそのレイアウトを適用できるかどうかがプラグインの現在のパラメータ状態に依存する、というようなケースなど。ちょっと特殊。
- 例えば、
- 通常は、プラグイン開発者がこのメンバ関数をオーバーライドすることは、ほとんどないはず。既定の実装は、単に
isBusesLayoutSupported()
を呼び出してその結果を返すだけ。- ホストとしてVST3プラグインをロードするときにJUCEの内部的に使用される
VST3PluginFormat
というクラスでは、この関係が逆転して、isBusesLayoutSupported()
のオーバーライドからcanApplyBusesLayout()
のオーバーライドを呼び出している。
- ホストとしてVST3プラグインをロードするときにJUCEの内部的に使用される
virtual bool canApplyBusCountChange(bool isInput, bool isAddingBuses, BusProperties& outNewBusProperties)メンバ関数
-
AudioProcessor
のバスを追加/削除できるかどうかを判定する関数。 -
isBusesLayoutSupported()
に対するcanApplyBusesLayout()
と同じような意味合いで、canAddBus()
/canRemoveBus()
がtrue
を返す場合でも、バスの追加/削除を拒否したいような状況を考慮して、このメンバ関数が提供されている。ちょっと特殊。 - 通常は、プラグイン開発者がこのメンバ関数をオーバーライドするケースはほとんどないはず。
- 既定の実装では、入力用か出力用に指定されたバスの追加/削除を、
canAddBus()
/canRemoveBus()
で判定し、isAddingBuses == true
のときは、追加するバスの仮の情報をoutNewBusProperties
に設定するようになっている。
bool checkBusesLayoutSupported(const BusesLayout& layouts) constメンバ関数
- 指定した
BusesLayout
が、このAudioProcessor
のバスでサポートされているかどうかを返す。 - 実質的には、
layouts
に含まれる入力用/出力用それぞれのバスの数が、AudioProcessor
の現在のバスの数と一致するかどうかをチェックしてから、isBusesLayoutSupported(layouts)
の呼び出し結果を返すだけ。
bool setChannelLayoutOfBus(bool isInputBus, int busIdx, const AudioChannelSet& layout)メンバ関数
- 指定したバスに対して、指定したチャンネル情報をセットする。
-
Bus
のsetCurrentLayout()
メンバ関数の呼び出しも、この関数の呼び出しとなる。 - 内部で
Bus
のgetBusesLayoutForLayoutChangeOfBus()
を呼び出して、layout
適用後のバス状態を取得し、layout
が正しく適用されるどうかを判定する。適用されること確認できた場合は、applyBusLayouts()
を呼び出して、layout
適用後のバス全体の状態をすべてのバスに適用する。
bool applyBusLayouts(const BusesLayout &layouts)メンバ関数
- 指定したレイアウトをバス全体に適用する関数。
- 処理が成功した場合は、
audioIOChanged()
メンバ関数を呼び出す。
void audioIOChanged(bool busNumberChanged, bool channelNumChanged)メンバ関数
-
addBus()
/removeBus()
/applyBusLayouts()
などによって、バスの状態が変更されたときに呼び出される関数。 - 各
Bus
が内部的に持っているチャンネル数の情報を更新し、numBusesChanged()
やnumChannelsChanged()
などのコールバック関数を呼び出す。
containsLayout()/getNextBestLayoutInLayoutList() staticメンバ関数
- Projucerのチャンネル設定機能を使用したときに使用されるメンバ関数。下のセクションを参照。
Projucerにある、プラグインのチャンネル設定機能について
今のバス関連API(MultiBus API
)が用意される以前のJUCEでは、プラグインのバスがサポートするチャンネル情報は、Introjucer(Projucerの前身)によって設定していた。
具体的には、Introjucerで.jucer
ファイルを開いたときに、Project Settings
のPlugin Channel Configuration
というプロパティに{1, 1}, {2, 2}
のようにして値を設定すると、1in/1outか2in/2outのバス接続をサポートするようなプラグインが作成できる仕組みになっていた。
この方式は、プラグインがサポートできるチャンネル数がコンパイル時に決まっている必要があり、また、どのチャンネルがどのスピーカーに対応するかというチャンネル情報も指定できないため、柔軟性に欠けていた。
それを解決するための新しいバスの仕組みが一度JUCE 4.1.0で導入されたが、いろいろ問題があったのかその仕組みもdeprecatedとなり、その後、今の形に近いMultiBus API
がJUCE 4.3.0のあたりで導入された。
https://forum.juce.com/t/multibus-api/18491
柔軟性に欠けるとはいえ、この方式は簡潔であり、またおそらく後方互換性も考慮してか、この仕組みはいまも取り除かれずに残されている。
(というか、JUCE 4.1.0の時点でこの仕組みは、deprecated扱いになっていたのだが、現在もProjucerで使用でき、deprecatedという表示も外されているようなので、このまま残していく方針なのだろうか?)
また、juce_RTAS_Wrapper.cpp
というソースには、このマクロに適切な値が設定されていることを期待している箇所があるので、もしRTASという規格でプラグインを作成する場合は、この仕組みを使う必要があるようだ。
現在、Projucerで.jucer
ファイルを開いて、このプロパティに値(例えば{1, 2}, {3, 4}
)を設定すると、AppConfig.h
ファイル内に、
#ifndef JucePlugin_MaxNumInputChannels
#define JucePlugin_MaxNumInputChannels 3
#endif
#ifndef JucePlugin_MaxNumOutputChannels
#define JucePlugin_MaxNumOutputChannels 4
#endif
#ifndef JucePlugin_PreferredChannelConfigurations
#define JucePlugin_PreferredChannelConfigurations {1, 2}, {3, 4}
#endif
のようなマクロが定義される。
このマクロが定義されているときは、MultiBus API
の機能が制限されて、いくつかの箇所で、このマクロの値を優先して使用するようになる。また、前のセクションの最後にある、containsLayout()
/getNextBestLayoutInLayoutList()
staticメンバ関数は、このマクロが定義されているときにだけ使用される。
Projucerで表示されるこのプロパティの説明文にあるように、この方式を使用したときには、サイドチェインやAUX出力用のバスをプラグインに指定できない。そのため、そのような機能を持つプラグインを作成したい場合には、このプロパティの値を空にして上記のマクロが定義されないようにし、冒頭のBusesProperties
クラスを使用する必要がある。