private static async Task FindAllScalesAsync(ScaleFinderResultSet results, NoteNode noteNode, InternalNote[] targetNotes, int nextNote, int str, IScaleFinderOptions scaleFinderOptions, CancellationToken cancelToken) { if (cancelToken.IsCancellationRequested) { return; } IInstrument instrument = scaleFinderOptions.Instrument; if (nextNote == targetNotes.Length) // Build a scale result { List <MarkPosition> marks = new List <MarkPosition>(); NoteNode nn = noteNode; // Walk back up the tree to set the marks on the result and flag each target note while (null != nn) { if (nn.Fret >= 0) { marks.Add(new MarkPosition(nn.String + 1, nn.Fret)); } nn = nn.Parent; } results.AddResult(marks); } else if (str < instrument.NumStrings) // Keep building the tree { // Look at all the notes on the string int startingFret = scaleFinderOptions.AllowOpenStrings ? 0 : 1; if (null != noteNode && noteNode.String == str) { startingFret = noteNode.Fret + 1; } for (int fret = startingFret; fret <= scaleFinderOptions.MaxFret; fret++) { InternalNote note = NoteUtils.Shift(scaleFinderOptions.Tuning.RootNotes[str].InternalNote, fret); // See if the note is the next target note if (note == targetNotes[nextNote]) { NoteNode child = new NoteNode(str, fret, note, noteNode); // Add found note await FindAllScalesAsync(results, child, targetNotes, nextNote + 1, str, scaleFinderOptions, cancelToken); // Look for the next note on the same string } } await FindAllScalesAsync(results, noteNode, targetNotes, nextNote, str + 1, scaleFinderOptions, cancelToken); // Look for the next note on the next string } }
public InternalNote InternalNoteAt(int str, int fret) { if (str < 0 || str >= RootNotes.Length) { throw new ArgumentOutOfRangeException(nameof(str)); } if (fret < 0) { throw new ArgumentOutOfRangeException(nameof(fret)); } return(NoteUtils.Shift(RootNotes[str].InternalNote, fret)); }
public static InternalNote[] GetNotes(InternalNote root, int[] intervals) { if (null == intervals || intervals.Length == 0) { throw new ArgumentNullException(nameof(intervals)); } InternalNote[] notes = new InternalNote[intervals.Length]; for (int i = 0; i < notes.Length; i++) { notes[i] = NoteUtils.Shift(root, intervals[i]); } return(notes); }
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 { 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; } } } } }
public InternalNote NoteAt(MarkPosition position) { return(NoteUtils.Shift(Parent.ScaleFinderOptions.Tuning.RootNotes[position.String - 1].InternalNote, position.Fret)); }