少しづつシンプルなディレイを改造していきたいと思います。
まずは基本パラメータを可変にしたいよね~
ディレイプラグインの作成をしています。前回の記事で作成した、シンプルなディレイエフェクトの固定パラメータをAPVTS機能を利用して、可変にしていきたいと思います。
前回の記事の続きとなります。
こんな人の役に立つかも
・JUCEを勉強している人
・JUCEでVSTプラグインを作成したい人
・JUCEでディレイを実装したい人
概要
MaxDelayTimeについては、単純にパラメータ追加すると、バッファのサイズに影響するので、例外にかかってしまいました。いろいろと試してみたのですが、ちょっと現状でリングバッファを動的に可変させるようにできなかった(C++的実力不足^^;)ので、とりあえず今回は、最大遅延時間を固定として、右のディレイ時間、左のディレイ時間、ディレイのウェットレベル、ディレイのフィードバックを調整できるように、APVTSパラメータを導入してみようと思います。
APVTS(AudioProcessorValueTreeState)でのパラメータ追加については、こちらの記事でもまとめていますので、ご参照ください。
追加するパラメータとしては、
・delayTime_L:0.1f~0.9fのフロート型パラメータとしました。初期値は0.5fとします。
・delayTime_R:0.1f~0.9fのフロート型パラメータとしました。 初期値は0.5fとします。
・wetLevel:0.0f~010fの範囲のフロート型パラメータとしました。 初期値は0.8fとします。
・feedback:0.1f~0.99fの範囲のフロート型パラメータとしました。初期値は0.5fとしました。
の4つです。
プロセッサ側
PluginProcessor.h
class TheDelayAudioProcessor : public juce::AudioProcessor
{
public:
//...略...
private:
//以下のパラメータを追加します。
juce::AudioProcessorValueTreeState parameters;
//std::atomic<float>* maxDelayTime = nullptr;
std::atomic<float>* delayTime_L = nullptr;
std::atomic<float>* delayTime_R = nullptr;
std::atomic<float>* wetLevel = nullptr;
std::atomic<float>* feedback = nullptr;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TheDelayAudioProcessor)
};
PrivateなメンバにAudioProcesorValueTreeStateとパラメータを追加しました。
PluginProcessor.cpp
コンストラクタ
次に、コンストラクタでパラメータの設定と初期化を行います。
TheDelayAudioProcessor::TheDelayAudioProcessor()
//...略...
, parameters(*this, nullptr, juce::Identifier("APVTSTutorial"),
{
//[1]パラメータの設定です。
/*std::make_unique<juce::AudioParameterFloat>("maxDelayTime", // ID
"MaxDelayTime", // name
0.1f, // min
2.0f, // max
0.1f) // default
,*/
std::make_unique<juce::AudioParameterFloat>("delayTimeL", // ID
"DelayTimeL", // name
0.1f, // min
0.9f, // max
0.5f) // default
,
std::make_unique<juce::AudioParameterFloat>("delayTimeR", // ID
"DelayTimeR", // name
0.1f, // min
0.9f, // max
0.5f) // default
,
std::make_unique<juce::AudioParameterFloat>("wetLevel", // ID
"WetLevel", // name
0.0f, // min
1.0f, // max
0.8f) // default
,
std::make_unique<juce::AudioParameterFloat>("feedback", // ID
"Feedback", // name
0.1f, // min
0.99f, // max
0.5f) // default
})
{
//[2]パラメータを紐づけます。
//maxDelayTime = parameters.getRawParameterValue("maxDelayTime");
delayTime_L = parameters.getRawParameterValue("delayTimeL");
delayTime_R = parameters.getRawParameterValue("delayTimeR");
wetLevel = parameters.getRawParameterValue("wetLevel");
feedback = parameters.getRawParameterValue("feedback");
}
[1]のように、コンストラクタのイニシャライザでパラメータを設定して、[2]で、パラメータに紐づけを行います。
processBlock関数
次に、音声処理内でパラメータの変更を反映させます。
void TheDelayAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
//...略...
//[1]パラメータを取得します。
//float val1 = *maxDelayTime;
float val2 = *delayTime_L;
float val3 = *delayTime_R;
float val4 = *wetLevel;
float val5 = *feedback;
//[2]パラメータを反映させます。
//processorChain.get<DelayIndex>().setMaxDelayTime(val1);
processorChain.get<DelayIndex>().setDelayTime(0,val2);
processorChain.get<DelayIndex>().setDelayTime(1, val3);
processorChain.get<DelayIndex>().setWetLevel(val4);
processorChain.get<DelayIndex>().setFeedback(val5);
auto block = juce::dsp::AudioBlock<float>(buffer).getSubBlock((size_t)0, (size_t)buffer.getNumSamples());
auto context = juce::dsp::ProcessContextReplacing<float>(block);
processorChain.process(context);
}
[1]では、APVTSのパラメータからパラメータを取得しています。[2]でProcessorChainからディレイモジュールを呼び出し、Delayクラスに定義した各種パラメータ設定関数「set〇〇」系の関数を呼び出しています。音声バッファ毎に、パラメータの反映をさせるので、パラメータの変更は音声バッファの単位で変更が反映されます。
createEditor関数では、APVTSのパラメータをEditorに渡すように変更します。
juce::AudioProcessorEditor* TheDelayAudioProcessor::createEditor()
{
//エディタにパラメータを渡すように引数を追加しました。
return new TheDelayAudioProcessorEditor (*this, parameters);
}
エディタ側
スライダーを4個追加して、APVTSのパラメータを動かすことができるようにスライダーを追加します。
PluginEditor.h
class TheDelayAudioProcessorEditor : public juce::AudioProcessorEditor
{
public:
//[1]引数を追加します。
TheDelayAudioProcessorEditor (TheDelayAudioProcessor&, juce::AudioProcessorValueTreeState& vts);
~TheDelayAudioProcessorEditor() override;
//==============================================================================
void paint (juce::Graphics&) override;
void resized() override;
//[2]アタッチメントのtypedefを追加しました。
typedef juce::AudioProcessorValueTreeState::SliderAttachment SliderAttachment;
private:
TheDelayAudioProcessor& audioProcessor;
//[3]GUIコンポーネントを追加しました。
juce::AudioProcessorValueTreeState& valueTreeState;
//juce::Slider delayMaxTimeSlider;
juce::Slider delayTimeLSlider;
juce::Slider delayTimeRSlider;
juce::Slider wetLevelSlider;
juce::Slider feedbackSlider;
//std::unique_ptr<SliderAttachment> delayMaxTimeAttachment;
std::unique_ptr<SliderAttachment> delayTimeLAttachment;
std::unique_ptr<SliderAttachment> delayTimeRAttachment;
std::unique_ptr<SliderAttachment> wetLevelAttachment;
std::unique_ptr<SliderAttachment> feedbackAttachment;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TheDelayAudioProcessorEditor)
};
[1]では、コンストラクタに、APVTSのパラメータを受け取ることができるように引数を追加しました。[2]では、スライダーのアタッチメントクラスを再定義します。(名前が長いのでtypedefしています。)
[3]に、GUIのスライダーを作成するための、juce::Sliderとパラメータ紐づけのためのアタッチメントを準備します。
PluginEditor.cpp
GUIにスライダーを反映させます。
まずは、引数を追加したので、イニシャライザで[1]のようにAPVTSをvalueTreeStateに受けます。[2]でスライダーの可視化をして、APVTSパラメータに紐づけを行います。
TheDelayAudioProcessorEditor::TheDelayAudioProcessorEditor (TheDelayAudioProcessor& p, juce::AudioProcessorValueTreeState& vts)//add second param
: AudioProcessorEditor (&p), audioProcessor (p), valueTreeState(vts)//[1]
{
//[2]スライダーの初期化をします。
//addAndMakeVisible(delayMaxTimeSlider);
addAndMakeVisible(delayTimeLSlider);
addAndMakeVisible(delayTimeRSlider);
addAndMakeVisible(wetLevelSlider);
addAndMakeVisible(feedbackSlider);
//delayMaxTimeAttachment.reset(new SliderAttachment(valueTreeState, "maxDelayTime", delayMaxTimeSlider));
delayTimeLAttachment.reset(new SliderAttachment(valueTreeState, "delayTimeL", delayTimeLSlider));
delayTimeRAttachment.reset(new SliderAttachment(valueTreeState, "delayTimeR", delayTimeRSlider));
wetLevelAttachment.reset(new SliderAttachment(valueTreeState, "wetLevel", wetLevelSlider));
feedbackAttachment.reset(new SliderAttachment(valueTreeState, "feedback", feedbackSlider));
setSize (400, 300);
}
//...略...
void TheDelayAudioProcessorEditor::resized()
{
//[3]スライダーの配置をします。
//delayMaxTimeSlider.setBounds(10, 10, 200, 30);
delayTimeLSlider.setBounds(10, 40, 200, 30);
delayTimeRSlider.setBounds(10, 70, 200, 30);
wetLevelSlider.setBounds(10, 100, 200, 30);
feedbackSlider.setBounds(10, 130, 200, 30);
}
[3]で、スライダーをGUI上に配置しました。