This commit is contained in:
2025-05-13 00:34:26 +03:00
parent ba0eb53334
commit f2b9d7c0db
12 changed files with 707 additions and 0 deletions
+135
View File
@@ -0,0 +1,135 @@
using System;
using System.Collections.Concurrent;
using System.Threading;
using static RushMidiLibrary.MidiApiWindows;
namespace RushMidiLibrary {
public class MidiInputDevice : MidiDevice {
private MidiApiWindows.MidiInProc _inputCallback;
private UIntPtr _deviceId;
private MidiApiWindows.HMIDIIN _deviceHandle;
private Thread _messageProcessingThread;
private bool _messageProcessingThreadExitRequest = false;
readonly BlockingCollection<Message> _messageQueue = new BlockingCollection<Message>();
private struct Message {
public MidiApiWindows.HMIDIIN hMidiIn;
public MidiApiWindows.MidiInMessage wMsg;
public UIntPtr dwInstance;
public UIntPtr dwParam1;
public UIntPtr dwParam2;
}
public MidiInputDevice(UIntPtr deviceId, MidiApiWindows.MIDIINCAPS caps) {
_deviceId = deviceId;
}
public static MidiInputDevice[] Enumerate() {
var devs = MidiApiWindows.midiInGetNumDevs();
MidiInputDevice[] result = new MidiInputDevice[devs];
for (uint deviceId = 0; deviceId < devs; deviceId++) {
MidiApiWindows.MIDIINCAPS caps;
MidiApiWindows.midiInGetDevCaps((UIntPtr)deviceId, out caps);
result[deviceId] = new MidiInputDevice((UIntPtr)deviceId, caps);
}
return result;
}
public void Open() {
_inputCallback = this.InputCallback;
BeginMessageProcessing();
try {
CheckMMResult(MidiApiWindows.midiInOpen(out _deviceHandle, _deviceId, _inputCallback, (UIntPtr)0));
}
catch (Exception) {
EndMessageProcessing();
throw;
}
}
public void Start() {
CheckMMResult(MidiApiWindows.midiInStart(_deviceHandle));
}
private void InputCallback(MidiApiWindows.HMIDIIN hMidiIn, MidiApiWindows.MidiInMessage wMsg, UIntPtr dwInstance, UIntPtr dwParam1, UIntPtr dwParam2) {
Message message = new Message();
message.hMidiIn = hMidiIn;
message.wMsg = wMsg;
message.dwInstance = dwInstance;
message.dwParam1 = dwParam1;
message.dwParam2 = dwParam2;
_messageQueue.Add(message);
}
private void BeginMessageProcessing() {
_messageProcessingThreadExitRequest = false;
_messageProcessingThread = new Thread(MessageProcessingThreadHandler);
_messageProcessingThread.Start();
}
private void MessageProcessingThreadHandler() {
while (!_messageProcessingThreadExitRequest) {
Message message;
if (_messageQueue.TryTake(out message, 100)) {
HandleMessage(message);
}
}
}
private void EndMessageProcessing() {
_messageProcessingThreadExitRequest = true;
_messageProcessingThread.Join();
}
private void HandleMessage(Message message) {
switch (message.wMsg) {
case MidiInMessage.MIM_DATA:
HandleMessageData(new MidiShortMessage(message.dwParam1, message.dwParam2));
break;
case MidiInMessage.MIM_LONGDATA:
HandleMessageLongData(message.dwParam1, message.dwParam2);
break;
default:
break;
}
}
private void HandleMessageData(MidiShortMessage message) {
if (message.IsNoteOn) {
MidiChannel channel;
int noteId;
int velocity;
uint timestamp;
message.GetNoteOn(out channel, out noteId, out velocity, out timestamp);
var note = new MidiNote(noteId);
Console.WriteLine($"Received short message NoteOn: Name={note.Name} Octave={note.OctaveName} Channel={channel.ToString()}, NoteId={noteId}, Velocity={velocity}, Timestapm={timestamp}");
} else if (message.IsNoteOff) {
MidiChannel channel;
int noteId;
int velocity;
uint timestamp;
message.GetNoteOff(out channel, out noteId, out velocity, out timestamp);
var note = new MidiNote(noteId);
Console.WriteLine($"Received short message NoteOff: Name={note.Name} Octave={note.OctaveName} Channel={channel.ToString()}, NoteId={noteId}, Velocity={velocity}, Timestapm={timestamp}");
} else {
Console.WriteLine($"Received short message");
}
}
private void HandleMessageLongData(UIntPtr dwParam1, UIntPtr dwParam2) {
Console.WriteLine($"Received long message");
}
}
}