スライダー以外のGUI部分を作成しました。
配置の調整くらいかな~
JUCEでのディレイプラグイン製、スライダー以外のGUI部分を整えていきました。
赤枠の部分の作成の備忘録になります。
また、Macでビルドしたら、タイマーを使うと正常に機能していない部分をMac版のみプログラムを変更して対応しましたので、その修正点をまとめます。
こんな人の役に立つかも
・JUCEプラグイン開発をしている人
・本ブログのディレイプラグイン作成をしている人
・JUCEでグラフィカルなGUIを作成したい人
プログラムの変更
コンストラクタ
TheDelayAudioProcessorEditor::TheDelayAudioProcessorEditor (TheDelayAudioProcessor& p, juce::AudioProcessorValueTreeState& vts, juce::UndoManager& um)//20211104
//...略...
, undoButton("<-"), redoButton("->")//[1]アンドゥ、リドゥボタンの表記を変更しました。
//...略...
//[2]トグルボタンの色をグレーにします。
getLookAndFeel().setColour(juce::ToggleButton::tickColourId, juce::Colours::grey);
getLookAndFeel().setColour(juce::ToggleButton::tickDisabledColourId, juce::Colours::grey);
setSize (400, 300);
}
[1]で、アンドゥ、リドゥボタンに記載する文字をコンストラクタで変更しました。->という記号がちょうど良い大きさで、わかりやすい記号になったと思います。
[2]では、テンポシンク機能のトグルボタンの枠の色を変更します。デフォルトでは、白なので、背景により見にくくなってしまいます。そのため、setColour関数で、「tickColourId」と「tickDisabledColourId」を「grey」とすることで、トグルボタンの枠と、チェックマークがグレーになりました。
Paint関数
右下のロゴの画像を追加しました。
void TheDelayAudioProcessorEditor::paint (juce::Graphics& g)
{
//...略...
//ロゴの画像を描画します。
juce::Image logo = juce::ImageCache::getFromMemory(BinaryData::logo_png, BinaryData::logo_pngSize);
g.drawImageAt(logo, 250, 220);
}
resized関数
最終的なresized関数でのGUIコンポーネントの配置は次のようになりました。力業で微調整を行っています。
void TheDelayAudioProcessorEditor::resized()
{
//スライダー4個
delayTimeLSlider.setBounds(40, 65, 64, 64);
delayTimeRSlider.setBounds(122, 65, 64, 64);
wetLevelSlider.setBounds(208, 70, 64, 64);
feedbackSlider.setBounds(287, 70, 64, 64);
//コンボボックス
DelayNumerator.setBounds(40, 220, 100, 30);
//テキストボタン
undoButton.setBounds(260, 190, 30, 30);
redoButton.setBounds(300, 190, 30, 30);
//トグルボタン
tempoSyncButton.setBounds(115, 185, 30, 30);
}
Macでのプログラム変更
Macでビルドして、LogicProXでプラグインを動作させると、テンポシンクの機能が正常に動作しておらず、タイマーを使わず音声処理内でパラメータ更新を行うと、うまく動作しました。
音声処理内で条件などを利用する部分について、少し後ろめたい感じもありましたが、正常に動作しましたので、Mac版については、この方式で行きたいと思います。
コンストラクタのタイマーを起動させないようにしました。
//AudioProcessorクラスのコンストラクタです。
{
//...略...
//タイマーを停止します。
//startTimerHz(30);
}
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;
if (tempopSyncState == true) {
playHead = this->getPlayHead();
playHead->getCurrentPosition(currentPositionInfo);
current_bpm = currentPositionInfo.bpm;
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);
if (val2 >= 2.0f) {
val2 = 1.99f;
}
val3 = val2;
}
else {
val2 = *delayTime_L;
val3 = *delayTime_R;
if (val2 >= 2.0f) {
val2 = 1.99f;
}
if (val3 >= 2.0f) {
val3 = 1.99f;
}
}
processorChain.get<DelayIndex>().setDelayTime(0, val2);
processorChain.get<DelayIndex>().setDelayTime(1, val3);
//ここまでを追加しました。
float val4 = *wetLevel;
float val5 = *feedback;
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);
}