JUCEでアプリケーション開発、プラグインコーディング4、MIDIデータの加工と動作検証

実際にMIDIデータを変更するプログラムを作成しました。

今回はどちらかというと動作検証が大変だったね~

今回は実際にMIDIデータへ変化を加えるようなプログラムを追加していきます。分量としては大した量ではないのですが、ひとつづつ理解して進めているので、たいして進んでいないのですが、ご了承ください。

チュートリアルページはこちらのページの「Modify MIDI notes」をやっていきます。

前回の続きとなります。前回の記事はこちらをご参照ください。

ぱんだクリップ
JUCEでアプリケーション開発、プラグインコーディング3、GUIスライダーの値を取得する | ぱんだクリップ オブジェクト指向、結構苦手なんですよ ガシガシやって慣れていきたいね~ 引き続き、JUCEチュートリアルを進めています。今回は、「Pass control information to the proc...
目次

MIDIデータへ反映

processBlockのプログラム

「PluginProcessor.cpp」のprocessBlock関数の中身をごっそりと以下のものに変更します。

Processorクラスは、processBlock関数にオーディオやMIDIのバッファが入ってくるようになっています。

C++の参照渡しが利用されています。ここでは、「buffer」が音声のバッファ、「midiMessages」がmidi信号と、簡単にとらえておくことにします。

Qiita
ポインタ渡しより参照渡しを使う - Qiita C++ではポインタ渡しよりも参照渡しを使いたい。既に多くの人が指摘しているでしょうけれども、参照渡しをすることで安全なコーディングをすることができます。ポインタを...

今回はMIDIへ影響を与えるようなプログラムにしていきますので、音声バッファはプログラム最初に「buffer.clear()」をするのみとなっています。

void TutorialPluginAudioProcessor::processBlock (juce::AudioSampleBuffer& buffer, juce::MidiBuffer& midiMessages)
{
    //今回はオーディオバッファーは最初にクリアするのみ
    buffer.clear();
 
    //空のMidiBufferを準備します。
    juce::MidiBuffer processedMidi;
    int time;
    juce::MidiMessage m;
 
    for (juce::MidiBuffer::Iterator i (midiMessages); i.getNextEvent (m, time);)
    {
        //MIDIノートオンに対する反応
        if (m.isNoteOn())
        {
            //uint8ではビルドできなかったのです・・・
            //uint8 newVel = (uint8)noteOnVel;
            uint8_t newVel = (uint8_t)noteOnVel;
            m = juce::MidiMessage::noteOn(m.getChannel(), m.getNoteNumber(), newVel);
        }
        //MIDIノートオフに対する反応
        else if (m.isNoteOff())
        {
        }
        //MIDIアフタータッチに対する反応
        else if (m.isAftertouch())
        {
        }
        //ピッチベンドのMIDIに対する反応
        else if (m.isPitchWheel())
        {
        }
        //空のprocessedMidiに加工済みMidiデータを格納します。
        processedMidi.addEvent (m, time);
    }
    //ここで生のMIDIデータを加工したprocessedMidiの内容に入れ替えます。
    midiMessages.swapWith (processedMidi);
}

MIDIのバッファーには、次のようにfor文でアクセスできるようです。

「for (juce::MidiBuffer::Iterator i (midiMessages); i.getNextEvent (m, time);)」

このfor文は定型になりそうな予感がします。そして、mに取得してきたMidiのメッセージ内容に対して条件文で反応します。

・isNoteOn:MIDIノートonの信号に対して反応します。

今回は、MIDIノートオンのMIDI信号の時に、MIDIのベロシティ値をスライダー値に変更するという処理を行います。MIDIノートON信号には(MIDIチャンネル,ノート番号,ベロシティ)という情報が含まれます。最後のベロシティの部分をスライダーの値として置き換えます。

・isNoteOff:midiノートoff信号に対して反応します。

・isAfterTotouch:ノートオン信号のあとのアフタータッチに対する情報です。

・isPitchWheel:ピッチベンドホイールのMIDIデータに対する反応です。

今回は、ノートオンMID信号に対してベロシティを書き換える、という処理を行います。

ここでuint8がビルド時にエラーとなりました。uint8はなかったのですが、uint8_tがありましたので、uint8_tに変更しました。

MIDIデータのスワップについて

processBlock関数の「juce::MidiBuffer& midiMessages」という引数では、MidiBufferのアドレスがmidiMessagesに入ってきます。midiMessagesのアドレスを参照すると、生のMIDIデータを見ることができる、ということになります。MIDIデータに変更を加える際には、直接データを持ってきて利用するのではなく、処理の中では仮のmidiBufferで値を作成しつつ、最後に出来上がったMidi値をswapWithメソッドですり替える、というような処理を行います。

演奏データなので、リアルタイム性が要求されます。そのため、このような方法となっているのかと思われます。

動作の検証

チュートリアルの最後に、今回のプラグインはMIDIの発音するための仕組みが必要になり、発音するには今後やるチュートリアルを参考にしてくれ、見たいに記載があり、困惑しました。(以前ビルドしたホストアプリで検証はできません^^;)

フリーDAWの旅

普段、私はLogicProXを利用しているので、WindowのDAWを持ち合わせていませんでした。

フリーのDAWに挿して検証しようと思いましたが・・・cakewalkはインストールでエラーがでて開けなくなり、studio one 5 primeは外部vstを追加できず、Reason lite 11はVST3自体が対応していないというここにかなりの時間を使いました^^;

最終的に、Peaperというフリーでも利用できるDAWをインストールして動作検証を行いました。

あわせて読みたい

PeaperでのVSTの設定

「Ctrl + P」でpreferenceを表示させます。

図のように、VSTの項目から、Editボタンを押し、Addで開発したVST3の階層を選択します。拡張子「.vst3」が入っている階層です。そして、Re-scanボタンを押します。

トラックのFXボタンを押すと、ここにMIDIのプラグインが挿せるようになっています。あらかじめ赤丸のように適当なMIDIデータを打ち込んで置き、ループ再生するようにしてあります。

FXボタンを押すと次の図のウィンドウがでますので、①の「add」ボタンを押します。プラグインの一覧がでてきますので、「New」を見ると、ビルドしたプラグインが出てきます。(すみません、今回はMyPlugin2という名前で再度作成しました。)

③の作成したプラグインを選択して④のAddを押します。そして、⑤のようにプラグインに挿入されます。

今回作成したMIDI情報を変更するプラグインは図のように、発音するMIDIプラグインより前に挿入しなければいけません。図の場合は、ReasonのRackプラグインでシンセを発音しています(いきおいでReason使ってしまいました^^;)が、デフォルトのcakewalkのSI-Bass(次の図)でも発音できます。ここで重要なのが、この発音プラグインよりも前にビルドしたプラグインを挿入することです。

今回のプラグインは、UIを離れて再度UIを表示させると、初期値の0に値がもどってしまいます。この点は改善点かな、と感じます。

これで、GUIのスライダーで音量をスライダーの値と変更することができました。

Reaperに感謝します

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次