JUCE vNext?に入りそうなMIDI 2.0サポートについて

JUCE Advent Calendar 2020 5日目が空いていたので、今週developブランチに追加されたMIDI 2.0 UMPサポートを実装するコードについて解説します。

https://github.com/juce-framework/JUCE/commit/9032f58

先月のADC 2020でJUCEブースに行って「MIDI 2.0をサポートする予定はある?」って質問してきたばかりだったので("We're working on it" みたいな感じでした)、もう出てきたか…!という感じですが、UMP仕様の正式版が決まってからもうすぐ1年になろうとしているので、順当にin a timely mannerで出てきた感じではあります。ADC 2019の頃に「そのうちリリースする」って言っていたMMA (MIDI Manufactures Association) のMIDI 2.0実装ライブラリはどうなったんだろう…

MIDI 2.0とUMPについて(復習)

MIDI 2.0 UMPについてはMIDI 2.0 UMPガイドブック (PDFのみ版)で詳しく解説したのでここで繰り返すことはありませんが、MIDI 1.0ではMIDIイベントとかMIDIメッセージと言われていたものに相当するMIDI 2.0の仕様です。「MIDI 2.0ノートオン」「MIDI 2.0ピッチベンド」「MIDI 2.0ノート別コントローラー」「MIDI 2.0システムエクスクルーシブ8」といったものが規定されています(そんなにMIDI 2.0ってprefixは付けないかもしれない)。

SMF(MIDIファイル、*.midファイル)の仕様や、特定のトランスポート(USBとかBLEとか)で転送する方式の仕様は、MIDI 2.0ではまだ(?)規定されていないので、今回のコードにも関係ありません。またMIDI-CIで新たに可能になった双方向のやり取りに関する仕様もUMPの範囲ではないので、今回のコードに関係ありません。

MIDI 2.0に対応「する」ハードウェアデバイスとしては、Roland A-88 MkIIが知られています。あと最近どこかがタッチパネル系のコントローラー(大昔にあったJazzMutant Lemurみたいなやつ)をMIDI 2.0対応させるって言ってindiegogoかなんかに出していた気がします(うろ覚え…)。MIDI 2.0 USBトランスポートは今年の6月に正式に規定されているはずなので、もう対応しているかもしれません。

プラットフォームAPIとの関係

これを書いている時点で、主要プラットフォームのAPIMIDI 2.0 UMPサポートが含まれているのはAppleの最新版OS上のCoreMIDIのみです。iOS 14.0、macOS 11.0, Mac Catalyst 14.0以降ということになります。Windows APIにもALSAにも対応するAPIはありません。

UMP仕様自体はパケットデータのフォーマットを規定しているといえるもので、この意味ではプラットフォームAPIとは無関係にAPIを規定できるものです。その意味ではプラットフォームAPIに対応するものが無いことは、ほぼ障害になりません。

一方で、プラットフォームAPIが無いうちは、そのプラットフォーム上に「有効なMIDI 2.0デバイス」を登録したりそれを発見したりする術がないので、特定のソフトウェア上のプロトコルに基づいてのみ、MIDI 2.0の機能が使えるということになります。たとえばUSB MIDI 2.0クラスは既に存在している(はずな)ので、USB接続から独自にMIDI 2.0デバイスを発見して読み書きすることは可能でしょう。ただしWinMMやALSAMIDIサポートは未だに1.0のみなので、それらのAPIを使用してデバイスとのメッセージをやり取りしようと思ったら、MIDI 1.0の範囲(精度)に丸めるしかありません。

CoreMIDIが追加されたAppleの各種OSについては、CoreMIDI APIMIDIエンドポイントに接続して、CoreMIDI APIのUMPパケット(MIDIMessage_64など)に変換して送信する(あるいはその逆で受信する)などの実装が追加されています(どちらかというと、既存のC++実装がObjective-C実装に書き換えられているので、MIDI 2.0とは無関係にひとつの大仕事っぽいというのが実態ですが…)。

MIDI 2.0 UMP仕様では、実のところ、MIDI 2.0 UMPをMIDI 1.0の範囲で表現できるデータに変換する方式が規定されており、今回JUCEに追加されたコードでもこれが実装されています。

オーディオプラグインAPIとの関係

これを書いている時点で、MIDI 2.0を直接サポートしているオーディオプラグイン規格はありません。

ただし、VST3.7がリリースされたときに、Steinbergは「MIDI 2.0で規定されている機能をVST3の機能でカバーすることは可能であるという」アナウンスを出していて、MMAはこれをもって「VST3はMIDI 2.0をサポートしている」とアナウンスしています。

(わたしはこれは不正確で不適切なメッセージだと思うので、常に正確なところを表現しようと思っています。実際VST3ではMIDIサポートが落とされた結果、VST2の頃に実現できていたマルチチャネル対応が不可能になっていたりします(具体例)。)

MIDI 2.0の機能をカバーしている」というのは、具体的にはノートエクスプレッションのサポート(MIDI 2.0ではノートの「属性」のサポート)、高精度のピッチベンドなどで、これは実際正しく、MIDI 2.0 UMPでMIDI 2.0デバイスから受け取ったメッセージをVST3のコントローラーメッセージに変換してVST3のフィルター(プラグイン)チェインに処理させることは、部分的には可能かもしれません(DAWMIDIレコーディング機能などと連動させるのは無理かも)。

Roland A-88 MkIIみたいなデバイスがVST3対応のプラグインを作ることも、やろうと思えばOSサポートとは無関係に独自にできるわけです(A-88 MkIIのためにどんなソフトウェアがいま提供されているかは知りません)。

AppleのCoreMIDIには、MIDI 2.0 UMPをあらわすAPIやそれをデバイスとやり取りするAPIは定義されていますが、AudioUnitにUMPを扱うAPIが追加された様子はありません。AudioUnitはVST3とは異なりMIDIを明示的にサポートするAPIが含まれているので、MIDI 2.0 UMPをサポートする段階になったらそのためのAPIが追加されるはず…というのがわたしの理解です(ただAUについてはそんなに頻繁・入念にチェックしていないので、見落としているかもしれません)。

とはいえ、UMPは所詮バイト列で表現できるデータフォーマットにすぎないので、CoreMIDIのMIDI-CI実装がMIDIバイスとホストアプリケーションの間のプロトコル情報のやり取りを適切に処理できていれば、アプリケーションはUMPパケットをバイト列で受け取るだけでMIDI 2.0のメッセージを受信できているかもしれません。

AudioUnitにMIDI 2.0固有のAPIが何も追加されていない現在、JUCEで独自にMIDI 2.0サポートがAudioProcessorなどに追加されていることもありません。VST3にプラグイン開発者が独自に対応するようにJUCEが独自に追加することはあるかもしれませんが、おそらくAudioUnitに正式にMIDI 2.0サポートが追加されるのを待つのではないかと思います。その際にはVST3用のAudioPluginFormatなどにもUMPサポートの実装が追加されることになるでしょう(現在は何も追加されていないはずです)。

UMPサポートAPIの詳細

そういうわけで、まだMIDIバイスにもオーディオプラグインにも十分な(もしかしたら「必要な」)サポートがなさそうなMIDI 2.0 UMPですが、バイトストリームからのUMPの解析とUMP構造の取得、あるいはUMP構造とUMPストリームの生成と仮想的な「送受信」は、今回追加されたAPIでも可能です。今回追加されたクラスはたとえば次のようなものです(全てを列挙はしません)。

  • Packet<numWords> - 1つのUMPをあらわす
  • Packets - add(), clear(), uint32_t* data() などUMPシーケンスをあらわす
  • Factory - makeJRClock(), makeNoteOnV1(), makeAssignableControllerV2() などPacket<T>を構築できる関数をもつ
  • Iterator - uint32_t*から生成され、UMP1つ1つを取得するためのiteratorとなる(個別の要素としてはViewoperator*()operator->()で返される)
  • View - uint32_t*から生成され、1つのUMPをあらわす(こちらにもbegin()end()が定義されているが、これは1パケット中の4バイト単位のデータをiterateするためのもの)
  • Midi1ToBytestreamTranslator - uint32_tのUMPシーケンスをMIDI 1.0のMidiMessagesに変換する
  • Midi1ToMidi2DefaultTranslator - MIDI 1.0入力をMIDI 2.0のメッセージに(精度などを)変換する
  • Receiver - MIDI 2.0のメッセージを受信する役割を担うインターフェース。開発者はpacketReceived(const View& packet, double time)を実装する必要がある。
  • U32ToBytestreamHandler - MidiInputMidiInputCallbackから生成して、pushMidiData (const uint32_t* begin, const uint32_t* end, double time)の呼び出しでUMPシーケンスを渡されると、それをMidiInputCallback.handleIncomingMidiMessage()に流すようになっている
  • U32ToUMPHandler - PacketProtocolReceiver&から生成して、pushMidiData (const uint32_t* begin, const uint32_t* end, double time)の呼び出してUMPシーケンスを渡されると、それをReceiver.packetReceived()に流すようになっている

これで何が出来るの?

これらのAPIだけでどんなことができるかは、具体的な実装なしで説明するくらいしか現時点ではできませんが(今その辺の作業をやっているわけではないので…)、たとえば現在Fluidsynthには部分的にMIDI 2.0の精度でピッチベンドなどを処理するAPIが追加されているので、UMPストリームを何らかの方法で生成して*1、UMPの内容を(サポートされている機能の範囲で)Fluidsynthに渡すようなReceiverを実装して、それをU32ToUMPHandlerで処理するようなアプリケーションを書けば、FluidsynthにMIDI 2.0のデータを演奏させることができるでしょう。あるいはSteinbergが「サポートしている」といっているVST3プラグインに処理させることもできそうです。

とはいえ、まだ正式に発表された機能でもないですし、APIが変更される可能性もあるので、そこは(試すにしても)気をつけて使ってみるのが良いでしょう。

*1:たとえばMIDI 2.0に対応したMMLコンパイラを作るとか! (SMF相当のフォーマットが無いけど)

JUCEで作られたOSSオーディオプラグインをかき集めてみた

JUCE Advent Calendar 2020 3日目のエントリーはゆる〜く自分がこれまでかき集めてきた「JUCEで作られたOSSのオーディオプラグイン」をいろいろ紹介します。

目次

Rationale

そもそも何でそんなのを集めているのか?という話ですが、単に趣味で集めていたわけではありません(いや、あるか?)。まずChrome*1でこのページを見てみてください(宣伝)。

juce-demos.atsushieno.dev

わたしがちょっと手伝っていたjuce_emscriptenのデモとして、世に出回っているJUCE系アプリケーションをWeb Assemblyアプリとして動かしているものです。ファイル関連APIなどいろいろな機能制限もあるため、完全なかたちではないにしても、さまざまなアプリケーションが既に動いています。作ったのは今春くらいなのですが、juce_emscriptenも特に進化していないので*2これが最新版という感じです。

もうひとつ、Android用に自作しているオーディオプラグインフレームワークがあって、JUCEからの移植もサポートしていて、少し手を加えるだけでJUCEプラグインのオーディオ部分を鳴らすことができるものが少なくないので、気が向いた時に動かせそうなものを探しています。

github.com

もちろん、自分のLinuxデスクトップでも使えるオーディオプラグインは常に探しています(何しろ選択肢が少ないので)。わたしのようなユーザーにとっては、ソース付きで公開されているJUCE系のプラグインは良い狩り場(?)になるのです。大概はjucerファイルをちょっと加工すればLinuxでもビルドできるようになるので。

そんなわけで、JUCE系のプラグインやアプリケーションをいろいろ探しては試す癖がついていました。それなりに使えそうな知見になってきた気もするので、この機会にいろいろ紹介しようと思います。こういう契機なので紹介内容はOSS…少なくともソースコードのあるソフトウェア限定です。最近リリースされたVitalとか、(juce_emscriptenの原点である)Synthesizer Vとかは含まれません。

サンプラー → シンセ → FM/PSGエミュレーターエフェクター くらいの雑な順番になっています。

Birch-san/juicysfplugin

github.com

Fluidsynthを経由してサウンドフォント(SF2/SF3)をサポートするサンプラー音源です。MIDI音色に相当するインストゥルメントプラグインとして使うにはコレが手っ取り早くて助かります。SF2はかなり古いフォーマットですが、まだ使われることもあるようです(やや練度の足りない内容ですがこれも2年前にまとめてあります)。Fluidsynthは今でも開発が継続していて、最近ではMIDI 2.0 UMPサポートなども実装されつつあるようです。

移植性の観点では、まずfluidsynthのビルドを取り込まないといけないところで躓くことになるかもしれません。Androidビルドは公式にCIがあるので(わたしがAndroidサポートを追加したときに書いたビルドスクリプトをCI設定してくれた人がいたらしい)、そこから引っ張ってくるのが安牌です。また割と無邪気にFluidsynthを共有ライブラリとして参照解決するので(互換性のないバージョンを参照したり、共有ライブラリのロードパスの関係で問題を引き起こしたりするので、依存関係はなるべく静的に取り込んでビルドするほうが好ましいです)、ホストによってはロードできずに落ちたりすることもあります。

サウンドフォントでよく言及されるのはDebianなどで配布されているFluidR3_GM.sf2ですが、探すと他にもいろいろ見つかります。自分の場合は最近は musical-artifacts.com で見つけた https://musical-artifacts.com/artifacts/1057 を使うことが多いです。

osxmidi/SFZero-X

github.com

SF2ではなくSFZのサンプラープラグインとして作られているのがSFZeroです。osxmidi/SFZero-Xは今では開発されていないオリジナルのstevefolta/SFZeroからの派生版で、音源部分はSFZeroModuleという別リポジトリに含まれているsfzeroという非JUCEモジュールの実装です。

ただ、SFZフォーマットは現在でも継続的に開発されている現役のフォーマットなのですが、SFZeroの音源部分はもう5年近く開発されていないので、わたしがSFZサンプラーとしてSFZero-Xを推薦することはないです。サポートされていないSFZ opcodeも数多くあります。今一番アクティブに開発されていてopcodeのカバレッジも広いOSSsfztools/sfizzですが、これは今はVSTGUIでUIが作られているVST3/LV2音源なので、今回はSFZero-Xの紹介としました*3。どうしてもJUCEでやる必要がある/移植する必要がある場合はこちらでしょう。

TheWaveWarden/odin2

github.com

モダンでクールなGUIを備えた高機能シンセサイザーです。JUCE6で全プラットフォームVST3に対応しているほか、LV2 Porting Projectを使用したビルドにも考慮しています(README.mdで詳しく説明されています)。Surgeと同様Odin2もOne Synth Challengeで数多くの楽曲が作られています

プリセット音色もたくさん用意されているのですが、現状のビルドではバンクに相当するodsファイルが何もビルドされず、ユーザー定義音色の格納場所についても問題を抱えているので、プリセットを1つ1つ手作業で選択していく作業が必要になっています。この辺りが(多分)次のリリースで改善されるとだいぶ実用的になると思います。

f:id:atsushieno:20201202211921p:plain

artfwo/andes

github.com

オシレーター1つのシンプルで移植の難易度が低いシンセサイザーです。もっとも、シンプルとは言っても、このオシレーター自体はPerlin noiseをオーディオ処理に適用するという実験を実装したもので、Linux Audio Conferenceのサイトで論文(というのが適切なのかは分かりませんが)も提出されています。

移植作業の最初の一歩として試すには良い選択肢です。ただしPerlin noiseの処理にそれなりにコストがかかるのか、(自分がAndroid環境で試した限りでは)オーディオ処理はあまり軽量ではありません。素でglitch noiseが発生するほどではありませんが、組み込みデバイスなどで最初に試すのには向いていないかもしれません。

f:id:atsushieno:20201202212453p:plain

asb2m10/dexed

github.com

このはてなブログではちょいちょい登場していますが、YAMAHA DX-7のエミュレーターをなぜかGooglerがAndroid向けに趣味で(?)開発したもの*4を、外部の開発者がデスクトップでJUCEのGUIを付けて公開したものです。DX-7の音色バンクとなるCartのサポートなども追加されています。

音源側のコードであるmusic-synthesizer-for-Androidについては2年前に書いたのでそちらを見てください。

f:id:atsushieno:20201202212020p:plain

jpcima/ADLplug

github.com

これもこれまでちょいちょい登場しているFM音源(OPL/OPN/OPM)のエミュレーターです。実態はlibADLMIDIとlibOPNMIDIにJUCE GUIを付けたものと言えます。

これらのライブラリはさらに別のさまざまなFM音源エミュレーター(libOPNMIDIならNuken, MAME, Neko, PMDWinなど)を包括的にサポートしていて、エミュレーション結果が気にならなければ別のエミュレーターを試せるようになっています。

個人的には、今年はFM音源エミュレーターのコードにコントリビュートしてもsfizzのコードにコントリビュートしてもJUCE LV2のコードにコントリビュートしてもこの開発者が出てきて、この人強すぎでは…??ってなりました。

f:id:atsushieno:20201202212512p:plain

yokemura/Magical8bitPlug2

github.com

ゲーム向けのPSG音源を再現するインストゥルメントプラグインです。オシレーターはシンプルですが、ADSRのほかにLFOや自動ピッチベンドなどゲーム用途らしいパラメーターが用意されているのが、いかにもという感じの使いやすさをもたらしている音源です。

コードベースがJUCE 5.4.7と新し目なので、これも移植難易度が低く、実験には有用です。JUCE 5.4.7はアプリケーション次第では(?)そのままだとLinux gccビルドがコケる鬼門バージョンでもあるので、失敗したらCXX=clangでのビルドを試すようにすると良いでしょう。

f:id:atsushieno:20201202212112p:plain

ffAudio/Frequalizer

github.com

6点マルチバンドEQを実現するJUCEプラグインです。最初やや取っ付きにくいのですが、たぶん小一時間くらい使って慣れると、多機能でよく出来ていることがわかります。リアルタイムで入出力の波形が表示されるので、適用結果を視覚的に確認できるようにもなっています。

取っ付きにくい理由は主に(1)最初に6点それぞれのどこにコントロールポイントがあるのか完全にわかりにくい(細い縦線が見にくいのと、発見できた後もy軸の中央すなわち0dbの位置に点があるのが見えず丸型スライダーで値をずらさないと発見できない)のと、(2)制御点のそれぞれがPeak/Low Shelf/High Passなど10種類以上の選択肢があって、慣れないと意図した曲線を描けないのと、(3)初期値で6点は多分多すぎるためです。これさえ把握していれば多分何とかなります。点の多さはアクティブな点を減らすことで解決できるでしょう(Aボタンがたぶんactivateの意図なんですが、これで制御できます)。

ffAudioにはPluginGuiMagicというプラグインGUIをパラメーターから(たぶん)簡単に構築できるJUCEベースのGUIコンポーネントのコレクションもあり、Frequalizerはこれを使って構築されています。

f:id:atsushieno:20201202212151p:plain

GuitarML/SmartGuitarAmp

github.com

Googleのメディア/アート系プロジェクトに深層学習を応用するWaveNetを使ってギターアンプやペダルの既成品をシミュレートする GuitarML/PedalNetRT というプロジェクトがあるのですが、これをJUCEと組み合わせてオーディオプラグイン化したのがSmartGuitarAmpです。

紹介するのは同じpedalnetを使用している(そしてこのプロジェクトの元ネタでもある)damskaggep/WaveNetVAでも良かったのですが、新しいほうを選びました。WaveNetVAのほうはデモページでさまざまな適用結果を聞くことができます。

ただ、これは環境依存なのかもしれませんが、WaveNetVA同様、CPUコストが非常に大きく、まだまだリアルタイムでのまともな発声は無理だと思います。standaloneでビルドしたアプリでJUCEのオーディオテストがブツ切れになるレベルです。非リアルタイム用途では使えるかもしれない、といったところです。

関連: hacker newsのスレッド

surge-synthesizer/surge-fx

github.com

surgeは、旧くはVermber Audioから配布され今はOSSで開発されている多機能シンセサイザーです。surge-fxはそのエフェクト部分をプラグインとして抜き出してJUCE GUIを付けたものという位置づけになるようです。surgeはsurgeで独自にUIが構築されています。surgeは基本的にJUCEを使っていないようなので今回は紹介しませんでしたが、JUCEを有効にしたビルドオプションというものも存在するようです(patch_playerというコードもあってこれがJUCEアプリケーションになっているようですが、詳しくは未確認)。

surge-fxとして単独で使用したい場面がどれほどあるかわかりませんが、JUCE6にアップデート済なので、JUCE6を使用したビルドの動作確認には有用です。ただ、内部的に巨大なsurgeのコードを(全部ではないにしても)ビルドすることもあって、移植性は高くないかもしれません。*5

f:id:atsushieno:20201202212245p:plain

*1:もしかしたらChromium Edgeでも可かも

*2:春先に自分が手を入れたWebMIDIサポートが取り込まれたくらい

*3:以前はsfizz-juceというものがあったのですが

*4:初期チェックインの後はメンテナンスされていません

*5:半年ほど前にjuce_emscriptenでビルドしようとした時は、xmmintrin.h依存が解決できなくてあきらめたのですが、emscriptenではサポートされている雰囲気もあるので、がんばればビルドできるかもしれません。

M3 2020秋 サークル参加情報

今回も直前まで書かずに来てしまいましたが、明日10/25のM3 2020秋にサークル"ginga"として参加しています。割と最近(数週間くらい)に気づいたんですが、同人音楽サークルとしてgingaって名前だとgingaレーベルと紛らわしいんですよね…*1

追記: 素で書き忘れていましたが(!)第一展示場G-22です。Web会場も銀08としてLV2開発本のみ委託販売します*2

頒布物

音楽技術同人誌3冊の紙版を部数少なめに持っていきます。全部で50冊無いくらい。いずれもイベント価格¥500で頒布します。原価割れライン…! ダウンロード版も会場でお渡しします。

※boothにリンクしていますが、全て電子版へのリンクです。紙版はM3終了後に残った部数を設定して販売する予定です。

xamaritans.booth.pm

技術書典9で発表したMIDI 2.0 UMPガイドブックです。私の知る限り世界初です*3。それなりに売れたのですが発注部数より多く刷られていたので*4、M3でも販売できる運びとなりました。

xamaritans.booth.pm

同じく技術書典9で発表したLV2オーディオプラグイン開発者ガイドです*5Linuxデスクトップで使われている代表的なオーディオプラグイン規格の解説書として、おそらく世界でも類を見ないものだと思うのですが、これは予想通りだいぶニッチだったのでまだまだ在庫があります。*6 展示コーナーとも合わせてたのしめる本です。*7

xamaritans.booth.pm

M3 2019秋に発表した、DAWの仕組みを探るためにソフトウェア構成部品を理解しよう!という本です。これも他に類を見ない書籍として書いたつもりです。こちらは紙版も既にboothで購入できます(上記リンク先から探してください)。

xamaritans.booth.pm

2019年3月の幻想音楽祭でリリースした音楽作品です。自作コンパイラMMLとTracktion Waveform10で打ち込んだデータもお渡ししています。

展示コーナー

今回、新譜を作るつもりだったのですが、ソフトウェアが間に合わずとても着手には至りませんでした…。その話は後で書きますが、取り急ぎ代替となる展示物として、今回の頒布物であるLV2オーディオプラグインをその場で体験できるPCコーナーを設置します。*8

またPCに触れなくても、LV2プラグインにどんなものがあるのか、気軽に立ち読みできるパネル的なものを、書類ケースに入れて置いておきます。

また、これらのプラグインのいくつかはAndroidにも移植しているので、Androidエミュレーター上で試せる範囲で遊べるように環境を用意しておきます。

併せて、Ardour6, QTractor, Zrythmなど、ホスト/DAW側も、ほぼ最新のバージョンをお見せできるようにビルドしてあります。

今回展示できなかったもの

今回は、ほんとうはtracktion_engineを使いつつWaveformなしで最後まで打ち込んでAndroid上で再生できるところまで作りたかったのですが、Android上ではAudioPluginHost上でプラグインから音が出るところまでだけ出来ているという状態です…ここ2週間くらいのAndroid Studio 4.2-alpha(13, 14あたり)でネイティブコードのデバッガーが壊れていてデバッグ作業が困難なので(最近気づいたのですが、Android StudioC++サポート機能はプロプラエタリでAOSPに含まれていないんですね。原因を追求できませんでした)、いつ開発作業が再開できるのかわからない状態です。

Androidから離れて、Linux環境ではMML…とプロジェクトXMLファイル…からコンパイラとtracktion_engineだけで打ち込みができるところまでは出来ています。tracktion_engineにjlv2を追加してLV2プラグインとVST3プラグインを混ぜて利用できるようにしたので限りなく便利です。もっとも、Waveform11 on LinuxはLV2もVST3もサポートしていないので、DAWで微調整が一切できない楽曲になってしまいます(!?)

ひとつクリティカルな問題として、MMLからSMFにコンパイルして、それをJUCE AudioPluginHostのfiltergraphファイルと合わせてtracktioneditファイルにコンパイルして、それを再生するというツールチェインのパイプラインになっているため、プレイヤーが毎回オーディオプラグインをメモリ上にロードするのが重くて制作ワークフローとしてはイマイチです。これはtracktioneditコンパイラとプレイヤーを統合して、MIDIシーケンスの部分だけをhot reloadするような仕組みに作り変えれば改善する見込みです。そのためには.NETアプリケーションであるところのコンパイラをJUCEベースのコードに作り直す必要があるのでお手軽ではなく、今回は先送りにしました。

あと、前回audio plugin portabilityの問題として書きましたが、通常のオーディオプラグインはオーディオプラグインフレームワークを跨いでstateデータを再利用できるように構築されていないので、その解決策を模索していて時間切れになったこともあります。最初から移植性のあるstate情報・パラメーター情報を保存する仕組みを作ってそこに載せないとダメそうですが、これは日を改めて考察をまとめたいと思います。

この辺の話はいろいろ出てくるので、当日会場に来られる方で興味ある方がいたらぜひお話ししましょう。混雑するブースになる予定はありませんし*9

*1:うちは2004年にはてなに引っ越してくる前に使っていた名前なので多分こちらのほうが先なのですが

*2:これはWebイベントの設計が良くなくて、当日の販売状況に応じて販売数を調整できないようになっているためです

*3:最近洋書で他にも出たっぽい話を見ました。既刊本の改訂のついでのようでしたが。

*4:一般的にあることです

*5:もともとM3向けに計画して書き始めていたやつですが、技術書典9のほうが先に来たので

*6:MIDI 2.0本も原価割れなのですが、面倒なので価格を統一した感じです

*7:といっても会場で読む人はいないと思うので、展示を思い返して楽しむ感じになるかと思います

*8:広いスペースがあるわけではないので、そこはご理解ください

*9:これフラグになんねーかなー(

Q3〜10月前半の開発記録

7月の作業記録は別途書いてあって、8月の作業記録はMIDI 2.0本の告知がだいぶ持っていってしまったのですが、他のこともちょろちょろとあったので、最近までの自分用開発記録をまとめておきます。時系列は順不同です。

ADLplug/VST3 on LinuxとJUCE6+LV2

JUCEが 6.0でようやくLinux対応したので、ADLplugのようなJUCEベースのオーディオプラグインがまた本家JUCEだけでもビルドできるようになったのですが、ADLplugは独自にLV2対応を進めていたこともあって、JUCE6へのアップデートは行われていません。

このままだとVST3版は永久に出てこないことになって、LV2版を使っている自分としては特に困らない予定だったのですが、いま自分のaugeneプロジェクトでMML + tracktion_engineを使った打ち込み環境に全面移行を図っていて、そこではまだLV2サポートをホスト側で統合できていないので、VST3版が必要になってしまいました。

本家JUCEに切り替えた上でLV2サポートを切り捨ててビルドしても良いのですが、毎回ビルド切り替えのためにJUCEブランチを切り替えるのも面倒なので、とりあえずADLplugで使われているLV2サポート付きのJUCEをJUCE6にアップグレードしました。

github.com

これをもとに更新したADLplugも公開してあります。

github.com

ひとつ問題になっているのが、JUCE6にアップグレードした段階でVST2 SDKの代替として機能するVeSTigeが、既存のコードだけではJUCEのVST2 Wrapperを十分にビルドできなくなってしまったため、VST2サポートが切り落とされてしまっていることです。VeSTige、もともとはLMMSの一部なのですが、いろんなところで改良版?が作られているので、どこに使えるバージョンがあるのかよくわからないんですよね…。そういうわけでコレを使う限り & 本家VST2 SDKを使わない限り、VST2ビルドは失敗します。

あとVST3版にするとマルチチャンネルで使う時にプログラムチェンジが正しく処理されないという問題があって、これはアプリの問題ではなくVST3の仕様レベルでの問題っぽいというのが現時点での評価です。この問題があるのとJUCE6アップデートに上記の副作用があるのとで、本家にはマージされない可能性が大いにあります。作者もFM音源からは割と足を洗ってsfizzに集中しているそうですし。

fmbank

OPNplugは音色を定義して使えないとあまり意味がありません(プリセットで満足するタイプならそれでも良いのですが、わたしは他人の作ったFM音色を探すことに意義を見出せないので…)。そういうわけで、大昔にFM音源をいじっていた頃に自作していたOPNのFM音色をつかうわけですが、OPNplugなどで使えるフォーマットが全然違うので、まずはOSSでよく使われていそうなopm形式のテキストデータにしてgithubで公開しました。

github.com

FM音色データとして流通?しているものにもいくつかのフォーマットがあって、OPNplugでサポートされているのはwopnというバイナリのフォーマットのみです。この辺のフォーマットの変換にはOPN2BankEditorというプロジェクトが便利です。古いMMLデータ形式から新しいmml2vgm形式(やmucom88形式とかも)、それと各種FM音色エディタの形式がサポートされています。

github.com

ただ、エディタ上にコピペしてペーストするような作業になるので、大量に音色がある場合はコンバーターを頑張って作ったほうが良いかもしれません。わたしはコンバーターを書く時間のうちに手作業で変換が終えられてしまいそうなので手作業でやっつけました…。あとちょっと変換処理に問題があったので修正して反映してもらったりしていました。

この辺のツールの使い方は時間が無限に使えるようになったらmusilあたりに書いていきたいと思っています。

sfizz on AAP

sfzサウンドフォントをオーディオプラグインとして使えるsfizzを、Android assetsから読み込むアプローチをとりあえず一旦放棄して、ローカルファイルとして格納するようにしたら、無事プラグインとしてロードして動作するようになりました。ただなぜかホストに依存するようで、JUCE AudioPluginHostからだとどうもうまくいかないのでまだ検証が必要なやつです。

最近この辺をちょいちょいいじりながら本家のバグを見つけてプルリクなどを送ったりDiscordの開発コミュニティに顔を出したりしていたら、大して貢献しているわけでもないのにcontributorsリストに名前が載ってしまったので、もうちょっとsfzが広まるようにやっていくか…みたいなモードになっています(安い釣り針だ)。ARIA UIの実装実験もAndroidプラグインも既に彼らに知られていたので、その辺が大きかったのかもしれません。協力できるところは協力していこうと思っています。UI Standard GuitarのKSOPとかUI Metal GTXが使えるところまではもっていきたいですし(そこまで手を出せる技術知は今のところありませんが)。

ちなみにsfizzではlibsndfileに依存している部分を置き換える作業も行われていたりするので、これが通るとファイルシステム依存部分が減ってassetからのロードが無理なく実現できるようになるかもしれないので、現時点では今のコードに無理にassetサポートを追加しない方針で様子見です。(libsndfileはFluidsynthでもsf3サポートのために使われているので、libsndfileのファイル名を指定するAPIに依存しないアプリケーションコードを書くことも可能なはずではありますが。)

aria2webのスクショを見てわかる人はわかると思いますが、sfizzはKontaktの次の時代を作るOSSとして発展できるポテンシャルは十分にあると思います(SforzandoがOSSになってLinux対応できればそれでもいいのですが)。Kontakt、Komplete 13でもVST3版が出ることはなかったですし、この辺は世代交代を期待したいところです(とはいえVST3には前述の問題もあるのでVST2が使われ続けることになるのかも…それはそれで不幸な話なのですが)。現状sfzをサポートするOSSはopcodes実装がSforzandoに遠く及ばないとされていたのが、sfizzがえらい勢いで進化しているので、しばらく経つとこの辺の勢力図が変わってくるのではないかと思います。

tracktion_engine app on Android

しばらく前からaugeneというMML => MIDI + AudioPluginHost (filtergraph) => tracktion(edit) という流れのツールチェインを構築していて、最近ようやくMMLからOPNplugやsfizzでギター音源sfzの奏法をMMLで指定して演奏できるところまで実現できたので、次はこれをAndroidに移植する作業を進めていました。

tracktion_engine自体はStepSequencerDemoを動かしたことがあるので*1、基本的には移植で困ることは多分ありません。多分、というのは、StepSequencerDemo以外で使われている機能については使ってみないとわからないためです。実際、Editをファイルからロードして演奏する処理については、Android用にassetsからロードする仕組みはNDKにもJUCEにも無いので、sfizzと同様にローカルファイルストレージにいったんコピーしてからロードするというやっつけ工程が必要になりました。

あとJUCE6がCMakeに対応したので、外部ライブラリに依存しているaugeneもCMake化したほうが楽だと思って移行したのですが、Androidサポートについては、Projucerで行われているプロジェクトファイル生成はCMakeでは全くサポートされていないので、自前でテンプレートを用意するかどうかで試行錯誤した結果、とりあえず従来のProjucer方式でプロジェクトを生成しています。aap-juceのビルドシステムがProjucer前提で組まれているのが最大の理由です。CMake前提のビルドに書き換えようとも思ったのですが、移植対象のアプリがそもそもCMakeに書き換わっていない(そして古いアプリもあるので多分書き換わらない)ので、10月中は無理だと判断しました(この辺をいじっていた頃はM3出展を視野に入れていたのです)。

audio plugin portabilityの問題

Linuxデスクトップ上でMMLで打ち込んで生成したtracktioneditと、Androidに移植したtracktion_engineアプリがあれば完結するかと思われたこの課題ですが、本当の(そして現在進行系の)課題は、複数の環境をまたいで編集・再生できるポータブルな楽曲編集環境を構築するところにあります。

AAPはVST3をサポートできないので(そもそもvst3sdkがまだAndroid NDKでビルドできないので)、VST3でビルドした音源を使った楽曲がAndroid上でシームレスに演奏できることを期待するのはちょっと無理があります。正確には、音源そのものはJUCEでビルドされていてaap-juceでビルドできるのですが、AudioPluginHostで編集したfiltergraph上にはプラグインのstateが生バイナリをbase64変換して保存されており、この生バイナリのデータが他のプラグインフォーマットとは共有できません。つまり、ユーザーが打ち込んだデータのクロスプラグインフレームワーク互換性の問題です。

これは別に自分のプロジェクト固有の問題ではなくて、オーディオプラグインの世界全体の問題です。たとえばRoland Sound Canvas VAをVSTで打ち込んでいたものをAUに置き換えても互換性が無いことになっています。

本当にstateデータを共有できないのかどうか試してみたのですが、JUCEのVST3サポートの実装ではVST3固有の情報を出力に含めていて無理でした(OPNplugの実装でいえば、stateのXMLのroot要素判定に"VST3PluginState"が渡される)。手作業で回避コードを書くこともできるのですが、課題はADLplugという個別のプラグインを動かすことでもなければJUCEベースのプラグインのみパッチ対応することでもないので、そういう対応は現状考えていません。

現状で一番現実的に可能そうなのはtracktion_engineをLV2サポート付きのJUCEでビルドしてAudioPluginHostもaugeneもLV2を使って制作して、それをaap-lv2でビルドしたプラグインを使って再生する、といったところです。JUCEのLV2サポートもホスト側(juce_audio_processors)について実装されている必要があり、現状ではjlv2というモジュールしか見当たりません。ADLplugのLV2サポートなど大半のLV2サポートブランチはjuce_audio_plugin_clientのみなのです。

この問題をどう解決するか、については、そもそも音楽制作環境におけるクロスプラットフォーム・クロスプラグイン環境をどう実現すべきか?という課題について整理して別の機会にまとめたいと思っています。進展があればgithubの自分のプロジェクトである程度まとめていくかもしれません。

*1:ちなみにStepSequencerDemoはjuce_emscriptenを使ってWeb上で動作していて、tracktion_engineの開発者にも知られています

MIDI 2.0 UMPの中にメタデータを埋め込む

今日SMFに近い演奏データのデータフォーマットをMIDI 2.0 UMPベースで実装しようとしていて気付いた小ネタ。いろいろ増やしてMIDI 2.0 UMPガイドブックの改訂版を出す場合はその時に取り込もうと思っています。(改訂版は技術書典サイトとboothではアップデートを出せるので、新たに購入する必要がないようにするつもりです*1。)


MIDI 1.0におけるSMF(MIDIファイル)には、可変長のデータを保存する命令としてSYSEXとメタイベントが利用できます。SYSEXはF0h〜F7hに、メタイベントはFFhから指定長のデータを保存できます。メタイベントにはメタイベント種別があり、MIDIイベントとしては存在しない次の各命令に使えます。

メタイベントID 意味
0 シーケンス番号
1 テキスト
2 著作権表示
3 シーケンス名またはトラック名
4 楽器名
5 歌詞
6 マーカー
7 キューポイント
0x20 MIDIチャネルプレフィックス指定
0x2F トラック終端指定
0x51 テンポ
0x54 SMPTEオフセット
0x58 拍子指定
0x59 調指定
0x7F シーケンサー固有イベント

ところでメタイベントの識別子になるFFhには、実はMIDIイベントが存在しており(システムリセット)、自由に使える領域ではありません。SMFでこれを使えるのは、単に概念として演奏データファイル中にシステムリセットが出現することがあり得ないためです。

MIDI 2.0でメタイベントを表現することを考える場合、MIDI 1.0イベントとMIDI 2.0 UMPは根本的に前提が異なる形式になっているので、半ばゼロベースで構造を考えなければいけません。MIDI 1.0時代のSMFの構成は次のようになっています。

  • SMFヘッダ
    • フォーマット指定 (format 0, 1, 2)
    • デルタタイム分解能指定 (division)
  • SMFトラック
    • MIDIメッセージ配列: 各MIDIメッセージの構造は
      • デルタタイム (7bit-encoded variable length)
      • MIDIイベント (2 / 3 / nバイト)

MIDI 2.0にはUMPとしてJR Timestampメッセージがあるので、デルタタイム指定の代替として機能するかもしれません。ただしJR Timestampのタイムスタンプ値は16ビットで1/31250秒単位のフレーム数を指定するので、たかだか2秒くらいしか表現できません。全音符・全休符などを表現するには複数のJR Timestampメッセージが必要ということになります。これはいまいちなので別の表現形式のほうが適切なのかもしれません(未検討)。

話を少し本題に戻しましょう。SMFにしか存在しない概念であるメタイベントをMIDI 2.0 UMPの上に構成するにはどうすればよいでしょうか? MIDI 2.0には次の3通りの可変長データ表現があります。

SYSEXはあくまでSYSEXなので、わかりやすく区別するためにはMDSを使うのがシンプルな解に思えます。しかしMDSにはSYSEX7やSYSEX8に無い特性があり、メタイベントには適していません。なぜでしょうか? その答えはMDSが分割送信できるとされていることにあります。

MDSはMIDIケーブルを通じてファームウェアアップデートを実行するような場面で活用できるように設計されたものですが、分割送信できるデータはいつ終端が届くかわからず、先頭と末尾の間にJR Timestampが含まれる可能性もあります。テンポ変更や拍子指定などのイベントでは正確なタイムスタンプが重要ですが、MDSではデータを最後まで受信しないと完全なMDSを取得できません。UMPをストリーミング処理していると、MDSを最後まで受信した頃にはもう処理時間が変わってしまっている可能性があります。UMPをバッファリング処理しないとメタイベントを正しいタイミングで取得・処理できないというのは、効率的ではありません。

あとは、UMPで予約されている領域を活用する方法もありますが、UMPの基本設計のひとつとして、可変長データを固定長データのフォーマットに変形する仕組みがあります。これを崩さずに可変長データを送信するのであれば、8ビットをフルに使えるSYSEX8を使うのが一番無難でしょう。適当にManufacturer IDを使う手もありますが、ユニバーサルSYSEXでSMFのシステムリセットのようにファイルへの保存があり得ないような命令の領域を使えば、無難にメタデータを格納できるのではないでしょうか。MMAのユニバーサルSYSEXのリストを眺めてみると、non-realtimeの7Bh〜7Fhの辺りは問題なく使いまわせそうです。

そういうわけで、SMFにおけるメタデータを表現するなら、おそらくSYSEX8を使ってユニバーサルSYSEXの一部領域を乗っ取りつつ、既存のパケットフォーマットを使い回すのが良さそうだというのが、現時点での自分の理解です。

*1:約束するというものではなく、債務者たるわたしが進んでこれを履行するときは債務の履行になる特殊な債権債務関係()と理解してください

技術書典9で買って読んで良かった新刊リスト

技術書典9の気になった新刊リストその2…を書くタイミングではないので、実際に買って読んだ本について一昨日くらいに書いた感想ツイーヨの配列を返します。手抜きでアレですが読まれてほしい〜

あと感想をmentionにしてしまったので出し方が変になっちゃうけどこちらも:

まだあと6時間くらいは買えるので(電子版の販売はその後どこかしらで復活するはずですが)、今のうちにどうぞ…!

MIDI 1.0/2.0はどのくらい「現役」の規格なのか?

MIDI 2.0の同人誌を出して、ぼちぼち売れているのですが*1、この本にどういう意義があるのか説明しておいたほうがいいかなと思いました。

みんな「MIDIなんてもう使われていない古い規格じゃないの?」とか「新しいバージョンを出して何の意味があるんだ?」って思うじゃないですか。でも実際には全然使われていないなんてことはなくて、今でもバリバリ現役で使われているし、MIDI 2.0は懐古趣味で作られた規格じゃないし、この本も懐古趣味で書いたわけではないんですよ。2020年に出るに相応しい規格なのです。

MIDIってそもそも何なんだっけ?

MIDI」と一言でいっても実はいろいろな構成要素があります。皆さんが「MIDI」と聞いて思い浮かべるものは、実際にはどれでしょうか?

多くは相互に依存しないので、現代でも役に立つものとそうでないものがありますし、MIDI 2.0としてバージョンアップする価値があるものとそうでないものがあるわけです。そういうわけで、以下ではこれら「MIDI」として扱われている技術要素が今後も存続する価値があるのか、個別に判断・解説していきます。

MIDIキーボード(入力デバイス) : 現役

MIDI規格に基づいて接続できるデバイスMIDIバイスと呼びますが、いま音楽制作の場面でMIDIバイスって使われているんでしょうか? その答えは圧倒的にYESで、たとえば音楽制作のためにDAWを繋いで楽器パートを打ち込む場面ではMIDIキーボードを使う人が多数でしょう*2DAWMIDIキーボードを使わない制作場面があるとしたらこんな感じです:

  • 全部オーディオチャンネルで録音して加工している(打ち込みパートなし)
  • ピアノロールに直接打ち込んでいる(こっちのほうが効率が良い/キーボードを弾けない(!))

…2つしか思いつかなかった。他にもこんな状況が考えられる、というのを思いついた人はコメント欄なりはてぶなりTwitterなりで言及してもらえればと思います。

MIDI音源モジュール(出力デバイス): ほぼ死亡

MIDIキーボードはあくまでMIDI入力」デバイスです。20世紀頃に「MIDIファイル」(SMF)が流行っていた頃はMIDI「音源」というのもあって、これらはMIDI出力」デバイスとしてMIDIメッセージを受け取って音楽を再生できる楽器として機能していました。こちらは、今では日の目を見ない存在です。特にSMFを視聴目的で利用する機会はほぼなくなりました(MIDIファイルの節とGeneral MIDIの節でまた触れます)。MIDIファイルでBGMを鳴らすWebサイトがもう無いのと同じです。音楽を聴くならMP3やFLACなどのPCMデータ一択でしょう。

そういうわけで「MIDI 2.0対応の音源モジュール」が出るとはちょっと考えられないです*3

懐古趣味で古いMIDI楽器を使う場面も考えられなくはないですが*4、昔ポピュラーだったMIDI楽器はだいたいソフトウェア音源として復刻しているので、およそ出番は無くなったと言ってよいでしょう。

もちろんシンセサイザーとしてのキーボードなどでは生演奏のほかにMIDI入力を受け取って音を出す目的で使えますし、人間の演奏入力をパイプラインで通して片方はシンセに流しつつもう片方は映像のコントロールなどに使うこともできるので、用途が無いわけではないです。

MIDIケーブル : だいたい死亡(USB / BLEに置き換え)

2020年現在、PCとMIDIを接続するのにシリアルMIDIケーブルを使う人はいないでしょう*5MIDI楽器同士、あるいはMI.1やmidiglueのような製品を介して古いMIDIバイスをPCと接続する場合には現役です。他にも電子工作方面はMIDIのシリアル接続と親和性が高いので、今でも使う人はいます。ただ一般的とは言い難いでしょう。DTM用途でMIDI楽器とPCを物理的に接続するなら、現在はUSB MIDI一択です。MIDIケーブルは過去のバイスと繋ぐ以外の役割を終えています。MIDIケーブルの新しい規格がMIDI 2.0のために出ることはないでしょう。

USBは1996年に初めて規定されたもので、MIDI音源でサポートしているものはかなり末期のものです(Roland SC-88Proに無くてSC-8850にあるくらい)。USB MIDIの仕様はMIDI 1.0が成立した1983年からだいぶ経ってから成立したものです。USB-MIDIについては昨年末に書きましたが別の同人誌がおすすめです

物理的に接続しない選択肢としては、BLEがあります。MaciOSAndroidではサポートされていますが、LinuxのBLE MIDIはまだ立ち位置が不安定です(一時期Bluezでサポートされていましたが外された模様)。あとBluetooth接続は遅延が問題になるので、USB接続を置き換える存在にはなりません。とはいえ、iOSAndroidのように、物理的に接続用コネクタを持ちようがない端末でもMIDI接続が可能になるポテンシャルは大きいものです。

MIDIメッセージ : 現役

OSIでいうところの物理層からトランスポート層あたりまでの話は時代性もありますが、その上でやり取りされるMIDI 1.0メッセージは、2020年現在でも現役で使われています。ここでは、90h がノートオンで80hがノートオフ、E0hがピッチベンドでF0hF7hがシステムエクスクルーシブ…といった意味付けが規定されています。このMIDIメッセージ仕様は、MIDI楽器とPCの間でやり取りするプロトコルとして用いられているだけでなく、純粋にソフトウェアの世界であるDAWVST/AUなどのオーディオプラグインの間でやり取りする場面でも内部的に使われます。特に音階の表現はMIDIの7ビット128段階の数値が広く一般的に用いられます。

MIDIでやり取りするのはデバイスを楽器として制御するための演奏命令(演奏に関する各種の命令)です。命令には、わかりやすくいえば「鍵盤を押す」ノートオン命令、「鍵盤から指を離す」ノートオフ命令、「音色を切り替える」プログラムチェンジ命令、「音量を変える」「左右の定位置を変える」「リバーブをかけて強さを指定する」などを実現するコントロールチェンジ命令などがあります(もちろん楽器は鍵盤だけではないので、あくまで概念です)。

もう少し具体的にいうと、ノートオン命令には「どのキーを押したか」「どれくらいの強さ(ベロシティ)で押したか」という情報が渡されます。MIDI 1.0の場合はどちらも0〜127で表します。全てのMIDIメッセージの形式が標準化されているので、どのMIDIバイスも命令を正しく伝えることができます。MIDI入力デバイスが今でも使われ続けているのは、どんなDAWでもほぼMIDI入力をサポートしているからです。

現役だけど内容は古い

もっとも、MIDI 1.0で規定された内容だけでは、音楽制作の現場ではだんだん機能不十分であると考えられるようになってきました。たとえば、データ部分が0〜127しか無いメッセージが大半で、この程度では表現力が足りません*6

また、MIDIメッセージには「チャンネル」を指定する部分もあって、これは同時に演奏できる音色の数にもなるのですが、MIDI 1.0では16チャンネルしかありません。現代のDAWを使った音楽制作では100トラック以上使うことがあり*7、16チャンネルでは到底足りません。

他にも、PCとMIDIバイスの間で機能の有無の確認などができればもう少し拡張機能を用意しやすいのですが、MIDI 1.0は単方向のプロトコルなのでそれも不可能です。こういった各種の機能拡大要求が溜まってきたので、MIDI 2.0としてこれまでとは互換性のない仕様を規定する必要が出てきたというわけです。

ちなみにMIDI 1.0の機能がしょぼすぎるということで、SteinbergはVST2からVST3に切り替えるにあたって、「MIDIサポート」を廃止しました。廃止したのにMIDIコントロールから入力を受け付けることができるのは、VSTホスト(DAW)側がMIDI入力を受け取ってVSTAPIによろしく変換してくれているということです。VST3には結局MIDIのノートオンに相当するNoteOnEventなどがあって使われています。

MIDI 2.0 UMPは、このMIDIメッセージ部分に相当する仕様です。今回同人誌としてUMPをターゲットにしたのは、ここがMIDI 2.0の新機能として一番わかりやすかったからでもあります。ちなみにプロトコルは主にMIDI-CIという別の仕様で規定されています。

楽器番号/音色セット(General MIDI): ほぼ死亡

MIDI楽器はプログラムチェンジという命令で「音色」を切り替えることができます。プログラムチェンジで指定できるのは0〜127の番号、あとせいぜい追加の「バンク指定」で0〜127の数字を2つ指定できるだけで、それ以上具体的な、たとえば波形データなどを指定することはできません。MIDI 1.0仕様が前提としているのは、その番号には既に楽器となるデジタル音源データが用意されていることです。これを用意していたのがMIDI音源モジュールであり、MIDI出力デバイスとして機能するキーボードシンセサイザーです。

この音色番号は、General MIDI (GM)という仕様によって、「1番はピアノ、16番はオルガン、24番はギター…」というように決まっていました。決まっていたのはあくまでざっくりとした音色名であり、そこにどんな音があるかは楽器のベンダー次第です。「ピアノ」と言ってもいろんな音があるのと同じです。MIDIデータとして制作し表現する音楽は、ここに限界がありました。

現代の音楽制作で使われているのは一般にはオーディオプラグインと呼ばれるもので、具体的にはSteinbergVSTAppleのAudioUnitといったAPIに基づいて作られたソフトウェアです(Linux方面でもLV2というISCライセンス前提の規格があって、今回技術書典9で同時に公開した「LV2オーディオプラグイン開発ガイド」はこのために書いたものです)。現代のDAWは、プログラムチェンジの音色番号を指定する代わりにこれらのプラグインのIDを指定して、プラグインインスタンスを生成し、そのプラグインのパラメーターを指定したり、よくstateと呼ばれる状態データの復元/保存によって標準的なパラメーターに収まらないデータを楽器のデータとして利用します。

こういう時代になると、音色番号を切り替えるだけで済む時代はおわりました。プログラムチェンジはおよそ死んだも同然です。もっとも、オーディオプラグインの中にはGMに相当する総合音源のようなものもあり*8、これらはプログラムチェンジを送るとプログラムチェンジとして機能することがあります。これらGM相当の総合音源も、単にGM互換だとGMを前提としたMIDIツールが使えるという以上のメリットは特にありません。

音色番号の代わりに楽器の情報を知る方法

オーディオプラグインが制作の中心になっている現在、DAWは複数オーディオプラグイン機構を同時にバラバラにサポートしなければならない状態になっています。楽器プラグインの詳細情報も、それぞれのプラグイン機構のやり方で取得しなければなりません。これを統一的に処理できるJUCEのようなフレームワークもありますが、あくまで私企業の実装であり、標準化されたデータ規約があれば、それに越したことはありません。

この方面では、MIDI 2.0にProperty ExchangeとProfile Configurationという仕様が策定されているのですが、まだ現在進行形です(器だけ決まっていて中身が規定されていない状態)。具体的な情報がまだ少ないので、今回の同人誌でも基本的に対象外のトピックとして、あまり触れていません。

MIDIファイル : ほぼ死亡

かつて音楽データを生のPCMデータでやり取りすることは、ネットワークの帯域の問題やPCの処理速度の問題で事実上不可能でした。MIDIファイルはそういう時代に音楽を表現する形式として有意義だったものです。しかし現在はそういう技術的な制約は消失し、作者が自らの手元で録音した音源をPCMのMP3やFLACなどの形式で配布できるようになりました。MIDIデータは音源次第で聞こえ方が大きく変わるので、細かくこだわって調整しても意味が無くなってしまい、芸術作品としてイマイチです。

そういうわけで、MIDIファイル形式としてのSMFは、もう楽曲の交換に使われることはほぼなくなりました。

データのエクスポート/インポート形式として今も使う場面がある

もっとも、SMFを「使う」場面が無くなったわけではありません。たとえばDAWを乗り換える場合や、細かい打ち込みの詳細情報が無い状態にして、複数環境でやり取りする必要がある場合、SMFでエクスポートしてそれを別の環境でインポートする、といったことは現代でも行われています。楽譜データを配信したり購入者特典にしたりする場合*9も、一般的とは言い難いスコアデータよりは、広く認知されておりツールサポートも一般的で活用しやすいSMFのほうが向いています。

DAWで表現できる音楽の互換性には一定のラインで限界があるので、エクスポート/インポートはあくまで可能な範囲でのみ行われます。SMFにエクスポートするということは、オーディオプラグインに関するデータは全て切り捨てられることになるので、それはインポートしてから制作者が頑張って復元するということになるわけです。アレンジ版の楽曲データを制作するような場合は、これで十分ともいえます。

MIDI 2.0は何が「新しい」のか?

MIDI 2.0 UMPは、MIDI 1.0でいうところのMIDIメッセージの仕様をモダンにしたものです。たとえば…

  • チャンネルが16から256まで拡大されている。ただし単純に4ビットから8ビットにするのではなく「グループ」の概念を導入している(そうしないとMIDI 1.0互換機能が崩壊する)
  • 7ビットの数値が32ビットビットになったりしている
  • ノート別に作用するパラメーターが新設されている
  • ノート命令にアーティキュレーションが追加されている
  • データの可変長要素が全て廃止され32/64/128ビット整数のみになった(sysexと7bit-encoded length, running status)

MIDIのプログラムを組んだことがある人なら、最後の変更点のインパクトが割と大きいことがわかるかもしれません。メッセージの種類に依存した動的なメモリ確保が不要になるのです! リアルタイムオーディオで使われることも多いMIDIメッセージの処理で、動的なメモリの心配をする場面が減るというのは、割と現代的で「わかっている」感じがしませんか??

もちろん新しい仕様には、うれしい新機能だけではなくて、難しい課題が出てくることもあります。先日書いたUMPにおけるノート命令についての解説は今回の同人誌の一部として書いたものですが、だいぶ難しい話題を取り上げています。

あと、SMFの更新はまだ出ていないけど仕様策定中らしいです。

Summary

今後MIDI標準に関連してアップデートされる価値があるやつとないやつを、以下のようなふいんきで一つ一つ解説していきました。

  • MIDIキーボード
  • MIDI音源モジュール
  • MIDIケーブル(電子工作を除く)
  • MIDIメッセージ ← MIDI 2.0 UMPはココ
  • General MIDI
  • MIDIファイル(演奏目的のやつ)

こうやってまとめると「やばい」「炎上要素しか無い」という感じですが、本文に足りない視点があったり有意義な用途を無視している点があったら、コメントなりはてぶなりSNSなりで指摘してもらえればと思います。

*1:お買い上げいただいた皆さんありがとうございます

*2:キーボード以外にもギターや管楽器などがあるんですが、話がややこしくなるのでキーボードとまとめちゃいます

*3:ハードウェア音源は数年に一度くらいごくまれに出る印象がありますが、RolandのSD-50が2010年に「8年ぶりに」出たと考えると、さすがにもう無いかな…と思います

*4:FM音源などはハードウェアのオリジナルに強くこだわるユーザーがちらほらいます

*5:昔はRS-232Cケーブルをモデムと同じ口に繋いだりしていましたが、最近は電話回線に繋ぐことも無いですね…

*6:DAWではMIDIキーボードは人間が演奏したベロシティの値を0〜127で受け取りますが、内部的にはもっと精細な数値(たとえば0〜65535とか、0.0〜1.0とか)で保存することが多いようです

*7:トラックとチャンネルは別々の概念ですが、ここではあいまいにしておきます

*8:たとえばCubaseに付属するHALionやRolandのSound Canvas VAなどがそうです

*9:わたしはPixiv FANBOXで支援しているアーティストが配布しているのをよく見かけます