C++
MIDI
JUCE
JUCEDay 19

JUCEのMIDI入力受付処理への理解を深める。

本記事はJUCE Advent Calendar 2017 の12月19日向けに投稿した記事です。

はじめに

初めまして、MachiaWorksと申します。
本業そこそこに趣味で作曲したりゲームやシンセサイザーのプログラム書いたりしてます。

で、ちょこちょこJUCEいじってました。
今回は「MIDI入力処理の大まかな流れ」についてサンプル見ながら書いていこうかと。
半ばメモ書きになってる部分もありますがご了承下さい。
1月初旬あたりに修正予定+Blocks持ってるのでそれをいじる形としたいかな、と。

参考資料

https://juce.com/doc/tutorial_handling_midi_events

上記リンク見てしまうと終わりなんですがそれはそれで。

サブ資料として以下のページも。

https://juce.com/doc/tutorial_midi_message
https://juce.com/doc/classCallbackMessage
https://juce.com/doc/classMidiInputCallback

MIDI入力の処理方法(ざっくりと)

MIDI入力について、大まかな流れとして以下の処理になるかと。
すげえ簡単に書いてるのでツッコミどころはありそうですが。

  • AudioDeviceManagerクラスに入力MIDI機器を登録する
  • MidiInputCallbackクラスのメソッドであるhandleIncomingMidiMessage関数にて、入力されたメッセージを受け取る
  • CallbackMessage クラスのメソッドであるmessageCallback 関数にて届いたMIDIメッセージを処理する。(サンプルではこの中でメッセージのパースを行ってますね)

サンプルを動かして遊んでる様子。
最初からコーディングする量は少ないです。

入力サンプル.PNG

あと面白いのが、MIDI鍵盤の入力について「マウスクリックについても最初から対応しているところ」です。
つまりマウスクリックするとMIDIメッセージとして処理されているということです。

これはMidiKeyboardComponentクラスにて実装されてます。
ただ、その入力元については情報がないようで、サンプルでは「外部からMIDIメッセージを受信した時」のみフラグを立てて外部デバイスとしてコールバック処理、そうじゃないときはオンスクリーンの入力として処理してるみたいです。

また、上記のクリックはMidikeyboardStateオブジェクトで受信してメッセージを処理しており(外部の入力についてメッセージ処理するメソッドを持っている)加えてNoteOn/Offする扱いとしてデータも入力できるみたいで、MidiKeyboardStateオブジェクトに入力データ渡す際に処理を加えることで、コード生成やアルペジエータみたいなこともできそうです。
ここらはサンプルのhandleIncomingMidiMessage関数の実装を見ると理解が深まるかと。

該当クラス資料:
https://juce.com/doc/classMidiKeyboardComponent
https://juce.com/doc/classMidiKeyboardState

コーディングする時に気づいたこと

自分がこういう系統のライブラリ使うのほぼ初めての状態で気づいたことを記載。(どちらかというとライブラリ使うの初めての人向け)

エラーが出る場合、以下の原因であることを考えると、早いとこ解決できるかと思います。

  • 初期に定義するメソッドのオーバーライド関数が不足すると、インスタンスが作られずビルドが失敗する
  • よって、エラーが何かを知る場合、まず自作コンポーネントが継承するクラスと必要なメソッドを中心に調べてみること。

要は仮想関数をオーバーライドする定義が抜けてるってことでした。
JUCEは全般的に必要なメソッドが網羅されているため、こういう形でエラーが出てたのを解決するのに時間かかりました。

使う人には当たり前の部分なんだけど、慣れてない人はエラーどこで取ったらいいんだと悩む(実際自分が悩んだ)ので、まずはエラーのとっかかりだけは知っておいたほうがいいのかなと思います。

逆にエラーの原因が大体理解できると、前述の通り網羅的に整備されているライブラリのため、アプリケーションの実装がかなり早いとこ出来てしまう印象です。

さいごに

ということで、せっかくBlocksも買ってしまったことですし、ちょこちょこJUCEをいじっていこうかと思ってます。
(元々MIDIキーボードの機能不足を補完する目的でBlocks買いましたしね)