JUCEって何?
JUCE (Jules' Utility Class Extensions)は、C++言語によるマルチメディア系アプリケーションの開発を支援するフレームワークです。クロスプラットフォーム設計のライブラリと、付属されているプロジェクトジェネレータ『Projucer』から各種IDE(VisualStudio, Xcode, Makefile)向けにプロジェクトファイルを出力することで、ワンソースからWindows, macOS, Linux, iOS, Android で動作するアプリケーションを作成することができます。
公式サイト
JUCEの最大の特徴として、オーディオプラグインを開発するためのテンプレートが充実していることが挙げられます。VST/AudioUnit/AAX/RTASプラグインといった、DTMユーザーにはお馴染みのプラグインフォーマットを開発するのに長けており、日本国内外で多くの採用事例があります。
JUCEについてより詳しく知りたい場合は、こちらの記事JUCE ハンズオン 〜JUCEをはじめよう〜や、JUCE Advent Calendar 2017をご覧いただければと思います。
JUCE 5.4.0からUnity Native Audio Pluginが正式サポート
これまではVST/AudioUnit/AAXといったDAW向けのオーディオプラグインのビルドがサポートされていましたが、5.4.0からはUnityゲームエンジンのNative Audio Pluginも仲間に加わりました。
これにより、VSTとして開発していたDSPのコードを、そのままUnity上で実行することができるようになります。
参考: https://juce.com/discover/stories/unity-native-plug-in-support
Unity Native Audio Pluginとは
UnityのAudio Mixerコンポーネントにインサートすることができるプラグイン形式のDSPです。
参考: https://docs.unity3d.com/Manual/AudioMixerNativeAudioPlugin.html
新規プロジェクトを作成する
それでは、サイン波を生成するオーディオプラグイン『HelloSinewave』を作成してみましょう。
プロジェクト作成ウィザードからAudio Plugi-In
を選択します。
プロジェクト設定で[Plugin Formats]内のUnity
にチェックを入れる
プロジェクトをIDEで開く
プロジェクト一覧にUnity用のプロジェクトが追加されていることが分かります。
HelloSinewaveのコーディング
PluginProcessor.h
を開き、メンバ変数を追加します。
class HelloSinewaveAudioProcessor : public AudioProcessor
{
~~~省略~~~
private:
AudioParameterFloat* angleDelta; // プラグインのパラメータ
float angle = 0; // サイン波の位相
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HelloSinewaveAudioProcessor)
};
PluginProcessor.cpp
を開き、パラメータのインスタンス生成・登録と、サイン波をレンダリングする処理を実装します。
HelloSinewaveAudioProcessor::HelloSinewaveAudioProcessor()
#ifndef JucePlugin_PreferredChannelConfigurations
: AudioProcessor (BusesProperties()
#if ! JucePlugin_IsMidiEffect
#if ! JucePlugin_IsSynth
.withInput ("Input", AudioChannelSet::stereo(), true)
#endif
.withOutput ("Output", AudioChannelSet::stereo(), true)
#endif
)
#endif
{
// パラメータのインスタンス生成とパラメータの登録
angleDelta = new AudioParameterFloat("ANGLE_DELTA", "Angle Delta", 0.0f, 1.0f, 0.1f);
addParameter(angleDelta);
}
void HelloSinewaveAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear (i, 0, buffer.getNumSamples());
// サイン波をレンダリングする処理
for (int sampleIndex = 0; sampleIndex < buffer.getNumSamples(); sampleIndex++)
{
angle += angleDelta->get();
for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
auto* channelData = buffer.getWritePointer(channel);
channelData[sampleIndex] = std::sinf(angle) * 0.3f;
}
}
}
ビルドを実行
ビルドが完了すると、ファイル名にaudioplugin_
の接頭辞が追加された動的ライブラリが生成されます。
Unityで実行する
Unityでプロジェクトを作成する
Unityを開き、Native Audio Pluginの実行に必要な作業を行います。
- AudioSourceコンポーネントをシーンに追加する
- AudioMixerをアセットに追加する
- AudioMixerをAudioSourceコンポーネントの
Output
にセットする - audioplugin_HelloSinewaveをアセットに追加する
AudioMixerにプラグインを追加する
AudioMixerファイルを選択したら、インスペクターから[Add Effect]をクリックして、リストに表示されたaudioplugin_HelloSinewave
をクリックします。
シーンを再生する
シーンを再生すると、audioplugin_HelloSinewave
によってミキサーのトラックにサイン波が流れます。
インスペクターの[Edit in Playmode]をクリックすると、シーン再生時にパラメータをインスペクターから操作することができます。
[Angle Delta] パラメータを操作すると、サイン波のピッチ(周波数)が上下することが確認できます。
プラグインのパラメータをC#スクリプトから操作できるようにする
インスペクターに表示されたパラメータ名を右クリックすると、コンテキストメニューにExpose xxx
という項目が表示されます。
この項目を有効にしたパラメータはC#スクリプトからアクセスすることができるようになります。
スクリプト用に抽出されたパラメーターは、SetFloat 関数を使って設定することができます。
参考: オーディオミキサーパラメーターの抽出 (Exposed Parameters)
注意点
Unity Native Audio PluginではMIDI入出力を扱うことができません。
そのため、MIDIデータをトリガーとして処理を実行するようなインストゥルメント系などを移植する場合は、別途トリガー系のパラメータを用意しておくなどの実装が必要になるでしょう。