2019-10-05 12:18:52 +00:00
|
|
|
using System;
|
|
|
|
using UnityEngine.Events;
|
|
|
|
|
|
|
|
namespace cylvester
|
|
|
|
{
|
|
|
|
[Serializable]
|
2019-10-27 10:21:33 +00:00
|
|
|
public class UnityMidiEvent : UnityEvent<MidiMessage>
|
2019-10-05 12:18:52 +00:00
|
|
|
{}
|
2019-10-30 14:01:06 +00:00
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
public class UnitySyncEvent : UnityEvent<MidiSync>
|
|
|
|
{}
|
|
|
|
|
|
|
|
public enum MidiSync
|
|
|
|
{
|
|
|
|
Start = 250,
|
|
|
|
Stop = 252,
|
|
|
|
Clock = 248,
|
|
|
|
}
|
2019-10-05 12:18:52 +00:00
|
|
|
|
2019-10-26 20:15:30 +00:00
|
|
|
public struct MidiMessage
|
2019-10-05 12:18:52 +00:00
|
|
|
{
|
2019-10-26 20:15:30 +00:00
|
|
|
public byte Status;
|
|
|
|
public byte Data1;
|
|
|
|
public byte Data2;
|
2019-10-26 20:45:33 +00:00
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
{
|
|
|
|
var statusStr = Status.ToString();
|
|
|
|
var data1Str = Data1.ToString();
|
|
|
|
var data2Str = Data2.ToString();
|
|
|
|
return statusStr + " " +data1Str + " " +data2Str;
|
|
|
|
}
|
2019-10-05 12:18:52 +00:00
|
|
|
}
|
|
|
|
public interface IMidiParser : IDisposable
|
|
|
|
{
|
2019-10-26 20:15:30 +00:00
|
|
|
event Action<MidiMessage> MidiMessageReceived;
|
2019-10-30 14:01:06 +00:00
|
|
|
event Action<MidiSync> MidiSyncReceived;
|
2019-10-05 12:18:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public class MidiParser : IMidiParser
|
|
|
|
{
|
|
|
|
private enum Accept
|
|
|
|
{
|
|
|
|
StatusByte,
|
|
|
|
DataByte1,
|
|
|
|
DataByte2
|
|
|
|
}
|
|
|
|
|
|
|
|
private MidiMessage message_;
|
|
|
|
private Accept accept_ = Accept.StatusByte;
|
|
|
|
private readonly IPdReceiver pdReceiver_;
|
|
|
|
private readonly Action<byte[]> onDataReceived_;
|
|
|
|
|
|
|
|
public MidiParser(IPdReceiver pdReceiver)
|
|
|
|
{
|
|
|
|
pdReceiver_ = pdReceiver;
|
|
|
|
|
|
|
|
onDataReceived_ = (bytes) =>
|
|
|
|
{
|
|
|
|
foreach (var element in bytes)
|
|
|
|
{
|
2019-10-30 14:01:06 +00:00
|
|
|
if (ProcessSyncByte(element))
|
|
|
|
continue;
|
|
|
|
|
2019-10-05 12:18:52 +00:00
|
|
|
if (element >= 128)
|
|
|
|
{
|
|
|
|
message_ = new MidiMessage {Status = element};
|
|
|
|
accept_ = Accept.DataByte1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (accept_ == Accept.DataByte1 && element <= 128)
|
|
|
|
{
|
|
|
|
message_.Data1 = element;
|
|
|
|
accept_ = Accept.DataByte2;
|
|
|
|
}
|
|
|
|
else if (accept_ == Accept.DataByte2 && element <= 128)
|
|
|
|
{
|
|
|
|
message_.Data2 = element;
|
2019-10-27 10:21:33 +00:00
|
|
|
MidiMessageReceived?.Invoke(message_);
|
2019-10-05 12:18:52 +00:00
|
|
|
accept_ = Accept.StatusByte;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
pdReceiver_.DataReceived += onDataReceived_;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
pdReceiver_.DataReceived -= onDataReceived_;
|
|
|
|
}
|
2019-10-30 14:01:06 +00:00
|
|
|
|
|
|
|
private bool ProcessSyncByte(byte element)
|
|
|
|
{
|
|
|
|
if (element != (byte)MidiSync.Clock &&
|
|
|
|
element != (byte)MidiSync.Start &&
|
|
|
|
element != (byte)MidiSync.Stop)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
MidiSyncReceived?.Invoke((MidiSync)element);
|
|
|
|
return true;
|
|
|
|
}
|
2019-10-05 12:18:52 +00:00
|
|
|
|
2019-10-26 20:15:30 +00:00
|
|
|
public event Action<MidiMessage> MidiMessageReceived;
|
2019-10-30 14:01:06 +00:00
|
|
|
public event Action<MidiSync> MidiSyncReceived;
|
2019-10-05 12:18:52 +00:00
|
|
|
}
|
|
|
|
}
|