1
0
Fork 0

Add Read functions + Synchronize + Filters

This commit is contained in:
Florian RICHER (MrDev023) 2019-02-24 16:35:02 +01:00
parent cc3af59dc7
commit c118019f40
2 changed files with 155 additions and 0 deletions

View file

@ -55,6 +55,18 @@ namespace PortMidi
[DllImport(NativeLibrary, EntryPoint = "Pm_Abort", CallingConvention = CallingConvention.Cdecl)]
private static extern PmError Pm_Abort(IntPtr stream);
[DllImport(NativeLibrary, EntryPoint = "Pm_Poll", CallingConvention = CallingConvention.Cdecl)]
private static extern PmError Pm_Poll(IntPtr stream);
[DllImport(NativeLibrary, EntryPoint = "Pm_Synchronize", CallingConvention = CallingConvention.Cdecl)]
private static extern PmError Pm_Synchronize(IntPtr stream);
[DllImport(NativeLibrary, EntryPoint = "Pm_SetFilter", CallingConvention = CallingConvention.Cdecl)]
private static extern PmError Pm_SetFilter(IntPtr stream, int filters);
[DllImport(NativeLibrary, EntryPoint = "Pm_Read", CallingConvention = CallingConvention.Cdecl)]
private static extern int Pm_Read(IntPtr stream, PmEvent* e, int length);
[DllImport(NativeLibrary, EntryPoint = "Pt_Time", CallingConvention = CallingConvention.Cdecl)]
private static extern int Pt_Time();
@ -262,6 +274,100 @@ namespace PortMidi
}
}
// Reads from the input stream, the max number events to be read are
// determined by max.
public static Event[] Read(Stream stream, int max)
{
Event[] events = new Event[0];
if (max > stream.bufferSize) throw new Exception("Out of bounds");
PmEvent[] pm_events = new PmEvent[max];
fixed (PmEvent* p = &pm_events[0])
{
int numEvents = Pm_Read(stream.pmStream, p, max);
events = new Event[numEvents];
for (int i = 0; i < numEvents; i++)
{
Event e = new Event();
e.Timestamp = pm_events[i].timestamp;
e.Status = (int)(pm_events[i].message) & 0xFF;
e.Data1 = (int)(pm_events[i].message >> 8) & 0xFF;
e.Data2 = (int)(pm_events[i].message >> 16) & 0xFF;
events[i] = e;
}
}
return events;
}
// ReadSysExBytes reads 4*max sysex bytes from the input stream.
public static byte[] ReadSysExBytes(Stream stream, int max)
{
byte[] msg = new byte[0];
if (max > stream.bufferSize) throw new Exception("Out of bounds");
PmEvent[] pm_events = new PmEvent[max];
fixed (PmEvent* p = &pm_events[0])
{
int numEvents = Pm_Read(stream.pmStream, p, max);
msg = new byte[4 * numEvents];
for (int i = 0; i < numEvents; i++)
{
msg[4 * i + 0] = (byte)(pm_events[i].message & 0xFF);
msg[4 * i + 1] = (byte)((pm_events[i].message >> 8) & 0xFF);
msg[4 * i + 2] = (byte)((pm_events[i].message >> 16) & 0xFF);
msg[4 * i + 3] = (byte)((pm_events[i].message >> 24) & 0xFF);
}
}
return msg;
}
// Poll reports whether there is input available in the stream.
public static bool Poll(Stream stream)
{
PmError error = Pm_Poll(stream.pmStream);
if (error < 0)
{
throw new Exception(ConvertToError(error));
}
return error > 0;
}
// instructs PortMidi to (re)synchronize to the time_proc passed when the stream was opened.
public static bool Synchronize(Stream stream)
{
PmError error = Pm_Synchronize(stream.pmStream);
if (error < 0)
{
throw new Exception(ConvertToError(error));
}
return error > 0;
}
// sets filters on an open input stream to drop selected input types. By default, only active sensing messages are filtered
public static void SetFilter(Stream stream, PortMidiFilter[] filters)
{
if (filters.Length == 0)
{
PmError err = Pm_SetFilter(stream.pmStream, (int)PortMidiFilter.PM_FILT_ACTIVE);
if (err != 0)
{
throw new Exception(ConvertToError(err));
}
}
int filtersMask = 0;
foreach (PortMidiFilter filter in filters)
{
filtersMask |= (int)filter;
}
PmError error = Pm_SetFilter(stream.pmStream, (int)PortMidiFilter.PM_FILT_ACTIVE);
if (error != 0)
{
throw new Exception(ConvertToError(error));
}
}
public static byte[] StringToByteArrayFastest(string hex)
{
if (hex.Length % 2 == 1)

View file

@ -0,0 +1,49 @@
namespace PortMidi
{
// Filter bit-mask definitions
public enum PortMidiFilter
{
// filter active sensing messages (0xFE)
PM_FILT_ACTIVE = (1 << 0x0E),
// filter system exclusive messages (0xF0)
PM_FILT_SYSEX = (1 << 0x00),
// filter MIDI clock message (0xF8)
PM_FILT_CLOCK = (1 << 0x08),
// filter play messages (start 0xFA, stop 0xFC, continue 0xFB)
PM_FILT_PLAY = ((1 << 0x0A) | (1 << 0x0C) | (1 << 0x0B)),
// filter tick messages (0xF9)
PM_FILT_TICK = (1 << 0x09),
// filter undefined FD messages
PM_FILT_FD = (1 << 0x0D),
// filter undefined real-time messages
PM_FILT_UNDEFINED = PM_FILT_FD,
// filter reset messages (0xFF)
PM_FILT_RESET = (1 << 0x0F),
// filter all real-time messages
PM_FILT_REALTIME = (PM_FILT_ACTIVE | PM_FILT_SYSEX | PM_FILT_CLOCK | PM_FILT_PLAY | PM_FILT_UNDEFINED | PM_FILT_RESET | PM_FILT_TICK),
// filter note-on and note-off (0x90-0x9F and 0x80-0x8F
PM_FILT_NOTE = ((1 << 0x19) | (1 << 0x18)),
// filter channel aftertouch (most midi controllers use this) (0xD0-0xDF)
PM_FILT_CHANNEL_AFTERTOUCH = (1 << 0x1D),
// per-note aftertouch (0xA0-0xAF)
PM_FILT_POLY_AFTERTOUCH = (1 << 0x1A),
// filter both channel and poly aftertouch
PM_FILT_AFTERTOUCH = (PM_FILT_CHANNEL_AFTERTOUCH | PM_FILT_POLY_AFTERTOUCH),
// Program changes (0xC0-0xCF)
PM_FILT_PROGRAM = (1 << 0x1C),
// Control Changes (CC's) (0xB0-0xBF)
PM_FILT_CONTROL = (1 << 0x1B),
// Pitch Bender (0xE0-0xEF)
PM_FILT_PITCHBEND = (1 << 0x1E),
// MIDI Time Code (0xF1)
PM_FILT_MTC = (1 << 0x01),
// Song Position (0xF2)
PM_FILT_SONG_POSITION = (1 << 0x02),
// Song Select (0xF3)
PM_FILT_SONG_SELECT = (1 << 0x03),
// Tuning request (0xF6)
PM_FILT_TUNE = (1 << 0x06),
// All System Common messages (mtc, song position, song select, tune request)
PM_FILT_SYSTEMCOMMON = (PM_FILT_MTC | PM_FILT_SONG_POSITION | PM_FILT_SONG_SELECT | PM_FILT_TUNE),
}
}