/// <summary> /// Reads a meta-event from a stream /// </summary> /// <param name="br">A binary reader based on the stream of MIDI data</param> /// <returns>A new MetaEvent object</returns> public static MetaEvent ReadMetaEvent(BinaryReader br) { MetaEventType metaEvent = (MetaEventType) br.ReadByte(); int length = ReadVarInt(br); MetaEvent me = new MetaEvent(); switch(metaEvent) { case MetaEventType.TrackSequenceNumber: // Sets the track's sequence number. me = new TrackSequenceNumberEvent(br,length); break; case MetaEventType.TextEvent: // Text event case MetaEventType.Copyright: // Copyright case MetaEventType.SequenceTrackName: // Sequence / Track Name case MetaEventType.TrackInstrumentName: // Track instrument name case MetaEventType.Lyric: // lyric case MetaEventType.Marker: // marker case MetaEventType.CuePoint: // cue point case MetaEventType.ProgramName: case MetaEventType.DeviceName: me = new TextEvent(br,length); break; case MetaEventType.EndTrack: // This event must come at the end of each track if(length != 0) { throw new FormatException("End track length"); } break; case MetaEventType.SetTempo: // Set tempo me = new TempoEvent(br,length); break; case MetaEventType.TimeSignature: // Time signature me = new TimeSignatureEvent(br,length); break; case MetaEventType.KeySignature: // Key signature me = new KeySignatureEvent(br, length); break; case MetaEventType.SequencerSpecific: // Sequencer specific information me = new SequencerSpecificEvent(br, length); break; case MetaEventType.SmpteOffset: me = new SmpteOffsetEvent(br, length); break; default: //System.Windows.Forms.MessageBox.Show(String.Format("Unsupported MetaEvent {0} length {1} pos {2}",metaEvent,length,br.BaseStream.Position)); me.data = br.ReadBytes(length); if (me.data.Length != length) { throw new FormatException("Failed to read metaevent's data fully"); } break; } me.metaEvent = metaEvent; me.metaDataLength = length; return me; }
/// <summary> /// Reads a meta-event from a stream /// </summary> /// <param name="br">A binary reader based on the stream of MIDI data</param> /// <returns>A new MetaEvent object</returns> public static MetaEvent ReadMetaEvent(BinaryReader br) { MetaEventType metaEvent = (MetaEventType)br.ReadByte(); int length = ReadVarInt(br); MetaEvent me = new MetaEvent(); switch (metaEvent) { case MetaEventType.TextEvent: // Text event case MetaEventType.Copyright: // Copyright case MetaEventType.SequenceTrackName: // Sequence / Track Name case MetaEventType.TrackInstrumentName: // Track instrument name case MetaEventType.Lyric: // lyric case MetaEventType.Marker: // marker case MetaEventType.CuePoint: // cue point case MetaEventType.ProgramName: case MetaEventType.DeviceName: me = new TextEvent(br, length); break; case MetaEventType.EndTrack: // This event must come at the end of each track if (length != 0) { throw new FormatException("End track length"); } break; case MetaEventType.SetTempo: // Set tempo me = new TempoEvent(br, length); break; case MetaEventType.TimeSignature: // Time signature me = new TimeSignatureEvent(br, length); break; default: //System.Windows.Forms.MessageBox.Show(String.Format("Unsupported MetaEvent {0} length {1} pos {2}",metaEvent,length,br.BaseStream.Position)); me.data = br.ReadBytes(length); if (me.data.Length != length) { throw new FormatException("Failed to read metaevent's data fully"); } break; } me.metaEvent = metaEvent; me.metaDataLength = length; return(me); }
public static Composition LoadFromMIDI(string filename) { Composition comp = new Composition(); comp.Tracks.Clear(); NAudio.Midi.MidiFile f = new MidiFile(filename); // if (f.Events.MidiFileType == 1) // return LoadMidiType1(f); f.Events.MidiFileType = 0; byte max_channels = 0; foreach(var trackEvent in f.Events) foreach (var e in trackEvent) if (e.Channel > max_channels) max_channels = (byte)e.Channel; max_channels++; Track[] tracks = new Track[max_channels]; MelodySequence[] seqs = new MelodySequence[max_channels]; TempoEvent[] tempos = new TempoEvent[max_channels]; for (byte i = 0; i < max_channels; i++ ) { tracks[i] = new Track(PatchNames.Acoustic_Grand, i); seqs[i] = new MelodySequence(); tempos[i] = new TempoEvent((int)(Note.ToRealDuration((int)Durations.qn, 60) * 1000), 0); tempos[i].Tempo = 60; } foreach(var trackEvents in f.Events) foreach (var e in trackEvents) { if (e as TempoEvent != null) { tempos[e.Channel] = (TempoEvent)e; } if (e as PatchChangeEvent != null) { var p = e as PatchChangeEvent; tracks[p.Channel].Instrument = (PatchNames)p.Patch; } NoteOnEvent on = e as NoteOnEvent; if (on != null && on.OffEvent != null) { int total_dur = Note.ToNoteLength((int)on.AbsoluteTime, f.DeltaTicksPerQuarterNote, tempos[on.Channel].Tempo); if (total_dur > seqs[on.Channel].Duration) seqs[on.Channel].AddPause(total_dur - seqs[on.Channel].Duration); int duration = Note.ToNoteLength(on.NoteLength, f.DeltaTicksPerQuarterNote, tempos[on.Channel].Tempo); seqs[on.Channel].AddNote(new Note(on.NoteNumber, (int)duration)); } } for(byte i = 0; i < max_channels; i++) { if(seqs[i].Length > 0) { tracks[i].AddSequence(seqs[i]); comp.Tracks.Add(tracks[i]); } } comp.NameTag = System.IO.Path.GetFileNameWithoutExtension(filename); return comp; }
/// <summary> /// Loads a Harmony Sequence though /// </summary> /// <param name="f"></param> /// <returns></returns> public static Composition LoadMidiType1(MidiFile f) { Composition comp = new Composition(); int c = 1; foreach(var trackEvents in f.Events) { Track t = new Track(); t.Channel = (byte)c++; TempoEvent tempo = new TempoEvent((int)(Note.ToRealDuration((int)Durations.qn, 60) * 1000000), 0); HarmonySequence seq = new HarmonySequence(); long lastAbsTime = -1; List<int> chordNotes = new List<int>(); int chordDuration = 0; PatchNames instr = (PatchNames)9999; bool add = true; foreach(var e in trackEvents) { if (e as TempoEvent != null) { tempo = (TempoEvent)e; } if (e as PatchChangeEvent != null) { var p = e as PatchChangeEvent; t.Instrument = (PatchNames)p.Patch; if(t.Instrument == instr) { break; } instr = t.Instrument; /*if(t.Duration < 1) { foreach(var t_ in comp.Tracks) if(t_.Instrument == (PatchNames)p.Patch) { t = t_; seq = t_.GetMainSequence() as HarmonySequence; add = false; break; } }*/ } NoteOnEvent on = e as NoteOnEvent; if (on != null && on.OffEvent != null) { int newDuration = Note.ToNoteLength(on.NoteLength, f.DeltaTicksPerQuarterNote, tempo.Tempo); if (on.AbsoluteTime == lastAbsTime && chordDuration==newDuration)//skip chords { chordNotes.Add(on.NoteNumber); } else { Chord lastChord = new Chord(chordNotes.ToArray(), chordDuration); chordNotes.Clear(); chordDuration = 0; seq.AddChord(lastChord); chordNotes.Add(on.NoteNumber); } chordDuration = newDuration; lastAbsTime = on.AbsoluteTime; } } if(chordNotes.Count > 0) { Chord lastChord = new Chord(chordNotes.ToArray(), chordDuration); chordNotes.Clear(); chordDuration = 0; seq.AddChord(lastChord); } t.AddSequence(seq); if (!comp.Tracks.Contains(t) && t.Duration > 0 && add) comp.Add(t); } return comp; }
public static MetaEvent ReadMetaEvent(BinaryReader br) { MetaEventType metaEventType = (MetaEventType)br.ReadByte(); int num = MidiEvent.ReadVarInt(br); MetaEvent metaEvent = new MetaEvent(); MetaEventType metaEventType2 = metaEventType; if (metaEventType2 <= MetaEventType.SetTempo) { switch (metaEventType2) { case MetaEventType.TrackSequenceNumber: metaEvent = new TrackSequenceNumberEvent(br, num); goto IL_E9; case MetaEventType.TextEvent: case MetaEventType.Copyright: case MetaEventType.SequenceTrackName: case MetaEventType.TrackInstrumentName: case MetaEventType.Lyric: case MetaEventType.Marker: case MetaEventType.CuePoint: case MetaEventType.ProgramName: case MetaEventType.DeviceName: metaEvent = new TextEvent(br, num); goto IL_E9; default: if (metaEventType2 != MetaEventType.EndTrack) { if (metaEventType2 == MetaEventType.SetTempo) { metaEvent = new TempoEvent(br, num); goto IL_E9; } } else { if (num != 0) { throw new FormatException("End track length"); } goto IL_E9; } break; } } else { if (metaEventType2 == MetaEventType.SmpteOffset) { metaEvent = new SmpteOffsetEvent(br, num); goto IL_E9; } switch (metaEventType2) { case MetaEventType.TimeSignature: metaEvent = new TimeSignatureEvent(br, num); goto IL_E9; case MetaEventType.KeySignature: metaEvent = new KeySignatureEvent(br, num); goto IL_E9; default: if (metaEventType2 == MetaEventType.SequencerSpecific) { metaEvent = new SequencerSpecificEvent(br, num); goto IL_E9; } break; } } metaEvent.data = br.ReadBytes(num); if (metaEvent.data.Length != num) { throw new FormatException("Failed to read metaevent's data fully"); } IL_E9: metaEvent.metaEvent = metaEventType; metaEvent.metaDataLength = num; return(metaEvent); }