/**
   * Returns a copy of the Score.
   *
   * @return Score a copy of the Score
   */
  public Score copy() {
    // Trace.log(2, "copying Score of size " + size());
    Score newScore = new Score(title, tempo);
    newScore.setMetre(metre[0], metre[1]);
    PartList newPartList = new PartList(partList.size());
    ListIterator<MelodyPart> i = partList.listIterator();

    while (i.hasNext()) newPartList.add(i.next().copy());

    newScore.partList = newPartList;
    newScore.chordProg = chordProg.copy();

    newScore.setChordInstrument(getChordInstrument());
    newScore.setBassInstrument(getBassInstrument());

    newScore.setBassMuted(getBassMuted());
    newScore.setDrumMuted(getDrumMuted());
    newScore.setChordMuted(getChordMuted());
    newScore.setMelodyMuted(getMelodyMuted());
    newScore.setMasterVolumeMuted(getMasterVolumeMuted());

    newScore.setBassVolume(getBassVolume());
    newScore.setDrumVolume(getDrumVolume());
    newScore.setChordVolume(getChordVolume());
    newScore.setMelodyVolume(getMelodyVolume());
    newScore.setMasterVolume(getMasterVolume());

    newScore.countInProg = countInProg == null ? null : countInProg.copy();

    return newScore;
  }
  public void setChordInstrument(int instrument) {
    // System.out.println("score setChordInstrument to " + instrument);

    chordProg.setChordInstrument(instrument);
    Style style = chordProg.getStyle();
    if (style != null) {
      style.setChordInstrument(instrument, "Score");
    }
  }
 /** Calls makeSwing on each individual Part. */
 public void makeSwing() {
   ListIterator<MelodyPart> i = partList.listIterator();
   while (i.hasNext()) {
     MelodyPart m = i.next();
     Style style = chordProg.getStyle();
     if (style != null) {
       m.setSwing(style.getSwing());
     }
     m.makeSwing(chordProg.getSectionInfo());
   }
 }
  public void checkLength() {
    int maxLength = length;

    if (chordProg.size() > maxLength) maxLength = chordProg.size();

    ListIterator<MelodyPart> i = partList.listIterator();
    while (i.hasNext()) {
      MelodyPart part = i.next();
      if (part.size() > maxLength) maxLength = part.size();
    }

    setLength(maxLength);
  }
 public boolean[] getCurrentEnharmonics(int index) {
   Polylist tones = new Polylist();
   Chord currentChord = chordProg.getCurrentChord(index);
   if (currentChord != null && !currentChord.getName().equals(NOCHORD)) {
     try {
       tones = chordProg.getCurrentChord(index).getPriority();
     } catch (NullPointerException e) {
       tones = new Polylist();
       Trace.log(2, "Null pointer exception should be fixed in Score.getCurrentEnharmonics.");
       Trace.log(2, e.getStackTrace().toString());
     }
   }
   return getCurrentEnharmonics(index, tones);
 }
  /**
   * Creates and returns a MIDI sequence from the Score. Calls Part.render on each Part and (for
   * now) creates a new channel for each Part. This means that you can only have 16 Parts, which
   * should be changed in the future.
   *
   * @param ppqn the resolution for the Sequence
   * @return Sequence the MIDI render
   */
  public Sequence render(short ppqn, int transposition, boolean useDrums, int endLimitIndex)
      throws InvalidMidiDataException {
    // to trace sequencing
    // System.out.println("Score: render, start 0, endLimitIndex = " + endLimitIndex);
    MidiSequence seq = new MidiSequence(ppqn);

    long time = 0;

    if (countInProg != null) {
      // Handle count-in render

      int len = getCountInOffset();
      if (endLimitIndex != ENDSCORE) {
        endLimitIndex += len;
      }

      time = countInProg.render(seq, time, seq.getChordTrack(), 0, true, endLimitIndex);
    }

    // System.out.println("time = " + time);

    ListIterator<MelodyPart> i = partList.listIterator();
    while (i.hasNext() && Style.limitNotReached(time, endLimitIndex)) {
      // render the chord progression in parallel with each melody chorus

      long melTime =
          i.next()
              .render(
                  seq,
                  ImproVisor.getMelodyChannel(),
                  time,
                  seq.getMelodyTrack(),
                  transposition,
                  endLimitIndex);

      long chTime =
          chordProg.render(seq, time, seq.getChordTrack(), transposition, useDrums, endLimitIndex);
      time = Math.max(melTime, chTime);
    }

    // System.out.println("seq = " + seq);

    // Find the longest track, and put a Stop event at the end of it
    MidiSynth.endSequence(seq.getSequence());
    // Trace.log(0, "done rendering, tickLength = " + seq.getSequence().getTickLength());

    // System.out.println("countIn size = " + getCountInOffset());
    return seq.getSequence();
  }
 /**
  * Returns the Note at the specified index across all parts
  *
  * @param index the index of the Note to get
  * @return the Note at the specified index
  */
 public Note getNote(int index) {
   int sizeOfPart = chordProg.size();
   int partNum = index / sizeOfPart;
   int indexWithinPart = index % sizeOfPart;
   MelodyPart part = partList.get(partNum);
   return part.getNote(indexWithinPart);
 }
 public void setBassInstrument(int instrument) {
   bassInstrument = instrument;
   Style style = chordProg.getStyle();
   if (style != null) {
     style.setBassInstrument(instrument);
   }
 }
 /**
  * Sets the key signature of the Score
  *
  * @param keySig the key signature to set the Score to
  */
 public void setKeySignature(int keySig) {
   Trace.log(2, "setting key signature of score to " + keySig);
   this.keySig = keySig;
   chordProg.setKeySignature(keySig);
   ListIterator<MelodyPart> i = partList.listIterator();
   while (i.hasNext()) {
     i.next().setKeySignature(keySig);
   }
 }
  /**
   * Sets the metre of the Score metre is now represented in most places as a 2-elt array, where the
   * first element is the top of the time signature, and the second element is the bottom.
   */
  public void setMetre(int top, int bottom) {
    metre[0] = top;
    metre[1] = bottom;
    chordProg.setMetre(top, bottom);
    ListIterator<MelodyPart> i = partList.listIterator();

    while (i.hasNext()) {
      i.next().setMetre(top, bottom);
    }
  }
  /**
   * Creates and returns a String representation of the Score.
   *
   * @return String the Score as a String
   */
  public String toString() {
    String scoreData = "Score: " + '\n';

    scoreData += "ChordProg: " + '\n' + chordProg.toString() + '\n';

    ListIterator<MelodyPart> i = partList.listIterator();
    while (i.hasNext()) {
      scoreData += "Part " + i.nextIndex() + ":" + '\n' + i.next().toString() + '\n';
    }
    return scoreData;
  }
  /**
   * Writes the Score to the BufferedWriter passed to this method in Leadsheet notation.
   *
   * @param out a BufferedWriter to save the score onto
   */
  public void saveLeadsheet(BufferedWriter out) throws IOException {
    Chord.initSaveToLeadsheet();
    chordProg.saveLeadsheet(out, "chords");
    out.newLine();

    ListIterator<MelodyPart> i = partList.listIterator();
    while (i.hasNext()) {
      ((MelodyPart) i.next()).saveLeadsheet(out, "melody");
      out.newLine();
    }
  }
  public int getActiveBarsInChorus() {
    int activeBars = chordProg.getActiveBars();
    ListIterator<MelodyPart> i = partList.listIterator();

    while (i.hasNext()) {
      int barsInChorus = i.next().getActiveBars();
      if (barsInChorus > activeBars) {
        activeBars = barsInChorus;
      }
    }
    // System.out.println("active bars = " + activeBars);

    return activeBars; // TEMP!
  }
 public void setLength(int newLength) {
   if (newLength == length) {
     return; // avoid unnecessary setting
   }
   Trace.log(3, "setting score length to " + newLength);
   length = newLength;
   if (chordProg != null) {
     chordProg.setSize(length);
   }
   Iterator<MelodyPart> i = partList.listIterator();
   while (i.hasNext()) {
     i.next().setSize(length);
   }
 }
 /**
  * Adds the specified chord progression to the Score.
  *
  * @param chordProg ChordPart to set as chordProg
  */
 public void setChordProg(ChordPart chordProg) {
   setLength(chordProg.size());
   this.chordProg = chordProg;
 }
 public int getCountInOffset() {
   return countInProg == null ? 0 : countInProg.size();
 }
 /**
  * Populate a RoadMapFrame with this Score
  *
  * @param roadmap
  */
 public void toRoadMapFrame(RoadMapFrame roadmap) {
   roadmap.setMusicalInfo(this);
   chordProg.toRoadMapFrame(roadmap);
 }
  /**
   * Creates and returns a MIDI render out of the Score. Calls Part.render on each Part and (for
   * now) creates a new channel for each Part. This means that you can only have 16 Parts, which
   * should be changed in the future.
   *
   * @param ppqn the resolution for the Sequence
   * @return Sequence the MIDI render
   */
  public Sequence render(short ppqn, int transposition) throws InvalidMidiDataException {

    int endIndex = chordProg.size(); // correct?

    return render(ppqn, transposition, true, endIndex);
  }
 /** Returns the style of this score */
 public Style getStyle() {
   return chordProg.getStyle();
 }
 public Score(ChordPart chordPart) {
   this();
   addPart();
   setLength(chordPart.size());
   chordProg = chordPart;
 }
 public void addChord(Chord chord) {
   chordProg.addChord(chord);
 }
 public int getBarsPerChorus() {
   return chordProg.getBars();
 }
 /** Add chords in the current selection in RoadMapFrame to this Score. */
 public void fromRoadMapFrame(RoadMapFrame roadmap) {
   chordProg.addFromRoadMapFrame(roadmap);
   setLength(chordProg.size());
 }
 public RoadMap getRoadMap() {
   return chordProg.getRoadMap();
 }
 public void setSectionInfo(SectionInfo si) {
   chordProg.setSectionInfo(si);
 }
 /** Set the style of this score, but only if there is no SectionInfo already established. */
 public void setStyle(Style style) {
   if (chordProg.getSectionInfo() == null || chordProg.getSectionInfo().hasOneSection()) {
     chordProg.setStyle(style);
   }
 }
 public int getChordInstrument() {
   return chordProg.getInstrument();
 }
  // Determine whether '#' or 'b' is visible in the lick triage utility, based on
  // whatever the current chord is.
  public boolean[] getCurrentEnharmonics(int index, Polylist tones) {
    boolean[] enh = new boolean[5];

    // We set the default visible accidental to '#' if we're in a sharp key; otherwise, set
    // the default to 'b'.
    if (keySig >= 0) {
      enh[CSHARP] = true;
      enh[DSHARP] = true;
      enh[FSHARP] = true;
      enh[GSHARP] = true;
      enh[ASHARP] = true;
    } else {
      enh[CSHARP] = false;
      enh[DSHARP] = false;
      enh[FSHARP] = false;
      enh[GSHARP] = false;
      enh[ASHARP] = false;
    }

    // Get the current chord if there is one.
    Chord current = chordProg.getCurrentChord(index);

    if (current == null || current.getName().equals(NOCHORD)) {
      return enh;
    }

    if (tones == null || tones.isEmpty()) {
      return enh;
    }

    // Look at all the chord tones in the list and determine whether we need to change
    // any accidental labels from '#' to 'b'
    while (tones.nonEmpty()) {
      NoteSymbol first = (NoteSymbol) tones.first();
      tones = tones.rest();

      if (first.getPitchString().length() > 1) {
        switch (first.getPitchString().charAt(0)) {
          case 'c':
            if (first.getPitchString().charAt(1) == '#') {
              enh[CSHARP] = true;
            }
            break;
          case 'd':
            if (first.getPitchString().charAt(1) == 'b') {
              enh[CSHARP] = false;
            } else if (first.getPitchString().charAt(1) == '#') {
              enh[DSHARP] = true;
            }
            break;
          case 'e':
            if (first.getPitchString().charAt(1) == 'b') {
              enh[DSHARP] = false;
            }
            break;
          case 'f':
            if (first.getPitchString().charAt(1) == '#') {
              enh[FSHARP] = true;
            }
          case 'g':
            if (first.getPitchString().charAt(1) == 'b') {
              enh[FSHARP] = false;
            } else if (first.getPitchString().charAt(1) == '#') {
              enh[GSHARP] = true;
            }
            break;
          case 'a':
            if (first.getPitchString().charAt(1) == 'b') {
              enh[GSHARP] = false;
            } else if (first.getPitchString().charAt(1) == '#') {
              enh[ASHARP] = true;
            }
            break;
          case 'b':
            if (first.getPitchString().charAt(1) == 'b') {
              enh[ASHARP] = false;
            }
            break;
        }
      }
    }
    return enh;
  }
 public void setAllStyles(ArrayList<Block> blocks) {
   chordProg.setAllStyles(blocks);
 }