예제 #1
0
        // 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);
        }
예제 #2
0
        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;
                }
            }
        }
예제 #3
0
        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);
        }