예제 #1
0
        protected void ActiveNote(int channel, int note, bool active)
        {
            if (note >= 128 || channel >= 16)
            {
                return;
            }

            if (active)
            {
                ActiveNotes[note] |= (ushort)(1 << channel);
            }
            else
            {
                ActiveNotes[note] &= (ushort)~(1 << channel);
            }

            // See if there are hanging notes that we can cancel
            foreach (var hangingNote in HangingNotes.Reverse())
            {
                if (hangingNote.Channel == channel && hangingNote.Note != 0 && hangingNote.TimeLeft != 0)
                {
                    hangingNote.TimeLeft = 0;
                    --HangingNotesCount;
                    break;
                }
            }
        }
예제 #2
0
        protected void HangingNote(int channel, int note, int timeLeft, bool recycle = true)
        {
            NoteTimer best = null;

            if (HangingNotesCount >= HangingNotes.Length)
            {
//                Console.Error.WriteLine("MidiParser::hangingNote(): Exceeded polyphony");
                return;
            }

            foreach (var hangingNote in HangingNotes.Reverse())
            {
                if (hangingNote.Channel == channel && hangingNote.Note == note)
                {
                    if (hangingNote.TimeLeft != 0 && hangingNote.TimeLeft < timeLeft && recycle)
                    {
                        return;
                    }
                    best = hangingNote;
                    if (hangingNote.TimeLeft != 0)
                    {
                        if (recycle)
                        {
                            SendToDriver(0x80 | channel, note, 0);
                        }
                        --HangingNotesCount;
                    }
                    break;
                }
                else if (best == null && hangingNote.TimeLeft == 0)
                {
                    best = hangingNote;
                }
            }

            // Occassionally we might get a zero or negative note
            // length, if the note should be turned on and off in
            // the same iteration. For now just set it to 1 and
            // we'll turn it off in the next cycle.
            if (timeLeft == 0 || ((timeLeft & 0x80000000) != 0))
            {
                timeLeft = 1;
            }

            if (best != null)
            {
                best.Channel  = channel;
                best.Note     = note;
                best.TimeLeft = timeLeft;
                ++HangingNotesCount;
            }
            else
            {
                // We checked this up top. We should never get here!
//                Console.Error.WriteLine("MidiParser::hangingNote(): Internal error");
            }
        }