カテゴリー
C++ JUCE

JUCEでSimplePianoVisualizerを作る

MIDI Pianoの入力や演奏の様子を鍵盤上で「見る」だけの手頃でシンプルなVisualizer Pluginがなかったので、久しぶりにC++の復習も兼ねて作ってみた。

【C++の復習】juce::MidiKeyboardStateはPluginProcessor.hでインスタンス化し、その他のComponentではその参照を利用する。

// PluginProcessor.h

class SimplePianoVisualizerAudioProcessor  : public juce::AudioProcessor

{
public:

// 省略
  
  juce::MidiKeyboardState& getKeyboardState() {
    return keyboardState;
  } //インスタンスへの参照をゲットするpublic関数

private:
    //==============================================================================
  juce::MidiKeyboardState keyboardState; // ここでインスタンス化
  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SimplePianoVisualizerAudioProcessor)
};
// PluginEditor.cpp

SimplePianoVisualizerAudioProcessorEditor::SimplePianoVisualizerAudioProcessorEditor (SimplePianoVisualizerAudioProcessor& p)
    : AudioProcessorEditor (&p), audioProcessor (p), keyboardState(p.getKeyboardState())
{
    setSize (400, 300);
}

【C++の復習】keyboardComponentはPluginEditor.hでインスタンス化し、initialization listでイニシャライズする。

//PluginEditor.h

class SimplePianoVisualizerAudioProcessorEditor  :  public juce::AudioProcessorEditor

{
public:
    SimplePianoVisualizerAudioProcessorEditor (SimplePianoVisualizerAudioProcessor&);
    ~SimplePianoVisualizerAudioProcessorEditor() override;

    //==============================================================================
    void paint (juce::Graphics&) override;
    void resized() override;

private:
  SimplePianoVisualizerAudioProcessor& audioProcessor;
  juce::MidiKeyboardState& keyboardState;
  juce::MidiKeyboardComponent keyboardComponent;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SimplePianoVisualizerAudioProcessorEditor)
};
//PluginEditor.cpp

SimplePianoVisualizerAudioProcessorEditor::SimplePianoVisualizerAudioProcessorEditor (SimplePianoVisualizerAudioProcessor& p)
    : AudioProcessorEditor (&p), audioProcessor (p), keyboardState(p.getKeyboardState()), keyboardComponent(p.getKeyboardState(), juce::KeyboardComponentBase::horizontalKeyboard)
{

  setSize (400, 300);
}

【JUCEの復習】PluginEditor.cppのコンストラクタとresized()に記述し、画面上に表示する。

// Constructor
{
  addAndMakeVisible(keyboardComponent);

  setSize (400, 100);
  setResizable(true, false);
}

// resized()
void SimplePianoVisualizerAudioProcessorEditor::resized()
{

  auto area = getLocalBounds();
  keyboardComponent.setBounds(area);
}

これを実行すると、以下のように表示されます。縦・横を自由に表示されるようにするには、Sliderなどでサイズを可変にすると良いです。

void SimplePianoVisualizerAudioProcessorEditor::sliderValueChanged(juce::Slider *slider)
{
  horizontalSliderValue = horizontalSlider.getValue();
  verticalSliderValue = verticalSlider.getValue();
  // making sure the resized() (UI changes) are made on the UI thread
  (new SliderValueChangedCallback(this))->post();
}

void SimplePianoVisualizerAudioProcessorEditor::resized()
{
  auto area = getLocalBounds();

  auto verticalMargin = area.getHeight()/2.8;
  auto keyboardArea = area.removeFromBottom(verticalMargin).reduced(30, 0);
  keyWidth = 32 * (horizontalSliderValue/10);
  keyboardComponent.setKeyWidth(keyWidth);
  keyboardComponent.setBounds(keyboardArea.getX(), keyboardArea.getY(), keyboardArea.getWidth(), keyboardArea.getHeight()*(verticalSliderValue/10));

}

PluginProcessorのprocessBlockで下のように処理をすると、キーボードを弾くとスクリーン上のキーボードが反応するようになります。

void SimplePianoVisualizerAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
 
  for(const auto m: midiMessages) {
    keyboardState.processNextMidiEvent(m.getMessage());
  }
}