// Turns a channel event into a musical note object. public Note EventToNote(ChannelEvent eventIn) { Note note = new Note(); note.SetPitch((NotePitch)eventIn.GetParam1()); note.SetVelocity(eventIn.GetParam2()); note.SetChannel(eventIn.GetChannel()); return(note); }
public void ParseEvents() { Dictionary <NotePitch, Stack <Note> > activeNotes = new Dictionary <NotePitch, Stack <Note> >(); // Dictionary of all notes that have a NoteOn but no NoteOff. uint timeElapsed = 0; for (int i = 0; i < midiEvents.Count; i++) { Event tempEvent = midiEvents.ElementAt(i); timeElapsed += tempEvent.GetTime(); switch (tempEvent.GetEventType()) { case MidiEventType.NoteOn: ChannelEvent tempNoteOnEvent = (ChannelEvent)tempEvent; Note currentNoteOn = EventToNote(tempNoteOnEvent); currentNoteOn.SetTime(timeElapsed); // If there is already an active note in this pitch, add the new note to the existing stack. if (activeNotes.ContainsKey(currentNoteOn.GetPitch())) { activeNotes[currentNoteOn.GetPitch()].Push(currentNoteOn); } else // If there is no active note in this pitch, create the stack and then add the note. { Stack <Note> notesStack = new Stack <Note>(); notesStack.Push(currentNoteOn); activeNotes.Add(currentNoteOn.GetPitch(), notesStack); } break; case MidiEventType.NoteOff: ChannelEvent tempNoteOffEvent = (ChannelEvent)tempEvent; Note currentNoteOff = EventToNote(tempNoteOffEvent); // If there is already at least one active note in this pitch, pop the latest one and finalise its duration. if (activeNotes.ContainsKey(currentNoteOff.GetPitch())) { Note tempNote = activeNotes[currentNoteOff.GetPitch()].Pop(); tempNote.SetDuration(timeElapsed - tempNote.GetTime()); notes.Add(tempNote); if (activeNotes[currentNoteOff.GetPitch()].Count == 0) // If the stack of notes is empty, remove the entry from the dictionary of active notes. { activeNotes.Remove(currentNoteOff.GetPitch()); } } else // If there was a note off event at a certain pitch with no note on events at that pitch. { throw new InvalidOperationException("Note off without corresponding note on."); } break; case MidiEventType.SetTempo: bpm = CalculateBPM(((NumMetaEvent)tempEvent).GetNum()); break; case MidiEventType.TimeSignature: timeSig = CalculateTimeSignature(((NumMetaEvent)tempEvent).GetNum()); break; case MidiEventType.EndOfTrack: midiLength = timeElapsed > midiLength ? timeElapsed : midiLength; timeElapsed = 0; break; } } }
private int ParseChannelEvent(int index, uint time, byte type) { uint channel = (uint)(type & 0x0F); MidiEventType eventType = (MidiEventType)(type & 0xF0); ChannelEvent channelEvent = new ChannelEvent(); channelEvent.SetChannel(channel); channelEvent.SetTime(time); channelEvent.SetEventType(eventType); Console.WriteLine("--- Channel: " + channel); Console.WriteLine("--- Time: " + time); Console.WriteLine("--- Event Type: " + eventType); byte param1; byte param2; switch (eventType) { case MidiEventType.NoteOn: param1 = midi[index++]; param2 = midi[index++]; channelEvent.SetParam1(param1); channelEvent.SetParam2(param2); if (param2 == 0) { channelEvent.SetEventType(MidiEventType.NoteOff); } Console.WriteLine("--- Note: " + param1); Console.WriteLine("--- Velocity: " + param2); break; case MidiEventType.NoteOff: param1 = midi[index++]; param2 = midi[index++]; channelEvent.SetParam1(param1); channelEvent.SetParam2(param2); Console.WriteLine("--- Note: " + param1); Console.WriteLine("--- Velocity: " + param2); break; case MidiEventType.NoteAftertouch: param1 = midi[index++]; param2 = midi[index++]; channelEvent.SetParam1(param1); channelEvent.SetParam2(param2); Console.WriteLine("--- Note: " + param1); Console.WriteLine("--- Amount: " + param2); break; case MidiEventType.Controller: param1 = midi[index++]; param2 = midi[index++]; channelEvent.SetParam1(param1); channelEvent.SetParam2(param2); Console.WriteLine("--- Controller: " + param1); Console.WriteLine("--- Value: " + param2); break; case MidiEventType.ProgramChange: param1 = midi[index++]; channelEvent.SetParam1(param1); Console.WriteLine("--- Program: " + param1); break; case MidiEventType.ChannelAftertouch: param1 = midi[index++]; channelEvent.SetParam1(param1); Console.WriteLine("--- Amount: " + param1); break; case MidiEventType.PitchBend: param1 = midi[index++]; param2 = midi[index++]; channelEvent.SetParam1(param1); channelEvent.SetParam2(param2); Console.WriteLine("--- LSB Value: " + param1); Console.WriteLine("--- MSB Value: " + param2); break; default: return(-1); } midiEvents.Add(channelEvent); return(index); }