Exemplo n.º 1
0
  @Override
  public void handleScore(Score score, ScoreContext ctx) {
    Part part = ctx.getParts().get(PartType.ARPEGGIO);
    if (part == null) {
      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;
              }
            }
          }
          if (Chance.test(85) && currentNotes != null) {
            for (Note note : currentNotes) {
              arpeggioPhrase.addNote(note);
            }
          } else {
            arpeggioPhrase.addRest(new Rest(normalizedMeasureSize));
          }
        } else if (currentMeasureSize == 0 && (currentNote.isRest() || lastMeasure)) {
          arpeggioPhrase.addRest(new Rest(normalizedMeasureSize));
        }

        currentMeasureSize += currentNote.getRhythmValue();
        if (currentMeasureSize >= normalizedMeasureSize) {
          currentMeasureSize = 0;
          measures++;
        }
      }
      part.add(arpeggioPhrase);
    }
  }