private void DisplayScaleCore(Scale targetScale) { try { var noteInScale = targetScale.GetElementsNote().ToList(); foreach (var children in Pianokey.Children) { Image img = children as Image; string tag = img.Tag as string; Note note = NoteUtils.ParseNote(tag.Split('-')[1]); if (noteInScale.Contains(note)) { ChangePianoKeyChooseStatus(img, status: "Choose"); } else { ChangePianoKeyChooseStatus(img, status: "CancelChoose"); } } } catch (Exception) { MessageBox.Show("音阶键位显示出现未知错误!", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } }
public FullNote Shift(int steps, InternalNoteStringStyle style) { if (steps == 0) { return(new FullNote(NoteUtils.ToNote(InternalNote, style), Octave)); } int direction = Math.Sign(steps); InternalNote note = InternalNote; int octave = Octave; for (int i = 0; i < steps; i++) { int noteIndex = (int)note + direction; if (noteIndex < 0) { noteIndex += 12; } note = (InternalNote)(noteIndex % 12); if (direction > 0 && note == InternalNote.C) { octave++; } else if (direction < 0 && note == InternalNote.B) { octave--; } } return(new FullNote(NoteUtils.ToNote(note, style), octave)); }
private string GetText(InternalNote?[] notes, int str, MarkTextOption markTextOption) { if (str < 0 || str >= notes.Length) { throw new ArgumentOutOfRangeException(nameof(str)); } string text = ""; if (notes[str].HasValue) { switch (markTextOption) { case MarkTextOption.ShowNote_PreferFlats: text = NoteUtils.ToString(notes[str].Value, InternalNoteStringStyle.PreferFlat); break; case MarkTextOption.ShowNote_PreferSharps: text = NoteUtils.ToString(notes[str].Value, InternalNoteStringStyle.PreferSharp); break; case MarkTextOption.ShowNote_ShowBoth: text = NoteUtils.ToString(notes[str].Value, InternalNoteStringStyle.ShowBoth); break; } } return(text); }
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); }
public void Set(string key, Note value) { if (StringUtils.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } Set(key, NoteUtils.ToString(value)); }
public bool IsRoot(MarkPosition mark) { if (null == mark) { throw new ArgumentOutOfRangeException(nameof(mark)); } return(NoteAt(mark) == NoteUtils.ToInternalNote(Parent.ScaleFinderOptions.RootNote)); }
public bool TryGet(string key, out Note result, bool recursive = true) { if (TryGet(key, out string rawResult, recursive)) { return(NoteUtils.TryParseNote(rawResult, out result)); } result = default(Note); return(false); }
public static ObservableCollection <string> GetNotes() { ObservableCollection <string> collection = new ObservableCollection <string>(); for (int i = 0; i < Enum.GetValues(typeof(Note)).Length; i++) { collection.Add(NoteUtils.ToString((Note)i)); } return(collection); }
public static ObservableCollection <string> GetInternalNotes() { ObservableCollection <string> collection = new ObservableCollection <string>(); for (int i = 0; i < Enum.GetValues(typeof(InternalNote)).Length; i++) { collection.Add(NoteUtils.ToString((InternalNote)i, InternalNoteStringStyle.ShowBoth)); } return(collection); }
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 } }
private void DisplayScaleClickEvent(object sender, RoutedEventArgs e) { ClearChoosePianoKey(); string keyStr = ScaleKey.Text; string type = ScaleType.Text; ChordNameTextBox.Text = string.Empty; Scale targetScale = new Scale(NoteUtils.ParseNote(keyStr), Common.TryEnum <Tonic>(type)); DisplayScaleCore(targetScale); }
private void Button_Click(object sender, RoutedEventArgs e) { Left.Visibility = Visibility.Hidden; Right.Visibility = Visibility.Hidden; if (PianoKeyChooseNote.Count() == 0) { MessageBox.Show("未指定钢琴上的键位!", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } else { ArrowMode = "DetectChord"; string style = PianoChordStyle.Text; string bassStyle = PianoChordBassStyle.Text; string bassNoteStr = PianoKeyChooseNote.First(s => int.Parse(s.Split('-')[2]) == PianoKeyChooseNote.Min(k => int.Parse(k.Split('-')[2]))).Split('-')[1]; List <Note> NoteList = new List <Note>(); foreach (var keyNote in PianoKeyChooseNote) { int index = int.Parse(keyNote.Split('-')[0]); string noteStr = keyNote.Split('-')[1]; var note = NoteUtils.ParseNote(noteStr); if (!NoteList.Contains(note)) { NoteList.Add(note); } } RetroChord res; try { if (bassStyle == "不指定低音") { res = ChordAnalysis.ChordRecognizer(NoteList); } else { res = ChordAnalysis.ChordRecognizer(NoteList, bass: NoteUtils.ParseNote(bassNoteStr)); } candidate = res.Select(r => r.chord).ToList(); ChordNameTextBox.Text = res.BestChord.Title; Left.Visibility = Visibility.Visible; Right.Visibility = Visibility.Visible; } catch { MessageBox.Show("和弦分析出现未知错误!", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } }
public void SetTarget(Note rootNote, IChordQuality chordQuality) { if (null == chordQuality) { throw new ArgumentNullException(nameof(chordQuality)); } Settings[Prefix + "rootnote"] = NoteUtils.ToString(rootNote); Settings[Prefix + "chordquality"] = chordQuality.LongName; ChordQualityLevel = chordQuality.Level; _cachedChordQuality = chordQuality; }
public void SetTarget(Note rootNote, IScale scale) { if (null == scale) { throw new ArgumentNullException(nameof(scale)); } Settings[Prefix + "rootnote"] = NoteUtils.ToString(rootNote); Settings[Prefix + "scale"] = scale.LongName; ScaleLevel = scale.Level; _cachedScale = scale; }
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 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; } } }
/// <summary> /// Call from JQuery to find the chords. /// </summary> /// <param name="instrument">The instrument.</param> /// <param name="tuning">The tuning.</param> /// <param name="notes">The root note for the chord.</param> /// <param name="chordQualities">The chord qualities.</param> /// <param name="numFrets">The number of frets to display.</param> /// <param name="maxFrets">The maximum number of frets to use.</param> /// <param name="maxReach">The maximum fret reach for the fingers.</param> /// <param name="autoAddBarres">Auto add barres?</param> /// <param name="allowOpenStrings">Allow open strings?</param> /// <param name="allowMutedStrings">Allow muted strings?</param> /// <param name="mirrorResults">Mirror the results for left-handed chords?</param> /// <param name="allowRootlessChords">Allow rootless chords?</param> /// <returns>List of SVG images to display in the UI.</returns> public JsonResult FindChords(string instrument, string tuning, string notes, string chordQualities, string numFrets, string maxFrets, string maxReach, string autoAddBarres, string allowOpenStrings, string allowMutedStrings, string mirrorResults, string allowRootlessChords) { // Initialize the ConfigFile object. InitConfig(); // Define the objects. Instrument Instrument = null; ChordQuality ChordQuality = null; ChordFinderOptions myOptions = null; ChordFinder chordFinder = null; ChordResultSet chordResultSet = null; ChordOptions chordOptions = null; Tuning Tuning = null; Note myNote = NoteUtils.ParseNote(notes); Instrument = GetAnInstrument(instrument); ChordQuality = GetChordQuality(chordQualities); if (Instrument != null) { // Instantiate the selected tuning object from the instrument. Tuning = GetTheTuning(Instrument, tuning); // Instantiate the chord finder options. myOptions = BuildChordFinderOptions(instrument, tuning, numFrets, maxFrets, maxReach, autoAddBarres, allowOpenStrings, allowMutedStrings, mirrorResults, allowRootlessChords); // Instantiate the chord finder object. chordFinder = new ChordFinder(Instrument, Tuning); // Instantiate the chord result set. chordResultSet = chordFinder.FindChords(myNote, ChordQuality, myOptions); // Instantiate the chord options. chordOptions = BuildChordOptions(); // Build the list of SVG images to return to the screen. return(Json(BuildSVGList(chordResultSet, chordOptions), JsonRequestBehavior.AllowGet)); } else { // The instrument doesn't exist. return(Json(String.Empty, JsonRequestBehavior.AllowGet)); } }
[TestCase(new double[] { 1000, 3000 }, 0.3, 1, null)] // start + duration should not exceed 1 public void TestSliceNoteTime(double[] time, double startPercentage, double durationPercentage, double[] actualTime) { var note = new Note { StartTime = time[0], Duration = time[1], }; try { var sliceNote = NoteUtils.SliceNote(note, startPercentage, durationPercentage); Assert.AreEqual(sliceNote.StartTime, actualTime[0]); Assert.AreEqual(sliceNote.Duration, actualTime[1]); } catch { Assert.IsNull(actualTime); } }
private void DisplayChordAccordingToNameClickEvent(object sender, RoutedEventArgs e) { Chord target = GetChordByNameSet(); var bass = target.BassNote; int bassNum = ((int)bass + 1); ChordNoteNumTmp.Add(bassNum); string bassTag = "1-" + NoteUtils.ToString(bass) + "-" + bassNum.ToString(); var noteList = target.ToInternalNoteList().Where(n => n != null).Cast <InternalNote>().ToList(); List <string> noteTags = new List <string>() { bassTag }; noteList.ForEach(n => { string level; string note = NoteUtils.ToString(n); string num; if ((int)n > (int)bass) { level = "1"; num = (bassNum + (int)n - (int)bass).ToString(); } else if ((int)n == (int)bass) { level = "2"; num = (12 + bassNum).ToString(); } else { level = "2"; num = (12 + bassNum - (int)bass + (int)n).ToString(); } noteTags.Add($"{level}-{note}-{num}"); ChordNoteNumTmp.Add(int.Parse(num)); }); DisplayKeyCore(noteTags); ArrowMode = "DisplayChord"; ChordNoteNumTmp.Sort(); CheckArrowVisibleState(); }
private void DisplayChordArpeggioEvent(object sender, RoutedEventArgs e) { Left.Visibility = Visibility.Hidden; Right.Visibility = Visibility.Hidden; Chord target = GetChordByNameSet(); var noteList = target.ToInternalNoteList().Where(n => n != null).Cast <InternalNote>().ToList(); noteList.Add(target.BassNote); noteList.Distinct(); foreach (var children in Pianokey.Children) { Image img = children as Image; string imgTag = img.Tag as string; string noteStr = imgTag.Split('-')[1]; if (noteList.Any(n => noteStr == NoteUtils.ToString(n))) { ChangePianoKeyChooseStatus(img, status: "Choose"); } } }
public string GetText(MarkPosition mark, MarkTextOption markTextOption) { string text = ""; switch (markTextOption) { case MarkTextOption.ShowNote_PreferFlats: text = NoteUtils.ToString(NoteAt(mark), InternalNoteStringStyle.PreferFlat); break; case MarkTextOption.ShowNote_PreferSharps: text = NoteUtils.ToString(NoteAt(mark), InternalNoteStringStyle.PreferSharp); break; case MarkTextOption.ShowNote_ShowBoth: text = NoteUtils.ToString(NoteAt(mark), InternalNoteStringStyle.ShowBoth); break; } return(text); }
private void DisplayKeyCore(string tag) { try { foreach (var children in Pianokey.Children) { Image img = children as Image; string imgTag = img.Tag as string; Note note = NoteUtils.ParseNote(imgTag.Split('-')[1]); if (imgTag == tag) { ChangePianoKeyChooseStatus(img, status: "Choose"); break; } } } catch (Exception) { MessageBox.Show("和弦显示出现未知错误!", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } }
public static async Task <ChordFinderResultSet> FindChordsAsync(IChordFinderOptions chordFinderOptions, CancellationToken cancelToken) { if (null == chordFinderOptions) { throw new ArgumentNullException(nameof(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); }
public static FullNote Parse(string s) { if (StringUtils.IsNullOrWhiteSpace(s)) { throw new ArgumentNullException(nameof(s)); } s = s.Trim(); int splitIndex = s.IndexOfAny(digits); if (splitIndex <= 0) { throw new ArgumentException(Strings.InvalidNoteArgumentExceptionMessage); } string notePortion = s.Substring(0, splitIndex); string octavePortion = s.Substring(splitIndex); Note note = NoteUtils.ParseNote(notePortion); int octave = int.Parse(octavePortion); return(new FullNote(note, octave)); }
public Diagram ToDiagram(ChordFinderStyle chordFinderStyle) { int[] marks = MarkUtils.AbsoluteToRelativeMarks(Marks, out int baseLine, Parent.ChordFinderOptions.NumFrets); InternalNote?[] notes = MarkUtils.GetInternalNotes(Marks, Parent.ChordFinderOptions.Tuning); InternalNote rootNote = NoteUtils.ToInternalNote(Parent.ChordFinderOptions.RootNote); if (chordFinderStyle.MirrorResults) { Array.Reverse(marks); Array.Reverse(notes); } int numStrings = marks.Length; int numFrets = Parent.ChordFinderOptions.NumFrets; Diagram d = new Diagram(chordFinderStyle.Style, numStrings, numFrets); if (chordFinderStyle.AddTitle) { d.Title = NoteUtils.ToString(Parent.ChordFinderOptions.RootNote) + Parent.ChordFinderOptions.ChordQuality.Abbreviation; d.Style.TitleLabelStyle = DiagramLabelStyle.ChordName; } // Add marks for (int i = 0; i < marks.Length; i++) { int @string = i + 1; int fret = Math.Max(marks[i], 0); MarkPosition mp = new MarkPosition(@string, fret); DiagramMark dm = d.NewMark(mp); // Set mark type if (marks[i] == -1) // Muted string { dm.Type = DiagramMarkType.Muted; } else if (marks[i] == 0) // Open string { dm.Type = DiagramMarkType.Open; } // Change to root if necessary if (chordFinderStyle.AddRootNotes && notes[i].HasValue && notes[i].Value == rootNote) { dm.Type = (dm.Type == DiagramMarkType.Open) ? DiagramMarkType.OpenRoot : DiagramMarkType.Root; } // Add text if (chordFinderStyle.MarkTextOption != MarkTextOption.None) { dm.Text = GetText(notes, i, chordFinderStyle.MarkTextOption); } // Add bottom marks if (chordFinderStyle.AddBottomMarks) { MarkPosition bottomPosition = new MarkPosition(@string, numFrets + 1); DiagramMark bottomMark = d.NewMark(bottomPosition); bottomMark.Type = DiagramMarkType.Bottom; bottomMark.Text = GetText(notes, i, chordFinderStyle.BottomMarkTextOption); } } // Add nut or fret label if (baseLine == 0) { d.Style.GridNutVisible = true; } else { d.Style.GridNutVisible = false; FretLabelPosition flp = new FretLabelPosition(chordFinderStyle.FretLabelSide, 1); d.NewFretLabel(flp, baseLine.ToString()); } // Add barre BarrePosition bp = MarkUtils.AutoBarrePosition(marks, chordFinderStyle.BarreTypeOption, chordFinderStyle.MirrorResults); if (null != bp) { d.NewBarre(bp); } return(d); }
public override string ToString() { return(string.Format("{0}{1}", NoteUtils.ToString(Note), Octave)); }
public Diagram ToDiagram(ScaleFinderStyle scaleFinderStyle) { int numStrings = Parent.ScaleFinderOptions.Instrument.NumStrings; int numFrets = Parent.ScaleFinderOptions.NumFrets; IEnumerable <MarkPosition> marks = MarkUtils.AbsoluteToRelativeMarks(Marks, out int baseLine, numFrets, numStrings); Diagram d = new Diagram(scaleFinderStyle.Style, numStrings, numFrets); if (scaleFinderStyle.AddTitle) { d.Title = NoteUtils.ToString(Parent.ScaleFinderOptions.RootNote) + " " + Parent.ScaleFinderOptions.Scale.Name; d.Style.TitleLabelStyle = DiagramLabelStyle.Regular; } int markPositionIndex = 0; // Add existing marks foreach (MarkPosition mark in marks) { int @string = mark.String; if (scaleFinderStyle.MirrorResults) { @string = numStrings - (@string - 1); } int fret = mark.Fret; MarkPosition mp = new MarkPosition(@string, fret); DiagramMark dm = d.NewMark(mp); // Set mark type if (scaleFinderStyle.AddRootNotes && IsRoot(markPositionIndex)) // Use markPositionIndex, to get the correct roots in mirror mode { dm.Type = DiagramMarkType.Root; } if (fret == 0) // Open string { dm.Type = (dm.Type == DiagramMarkType.Root) ? DiagramMarkType.OpenRoot : DiagramMarkType.Open; } // Add text dm.Text = GetText(markPositionIndex, scaleFinderStyle.MarkTextOption); // Use markPositionIndex, not mp, to get the correct text in mirror mode markPositionIndex++; } // Add nut or fret label if (baseLine == 0) { d.Style.GridNutVisible = true; } else { d.Style.GridNutVisible = false; FretLabelPosition flp = new FretLabelPosition(scaleFinderStyle.FretLabelSide, 1); d.NewFretLabel(flp, baseLine.ToString()); } return(d); }
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; } } } } }
private bool IsRoot(int markPositionIndex) { return(NoteAt(markPositionIndex) == NoteUtils.ToInternalNote(Parent.ScaleFinderOptions.RootNote)); }