public MIDI入力デバイス() { using (Log.Block(FDKUtilities.現在のメソッド名)) { // 初期化する。 this._MIDI入力デバイスハンドルリスト = new List <MIDIINHANDLE>(5); // 5個もあれば十分? this._蓄積用入力イベントリスト = new List <InputEvent>(32); // 適当 this.入力イベントリスト = new List <InputEvent>(); // コールバックをデリゲートとして生成し、そのデリゲートをGCの対象から外す。 this._midiInProc = new MidiInProc(this.MIDI入力コールバック); this._midiInProcGCh = GCHandle.Alloc(this._midiInProc); // デバイス数を取得。 uint MIDI入力デバイス数 = midiInGetNumDevs(); Log.Info($"MIDI入力デバイス数 = {MIDI入力デバイス数}"); // すべてのMIDI入力デバイスについて... for (uint id = 0; id < MIDI入力デバイス数; id++) { // デバイス名を取得。 var caps = new MIDIINCAPS(); midiInGetDevCaps(id, ref caps, Marshal.SizeOf(caps)); this.DeviceName.Add(caps.szPname); Log.Info($"MidiIn[{id}]: {caps.szPname}"); // MIDI入力デバイスを開く。コールバックは全デバイスで共通。 MIDIINHANDLE hMidiIn = default; if (((uint)CSCore.MmResult.NoError == midiInOpen(ref hMidiIn, id, this._midiInProc, default, CALLBACK_FUNCTION)) && (default != hMidiIn))
private static extern uint midiInClose(MIDIINHANDLE hMidiIn);
private static extern uint midiInReset(MIDIINHANDLE hMidiIn);
private static extern uint midiInStop(MIDIINHANDLE hMidiIn);
private static extern uint midiInOpen(ref MIDIINHANDLE phMidiIn, uint uDeviceID, MidiInProc dwCallback, int dwInstance, int fdwOpen);
=> false; // 常に false protected virtual void MIDI入力コールバック(MIDIINHANDLE hMidiIn, uint wMsg, int dwInstance, int dwParam1, int dwParam2) { var timeStamp = QPCTimer.生カウント; // できるだけ早く取得しておく。 if (MIM_DATA != wMsg) { return; } int deviceID = this._MIDI入力デバイスハンドルリスト.FindIndex((h) => (h == hMidiIn)); if (0 > deviceID) { return; } byte ch = (byte)(dwParam1 & 0xFF); byte ev = (byte)(dwParam1 & 0xF0); byte p1 = (byte)((dwParam1 >> 8) & 0xFF); byte p2 = (byte)((dwParam1 >> 16) & 0xFF); if ((0x90 == ev) && (0 != p2)) // Velocity(p2)==0 を NoteOFF 扱いとする機器があるのでそれに倣う { #region " (A) Note ON " //---------------- var ie = new InputEvent() { DeviceID = deviceID, Key = p1, 押された = true, TimeStamp = timeStamp, Control = 0, Velocity = p2, Extra = $"{ch:X2}{p1:X2}{p2:X2}", }; lock (this._コールバック同期) this._蓄積用入力イベントリスト.Add(ie); //---------------- #endregion } else if ((0x80 == ev) || (0x90 == ev && 0 == p2)) // NoteOnかつVelocity(p2)==0 を NoteOFF 扱いとする機器があるのでそれに倣う { #region " (B) Note OFF " //---------------- var ie = new InputEvent() { DeviceID = deviceID, Key = p1, 押された = false, TimeStamp = timeStamp, Control = 0, Velocity = p2, Extra = $"{ch:X2}{p1:X2}{p2:X2}", }; lock (this._コールバック同期) this._蓄積用入力イベントリスト.Add(ie); //---------------- #endregion } else if (0xB0 == ev) { #region " (C) コントロールチェンジ(フットペダル他) " //---------------- var ie = new InputEvent() { DeviceID = deviceID, Key = 255, // コントロールチェンジのキーは 255 とする。 押された = true, // 押された扱い。 TimeStamp = timeStamp, Control = p1, // コントロールチェンジの番号はこっち。 Velocity = p2, // コントロール値はこっち。 Extra = $"{ch:X2}{p1:X2}{p2:X2}", }; lock (this._コールバック同期) this._蓄積用入力イベントリスト.Add(ie); //---------------- #endregion } }