diff --git a/BardMusicPlayer.Transmogrify/Song/BmpSong.cs b/BardMusicPlayer.Transmogrify/Song/BmpSong.cs
index 96a36f2e..eea422eb 100644
--- a/BardMusicPlayer.Transmogrify/Song/BmpSong.cs
+++ b/BardMusicPlayer.Transmogrify/Song/BmpSong.cs
@@ -745,298 +745,5 @@ public MemoryStream GetExportMidi()
return stream;
}
-
- ///
- /// Exports the song to a midi file
- ///
- ///
- public MemoryStream GetExportMidiB()
- {
- try
- {
- List c = new List();
- foreach (var tc in TrackContainers.Values)
- c.Add(tc.SourceTrackChunk);
-
- var midiFile = new MidiFile(c);
- midiFile.ReplaceTempoMap(SourceTempoMap);
-
-
- Console.WriteLine("Exporting... ");
- var loaderWatch = Stopwatch.StartNew();
- var newTrackChunks = new ConcurrentDictionary();
- var tempoMap = midiFile.GetTempoMap().Clone();
- long firstNote = midiFile.GetTrackChunks().GetNotes().First().GetTimedNoteOnEvent().TimeAs(tempoMap).TotalMicroseconds / 1000;
-
- var originalTrackChunks = new List();
-
- foreach (var trackChunk in midiFile.GetTrackChunks())
- {
- var thisTrack = new TrackChunk(new SequenceTrackNameEvent(trackChunk.Events.OfType().FirstOrDefault()?.Text));
- thisTrack.AddObjects(trackChunk.GetNotes());
- thisTrack.AddObjects(trackChunk.GetTimedEvents());
- originalTrackChunks.Add(thisTrack);
- }
-
- Parallel.ForEach(originalTrackChunks.Where(x => x.GetNotes().Any()), (originalChunk, loopState, index) =>
- {
- var watch = Stopwatch.StartNew();
- var tempoMap = midiFile.GetTempoMap().Clone();
- int noteVelocity = int.Parse(index.ToString()) + 1;
-
- Dictionary> allNoteEvents = new Dictionary>();
- for (int i = 0; i < 128; i++) allNoteEvents.Add(i, new Dictionary());
-
- foreach (Note note in originalChunk.GetNotes())
- {
- long noteOnMS;
- long noteOffMS;
-
- try
- {
- noteOnMS = 5000 + (note.GetTimedNoteOnEvent().TimeAs(tempoMap).TotalMicroseconds / 1000) - firstNote;
- noteOffMS = 5000 + (note.GetTimedNoteOffEvent().TimeAs(tempoMap).TotalMicroseconds / 1000) - firstNote;
- }
- catch (Exception) { continue; }
- int noteNumber = note.NoteNumber;
-
- Note newNote = new Note((SevenBitNumber)noteNumber,
- time: noteOnMS,
- length: noteOffMS - noteOnMS
- )
- {
- Channel = (FourBitNumber)index,
- Velocity = (SevenBitNumber)126,
- OffVelocity = (SevenBitNumber)126
- };
-
- if (allNoteEvents[noteNumber].ContainsKey(noteOnMS))
- {
- Note previousNote = allNoteEvents[noteNumber][noteOnMS];
- if (previousNote.Length < note.Length) allNoteEvents[noteNumber][noteOnMS] = newNote;
- }
- else allNoteEvents[noteNumber].Add(noteOnMS, newNote);
- }
- watch.Stop();
- Debug.WriteLine("step 1: " + noteVelocity + ": " + watch.ElapsedMilliseconds);
- watch = Stopwatch.StartNew();
-
- TrackChunk newChunk = new TrackChunk();
- for (int i = 0; i < 128; i++)
- {
- long lastNoteTimeStamp = -1;
- foreach (var noteEvent in allNoteEvents[i])
- {
- if (lastNoteTimeStamp >= 0 && allNoteEvents[i][lastNoteTimeStamp].Length + lastNoteTimeStamp >= noteEvent.Key)
- allNoteEvents[i][lastNoteTimeStamp].Length = allNoteEvents[i][lastNoteTimeStamp].Length - (allNoteEvents[i][lastNoteTimeStamp].Length + lastNoteTimeStamp + 1 - noteEvent.Key);
-
- lastNoteTimeStamp = noteEvent.Key;
- }
- }
- newChunk.AddObjects(allNoteEvents.SelectMany(s => s.Value).Select(s => s.Value).ToArray());
- allNoteEvents = null;
- watch.Stop();
- Debug.WriteLine("step 2: " + noteVelocity + ": " + watch.ElapsedMilliseconds);
- watch = Stopwatch.StartNew();
-
- Note[] notesToFix = newChunk.GetNotes().Reverse().ToArray();
- for (int i = 1; i < notesToFix.Count(); i++)
- {
- int noteNum = notesToFix[i].NoteNumber;
- long time = (notesToFix[i].GetTimedNoteOnEvent().Time);
- long dur = notesToFix[i].Length;
- int velocity = notesToFix[i].Velocity;
-
- long lowestParent = notesToFix[0].GetTimedNoteOnEvent().Time;
- for (int k = i - 1; k >= 0; k--)
- {
- long lastOn = notesToFix[k].GetTimedNoteOnEvent().Time;
- if (lastOn < lowestParent) lowestParent = lastOn;
- }
- if (lowestParent <= time + 50)
- {
- time = lowestParent - 50;
- if (time < 0) continue;
- notesToFix[i].Time = time;
- dur = 25;
- notesToFix[i].Length = dur;
- }
- }
-
- watch.Stop();
- Debug.WriteLine("step 3: " + noteVelocity + ": " + watch.ElapsedMilliseconds);
- watch = Stopwatch.StartNew();
-
- notesToFix = notesToFix.Reverse().ToArray();
- List fixedNotes = new List();
- for (int j = 0; j < notesToFix.Count(); j++)
- {
- var noteNum = notesToFix[j].NoteNumber;
- var time = notesToFix[j].Time;
- var dur = notesToFix[j].Length;
- var channel = notesToFix[j].Channel;
- var velocity = notesToFix[j].Velocity;
-
- if (j + 1 < notesToFix.Count())
- {
- switch (notesToFix[j].Length)
- {
- // BACON MEOWCHESTRA
- // Bandaid fix: If sustained note is 100ms or greater, ensure 60ms between the end of that note and the beginning of the next note.
- // Otherwise, leave the behavior as it was before.
- case >= 100 when notesToFix[j + 1].Time <= notesToFix[j].Time + notesToFix[j].Length + 60:
- dur = notesToFix[j + 1].Time - notesToFix[j].Time - 60;
- dur = dur < 60 ? 60 : dur;
- break;
- case < 100 when notesToFix[j + 1].Time <= notesToFix[j].Time + notesToFix[j].Length + 25:
- dur = notesToFix[j + 1].Time - notesToFix[j].Time - 25;
- dur = dur < 25 ? 25 : dur;
- break;
- }
- }
- fixedNotes.Add(new Note(noteNum, dur, time)
- {
- Channel = channel,
- Velocity = velocity,
- OffVelocity = velocity
- });
- }
- notesToFix = null;
-
- watch.Stop();
- Debug.WriteLine("step 4: " + noteVelocity + ": " + watch.ElapsedMilliseconds);
- watch = Stopwatch.StartNew();
-
- #region Tracknaming and octave shifting
- int octaveShift = 0;
- string trackName = originalChunk.Events.OfType().FirstOrDefault()?.Text;
-
- if (trackName == null) trackName = "";
- trackName = trackName.ToLower().Trim().Replace(" ", String.Empty);
- string o_trackName = trackName;
- Regex rex = new Regex(@"^([A-Za-z]+)([-+]\d)?");
- if (rex.Match(trackName) is Match match)
- {
- if (!string.IsNullOrEmpty(match.Groups[1].Value))
- {
- trackName = Instrument.Parse(match.Groups[1].Value).Name;
- if (!string.IsNullOrEmpty(match.Groups[2].Value))
- if (int.TryParse(match.Groups[2].Value, out int os))
- octaveShift = os;
-
- if (octaveShift > 0)
- trackName = trackName + "+" + octaveShift;
- else if (octaveShift < 0)
- trackName = trackName + octaveShift;
- }
-
- //last try with the program number
- if ((string.IsNullOrEmpty(match.Groups[1].Value)) || trackName.Equals("Unknown") || trackName.Equals("None"))
- {
- ProgramChangeEvent prog = originalChunk.Events.OfType().FirstOrDefault();
- if (prog != null)
- trackName = Instrument.ParseByProgramChange(prog.ProgramNumber).Name;
- }
-
- }
- newChunk = new TrackChunk(new SequenceTrackNameEvent(trackName));
- #endregion Tracknaming and octave shifting
-
- //Create Progchange Event
- foreach (var timedEvent in originalChunk.GetTimedEvents())
- {
- var programChangeEvent = timedEvent.Event as ProgramChangeEvent;
- if (programChangeEvent == null)
- continue;
- //Skip all except guitar | implement if we need this again
- if ((programChangeEvent.ProgramNumber < 27) || (programChangeEvent.ProgramNumber > 31))
- continue;
-
- var channel = programChangeEvent.Channel;
- using (var manager = new TimedObjectsManager(newChunk.Events))
- {
- TimedObjectsCollection timedEvents = manager.Objects;
- timedEvents.Add(new TimedEvent(new ProgramChangeEvent(programChangeEvent.ProgramNumber), 5000 + (timedEvent.TimeAs(tempoMap).TotalMicroseconds / 1000) - firstNote/* Absolute time too */));
- }
- }
- newChunk.AddObjects(fixedNotes);
-
- watch.Stop();
- Debug.WriteLine("step 5: " + noteVelocity + ": " + watch.ElapsedMilliseconds);
- watch = Stopwatch.StartNew();
-
- newTrackChunks.TryAdd(noteVelocity, newChunk);
-
- watch.Stop();
- Debug.WriteLine("step 6: " + noteVelocity + ": " + watch.ElapsedMilliseconds);
-
- });
-
- var newMidiFile = new MidiFile();
- newTrackChunks.TryRemove(newTrackChunks.Count, out TrackChunk trackZero);
- newMidiFile.Chunks.Add(trackZero);
- newMidiFile.TimeDivision = new TicksPerQuarterNoteTimeDivision(600);
- using (TempoMapManager tempoManager = newMidiFile.ManageTempoMap()) tempoManager.SetTempo(0, Tempo.FromBeatsPerMinute(100));
- newMidiFile.Chunks.AddRange(newTrackChunks.Values);
-
- tempoMap = newMidiFile.GetTempoMap();
- long delta = newMidiFile.GetTrackChunks().GetNotes().First().GetTimedNoteOnEvent().TimeAs(tempoMap).TotalMicroseconds / 1000;
-
- Parallel.ForEach(newMidiFile.GetTrackChunks(), chunk =>
- {
- var te = chunk.Events.OfType().FirstOrDefault()?.Text;
- var channel = chunk.Events.OfType().FirstOrDefault()?.Channel;
- using (var manager = chunk.ManageTimedEvents())
- {
- var prog = new ProgramChangeEvent((SevenBitNumber)Instrument.Parse(te).MidiProgramChangeCode);
- prog.Channel = (FourBitNumber)channel;
- manager.Objects.Add(new TimedEvent(prog, 5000));
- }
-
- using (var notesManager = chunk.ManageNotes())
- {
- foreach (Note note in notesManager.Objects)
- {
- long newStart = note.Time - delta;
- note.Time = newStart;
- }
- }
- using (var manager = chunk.ManageTimedEvents())
- {
- foreach (TimedEvent _event in manager.Objects)
- {
- var programChangeEvent = _event.Event as ProgramChangeEvent;
- if (programChangeEvent == null)
- continue;
-
- long newStart = _event.Time - delta;
- if (newStart <= -1)
- manager.Objects.Remove(_event);
- else
- _event.Time = newStart;
- }
- }
- });
-
- var stream = new MemoryStream();
-
- using (var manager = new TimedObjectsManager(newMidiFile.GetTrackChunks().First().Events))
- manager.Objects.Add(new TimedEvent(new MarkerEvent(), (newMidiFile.GetDuration().TotalMicroseconds / 1000)));
-
- newMidiFile.Write(stream, MidiFileFormat.MultiTrack, new WritingSettings { });
- stream.Flush();
- stream.Position = 0;
-
- loaderWatch.Stop();
- Console.WriteLine("Export finished MS: " + loaderWatch.ElapsedMilliseconds);
-
- return stream;
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- throw ex;
- }
- }
}
}