外部プラグイン向け C API
MidiInfoObject.aux2 は、読み込んだ MIDI 解析結果を 安定した C ABI で外部プラグインに公開します。他のプラグインから BPM・拍子・小節・ノート区間・チャンネル色・共有再生時刻などを取得できます。
Zel9278/midi-info-api
AviUtl2 MIDI Info プラグインの公開 C ABI ヘッダ。これ1つを取り込めば外部プラグインから利用できます。
MITgithub.com
- 公開ヘッダ:
MidiInfoAPI.h(上記リポジトリで管理。本体には submodule(external/midi-info-api)として取り込み。利用側はこの 1 ファイルだけコピーすれば十分) - エントリポイント:
MidiInfo_GetAPI(MidiInfoObject.aux2がエクスポート) - 関数一覧: 関数リファレンス
- 動く例: サンプルプラグイン
設計方針
- POD のみの関数テーブル(STL を跨がない)。コンパイラ・言語に依存せず安全。
- 解析ハンドルは内部で
shared_ptrを保持し、releaseまで配列ポインタが有効。 MidiInfoNoteSpanは内部表現とバイナリ互換で、コピー無しにポインタで返します。- 前方互換: 関数テーブルは末尾追加のみ。破壊的変更時に
MIDIINFO_API_VERSIONを上げます。struct_size/versionも保持しています。
はじめかた
1. API を取得する
MidiInfoObject.aux2 は同一プロセスに常駐しているので、GetModuleHandle + GetProcAddress で関数テーブルを取得します。
c
#include "MidiInfoAPI.h"
HMODULE h = GetModuleHandleW(L"MidiInfoObject.aux2");
if (!h) return; // 本体プラグインが入っていない
MidiInfo_GetAPI_Fn getapi =
(MidiInfo_GetAPI_Fn)GetProcAddress(h, MIDIINFO_GETAPI_SYMBOL);
const MidiInfoAPI* api = getapi ? getapi(MIDIINFO_API_VERSION) : NULL;
if (!api) return; // 互換バージョンが無いgetapi が NULL を返すとき
要求した requested_version が提供側より新しい場合、MidiInfo_GetAPI は NULL を返します。古い本体に新しい要求をした場合などです。
2. 解析を取得して使う
c
// path=NULL で「共有 MIDI」(MIDI Source が読み込んだもの)を取得
MidiInfoAnalysis* an = api->acquire(NULL); // または api->acquire(L"C:/song.mid")
if (api->is_ok(an)) {
double t = 1.5; // 秒
double bpm = api->bpm_at(an, t);
uint8_t num = 4, den = 4;
api->signature_at(an, t, &num, &den);
uint32_t notes = api->count_at(an, t, 0); // 現在時刻までの累積ノート数
const MidiInfoNoteSpan* spans;
int n = api->note_spans(an, 60, &spans); // C4(=60) の区間配列
for (int i = 0; i < n; ++i) {
// spans[i].start / .end(秒), .channel, .track, .color
}
}
api->release(an); // 取得したハンドルは必ず解放3. 再生位置に同期する
各オブジェクトと同じく、MIDI Source の共有再生時刻に同期できます。
c
double t = api->get_shared_time(); // 無効なら NaN
if (t != t) { // NaN チェック
t = /* 自分のオブジェクト時刻にフォールバック */ 0.0;
}ライフタイムとスレッド安全性
- ハンドルは必ず
releaseしてください(acquire/acquire_waitで得たもの)。内部shared_ptrを解放します。 note_spansが返す配列ポインタは、そのハンドルがreleaseされるまで有効です。is_okが真になるまで(=バックグラウンド解析の完了まで)は、未ロード状態のハンドルが返ることがあります。確実にデータが要る場面(エンコード等)ではacquire_waitを使ってください。- 解析データは生成後イミュータブルなので、複数スレッドからの読み取りは安全です。
acquire/release自体も内部ロックで保護されています。
配布するとき
- 自作プラグインに組み込む場合、
MidiInfoAPI.hの 1 ファイルだけコピーすれば十分です。 - リンクは不要です(
GetProcAddressで実行時解決)。