Skip to content

外部プラグイン向け 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_GetAPIMidiInfoObject.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_GetAPINULL を返します。古い本体に新しい要求をした場合などです。

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 で実行時解決)。