public static ChordFinderResultSet FindChords(IChordFinderOptions chordFinderOptions) { CancellationTokenSource cts = new CancellationTokenSource(); Task <ChordFinderResultSet> task = FindChordsAsync(chordFinderOptions, cts.Token); task.Wait(); return(task.Result); }
public static bool ValidateChord(int[] chordMarks, IChordFinderOptions chordFinderOptions) { if (null == chordMarks) { throw new ArgumentNullException("chordMarks"); } if (null == chordFinderOptions) { throw new ArgumentNullException("chordFinderOptions"); } MarkAnalysis ma = ChordAnalysis(chordMarks); bool reachPass = ma.Reach <= chordFinderOptions.MaxReach; bool openPass = chordFinderOptions.AllowOpenStrings ? true : !ma.HasOpenStrings; bool mutePass = chordFinderOptions.AllowMutedStrings ? true : !ma.HasMutedStrings; return(reachPass && openPass && mutePass); }
public static async Task <ChordFinderResultSet> FindChordsAsync(IChordFinderOptions chordFinderOptions, CancellationToken cancelToken) { if (null == chordFinderOptions) { throw new ArgumentNullException("chordFinderOptions"); } InternalNote root = NoteUtils.ToInternalNote(chordFinderOptions.RootNote); IChordQuality chordQuality = chordFinderOptions.ChordQuality; InternalNote[] notesInChord = NamedInterval.GetNotes(root, chordQuality.Intervals); ChordFinderResultSet results = new ChordFinderResultSet(chordFinderOptions); if (cancelToken.IsCancellationRequested) { return(results); } await FindAllChordsAsync(results, null, notesInChord, 0, chordFinderOptions, cancelToken); return(results); }
private static async Task FindAllChordsAsync(ChordFinderResultSet results, NoteNode noteNode, InternalNote[] targetNotes, int str, IChordFinderOptions chordFinderOptions, CancellationToken cancelToken) { if (cancelToken.IsCancellationRequested) { return; } IInstrument instrument = chordFinderOptions.Instrument; 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 (null != nn) { marks[str] = nn.Fret; for (int i = 0; i < targetNotes.Length; i++) { if (nn.Note == targetNotes[i]) { hasNotes[i] = true; } } nn = nn.Parent; str--; } InternalNote rootNote = NoteUtils.ToInternalNote(chordFinderOptions.RootNote); // Add result if it had all the target notes bool valid = true; for (int i = 0; i < hasNotes.Length; i++) { // Validate: // 1. All notes when !AllowRootlessChords // 2. Non-root notes only when AllowRootlessChords if (!chordFinderOptions.AllowRootlessChords || (chordFinderOptions.AllowRootlessChords && targetNotes[i] != rootNote)) { 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; await FindAllChordsAsync(results, muted, targetNotes, str + 1, chordFinderOptions, cancelToken); } // Look at all the notes on the string int startingFret = chordFinderOptions.AllowOpenStrings ? 0 : 1; for (int fret = startingFret; fret <= chordFinderOptions.MaxFret; fret++) { InternalNote note = NoteUtils.Shift(chordFinderOptions.Tuning.RootNotes[str].InternalNote, 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); await FindAllChordsAsync(results, child, targetNotes, str + 1, chordFinderOptions, cancelToken); break; } } } } }
internal ChordFinderResultSet(IChordFinderOptions chordFinderOptions) { ChordFinderOptions = chordFinderOptions; _results = new List <IChordFinderResult>(); }