using System.Text.Json.Serialization; using static QuikDawEditor.EDITING.MidiMethods; namespace QuikDawEditor.EditingClasses; public class QDMidiEvent : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged([CallerMemberName] string propertyName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public void UpdateMargin() { NotifyPropertyChanged(nameof(ValueLeftPixels)); } public void UpdateEventReverseZoom(double revzoomx) { revZoomX = revzoomx; NotifyPropertyChanged(nameof(WorkingGridXZoomFacReverse)); NotifyPropertyChanged(nameof(ValueBorderThickness)); NotifyPropertyChanged(nameof(ValueRectThickness)); NotifyPropertyChanged(nameof(NoteBorderThickness)); } public double WorkingGridXZoomFacReverse { get { return revZoomX; } } public double revZoomX = 1; private double _ValueRectThickness { get { if (this is QDSustain) return 16; if (this is QDMidiNote) return 8; return 5; } } public double ValueLeftPixels { get { return MsecToPixelsGrid(ClipRelTimeMs); } } public double ValueRectThickness { get { return _ValueRectThickness * revZoomX; } } private double _ValueLineThickness = 0.7; public Thickness ValueBorderThickness { get { return new Thickness(_ValueLineThickness * revZoomX, 0.7, _ValueLineThickness * revZoomX, 0.7); } } private double _NoteBorderThickness = 1; public Thickness NoteBorderThickness { get { return new Thickness(_NoteBorderThickness * revZoomX, 0.5, _NoteBorderThickness * revZoomX, 0.5); } } public Brush NoteBrush { get { return _selected ? SelectedMidiNoteBrush : IsHovering ? Brushes.Orange : NormalMidiNoteBrush; } } public SolidColorBrush EventBrush { get { return _selected ? Brushes.LawnGreen : IsHovering ? Brushes.Orange : Brushes.LightGray; } } public double MaxEventValue { get { if (this is QDPitchChange) return 16383; return 127; } } public Visibility EventRectVisibility { get { return this is QDSustain ? Visibility.Hidden : Visibility.Visible; } } public Visibility SustainVisibility { get { return this is QDSustain ? Visibility.Visible : Visibility.Hidden; } } public double FlipYTransform { get { return this is QDSustain ? MainValue >= 64 ? 1 : -1 : 1; } } private bool _IsHovering = false; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool IsHovering { get { return _IsHovering; } set { _IsHovering = value; NotifyPropertyChanged(nameof(EventBrush)); NotifyPropertyChanged(nameof(NoteBrush)); } } private bool _selected = false; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool Selected { get { return _selected; } set { _selected = value; NotifyPropertyChanged(nameof(Selected)); NotifyPropertyChanged(nameof(EventBrush)); NotifyPropertyChanged(nameof(NoteBrush)); } } internal double OriginalMs; private double _clipRelTimeMs; public double ClipRelTimeMs { get { return Math.Round(_clipRelTimeMs); } set { _clipRelTimeMs = Math.Round(value); ClipRelTimeMs60BPM = TranslateMsTo60BPM(value); } } public GridLength DisplayLineHeightPerc { get { double GridHeightPercVal = 9; if (this is QDMidiNote) { double Val = ((QDMidiNote)this).Velocity; GridHeightPercVal = 1 + Val / 128D * 10D; } if (this is QDPitchChange) { //Val is short from 0-16,384 with mid 8192 as 0 double Val = ((QDPitchChange)this).PitchValue; GridHeightPercVal = 1 + Val / 16384D * 10D; } if (this is QDSustain) { //Pedal is either on or off (Val <> 64) //Val = ((QDSustain)this).SustainValue; GridHeightPercVal = 6D; } if (this is QDModulation) { double Val = ((QDModulation)this).ModValue; GridHeightPercVal = 1 + Val / 128D * 10D; } return new GridLength(GridHeightPercVal, GridUnitType.Star); } } public GridLength ComplementaryDisplayLineHeightPerc { get { return new GridLength(11D - DisplayLineHeightPerc.Value, GridUnitType.Star); } } public double ClipRelTimeMs60BPM; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public double MainValue { get { int returnVal = -1; if (this is QDMidiNote) returnVal = ((QDMidiNote)this).Velocity; if (this is QDPitchChange) returnVal = ((QDPitchChange)this).PitchValue; if (this is QDSustain) returnVal = ((QDSustain)this).SustainValue; if (this is QDModulation) returnVal = ((QDModulation)this).ModValue; return returnVal; } set { int intvalue = (int)value; if (this is QDMidiNote) ((QDMidiNote)this).Velocity = intvalue; if (this is QDPitchChange) ((QDPitchChange)this).PitchValue = intvalue; if (this is QDSustain) ((QDSustain)this).SustainValue = intvalue; if (this is QDModulation) ((QDModulation)this).ModValue = intvalue; NotifyPropertyChanged(nameof(DisplayLineHeightPerc)); NotifyPropertyChanged(nameof(ComplementaryDisplayLineHeightPerc)); NotifyPropertyChanged(nameof(DisplayString)); } } public string DisplayString { get { string returnString = ""; if (this is QDMidiNote) returnString = "Vel: " + ((QDMidiNote)this).Velocity.ToString(); if (this is QDPitchChange) returnString = "Pitch: " + Math.Round(((QDPitchChange)this).PitchValue / (double)PITCHWHEEL_OFF_VALUE - 1D, 2).ToString(); if (this is QDSustain) returnString = "Sustain: " + (((QDSustain)this).SustainValue >= 64 ? "ON" : "OFF"); if (this is QDModulation) returnString = "Mod: " + ((QDModulation)this).ModValue.ToString(); return returnString; } } public int ControllerCode { get { int returnVal = -1; if (this is QDSustain) returnVal = SUSTAIN_CONTROLLER_CODE; if (this is QDModulation) returnVal = MOD_CONTROLLER_CODE; return returnVal; } } } public class QDPitchChange : QDMidiEvent, INotifyPropertyChanged { private int _PitchValue; public int PitchValue { get { return _PitchValue; } set { _PitchValue = value; NotifyPropertyChanged(nameof(DisplayLineHeightPerc)); NotifyPropertyChanged(nameof(ComplementaryDisplayLineHeightPerc)); NotifyPropertyChanged(nameof(DisplayString)); } } [JsonConstructor] public QDPitchChange() { } public QDPitchChange(QDPitchChange fromQDpch) { PitchValue = fromQDpch.PitchValue; } } public class QDModulation : QDMidiEvent, INotifyPropertyChanged { private int _ModValue; public int ModValue { get { return _ModValue; } set { _ModValue = value; NotifyPropertyChanged(nameof(DisplayLineHeightPerc)); NotifyPropertyChanged(nameof(ComplementaryDisplayLineHeightPerc)); NotifyPropertyChanged(nameof(DisplayString)); } } [JsonConstructor] public QDModulation() { } public QDModulation(QDModulation fromQDmod) { ModValue = fromQDmod.ModValue; } } public class QDSustain : QDMidiEvent, INotifyPropertyChanged { public int SustainValue { get; set; } [JsonConstructor] public QDSustain() { } public QDSustain(QDSustain fromQDsus) { SustainValue = fromQDsus.SustainValue; } } public class QDMidiNote : QDMidiEvent { public void UpdateNoteMsValues() { NotifyPropertyChanged(nameof(noteMarginPianoRoll)); NotifyPropertyChanged(nameof(noteWidthPixelsPianoRoll)); } public void UpdateNoteMsValuesMidiClip() { NotifyPropertyChanged(nameof(noteMarginMidiClip)); NotifyPropertyChanged(nameof(noteWidthPixelsMidiClip)); } public void UpdateNoteMsWidthMidiClip() { NotifyPropertyChanged(nameof(noteWidthPixelsMidiClip)); } [JsonConstructor] public QDMidiNote() { } public QDMidiNote(QDMidiNote fromQDmn) { Note = fromQDmn.Note; ClipRelNoteOnTimeMs = fromQDmn.ClipRelNoteOnTimeMs; ClipRelNoteOffTimeMs = fromQDmn.ClipRelNoteOffTimeMs; Velocity = fromQDmn.Velocity; revZoomX = fromQDmn.revZoomX; } internal double _clipRelNoteOffTimeMs; public double ClipRelNoteOffTimeMs { get { return Math.Round(_clipRelNoteOffTimeMs); } set { _clipRelNoteOffTimeMs = Math.Round(value); ClipRelNoteOffTimeMs60BPM = TranslateMsTo60BPM(_clipRelNoteOffTimeMs); NotifyPropertyChanged(nameof(noteWidthPixelsPianoRoll)); NotifyPropertyChanged(nameof(noteWidthPixelsMidiClip)); } } public double ClipRelNoteOnTimeMs { get { return Math.Round(ClipRelTimeMs); } set { ClipRelTimeMs = Math.Round(value); ClipRelTimeMs60BPM = TranslateMsTo60BPM(ClipRelTimeMs); NotifyPropertyChanged(nameof(noteMarginPianoRoll)); NotifyPropertyChanged(nameof(noteMarginMidiClip)); NotifyPropertyChanged(nameof(ValueLeftPixels)); } } public double ClipRelNoteOnTimeMs60BPM { get { return ClipRelTimeMs60BPM; } } public double ClipRelNoteOffTimeMs60BPM; public double ClipRelRightMs { get { return Math.Truncate(ClipRelNoteOnTimeMs + noteWidthMs); } } public int _Note; public int Note { get { return Math.Max(0, Math.Min(127, _Note)); } set { _Note = value; NotifyPropertyChanged(nameof(noteMarginPianoRoll)); NotifyPropertyChanged(nameof(noteMarginMidiClip)); NotifyPropertyChanged(nameof(NoteNameString)); } } public string NoteNameString { get { return GetNoteName(Note); } } private int _Velocity; public int Velocity { get { return _Velocity; } set { _Velocity = value; NotifyPropertyChanged(nameof(Velocity)); NotifyPropertyChanged(nameof(DisplayLineHeightPerc)); NotifyPropertyChanged(nameof(ComplementaryDisplayLineHeightPerc)); NotifyPropertyChanged(nameof(DisplayString)); } } public bool Released = false; public double NoteLengthMs { get { return Math.Max(100, ClipRelNoteOffTimeMs - ClipRelNoteOnTimeMs); } } public double NoteHeight { get { return PianoRollNoteHeight; } } public Thickness noteMarginPianoRoll { get { return new Thickness(MsecToPixelsGrid(ClipRelNoteOnTimeMs), (NumMidiNotesVertical - Note - 1) * PianoRollNoteHeight, 0, 0); } } public Thickness noteMarginMidiClip { get { return new Thickness(MsecToPixels(ClipRelNoteOnTimeMs), Note * NoteHeight % 60, 0, 0); } } public Thickness noteBorderThickness { get { return new Thickness(revZoomX * 0.7, 0.7, revZoomX * 0.7, 0.7); } } public double noteWidthMs { get { return ClipRelNoteOffTimeMs - ClipRelNoteOnTimeMs; } } public double noteWidthPixelsPianoRoll { get { return MsecToPixelsGrid(ClipRelNoteOffTimeMs - ClipRelNoteOnTimeMs); } } public double noteWidthPixelsMidiClip { get { return MsecToPixels(Math.Max(0, ClipRelNoteOffTimeMs - ClipRelNoteOnTimeMs)); } } }