Add Read functions + Synchronize + Filters
This commit is contained in:
parent
cc3af59dc7
commit
c118019f40
2 changed files with 155 additions and 0 deletions
|
@ -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)
|
||||
|
|
49
Assets/Scripts/PortMidiConst.cs
Normal file
49
Assets/Scripts/PortMidiConst.cs
Normal 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),
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue