public static async Task <ScaleFinderResultSet> FindScalesAsync(IScaleFinderOptions scaleFinderOptions, CancellationToken cancelToken) { if (null == scaleFinderOptions) { throw new ArgumentNullException(nameof(scaleFinderOptions)); } InternalNote root = NoteUtils.ToInternalNote(scaleFinderOptions.RootNote); IScale scale = scaleFinderOptions.Scale; InternalNote[] notesInScale = NamedInterval.GetNotes(root, scale.Intervals); ScaleFinderResultSet results = new ScaleFinderResultSet(scaleFinderOptions); if (cancelToken.IsCancellationRequested) { return(results); } foreach (NoteNode startingNode in FindNodes(notesInScale[0], scaleFinderOptions)) { await FindAllScalesAsync(results, startingNode, notesInScale, 1, startingNode.String, scaleFinderOptions, cancelToken); } return(results); }
internal ScaleFinderResult(ScaleFinderResultSet parent, IEnumerable <MarkPosition> marks) { if (null == marks) { throw new ArgumentNullException(nameof(marks)); } Parent = parent ?? throw new ArgumentNullException(nameof(parent)); _marks = new List <MarkPosition>(marks); }
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 } }