プログラムが見にくくなってきたので、ちょっと整理したいと思いました。
最大遅延時間は一つの場所で管理したいよね〜
定数とするべき最大遅延時間の数値が、手入力で色々な場所に発生していたのでちょっと整理したいな、と感じました。また、ディレイタイムを計算する処理がいくつかの場所で同じ処理を行なっていて、テストなどで処理の一部をコメントアウトしたりする際に変更場所が多くなってしまっているので、その点も少しだけ解消できるようにしてみました。
とても地味な備忘録です、ご了承ください><
ディレイプラグインを作成する前回までの一連の記事は、こちらをご参照ください。
最大ディレイ時間に関する変更
最大遅延時間は今まで適当に2秒と決めて、利用してきました。2秒は流石に短すぎますね^^;
色々なところに最大遅延時間の定数を手入力する場所が発生して、面倒になってきたので、「#define」を使って、最大遅延時間を一つの場所から変更できるように変更を行いました。
#pragma once
#include <JuceHeader.h>
#define MAXDELAYNUM 10.0f//追加しました。
この秒数は、ディレイラインクラスの中で、確保するメモリの量を決定します。10秒くらいあれば、ある程度長めでいいかな、ということで10.0fとしました。
template <typename Type, size_t maxNumChannels = 2>
class Delay
{
public:
Delay()
{
setMaxDelayTime(MAXDELAYNUM);//ここを変更しました。
setDelayTime(0, 0.7f);
setDelayTime(1, 0.5f);
setWetLevel(0.8f);
setFeedback(0.5f);
}
APVTSパラメータのdelayTimeの最大値を次のように変更しました。
std::make_unique<juce::AudioParameterFloat>("delayTimeL",
"DelayTimeL",
0.1f,
MAXDELAYNUM,//ここを変更しました。
0.5f)
,
std::make_unique<juce::AudioParameterFloat>("delayTimeR",
"DelayTimeR",
0.1f,
MAXDELAYNUM,//ここを変更しました。
0.5f)
,
次に、val2とval3の最大値を丸める処理をMAXDELAYNUMに変更していきます。
この処理は、全く同じ処理がprepareToPlay関数と、processBlock関数にあるので2箇所とも変更しました。
//prepareToPlay関数とprocessBlock関数の以下の場所
if (val2 >= MAXDELAYNUM) {
val2 = MAXDELAYNUM - 0.1f;
}
if (val3 >= MAXDELAYNUM) {
val3 = MAXDELAYNUM - 0.1f;
}
}
else {
val2 = *delayTime_L;
val3 = *delayTime_R;
//20211211
if (val2 >= MAXDELAYNUM) {
val2 = MAXDELAYNUM - 0.1f;
}
if (val3 >= MAXDELAYNUM) {
val3 = MAXDELAYNUM - 0.1f;
}
}
ディレイタイムの処理を関数化
ディレイタイムを決める処理が、prepareToPlay関数とprocessBlock関数の2つで同じことを行なっていますので、この処理を関数化することにしました。
class TheDelayAudioProcessor : public juce::AudioProcessor
{
public:
//...略...
private:
//以下の関数を追加しました。
void DelayTimeCalc(float& val2, float& val3);
DelayTimeCalc関数をPluginProcessor.cppに追加しました。
void TheDelayAudioProcessor::DelayTimeCalc(float& val2, float& val3){
if (tempopSyncState == true) {
playHead = this->getPlayHead();
playHead->getCurrentPosition(currentPositionInfo);
current_bpm = currentPositionInfo.bpm;
//test
//current_bpm = 120.0f;
float selected_delayNum = *delayNumerator;
float delayNum = 0.0f;
if (selected_delayNum == 1.0f) {
delayNum = 1.0f;
}
else if (selected_delayNum == 2.0f) {
delayNum = 2.0f;
}
else if (selected_delayNum == 3.0f) {
delayNum = 4.0f;
}
else if (selected_delayNum == 4.0f) {
delayNum = 8.0f;
}
val2 = ((float)60.0 / current_bpm) * (4.0f / delayNum);
selected_delayNum = *delayNumerator2;
delayNum = 0.0f;
if (selected_delayNum == 1.0f) {
delayNum = 1.0f;
}
else if (selected_delayNum == 2.0f) {
delayNum = 2.0f;
}
else if (selected_delayNum == 3.0f) {
delayNum = 4.0f;
}
else if (selected_delayNum == 4.0f) {
delayNum = 8.0f;
}
val3 = ((float)60.0 / current_bpm) * (4.0f / delayNum);
}
else {
val2 = *delayTime_L;
val3 = *delayTime_R;
}
//最大値の丸め処理を記載量を減らすために、最後に持ってきました。
if (val2 >= MAXDELAYNUM) {
val2 = MAXDELAYNUM - 0.1f;
}
if (val3 >= MAXDELAYNUM) {
val3 = MAXDELAYNUM - 0.1f;
}
}
val2とval3が最大時間を超えた時の丸め処理、重複していたので、if条件の外に出しました^^;
この関数を呼び出すべく、prepareToPlay関数とprocessBlock関数を次のように変更しました。
まずはprepareToPlay関数です。
void TheDelayAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
processorChain.prepare({ sampleRate, (juce::uint32) samplesPerBlock, 2 });
processorChain.get<DelayIndex>().setCutoffParam(cutoffParam);
float val2 = 0;
float val3 = 0;
//以下の処理を追加変更しました。
//作成した関数に渡すためのval2とval3の参照を準備します。
float &val2_ref = val2;
float &val3_ref = val3;
DelayTimeCalc(val2_ref, val3_ref);//val2とval3を参照で渡します。
/*以下の関数化した処理は削除しました。
if(tempopSyncState == true){...
*/
float val4 = *wetLevel;
float val5 = *feedback;
//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);
}
次に、processBlock関数です。
void TheDelayAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear (i, 0, buffer.getNumSamples());
float val2 = 0;
float val3 = 0;
//以下の処理を追加変更しました。
//作成した関数に渡すためのval2とval3の参照を準備します。
float &val2_ref = val2;
float &val3_ref = val3;
DelayTimeCalc(val2_ref, val3_ref);//作成した関数にval2とval3を参照で渡します。
/*以下の関数化した処理は削除しました。
if(tempopSyncState == true){...
*/
//...略...
今後やりたい点
今後、調査、改善したい点のメモです。
・ディレイの左右リンクの追加
左右のディレイタイムが一緒に変更されるような機能を追加していきたいです。
・WetをMix?へ機能変更
今のエフェクトのかかり方は、原音に対してWetでエフェクト音を追加していく方式なので、エフェクト音のみを出力することができません。Mix(でいいのでしょうか??)のように、ドライ音とウェット音を別々で変更できるようにして、センドリターンなどで利用できるようなエフェクトになるといいなと考えています「。
・ビット演算を利用した条件の判定
音声処理内で条件を軽量に処理できるようにこの辺りをチュートリアルで勉強していきたいです。
最後に、GUIがダサいなと感じてきました^^;