using QuikDawEditor.EditingClasses; using System; using System.Collections.Generic; using System.Linq; using static QuikDawEditor.EDITING.StaticProperties; namespace QuikDawEditor; public partial class ClipControl { private void FuseNewClipMidi() { //double widthChange = fusingClip.ClipWidthMs - fusingClip.ClipSourceLenMilliseconds; //if (widthChange == 0) return; //double startingRelStart = fusingClip.ClipRelativeLoopStartMs % fusingClip.ClipSourceLenMilliseconds; //Add notes looping to fill width double offset = 0; List addingEvents = new List(); while (offset < fusingClip.ClipRelativeLoopStartMs + fusingClip.ClipWidthMs) { addingEvents.AddRange(fusingClip.ClipMidiEvents.ToList().ConvertAll(admev => { QDMidiEvent newQDMidiEvent = new QDMidiEvent(); if (admev is QDMidiNote) { QDMidiNote qdmn = (QDMidiNote)admev; newQDMidiEvent = new QDMidiNote() { Note = qdmn.Note, ClipRelNoteOnTimeMs = qdmn.ClipRelNoteOnTimeMs + offset, ClipRelNoteOffTimeMs = qdmn.ClipRelNoteOffTimeMs + offset, Velocity = qdmn.Velocity, Selected = false }; } if (admev is QDSustain) { QDSustain qdss = (QDSustain)admev; newQDMidiEvent = new QDSustain() { ClipRelTimeMs = qdss.ClipRelTimeMs + offset }; } if (admev is QDPitchChange) { QDPitchChange qdpc = (QDPitchChange)admev; newQDMidiEvent = new QDPitchChange() { ClipRelTimeMs = qdpc.ClipRelTimeMs + offset }; } if (admev is QDModulation) { QDModulation qdmod = (QDModulation)admev; newQDMidiEvent = new QDModulation() { ClipRelTimeMs = qdmod.ClipRelTimeMs + offset }; } return newQDMidiEvent; })); offset += fusingClip.ClipSourceLenMilliseconds; } fusingClip.ClipMidiNotes.Clear(); fusingClip.ClipSustainEvents.Clear(); fusingClip.ClipPitchChangeEvents.Clear(); fusingClip.ClipModulationEvents.Clear(); fusingClip.ClipMidiEvents.Clear(); foreach (QDMidiEvent mevent in addingEvents) { switch (mevent.GetType()) { case var type when type == typeof(QDMidiNote): fusingClip.ClipMidiNotes.Add((QDMidiNote)mevent); break; case var type when type == typeof(QDSustain): fusingClip.ClipSustainEvents.Add((QDSustain)mevent); break; case var type when type == typeof(QDPitchChange): fusingClip.ClipPitchChangeEvents.Add((QDPitchChange)mevent); break; case var type when type == typeof(QDModulation): fusingClip.ClipModulationEvents.Add((QDModulation)mevent); break; } } //Truncate at start and end as necessary List toRemoveMidiEvents = new List (fusingClip.ClipMidiEvents.Where(mdn => (mdn.ClipRelTimeMs >= fusingClip.ClipRelativeLoopStartMs + fusingClip.ClipWidthMs) | (mdn.ClipRelTimeMs < fusingClip.ClipRelativeLoopStartMs))); foreach (QDMidiEvent midevent in toRemoveMidiEvents) { switch (midevent.GetType()) { case var type when type == typeof(QDMidiNote): fusingClip.ClipMidiNotes.Remove((QDMidiNote)midevent); break; case var type when type == typeof(QDSustain): fusingClip.ClipSustainEvents.Remove((QDSustain)midevent); break; case var type when type == typeof(QDPitchChange): fusingClip.ClipPitchChangeEvents.Remove((QDPitchChange)midevent); break; case var type when type == typeof(QDModulation): fusingClip.ClipModulationEvents.Remove((QDModulation)midevent); break; } } //Adjust relative times if start changed double startOffset = fusingClip.ClipRelativeLoopStartMs; if (startOffset != 0) { foreach (QDMidiEvent midevent in fusingClip.ClipMidiEvents) { switch (midevent.GetType()) { case var type when type == typeof(QDMidiNote): QDMidiNote qdmn = (QDMidiNote)midevent; qdmn.ClipRelNoteOnTimeMs = Math.Max(0, qdmn.ClipRelNoteOnTimeMs - startOffset); qdmn.ClipRelNoteOffTimeMs = Math.Max(0, qdmn.ClipRelNoteOffTimeMs - startOffset); break; case var type when type == typeof(QDSustain): QDSustain qdsus = (QDSustain)midevent; qdsus.ClipRelTimeMs = Math.Max(0, qdsus.ClipRelTimeMs - startOffset); break; case var type when type == typeof(QDPitchChange): QDPitchChange qdpch = (QDPitchChange)midevent; qdpch.ClipRelTimeMs = Math.Max(0, qdpch.ClipRelTimeMs - startOffset); break; case var type when type == typeof(QDModulation): QDModulation qdmod = (QDModulation)midevent; qdmod.ClipRelTimeMs = Math.Max(0, qdmod.ClipRelTimeMs - startOffset); break; } } } List keepGainPoints = new List(fusingClip.GainPoints.Where(gp => gp.sourcePointms <= fusingClip.ClipRelativeLoopStartMs + fusingClip.ClipWidthMs && gp.sourcePointms >= fusingClip.ClipRelativeLoopStartMs)); foreach (GainPoint gp in keepGainPoints) gp.sourcePointms -= fusingClip.ClipRelativeLoopStartMs; fusingClip.GainPoints.Clear(); foreach (GainPoint gp in keepGainPoints) fusingClip.GainPoints.Add(gp); fusingClip.ClipVirtualStartMs += fusingClip.ClipRelativeLoopStartMs; double oldrelloopstartms = fusingClip.ClipRelativeLoopStartMs; fusingClip.ClipRelativeLoopStartMs = 0; fusingClip.ClipWidthMs -= oldrelloopstartms; fusingClip.ClipSourceLenMilliseconds = fusingClip.ClipWidthMs; fusingClip.UpdateMidiImageSource(); fusingClip.RecreateClipUnitBackgrounds(); if (editingProject.pianoRoll.myClip == fusingClip) { editingProject.pianoRoll.myClip = null; editingProject.pianoRoll.myClip = fusingClip; editingProject.pianoRoll.IsVisible = true; } } }