/// <summary> /// Swaps the positions of two chord notes in the given bar, /// or in a randomly selected bar if <paramref name="barIndex"/> is null. /// <para>A random chord in the selected bar is selected, and two randomly /// selected notes which are played under this chord's time span are swapped /// by their positions.</para> /// </summary> /// <param name="melody"> The candidate melody to operate on.</param> /// <param name="barIndex"> Index of the bar to do the swap in. If no bar index supplied, then a random bar would be selected. </param> private protected virtual void SwapTwoNotesMutation(MelodyCandidate melody, int?barIndex = null) { // initialization INote note1, note2; IList <int> noteIndices; Random random = new Random(); int note1Index, note2Index, randomIndex1, randomIndex2, chordIndex; // if no specific bar has been requested then set it randomly int selectedBarIndex = barIndex ?? random.Next(melody.Bars.Count); IBar bar = melody.Bars[selectedBarIndex]; chordIndex = random.Next(bar.Chords.Count); bar.GetOverlappingNotesForChord(chordIndex, out noteIndices); // assure selected chord in bar contains at least two notes if (noteIndices.Count < 2) { return; } // select two random notes from withing the selected chord notes randomIndex1 = random.Next(1, noteIndices.Count); randomIndex2 = random.Next(0, randomIndex1); note1Index = noteIndices[randomIndex1]; note2Index = noteIndices[randomIndex2]; note1 = bar.Notes[note1Index]; note2 = bar.Notes[note2Index]; // swap the notes positions in the bar bar.Notes.RemoveAt(note1Index); bar.Notes.Insert(note1Index, note2); bar.Notes.RemoveAt(note2Index); bar.Notes.Insert(note2Index, note1); }