public ChordResultSet FindChords(Note root, ChordQuality chordQuality, ChordFinderOptions chordFinderOptions) { if (null == chordQuality) { throw new ArgumentNullException("chordQuality"); } if (null == chordFinderOptions) { throw new ArgumentNullException("chordFinderOptions"); } InternalNote[] notesInChord = chordQuality.GetNotes(NoteUtils.ToInternalNote(root)); ChordResultSet results = new ChordResultSet(root, chordQuality, chordFinderOptions); FindAllChords(results, null, notesInChord, 0, chordFinderOptions); return(results); }
private void FindAllChords(ChordResultSet results, NoteNode noteNode, InternalNote[] targetNotes, int str, ChordFinderOptions chordFinderOptions) { if (str == Instrument.NumStrings) // Build a chord result { int[] marks = new int[Instrument.NumStrings]; NoteNode nn = noteNode; str--; bool[] hasNotes = new bool[targetNotes.Length]; // Walk back up the tree to set the marks on the result and flag each target note while (nn != null) { marks[str] = nn.Fret; for (int i = 0; i < targetNotes.Length; i++) { if (nn.Note == targetNotes[i]) { hasNotes[i] = true; break; } } nn = nn.Parent; str--; } // The first target note is always the root, so ignore if we want // to allow rootless chords int firstTargetNote = chordFinderOptions.AllowRootlessChords ? 1 : 0; // Add result if it had all the target notes bool valid = true; for (int i = firstTargetNote; i < hasNotes.Length; i++) { valid = valid && hasNotes[i]; } if (valid) { results.AddResult(marks); } } else // Keep building the tree { // Look at the muted string if (chordFinderOptions.AllowMutedStrings) { NoteNode muted = new NoteNode(); muted.Parent = noteNode; FindAllChords(results, muted, targetNotes, str + 1, chordFinderOptions); } // Look at all the notes on the string int startingFret = chordFinderOptions.AllowOpenStrings ? 0 : 1; for (int fret = startingFret; fret <= chordFinderOptions.MaxFret; fret++) { InternalNote note = Tuning.NoteAt(str, fret); // See if the note is a target note for (int i = 0; i < targetNotes.Length; i++) { // If it's a target note add it and search on the next string if (note == targetNotes[i]) { NoteNode child = new NoteNode(fret, note, noteNode); FindAllChords(results, child, targetNotes, str + 1, chordFinderOptions); break; } } } } }