/// <summary> /// Reverses the order of a sequence of notes for a randomly selected /// chord in the given bar, or in a randomly selected bar if <paramref name="barIndex"/> is null. /// <para> The revese operation is made in place locally to the selected chord. /// The chord notes are determined by the logic in /// <see cref="Bar.GetOverlappingNotesForChord(IChord, out IList{int})"/>.</para> /// </summary> /// <param name="melody"> The candidate melody to operate on.</param> /// <param name="barIndex"> Index of the bar to do the reverse in. If no bar index supplied, then a random bar would be selected. </param> private protected virtual void ReverseChordNotesMutation(MelodyCandidate melody, int?barIndex = null) { // initialize random generator Random randomizer = new Random(); // if no specific bar has been requested then set it randomly int selectedBarIndex = barIndex ?? randomizer.Next(melody.Bars.Count); IBar selectedBar = melody.Bars[selectedBarIndex]; // select a random chord from within the selected bar int randomChordIndex = randomizer.Next(selectedBar.Chords.Count); IChord selectedChord = selectedBar.Chords[randomChordIndex]; // create a single chord element sequence IChord[] chordsToReverse = new[] { selectedChord }; // delegate reverse operation to superclass PermutateNotes(selectedBar, chordsToReverse, Permutation.Reversed); }
private IChord ModifyChord(IChord chord, params string[] modifications) { bool prevArgModifiedChord = false; int index = 0; do { var argument = modifications[index].ToLowerInvariant(); if (argument.StartsWith("sus")) { chord.Suspend(Int32.Parse(argument.Substring(3))); prevArgModifiedChord = true; } if (argument.StartsWith("add")) { chord.Add(Int32.Parse(argument.Substring(3))); prevArgModifiedChord = true; } index++; } while (prevArgModifiedChord && index < modifications.Length); return(chord); }
public bool Equals(IChord other) => ChordDefinition.Equals(other.ChordDefinition) && Key.Equals(other.Key);
public void UpdateChord(IChord chord) { _chordsRegistry.Update(chord, Owner.FromPrincipal(User)); }
public IUniqueItem AddChord(IChord chord) { return(_chordsRegistry.Add(chord, Owner.FromPrincipal(User))); }
private (List <IStringInstrumentNotePosition> notePositions, bool isValidChord) IsChord(IChord chord, IList <IStringInstrumentNotePosition> notesPerString) { var notePositions = new List <IStringInstrumentNotePosition>(); foreach (var nps in notesPerString) { if (nps == null) { notePositions.Clear(); } else { notePositions.Add(nps); } } var isValid = chord.Notes.All(chordNote => notePositions.Any(t => t.Note.Equals(chordNote))); return(notePositions, isValid); }
private IStringInstrumentChord GetStringInstrumentChord(IStringInstrument stringInstrument, IChord chord) { var possibilities = new List <IStringInstrumentChordPossibility>(); var ret = new StringInstrumentChord(); ret.Chord = chord; // semi tone index. for (var sti = 0; sti < stringInstrument.SemiToneCount; sti++) { // string note index. var stringNotePositions = stringInstrument.Strings .Select(currentString => { var notePositions = stringNotePositionForString(currentString, chord, sti, _typicalFingerSemiToneStretch); return(notePositions); }) .ToList(); stringNotePositions.ForEach(t => t.Insert(0, null)); var allCombinations = Combos(stringNotePositions); var combinationCases = allCombinations .Select(t => IsChord(chord, t)) .ToList(); var tempPossibilities = combinationCases .Where(t => t.isValidChord) .Select(t => new StringInstrumentChordPossibility { NotePositions = t.notePositions }); possibilities.AddRange(tempPossibilities); } ret.ChordPossibilities = possibilities .Aggregate(new List <IStringInstrumentChordPossibility>(), (prev, current) => { if (!prev.Any(t => t.Equals(current))) { prev.Add(current); } return(prev); }); return(ret); }
/// <summary> /// Returns notes that sound "good" under the given chord and pitch range restriction. /// </summary> /// <param name="chord"> he requested chrod to map the notes against. </param> /// <param name="mappingSource"> The mapping source - either scale notes or the chord's arpeggio notes. </param> /// <param name="minPitch"> Lower bound pitch range constraint for the mapped notes. </param> /// <param name="maxPitch"> Upper bound pitch range constraint for the mapped notes. </param> /// <returns> Notes that sound "good" under the given chord, mapping source, and pitch range restriction. </returns> internal static IEnumerable <NotePitch> GetNotes(IChord chord, ChordNoteMappingSource mappingSource, NotePitch minPitch, NotePitch maxPitch) { // build the scale (sequence of intervals from the chord's root note) var rootNote = ConvertToExternalNoteName(chord.ChordRoot); Scale scale = null; switch (chord.ChordType) { case ChordType.Diminished: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Three, Interval.Six }, rootNote); } else // diminished arppeigo with added 9th { scale = new Scale(new Interval[] { Interval.One, Interval.Two, Interval.Three, Interval.Six }, rootNote); } break; case ChordType.Dominant7: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Three, Interval.Two }, rootNote); } else // mixolydian scale with omitted 4th { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Three, Interval.Two, Interval.One, Interval.Two }, rootNote); } break; case ChordType.Dominant7b9: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Three, Interval.Three, Interval.FromHalfSteps(-1) }, rootNote); } else // harmonic minor v scale with 6th omitted { scale = new Scale(new Interval[] { Interval.One, Interval.Three, Interval.One, Interval.Two, Interval.Three, Interval.Two }, rootNote); } break; case ChordType.Dominant7Suspended4: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Five, Interval.Two, Interval.Three, Interval.Two }, rootNote); } else // mixolydian scale { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.One, Interval.Two }, rootNote); } break; case ChordType.Dominant7Augmented5: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Four, Interval.Two, Interval.Two }, rootNote); } else // whole tone scale { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Two, Interval.Two, Interval.Two, Interval.Two }, rootNote); } break; case ChordType.Dominant7Sharped9: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Three, Interval.Four, Interval.FromHalfSteps(-3) }, rootNote); } else // mixolydian #2 scale with omitted 4th { scale = new Scale(new Interval[] { Interval.Three, Interval.One, Interval.Three, Interval.Two, Interval.One, Interval.Two }, rootNote); } break; case ChordType.HalfDiminished: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Three, Interval.Four, Interval.Two }, rootNote); } else // locrian mode scale with ommited 2nd { scale = new Scale(new Interval[] { Interval.Three, Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.Two }, rootNote); } break; case ChordType.Major: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Five }, rootNote); } else // dorian major scale with omitted 4th and 7th { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Three, Interval.Two, Interval.Three }, rootNote); } break; case ChordType.Major7: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Four, Interval.One }, rootNote); } else // dorian major scale with omitted 4th { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Three, Interval.Two, Interval.Two, Interval.One }, rootNote); } break; case ChordType.MajorAugmented5: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Four, Interval.Four }, rootNote); } else // lydian augmented scale { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Two, Interval.Two, Interval.One, Interval.Two, Interval.One }, rootNote); } break; case ChordType.MajorSuspended4: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Five, Interval.Two, Interval.Five }, rootNote); } else // mixolydian scale { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.One, Interval.Two }, rootNote); } break; case ChordType.Minor: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Four, Interval.Five }, rootNote); } else // aeolian minor scale with omitted 2nd and 6th { scale = new Scale(new Interval[] { Interval.Three, Interval.Two, Interval.Two, Interval.Three, Interval.Two }, rootNote); } break; case ChordType.Minor6: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Four, Interval.Two, Interval.Three }, rootNote); } else // dorian minor scale with omitted 7th { scale = new Scale(new Interval[] { Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.Two, Interval.Three }, rootNote); } break; case ChordType.Minor7: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Four, Interval.Three, Interval.Two }, rootNote); } else // aeolian minor scale with omitted 6th { scale = new Scale(new Interval[] { Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.Three, Interval.Two }, rootNote); } break; case ChordType.MinorMajor7: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Three, Interval.Four, Interval.Four, Interval.One }, rootNote); } else // harmonic minor scale { scale = new Scale(new Interval[] { Interval.Two, Interval.One, Interval.Two, Interval.Two, Interval.One, Interval.Three, Interval.One }, rootNote); } break; case ChordType.Major13: if (mappingSource == ChordNoteMappingSource.Chord) { scale = new Scale(new Interval[] { Interval.Four, Interval.Three, Interval.Two, Interval.Three }, rootNote); } else // dorian major scale with omitted 4th and 7th { scale = new Scale(new Interval[] { Interval.Two, Interval.Two, Interval.Three, Interval.Two, Interval.Three }, rootNote); } break; default: break; } // get actual notes and filter out results according to range constraints var result = from note in scale.GetNotes() where (int)note.NoteNumber >= (byte)minPitch && (int)note.NoteNumber <= (byte) maxPitch select(NotePitch)(int) note.NoteNumber; return(result); }
public IUniqueItem Add(IChord item, IUser owner) { throw new NotImplementedException(); }
public void Update(IChord item, IUser owner) { throw new NotImplementedException(); }
public IReadOnlyList <IChordTarget> GetItemsByChord(IChord chord) { throw new ArgumentException("Unable to find requested items: fake registry is always empty!", nameof(chord)); }