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"); } }
protected MidiParser() { ActiveNotes = new ushort[128]; HangingNotes = new NoteTimer[32]; for (int i = 0; i < HangingNotes.Length; i++) { HangingNotes[i] = new NoteTimer(); } Tracks = new Track[120]; TimerRate = 0x4A0000; _ppqn = 96; tempo = 500000; _psecPerTick = 5208;// 500000 / 96 _nextEvent = new EventInfo(); _nextEvent.Start = 0; _nextEvent.Delta = 0; _nextEvent.Event = 0; Position = new Tracker(); }