Slide 1

Slide 1 text

Kotlin Multiplatformで MIDI 1.0/2.0 ライブラリを作っている話 atsushieno

Slide 2

Slide 2 text

@atsushieno Android / Kotlin app developer androidaudioplugin.org オーディオプラグイン研究所(技術書サークル) @[email protected] (ja) @[email protected] (en)

Slide 3

Slide 3 text

atsushieno/ktmidi (on GitHub) MIDI (musical instrument digital interface) を扱うKotlin Multiplatformライブラリ - MidiAccess : プラットフォーム別のMIDIデバイスにアクセス - Midi1Music, Midi2Music : SMF (MIDIファイル) 1.0 / 2.0もどき を読み書き - Midi1Player, Midi2Player : SMF 1.0 / 2.0もどき を演奏 - MIDI 2.0対応機能 - UMP、MIDI-CI(開発中)など MIDI 2.0サポートが特長 そもそもKotlinでMIDIを扱うライブラリが他に存在しない

Slide 4

Slide 4 text

Kotlin for music apps? 音楽アプリの音声処理にはリアルタイム処理が重要 - no GC pause, no locks, no (blocking) syscalls, no unbounded computation ... 音楽制作アプリをKotlinのようなGCやJITありきの言語で作るべきではない  (so as JavaScript, Java, C#, Python, Go, Ruby...)  Swiftも現状では非推奨 - Is Swift really not performant enough for realtime audio? 実際にはオーディオスレッドのコードだけ非GC言語で動かせばOK 例: Bitwig Studio (Java)

Slide 5

Slide 5 text

SMFサポート、MIDIプレイヤー SMFやSMF2 (MIDI Clip File)は単なるバイナリ配列なのでとても簡単 MIDIプレイヤーはタイマーイベントでMIDIデバイスにMIDIメッセージを送るだけ タイマー実装は単なるdelay() (mutex locked)

Slide 6

Slide 6 text

Platform MIDI Access API (C/C++/ObjC|Swift) MIDIデバイス: USB, BLE, その他(ソフトウェアMIDIデバイス、RTPなど) MIDIデバイスアクセスはプラットフォーム固有 - WinMM / UWP MIDI API - CoreMIDI - ALSA - Web MIDI API - Android MIDI API (Java), Android Native MIDI API (C) クロスプラットフォームMIDIライブラリ - rtmidi, portmidi, libremidi (MIDI 2.0対応), ...

Slide 7

Slide 7 text

MidiAccess: MIDI APIs on Kotlin Multiplatform (KMPの"Multiplatform"はWin/Mac/Linux/...ではない) - Kotlin/JVM: javax.sound.midi or JNIで前記C/C++ APIにアクセス - Android: android.media.midi - Kotlin/Native: cinteropで前記C/C++ APIのバインディングを生成 - Kotlin/JS: Web MIDI APIとnode.js用のMIDIライブラリをnpmで参照 - JAZZ-SOFT/JZZ: クロスプラットフォーム MIDIアクセスライブラリ - たぶんKotlin/Wasmもこれになる

Slide 8

Slide 8 text

Kotlin/JVM実装 - JvmMidiAccess : javax.sound.midi (非推奨) - Java MIDI APIは仮想MIDIデバイスを作成できない - Linuxでソフトシンセ等を使えない (alsa-sequencerではなくalsa-rawmidiを使っているため) - このせいでBitwig Studioなどはtimidity, fluidsynth,vmpk等を認識しない - RtMidiAccess : RtMidiバインディング - Win / Mac / Linux, 仮想MIDIデバイス作成も可能 (Windows以外) - AlsaMidiAccess : ALSAバインディング - Linux Kernel 6.5以降ではMIDI 2.0仮想デバイス作成も可能 (CoreMIDI JVMサポートもほしいけどup to dateなものが存在しない…)

Slide 9

Slide 9 text

Kotlin/JVMに向いているJNIバインディング機構は? JNA + JNAerator 󰢏 native glue codeの生成が不要 󰢄 JNAeratorはメンテされておらず arm64未対応 JavaCPP 󰢏 現役 󰢄 native glue codeの自動生成が必要   = Mavenパッケージがplatform / ABIごとに必要 󰢄 gradle-javacppの知見を集めるのは大変 JNI手書き 󰢄 しんどい 󰢏 余計な依存性が無い Panama 󰢏 glue codeは不要 󰢄 stableリリースされていない / Androidでは使えない

Slide 10

Slide 10 text

Kotlin/Nativeサポート RtMidiNativeAccess : RtMidi APIバインディング (cinterop) - rtmidi-javacppのRtMidiAccessとは別のAPI - サポート対象をデスクトップに限定するため独立したmoduleに切り出し - JavadocJarのサポートが厄介 (Kotlin/dokka/issues/3122) - ドキュメントJavadocJarが無いとMaven Centralでリリースできない - jvmターゲットが無いとJavadocJarが生成されない - Gradle 8.0でJavadocJarの扱いが変わってよろしくやってくれなくなった 他のネイティブAPIもcinteropバインディングを作成することになる…? Kotlin/Nativeでやる必要ある…?(多分ある…)

Slide 11

Slide 11 text

GitHub ActionsからMaven Centralへのリリース rtmidi-javacpp - GitHub Actionsでbuild matrixを設定  (macos13-xlargeを使いたい…) (ktmidiはまだ) OSSRH sonatypeへのアップロード - nexus-actions/create-nexus-staging-repoを利用 リリースは手動で承認

Slide 12

Slide 12 text

MIDI 2.0サポートの実装 MIDI 2.0仕様: 2020年に正式リリース / 2023年6月に大幅に改訂 - MIDI-CI 双方向の通信が可能になったのでデバイスの機能の有無などを確認するプロトコルを実現した 送信者・受信者のエージェント APIが必要 - UMP 2〜3バイトのMIDIメッセージに代わって 32 / 64 / 128ビットで表現できるようになった バイトデータの解析・生成 APIが大量に必要 / 1.0 / 2.0相互変換処理も必要 - SMF2 UMPに基づくMIDIファイル(現状「クリップファイル」のみ) UMP/SMF2は(基本部分は)バイト配列の処理で済む(MIDI-CIはもう少し複雑)

Slide 13

Slide 13 text

MIDI 2.0: プラットフォームのサポート まだ全然出揃っていない - 󰢄 MS: Windows MIDI Service (Microsoft/midi) - 2024年予定 - 󰢏 Apple: CoreMIDIで数年前から実装(macOS / iOS) - Sonomaまでは安心して使えなかった ? https://www.dtmstation.com/archives/63930.html - ? Linux: Kernel 6.5 / libasound 1.2.10 からサポート - 各種distroの安定版リリースを待つ必要 - ? Android: USB MIDI 2.0のみAndroid 13からサポート 「まだその時ではない」が、やる気があるなら今できなくもない

Slide 14

Slide 14 text

まとめ - KotlinのMultiplatformでネイティブAPIをサポートするには   (OS = platform) x (実行環境 = VMs) の実装が必要 - Kotlin/NativeのみのモジュールのJavadocJarはハマる - Kotlin/NativeのCIビルドはプラットフォーム別のレーンが必要 - atsushieno/ktmidiを使うと最先端のMIDI 2.0アプリ開発もそこそこできる