public static async Task <ScaleFinderResultSet> FindScalesAsync(IScaleFinderOptions scaleFinderOptions, CancellationToken cancelToken) { if (null == scaleFinderOptions) { throw new ArgumentNullException("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); }
public static ScaleFinderResultSet FindScales(IScaleFinderOptions scaleFinderOptions) { CancellationTokenSource cts = new CancellationTokenSource(); Task <ScaleFinderResultSet> task = FindScalesAsync(scaleFinderOptions, cts.Token); task.Wait(); return(task.Result); }
private static IEnumerable <NoteNode> FindNodes(InternalNote targetNote, IScaleFinderOptions scaleFinderOptions) { for (int str = 0; str < scaleFinderOptions.Instrument.NumStrings; str++) { InternalNote rootNote = scaleFinderOptions.Tuning.RootNotes[str].InternalNote; int fret = NoteUtils.GetShift(rootNote, targetNote); while (fret <= scaleFinderOptions.MaxFret) { yield return(new NoteNode(str, fret, targetNote, null)); fret += 12; } } }
public static bool ValidateScale(IEnumerable <MarkPosition> scaleMarks, IScaleFinderOptions scaleFinderOptions) { if (null == scaleMarks) { throw new ArgumentNullException("scaleMarks"); } if (null == scaleFinderOptions) { throw new ArgumentNullException("scaleFinderOptions"); } MarkAnalysis ma = ScaleAnalysis(scaleMarks, scaleFinderOptions.Instrument.NumStrings); bool reachPass = ma.Reach <= scaleFinderOptions.MaxReach; bool openPass = scaleFinderOptions.AllowOpenStrings ? true : !ma.HasOpenStrings; bool mutePass = scaleFinderOptions.AllowMutedStrings ? true : !ma.HasMutedStrings; return(reachPass && openPass && mutePass); }
internal ScaleFinderResultSet(IScaleFinderOptions scaleFinderOptions) { ScaleFinderOptions = scaleFinderOptions; _results = new List <ScaleFinderResult>(); }
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 } }