return;
}
Part mainPart = ctx.getParts().get(PartType.MAIN);
double currentMeasureSize = 0;
double normalizedMeasureSize = ctx.getNormalizedMeasureSize();
SpecialNoteType specialNoteType = null;
for (Phrase phrase : mainPart.getPhraseArray()) {
if (Chance.test(20)) { // change the special note type
if (Chance.test(60)) { // to a new value
specialNoteType = SpecialNoteType.values()[random.nextInt(SpecialNoteType.values().length)];
} else { // reset
specialNoteType = null;
}
}
Phrase arpeggioPhrase = new Phrase();
arpeggioPhrase.setTitle("Arpeggio phrase");
Scale currentScale = ((ExtendedPhrase) phrase).getScale();
// get copies of the static ones, so that we can shuffle them without affecting the original
List<Chord> scaleChords = new ArrayList<Chord>(ChordUtils.chords.get(currentScale));
Collections.shuffle(scaleChords, random);
Note[] notes = phrase.getNoteArray();
List<ToneType> firstToneTypes = new ArrayList<>();
int measures = 0;
Note[] currentNotes = null;
boolean useTwoNoteChords = Chance.test(14);
Chord chord = null;
for (int i = 0; i < notes.length; i++) {
Note currentNote = notes[i];
if (currentNote.getRhythmValue() == 0) {
continue; // rhythm value is 0 for the first notes of a (main-part) chord. So progress to the next
}
boolean lastMeasure = measures == ctx.getMeasures() - 1;
if (currentMeasureSize == 0 && !currentNote.isRest() && !lastMeasure) {
boolean preferStable = ToneResolver.needsContrastingChord(firstToneTypes, ToneGroups.UNSTABLE);
boolean preferUnstable = ToneResolver.needsContrastingChord(firstToneTypes, ToneGroups.STABLE);
// change the chord only in 1/4 of the cases
if (currentNotes == null || Chance.test(25)) {
// no alternatives for now - only 3-note chords
Chord previous = chord;
chord = ChordUtils.getChord(ctx, currentNote.getPitch(), previous, scaleChords, scaleChords, scaleChords, preferStable, preferUnstable);
if (chord != null) {
int[] pitches = chord.getPitches();
//remove the middle note in some cases (but make it possible to have three-note chords in a generally two-note phrase)
if (pitches.length == 3 && useTwoNoteChords && Chance.test(90)) {
pitches = ArrayUtils.remove(pitches, 1);
}
int count = Chance.test(90) ? (Chance.test(80) ? 4 : 2) : (Chance.test(80) ? 3 : 5);
currentNotes = new Note[count];
double length = normalizedMeasureSize / count;
for (int k = 0; k < count; k++) {
Note note = NoteFactory.createNote(pitches[random.nextInt(pitches.length)], length);
note.setDynamic(InstrumentGroups.getInstrumentSpecificDynamics(65 + random.nextInt(10), part.getInstrument()));
if (specialNoteType != null) {
note.setDuration(note.getRhythmValue() * specialNoteType.getValue());
}
currentNotes[k] = note;
}
}