double[] mutationArray = new double[population.length];
for (int i = 0; i < population.length; i++) {
mutationArray[i] = population[i].getEndTime();
}
for (int i = 0; i < population.length; i++) {
Phrase individual = population[i];
//Change the seed portion of the extension
if (modifyAll) {
initialSize = 0;
initialLength = 0.0;
}
// 1. Random Pitch Change
int n = individual.size() - initialSize;
double n2change1 = n * MUTATE_PERCENTAGE[0] / 100.0;
int n2change = 0;
if (n2change1 < 1.0) {
if (Math.random() < n2change1) {
n2change = 1;
} else {
n2change = 0;
}
} else {
n2change = (int) Math.floor(n2change1);
}
for (int j = 0; j < n2change; j++) {
int r = (int) (Math.random() * n);
mutate(individual.getNote(initialSize + r));
}
// 2. Bar sequence mutations
if (Math.random() < MUTATE_PERCENTAGE[1] / 100.0) {
int previousNoteOnBar = 0;
double beatCount = 0;
for (int j = 0; j < individual.size(); j++) {
beatCount += individual.getNote(j).getRhythmValue();
}
int[] notesOnBars = new int[(int) beatCount];
int[] barNumber = new int[(int) beatCount];
int index = 0;
beatCount = 0;
for (int j = 0; j < individual.size(); j++) {
if (beatCount / (double) beatsPerBar
== Math.floor(beatCount / (double) beatsPerBar)) {
notesOnBars[index] = j;
barNumber[index++] = (int) (beatCount * beatsPerBar);
}
beatCount += individual.getNote(j).getRhythmValue();
}
int countOfEncapsulatedBars = 0;
int[] notesBeginningEncapsulatedBars = new int[index];
if (index > 0) {
for (int j = 1; j < index; j++) {
if (barNumber[j] == barNumber[j - 1] + 1) {
notesBeginningEncapsulatedBars[
countOfEncapsulatedBars++] = notesOnBars[j - 1];
}
}
}
if (countOfEncapsulatedBars > 0) {
int r2 = 0;
while (r2 < (int) (initialLength / beatsPerBar) - 1) {
r2 = (int) (Math.random() * countOfEncapsulatedBars);
}
int r3 = (int) (Math.random() * 2 + 1);
switch (r3) {
case 1:
int transpose = 0;
if (Math.random() < 0.5) {
transpose = 2;
} else {
transpose = -2;
}
beatCount = 0;
index = notesBeginningEncapsulatedBars[r2];
while (beatCount < beatsPerBar) {
shiftPitch(individual.getNote(index), transpose);
beatCount += individual.getNote(index++).getRhythmValue();
}
break;
case 2:
default:
index = notesBeginningEncapsulatedBars[r2];
beatCount = 0;
while (beatCount < beatsPerBar) {
beatCount += individual.getNote(index++).getRhythmValue();
}
int notesInBar = index - notesBeginningEncapsulatedBars[r2];
index = notesBeginningEncapsulatedBars[r2];
if (notesInBar > 0) {
int[] tempPitches = new int[notesInBar];
double[] tempRhythmValues = new double[notesInBar];
for (int j = 0; j < notesInBar; j++) {
tempPitches[j] = individual.getNote(j + index).getPitch();
tempRhythmValues[j] = individual.getNote(j + index).getRhythmValue();
}
for (int j = 0; j < notesInBar; j++) {
individual.getNote(j + index).setPitch(tempPitches[notesInBar - j - 1]);
individual.getNote(j + index).setRhythmValue(tempRhythmValues[notesInBar - j - 1]);
}
}
}
}
}
// 3. Split and Merge
int n1 = individual.size() - initialSize;
double n2change2 = n1 * MUTATE_PERCENTAGE[2] / 100.0;
int n2change3 = 0;
if (n2change2 < 1.0) {
if (Math.random() < n2change2) {
n2change3 = 1;
} else {
n2change3 = 0;
}
} else {
n2change3 = (int) Math.floor(n2change2);
}
Vector vector = (Vector) individual.getNoteList().clone();
for (int j = 0; j < n2change3; j++) {
int r1 = (int) (Math.random() * (n1 - 1));
Note note5 = (Note) vector.elementAt(initialSize + r1);
int pitch5 = note5.getPitch();
double rhythmValue5 = note5.getRhythmValue();
if (rhythmValue5 >= 1.0 && rhythmValue5 % 1.0 == 0 &&
rhythmValue5 * 2.0 == Math.ceil(rhythmValue5 * 2.0)) {
vector.removeElementAt(initialSize + r1);
vector.insertElementAt(new Note(pitch5,
rhythmValue5 / 2.0),
initialSize + r1
);
vector.insertElementAt(new Note(pitch5,
rhythmValue5 / 2.0),
initialSize + r1
);
n1++;
} else {
double rhythmValue6 = rhythmValue5 + ((Note)
vector.elementAt(initialSize + r1 + 1))
.getRhythmValue();
if (rhythmValue6 <= 2.0) {
vector.removeElementAt(initialSize + r1);
vector.removeElementAt(initialSize + r1);
vector.insertElementAt(new Note(pitch5,
rhythmValue6),
initialSize + r1
);
n1--;
}
}
}
individual.addNoteList(vector, false);
// 4. Step interpolation
vector = (Vector) individual.getNoteList().clone();
int currentPitch;
double currentRV;
int previousPitch = (int) Note.REST;
double previousRV = 0;
int index1 = initialSize;
while (index1 < vector.size() && previousPitch == Note.REST) {
previousPitch = ((Note) vector.elementAt(index1)).getPitch();
previousRV = ((Note) vector.elementAt(index1)).getRhythmValue();
index1++;
}
int k = index1;
while (k < vector.size()) {
currentPitch = ((Note) vector.elementAt(k)).getPitch();
currentRV = ((Note) vector.elementAt(k)).getRhythmValue();
if (currentPitch != Note.REST) {
int interval = currentPitch - previousPitch;
if ((Math.abs(interval) == 4 || Math.abs(interval) == 3)
&& Math.random() < (MUTATE_PERCENTAGE[3] / 100.0)) {
int scalePitch = 0;
if (interval > 0) {
scalePitch = currentPitch - 1;
if (!isScale(scalePitch)) {
scalePitch--;
}
} else {
scalePitch = currentPitch + 1;
if (!isScale(scalePitch)) {
scalePitch++;
}
}
if (currentRV > previousRV) {
if (currentRV >= 0.5
&& (int) Math.ceil(currentRV * 2)
== (int) (currentRV * 2)) {
vector.removeElementAt(k);
vector.insertElementAt(new Note(currentPitch,
currentRV / 2.0), k);
vector.insertElementAt(new Note(scalePitch,
currentRV / 2.0), k);
k++;
}
} else {
if (previousRV >= 0.5
&& (int) Math.ceil(previousRV * 2)
== (int) (previousRV * 2)) {
vector.removeElementAt(k - 1);
vector.insertElementAt(new Note(scalePitch,
previousRV / 2.0), k - 1);
vector.insertElementAt(new Note(previousPitch,
previousRV / 2.0), k - 1);
k++;
}
}
}
previousPitch = currentPitch;
previousRV = currentRV;
}
k++;
}
individual.addNoteList(vector, false);
// 5. Tonal Pauses (make well positioned primary pitches longer
// by adding the value of two notes together)
individual.addNoteList(applyTonalPausesMutation(individual,
initialLength,
initialSize,
beatsPerBar),
false
);
// 6. Pitch Clean Up
double cumulativeRV = 0;
for (int j = initialSize; j < individual.size(); j++) {
int pitch = individual.getNote(j).getPitch();
double rv = individual.getNote(j).getRhythmValue();
if (pitch != Note.REST) {
if (!isScale(pitch)) {
if ((int) Math.ceil(cumulativeRV / 2.0)
== (int) (cumulativeRV / 2.0)) {
if (Math.random() < rv) {
if (Math.random() < 0.5) {
individual.getNote(j).setPitch(pitch + 1);
} else {
individual.getNote(j).setPitch(pitch - 1);
}
}
} else {
if (Math.random() < (rv / 2.0)) {
if (Math.random() < 0.5) {
individual.getNote(j).setPitch(pitch + 1);
} else {
individual.getNote(j).setPitch(pitch - 1);
}
}
}
}
}