Files
Vera Aguilera Puerto 59af9451be Various improvements to midi
- MidiEvent control is now an int
- Instead of hardcoding the channel count, we check the count on the synth itself.
- Do nothing for event 0x51
2021-08-26 15:01:34 +02:00

119 lines
3.5 KiB
C#

using System;
using NFluidsynth;
using Robust.Shared.Serialization;
namespace Robust.Shared.Audio.Midi
{
/// <summary>
/// This class is a data representation of a Midi Event.
/// It's 'compatible' with NFluidsynth's own MidiEvent class.
/// </summary>
[Serializable, NetSerializable]
public struct MidiEvent
{
public byte Type { get; set; }
public byte Channel { get; set; }
public byte Key { get; set; }
public byte Velocity { get; set; }
public int Control { get; set; }
public byte Value { get; set; }
public byte Program { get; set; }
public short Pitch { get; set; } // needs range from 0 to 16383
public uint Tick { get; set; }
public static explicit operator MidiEvent(NFluidsynth.MidiEvent midiEvent)
{
return new()
{
Type = (byte) midiEvent.Type,
Channel = (byte) midiEvent.Channel,
Control = midiEvent.Control,
Key = (byte) midiEvent.Key,
Pitch = (short) midiEvent.Pitch,
Program = (byte) midiEvent.Program,
Value = (byte) midiEvent.Value,
Velocity = (byte) midiEvent.Velocity,
};
}
public static implicit operator NFluidsynth.MidiEvent(MidiEvent midiEvent)
{
return new()
{
Type = midiEvent.Type,
Channel = midiEvent.Channel,
Control = midiEvent.Control,
Key = midiEvent.Key,
Pitch = midiEvent.Pitch,
Program = midiEvent.Program,
Value = midiEvent.Value,
Velocity = midiEvent.Velocity,
};
}
public override string ToString()
{
return $"{base.ToString()} >> TYPE: {Type} || CHANNEL: {Channel} || CONTROL: {Control} || KEY: {Key} || VELOCITY: {Velocity} || PITCH: {Pitch} || PROGRAM: {Program} || VALUE: {Value} <<";
}
public static implicit operator SequencerEvent(MidiEvent midiEvent)
{
var @event = new SequencerEvent();
switch (midiEvent.Type)
{
// NoteOff
case 128:
@event.NoteOff(midiEvent.Channel, midiEvent.Key);
break;
// NoteOn
case 144:
if(midiEvent.Velocity != 0)
@event.NoteOn(midiEvent.Channel, midiEvent.Key, midiEvent.Velocity);
else
@event.NoteOff(midiEvent.Channel, midiEvent.Key);
break;
// After Touch
case 160:
@event.KeyPressure(midiEvent.Channel, midiEvent.Key, midiEvent.Value);
break;
// CC
case 176:
@event.ControlChange(midiEvent.Channel, (short)midiEvent.Control, midiEvent.Value);
break;
// Program Change
case 192:
@event.ProgramChange(midiEvent.Channel, midiEvent.Program);
break;
// Channel Pressure
case 208:
@event.ChannelPressure(midiEvent.Channel, midiEvent.Value);
break;
// Pitch Bend
case 224:
@event.PitchBend(midiEvent.Channel, midiEvent.Pitch);
break;
}
return @event;
}
}
}