private void Form1_Load(object sender, EventArgs e) { _timedEventsManager = new TimedEventsManager(this, new TimedEvent(1000, () => textBox1.Text += "First\n"), new TimedEvent(5000, () => textBox1.Text += "Second\n"), new TimedEvent(2000, () => textBox1.Text += "Third\n") ); }
internal static MidiFile Load(string filePath) { try { MMSong mmSong = JsonExtensions.DeserializeFromFileCompressed <MMSong>(filePath); if (mmSong.schemaVersion < 1 && mmSong.schemaVersion > 2) { throw new FileFormatException("Error: This mmsong file format is not understood."); } // For now, just play the first available song. // if (mmSong.songs.Count != 1) throw new FileFormatException("Error: BMP currently only supports mmsong files with 1 song in them."); MMSong.Song song = mmSong.songs[0]; MidiFile sequence = new MidiFile(); sequence.Chunks.Add(new TrackChunk()); sequence.TimeDivision = new TicksPerQuarterNoteTimeDivision(600); using (TempoMapManager tempoMapManager = sequence.ManageTempoMap()) tempoMapManager.SetTempo(0, Tempo.FromBeatsPerMinute(100)); foreach (MMSong.Bard bard in song.bards) { List <Note> notes = new List <Note>(); bool failure = false; switch (bard.instrument) { case Instrument.Cymbal: case Instrument.Trumpet: case Instrument.Trombone: case Instrument.Horn: case Instrument.Tuba: case Instrument.Saxophone: case Instrument.Violin: case Instrument.Viola: case Instrument.Cello: case Instrument.DoubleBass: bard.sequence = bard.sequence.ToDictionary( x => x.Key + 2, x => x.Value); break; default: break; } if (bard.sequence.Count % 2 == 0) { long lastTime = 0; int lastNote = 254; foreach (KeyValuePair <long, int> sEvent in bard.sequence) { if (!failure) { if (lastNote == 254) { if (sEvent.Value <= 60 && sEvent.Value >= 24 && ((sEvent.Key * 25 % 100) == 50 || (sEvent.Key * 25) % 100 == 0)) { lastNote = sEvent.Value + 24; lastTime = sEvent.Key * 25; } else { failure = true; } } else { if (sEvent.Value == 254) { long dur = (sEvent.Key * 25) - lastTime; notes.Add(new Note((SevenBitNumber)lastNote, dur, lastTime) { Channel = (FourBitNumber)14, Velocity = (SevenBitNumber)(int)127, OffVelocity = (SevenBitNumber)(int)0 }); lastNote = 254; lastTime = sEvent.Key * 25; } else { failure = true; } } } } } else { failure = true; } if (failure) { throw new FileFormatException("Error: This mmsong file is corrupted"); } TrackChunk currentChunk = new TrackChunk(new SequenceTrackNameEvent(bard.instrument.ToString())); currentChunk.AddNotes(notes); notes = null; sequence.Chunks.Add(currentChunk); currentChunk = null; } using (var manager = new TimedEventsManager(sequence.GetTrackChunks().First().Events)) manager.Events.Add(new TimedEvent(new MarkerEvent(), (sequence.GetDuration <MetricTimeSpan>().TotalMicroseconds / 1000) + 100)); return(sequence); } catch (Exception ex) { throw ex; } }
public static Section ReadMidi(string filepath) { var midi = MidiFile.Read(filepath); var section = new Section(Path.GetFileNameWithoutExtension(filepath)); foreach (var midiChunk in midi.Chunks) { if (!(midiChunk is TrackChunk chunk)) { continue; } var phrase = new Phrase(); var programEvent = chunk.Events.OfType <ProgramChangeEvent>().FirstOrDefault(); if (programEvent != null) { phrase.Instrument = (MidiInstrument)(int)programEvent.ProgramNumber; } var nameEvent = chunk.Events.OfType <SequenceTrackNameEvent>().FirstOrDefault(); if (nameEvent != null) { phrase.Description = nameEvent.Text.Replace("\0", ""); } var tempoEvent = chunk.Events.OfType <SetTempoEvent>().FirstOrDefault(); if (tempoEvent != null) { phrase.Bpm = Math.Round(1M / (tempoEvent.MicrosecondsPerQuarterNote / 60M) * 1000000M, 2); } var panEvent = chunk.Events .OfType <ControlChangeEvent>().FirstOrDefault(x => x.ControlNumber == (SevenBitNumber)10); if (panEvent != null) { phrase.Panning = (panEvent.ControlValue / 126M * 2M) - 1M; } using (var manager = new TimedEventsManager(chunk.Events)) { phrase.Elements = manager.Events .Where(x => x.Event is NoteOnEvent) .Select(GetNewPhraseElement) .ToList(); var offNotes = manager.Events .Where(x => x.Event is NoteOffEvent) .Select(x => new Tuple <decimal, int>(Convert.ToDecimal(x.Time) / 24M, ((NoteOffEvent)x.Event).NoteNumber - NoteOffset)) .ToList(); foreach (var element in phrase.Elements) { var offNote = offNotes .FirstOrDefault(x => x.Item1 > element.Position && x.Item2 == element.Note); if (offNote == null) { throw new ApplicationException("No off note found"); } element.Duration = offNote.Item1 - element.Position; } } phrase.IsDrums = chunk.Events.OfType <NoteOnEvent>().Any(x => x.Channel == (FourBitNumber)DrumChannel); phrase.PhraseLength = NoteHelper.GetTotalDuration(phrase); phrase.Elements = phrase.Elements.OrderBy(x => x.Position).ThenBy(x => x.Note).ToList(); section.Phrases.Add(phrase); } if (section.Phrases.Count == 0) { throw new ApplicationException("Invalid Midi File"); } // remove blank tempo phrase if (section.Phrases.Count > 1 && section.Phrases[0].PhraseLength == 0 && section.Phrases[0].Instrument == MidiInstrument.AcousticGrandPiano && !section.Phrases[0].IsDrums) { section.Phrases.RemoveAt(0); } return(section); }
public List <List <ChartCommand> > ParseMidi() { List <List <ChartCommand> > commands = new List <List <ChartCommand> >(); commands.Add(new List <ChartCommand>()); commands.Add(new List <ChartCommand>()); commands.Add(new List <ChartCommand>()); int commandIndex = 0; MidiFile midiFile = MidiFile.Read(this.path); TempoMap tempoMap = midiFile.GetTempoMap(); foreach (var x in midiFile.GetTrackChunks()) { string trackName = ""; using (TimedEventsManager timedEventsManager = x.ManageTimedEvents()) { foreach (var e in timedEventsManager.Events) { if (e.Event is SequenceTrackNameEvent) { //Console.WriteLine(((SequenceTrackNameEvent)e.Event).Text); trackName = ((SequenceTrackNameEvent)e.Event).Text; switch (trackName) { case ("PART VOCALS"): commandIndex = -1; break; case ("HARM1"): commandIndex = 0; break; case ("HARM2"): commandIndex = 1; break; case ("HARM3"): commandIndex = 2; break; } } if (commandIndex != -1) { if (e.Event is NoteOnEvent) { if (((NoteOnEvent)e.Event).NoteNumber == 105) { ChartCommand noteOnCommand = new ChartCommand() { Command = "phrase_start", Parameter = "", Tick = (long)e.Time, OriginalCommand = "", TimeInMs = e.TimeAs <MetricTimeSpan>(tempoMap).TotalMicroseconds / 1000d }; commands[commandIndex].Add(noteOnCommand); if (commandIndex == 1) { commands[2].Add(noteOnCommand); } } } if (e.Event is NoteOffEvent) { if (((NoteOffEvent)e.Event).NoteNumber == 105) { ChartCommand noteOffCommand = new ChartCommand() { Command = "phrase_end", Parameter = "", Tick = (long)e.Time, OriginalCommand = "", TimeInMs = e.TimeAs <MetricTimeSpan>(tempoMap).TotalMicroseconds / 1000d }; commands[commandIndex].Add(noteOffCommand); if (commandIndex == 1) { commands[2].Add(noteOffCommand); } } } } if (e.Event is Melanchall.DryWetMidi.Core.TextEvent) { if (trackName.StartsWith("HARM")) { string line = ((Melanchall.DryWetMidi.Core.TextEvent)e.Event).Text; if (!line.StartsWith("[") && !line.EndsWith("]")) { if (line != "+") { MetricTimeSpan metricTime = e.TimeAs <MetricTimeSpan>(tempoMap); double timeInMs = metricTime.TotalMicroseconds / 1000d; var curCommand = new ChartCommand() { Tick = (int)e.Time, TimeInMs = timeInMs, Command = "lyric", Parameter = line, OriginalCommand = "" }; commands[commandIndex].Add(curCommand); } } } } /* * if (e.EventType == MidiEventType.Text) * { * Console.WriteLine(((TextEvent)e).Text); * } */ } } } commands[0] = commands[0].OrderBy(o => o.TimeInMs).ToList(); commands[1] = commands[1].OrderBy(o => o.TimeInMs).ToList(); commands[2] = commands[2].OrderBy(o => o.TimeInMs).ToList(); return(commands); }
void _ParseAuthoring() { _authoring.Clear(); if (!_HasMidiFile()) { return; } TrackChunk authTrack = _FindAuthoringTracks(); if (authTrack == null) { return; } using (TimedEventsManager timedEventsManager = authTrack.ManageTimedEvents()) { // Get timed events ordered by time TimedEventsCollection events = timedEventsManager.Events; AuthoringEvent newEvent = null; int curNote = -1; foreach (var midiEvent in events) { if (!(midiEvent.Event is SequenceTrackNameEvent) && !(midiEvent.Event is BaseTextEvent) && (midiEvent.Event is NoteOnEvent)) //ignore text events! { newEvent = new AuthoringEvent(); curNote = (midiEvent.Event as NoteOnEvent).NoteNumber; newEvent.NoteIdx = curNote - BaseInstrumentNote; if (newEvent.NoteIdx < 0) //note was less than our BaseInstrumentNote, so ignore! { continue; } float startSecs = midiEvent.TimeAs <MetricTimeSpan>(_tempoMap).TotalMicroseconds / 1000000.0f; newEvent.NoteOnBeat = SecsToBeats(startSecs); _authoring.Add(newEvent); //now find a nearby note-off pair /*foreach (var pairedEvent in events) * { * if (_IsNearEvent(pairedEvent, midiEvent) && (pairedEvent.Event is NoteOffEvent) && (curNote >= 0) && (curNote == (pairedEvent.Event as NoteOffEvent).NoteNumber)) //found paired note off * { * float endSecs = pairedEvent.TimeAs<MetricTimeSpan>(_tempoMap).TotalMicroseconds / 1000000.0f; * newEvent.NoteOffBeat = SecsToBeats(endSecs); * * if (newEvent.IsValid()) //done? * { * _authoring.Add(newEvent); * * //Debug.Log("added event " + newEvent.NoteOnBeat + " -> " + newEvent.NoteOffBeat); * } * * break; * } * }*/ } } } Debug.Log("Found " + _authoring.Count + " authoring events!"); }