soundvision/UnityProject/Assets/Scripts/PdConnection/MidiParser.cs

115 lines
3.1 KiB
C#
Raw Normal View History

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]
2019-10-30 15:02:20 +00:00
public class UnitySyncEvent : UnityEvent<MidiSync, int>
2019-10-30 14:01:06 +00:00
{}
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 15:02:20 +00:00
event Action<MidiSync, int> 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_;
2019-10-30 15:02:20 +00:00
private int count_;
2019-10-05 12:18:52 +00:00
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;
2019-10-30 15:02:20 +00:00
if (element == (byte) MidiSync.Clock)
count_++;
else
count_ = 0;
MidiSyncReceived?.Invoke((MidiSync)element, count_);
2019-10-30 14:01:06 +00:00
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 15:02:20 +00:00
public event Action<MidiSync, int> MidiSyncReceived;
2019-10-05 12:18:52 +00:00
}
}