public MidiMappingRecord[] FindMatchesInBuffer(Pitch[] buffer) { var results = new List<MidiMappingRecord>(); var events = buffer.Cast<Pitch?>().ToArray(); // Process chords first. Try to capture a chord with as many notes as possible. // This is O(scary), but seems quick enough in practice. (c) StackOverflow #184618 foreach (var mapping in chordMappingsOrdered) { bool isChordComplete = mapping.Trigger.Pitches.All(p => events.Any(e => e.HasValue && e == p)); if (isChordComplete) { // Exclude matched notes from further processing. for (int i = 0; i < events.Length; i++) { var pitch = events[i].Value; if (mapping.Trigger.Pitches.Any(p => p == pitch)) { events[i] = null; } } results.Add(mapping); } } // Process remaining single notes. foreach (var e in events.Where(e => e.HasValue)) { results.AddRange(FindSingleNoteMatches(e.Value)); } return results.ToArray(); }