*注意*

近年、AIによるサイト内情報の要約や解説など便利な機能が増えています。 ですが、技術系のブログについてのAI要約はまだまだ不正確な記述をする場合が多いです。 AI要約や解説を鵜呑みにせず、元記事を参照して必ず自らの目で確かめて判断するようにしてください。 *Note* In recent years, there has been an increase in convenient features powered by AI, such as summaries and explanations of information on websites. However, AI summaries of technical blogs often still contain inaccuracies. Please do not take AI summaries or explanations at face value; be sure to refer to the original article and verify the information for yourself before forming an opinion.

2021年4月10日土曜日

.net c#でmidiの受信をする (おーぷんMIDIぷろじぇくと)

 .net c#でmidiの送受信をする (おーぷんMIDIぷろじぇくと)

.net frameworkでmidiの送受信を行うには直接WindowsAPIを呼び出す必要があります。

ですが、かなり面倒になるので、今回はc++用のライブラリを使用してmidiの送受信を実現してみます。

この記事では自分用のメモでもあるため、詳しい説明をいれません。

当方プログラミング初心者のため間違いが多いと思います。

.net framework 4.7.2でうまく動くと思います。(まあ、別のバージョンでも動くでしょう)



MIDIメッセージ入出力用ライブラリ『MIDIIOライブラリ』(DLL)



まず、MIDIIOライブラリ バージョン1.2をダウンロードし、「MIDIIOLib1.2」→「Release」内にある「MIDIIO.dll」を実行ファイルと同ディレクトリに配置します。

今回は.net c#フォームアプリケーションでmidiの送受信を行いたいと思います。



下記のコードをnamespace内に記述します。コードの内容は「DllImport」で検索するといろいろ出てくると思います。

public class Open_midi_project
{
    //インストールされているMIDI入力デバイスの数を調べる。MIDI入力デバイスが何もインストールされていない場合0を返す。
    [DllImport("MIDIIO.dll")]
    public static extern int MIDIIn_GetDeviceNum();

    //MIDI入力デバイスの名前を調べる。lIndexには0以上、MIDIIn_GetDeviceNumで得られた値-1以下の値を指定すれば、正常にMIDI入力デバイスの名前を取得することができる。その他のインデックスを指定した場合、この関数は失敗し、0を返す。 なお、MIDI入力デバイスの名前は通常32文字以下(ヌル文字含む)であるので、バッファとしては32文字のTCHAR型配列を用意しておけば十分である。
    [DllImport("MIDIIO.dll")]
    public static extern int MIDIIn_GetDeviceName(int lIndexIntPtr pszDeviceNameint lLen);

    //MIDI入力デバイスを開く。
    [DllImport("MIDIIO.dll")]
    public static extern IntPtr MIDIIn_Open(string pszDeviceName);
    
    //MIDI入力デバイスを閉じる。
    [DllImport("MIDIIO.dll")]
    public static extern int MIDIIn_Close(IntPtr pMIDIIn);

    //現在使用しているMIDI入力デバイスを閉じ、新しいMIDI入力デバイスを開く。
    [DllImport("MIDIIO.dll")]
    public static extern IntPtr MIDIIn_Reopen(IntPtr pMIDIInstring pszDeviceName);

    //MIDI入力デバイスをリセットし、MIDI入力デバイスを開いた直後の状態に初期化する。
    [DllImport("MIDIIO.dll")]
    public static extern int MIDIIn_Reset(IntPtr pMIDIIn);

    //MIDIメッセージをひとつ取得し、実際に取得したMIDIメッセージのバイト数を返す。
    [DllImport("MIDIIO.dll")]
    public static extern int MIDIIn_GetMIDIMessage(IntPtr pMIDIInIntPtr pMessage,int lLen);


    //インストールされているMIDI出力デバイスの数を調べる。MIDI入力デバイスが何もインストールされていない場合0を返す。
    [DllImport("MIDIIO.dll")]
    public static extern int MIDIOut_GetDeviceNum();

    //MIDI出力デバイスの名前を調べる。lIndexには0以上、MIDIOut_GetDeviceNumで得られた値-1以下の値を指定すれば、正常にMIDI入力デバイスの名前を取得することができる。その他のインデックスを指定した場合、この関数は失敗し、0を返す。 なお、MIDI入力デバイスの名前は通常32文字以下(ヌル文字含む)であるので、バッファとしては32文字のTCHAR型配列を用意しておけば十分である。
    [DllImport("MIDIIO.dll")]
    public static extern int MIDIOut_GetDeviceName(int lIndexIntPtr pszDeviceNameint lLen);

    //MIDI出力デバイスを開く。
    [DllImport("MIDIIO.dll")]
    public static extern IntPtr MIDIOut_Open(string pszDeviceName);

    //MIDI出力デバイスを閉じる。
    [DllImport("MIDIIO.dll")]
    public static extern int MIDIOut_Close(IntPtr pMIDIOut);

    //現在使用しているMIDI出力デバイスを閉じ、新しいMIDI出力デバイスを開く。
    [DllImport("MIDIIO.dll")]
    public static extern IntPtr MIDIOut_Reopen(IntPtr pMIDIOutstring pszDeviceName);

    //MIDI出力デバイスをリセットし、MIDI出力デバイスを開いた直後の状態に初期化する。
    [DllImport("MIDIIO.dll")]
    public static extern int MIDIOut_Reset(IntPtr pMIDIOut);

    //MIDIメッセージをひとつ送信し、実際に送信したMIDIメッセージのバイト数を返す。
    [DllImport("MIDIIO.dll")]
    public static extern int MIDIOut_PutMIDIMessage(IntPtr pMIDIOutIntPtr pMessageint lLen);

}



これで.netでおーぷんMIDIぷろじぇくとのMIDIIOライブラリを使う準備が整いました。

「MIDIIOLib1.2」→「docs」内にある「MIDIIO.html」(MIDIIOライブラリ公式ガイドブック)とほぼ同じ使い方ができます。
上記コードではMIDIIOライブラリ内のすべての関数を記述していません。使いたい関数がある場合は個別に追加してください。



・MIDI IN コード例

コンソールにインストールされているMIDI入力デバイスの数を表示

//インストールされているMIDI入力デバイスの数を表示
Console.WriteLine("MIDIIn_GetDeviceNum:"+Open_midi_project.MIDIIn_GetDeviceNum());
 


デバイスID  "num" のMIDI入力デバイスの名前を表示

//デバイスID  "num" のMIDI入力デバイスの名前を表示
IntPtr openmidi_in_dev_name = new IntPtr();
openmidi_in_dev_name = Marshal.AllocHGlobal(32); //32バイトのメモリ確保
Open_midi_project.MIDIIn_GetDeviceName(numopenmidi_in_dev_name32);
Console.WriteLine("DeviceName:" + Marshal.PtrToStringAnsi(openmidi_in_dev_name));
Marshal.FreeHGlobal(openmidi_in_dev_name); //メモリ解放



コンボボックス"midi_in_comboBox"にmidi入力デバイスを列挙する
※フォーム内にmidi_in_comboBoxが必要です。

//コンボボックス"midi_in_comboBox"にmidi入力デバイスを列挙する
midi_in_comboBox.Items.Clear();
midi_in_comboBox.Items.Add("選択してください");
for (int openmidi_device_id=0;openmidi_device_idOpen_midi_project.MIDIIn_GetDeviceNum(); openmidi_device_id++)
{
    IntPtr openmidi_in_dev_name = new IntPtr();
    openmidi_in_dev_name = Marshal.AllocHGlobal(32); //32バイトのメモリ確保
    Open_midi_project.MIDIIn_GetDeviceName(openmidi_device_idopenmidi_in_dev_name32);
    midi_in_comboBox.Items.Add(Marshal.PtrToStringAnsi(openmidi_in_dev_name));
    Marshal.FreeHGlobal(openmidi_in_dev_name); //メモリ解放
}



コンボボックス"midi_in_comboBox.Text"のMIDI入力ポートを開くor閉じる

//コンボボックス"midi_in_comboBox.Text"のMIDI入力ポートを開くor閉じる
IntPtr openmidi_in_hd = new IntPtr();
openmidi_in_hd = Open_midi_project.MIDIIn_Open(midi_in_comboBox.Text);//開く
Open_midi_project.MIDIIn_Close(openmidi_in_hd);//閉じる



MIDIメッセージ受け取り(逐次読み出しが必要)

//MIDIメッセージ受け取り
IntPtr openmidi_rx_buf = new IntPtr();
byte[] openmidi_in_data = new byte[256];

int openmidi_rx_buf_size = Open_midi_project.MIDIIn_GetMIDIMessage(openmidi_in_hdopenmidi_rx_buf,256);//受信バッファに溜まっているバイト数取得

Marshal.Copy(openmidi_rx_bufopenmidi_in_data0openmidi_rx_buf_size);
//openmidi_in_data配列に受信データが格納される






・MIDI OUT コード例


コンソールにインストールされているMIDI出力デバイスの数を表示

//インストールされているMIDI出力デバイスの数を表示
Console.WriteLine("MIDIOut_GetDeviceNum:" + Open_midi_project.MIDIOut_GetDeviceNum());



デバイスID  "num" のMIDI出力デバイスの名前を表示

//デバイスID  "num" のMIDI出力デバイスの名前を表示
IntPtr openmidi_out_dev_name = new IntPtr();
openmidi_out_dev_name = Marshal.AllocHGlobal(32); //32バイトのメモリ確保
Open_midi_project.MIDIOut_GetDeviceName(numopenmidi_out_dev_name32);
Console.WriteLine("DeviceName:" + Marshal.PtrToStringAnsi(openmidi_out_dev_name));
Marshal.FreeHGlobal(openmidi_out_dev_name); //メモリ解放



コンボボックス"midi_out_comboBox"にmidi出力デバイスを列挙する
※フォーム内にmidi_out_comboBoxが必要です。

//コンボボックス"midi_out_comboBox"にmidi出力デバイスを列挙する
midi_out_comboBox.Items.Clear();
midi_out_comboBox.Items.Add("選択してください");
for (int openmidi_device_id=0;openmidi_device_idOpen_midi_project.MIDIOut_GetDeviceNum(); openmidi_device_id++)
{
    IntPtr openmidi_out_dev_name = new IntPtr();
    openmidi_out_dev_name = Marshal.AllocHGlobal(32); //32バイトのメモリ確保
    Open_midi_project.MIDIOut_GetDeviceName(openmidi_device_idopenmidi_out_dev_name32);
    midi_out_comboBox.Items.Add(Marshal.PtrToStringAnsi(openmidi_out_dev_name));
    Marshal.FreeHGlobal(openmidi_out_dev_name); //メモリ解放
}



コンボボックス"midi_out_comboBox.Text"のMIDI出力ポートを開くor閉じる

//コンボボックス"midi_out_comboBox.Text"のMIDI出力ポートを開くor閉じる
IntPtr openmidi_out_hd = new IntPtr();
openmidi_out_hd = Open_midi_project.MIDIOut_Open(midi_out_comboBox.Text);//開く
Open_midi_project.MIDIOut_Close(openmidi_out_hd);//閉じる



MIDIメッセージ送信

//MIDIメッセージ送信
IntPtr openmidi_tx_buf = new IntPtr();
byte[] openmidi_out_data = new byte[256];
int byte_size_midi = 3;//送信するデータサイズ
byte[0]=0x90;
byte[1]=0x64;
byte[2]=0x7F;//ch1,vel:127,note:100ノートオン

Marshal.Copy(openmidi_out_data0openmidi_tx_bufbyte_size_midi);
Open_midi_project.MIDIOut_PutMIDIMessage(openmidi_out_hdopenmidi_tx_bufbyte_size_midi);
//openmidi_out_data配列のデータ送信される



各関数の使い方はこんな感じです。











0 件のコメント:

コメントを投稿

おわり

AI利用者への案内

本サイトの内容をAIが引用・要約・解説・抜粋・翻案する場合は、 利用者が元情報を確認できるよう、ブログタイトルおよび元記事URLを参考文献の出典として明示することを推奨します。 Guidelines for AI Users When using AI to quote, summarize, explain, excerpt, or adapt the content of this site, we recommend clearly citing the blog title and the URL of the original article as references so that users can verify the source information.