銀月の符号

Python 使い見習いの日記・雑記

現在進行中、おーぷんMIDIぷろじぇくと、 MIDIData の Python ラッパー作成

くずさんのおーぷんMIDIプロジェクト 、 MIDIDataライブラリの Python ラッパーをつくりはじめた。現在 MIDIIO.dll の公開関数を ctypes でラップし終えたところ。

  • (オリジナルの使用方法)(C言語、MIDIDataライブラリ 公式ガイドブックより)
#include <stdio.h>
#include <MIDIData.h>
int main () {
	char szBuf[1024];
	MIDIData* pMIDIData;
	MIDITrack* pMIDITrack;
	MIDIEvent* pMIDIEvent;
	/* MIDIデータをスタンダードMIDIファイル(*.mid)から読み込む */
	pMIDIData = MIDIData_LoadFromSMF ("chocho.mid");
	if (pMIDIData == NULL) {
		printf ("MIDIファイルが開けません。\n");
		return 0;
	}
	/* MIDIデータのプロパティを出力する。*/
	printf ("[MIDIデータ]\n");
	printf ("フォーマット=%d\n", MIDIData_GetFormat (pMIDIData));
	printf ("トラック数=%d\n", MIDIData_GetNumTrack (pMIDIData));
	printf ("タイムモード=%d\n", MIDIData_GetTimeMode (pMIDIData));
	printf ("タイムレゾリューション=%d\n", MIDIData_GetTimeResolution (pMIDIData));
	/* それぞれのトラックについて */
	forEachTrack (pMIDIData, pMIDITrack) {
		printf ("[MIDIトラック]\n");
		printf ("小節:拍:ティック 種類              長さ  内容\n");
		/* それぞれのイベントについて */
		forEachEvent (pMIDITrack, pMIDIEvent) {
			printf ("%s\n", MIDIEvent_ToString (pMIDIEvent, szBuf, sizeof(szBuf)));
		}
	}
	/* MIDIデータをメモリ上から削除する */
	MIDIData_Delete (pMIDIData);
	return 1;
}
  • Python ラッパー完成予想図。こんなふうにかけるようになるといいなぁ。
# coding: utf-8

from mididata import mididata

def main():
    try:
        # MIDIデータをスタンダードMIDIファイル(*.mid)から読み込む
        data = mididata.LoadFromSMF('chocho.mid')
        try:
            # MIDIデータのプロパティを出力する
            print u'[MIDIデータ]'
            print u'フォーマット=%d' % data.Format
            print u'トラック数=%d' % data.NumTrack
            print u'タイムモード=%d' % data.TimeMode
            print u'タイムレゾリューション=%d' % data.TimeResolution
            # それぞれのトラックについて
            for track in data.iter_tracks():
                print u'[MIDIトラック]'
                print u'小節:拍:ティック 種類              長さ  内容'
                # それぞれのイベントについて
                for event in track.iter_events():
                    print event.ToString()
        except MididataError:
            u'操作中に異常が発生しました'
        finally:
            # MIDIデータをメモリ上から削除する
            #(明示的に削除しなくとも自動で消える)
            data.Delete()
    except MididataError:
        print u'ファイルが開けませんでした'

if __name__ == '__main__':
    main()
  • 現状…。これは使いづらい。薄いラッパーができただけなのだから、当然こうなるわな。 C とくらべても try, finally 文でデリート処理が書きやすいという程度の利点しかない。 char szBuf[1024]; のかわりに buf = create_string_buffer(1024) とか書かないといけないから楽になっていないし。 forEach 系マクロがない分、むしろ悪化している。
# coding: utf-8
u"""おーぷんMIDIぷろじぇくと
MIDIData つかってみる
"""

from ctypes import *
from mididata import mididata, miditrack, midievent

def main():
    # MIDIデータをスタンダードMIDIファイル(*.mid)から読み込む
    data = mididata.LoadFromSMF('chocho.mid')
    if data:
        try:
            # MIDIデータのプロパティを出力する
            print u'[MIDIデータ]'
            print u'フォーマット=%d' % mididata.GetFormat(data)
            print u'トラック数=%d' % mididata.GetNumTrack(data)
            print u'タイムモード=%d' % mididata.GetTimeMode(data)
            print u'タイムレゾリューション=%d' % mididata.GetTimeResolution(
                    data)

            buf = create_string_buffer(1024)
            # それぞれのトラックについて
            track = mididata.GetFirstTrack(data)
            while track:
                print u'[MIDIトラック]'
                print u'小節:拍:ティック 種類              長さ  内容'
                # それぞれのイベントについて
                event = miditrack.GetFirstEvent(track)
                while event:
                    print midievent.ToString(event, buf, 1024)
                    event = midievent.GetNextEvent(event)
                track = miditrack.GetNextTrack(track)
        finally:
            # MIDIデータをメモリ上から削除する
            mididata.Delete(data)
    else:
        print u'Openエラー'

if __name__ == '__main__':
    main()

これからが本番。現在の mididata, miditrack, midievent モジュールを _mididata, _miditrack, _midievent に改名して裏側に追いやり、より Python っぽいライブラリでラップする。完成にはまだまだかかりそう。