Esempio n. 1
0
  /**
   * Create and return a regular SongMeasure from the current position of the iterators.
   *
   * @param itM an iterator over the measures collection. It must be pointing so that itM.next()
   *     returns the current measure
   * @param itMTP an iterator over the measure-track pairs collection. It must be pointing so that
   *     itMTP.next() returns the first track of the current measure
   * @param tracks The tracks definitions
   * @return a new filled-out SongMeasure
   * @throws GP4AdaptorException
   */
  private static SongMeasure makeSongMeasure(
      Song song,
      ListIterator<GPMeasure> itM,
      ListIterator<GPMeasureTrackPair> itMTP,
      List<GPTrack> tracks) {
    GPMeasure measure = itM.next();

    int ending = measure.getNumberOfAlternateEnding();
    if (ending > 0) {
      logger.warning("Measure " + measure.getNumber() + " is alternate ending " + ending);
    }

    // TODO getNumber
    // TODO getNumberOfAlternateEnding
    // TODO getNumberOfRepetitions
    // TODO getTonality
    int numerator = measure.getNumerator();
    int denominator = measure.getDenominator();

    int measureLength = PPQ_HIGH_RESOLUTION * 4 * numerator / denominator;
    // OLD MGG logger.finer("Measure "+measure.getNumber()+",
    // "+numerator+"/"+denominator+", length " + measureLength);
    TimeSignature ts = new TimeSignature(numerator, denominator);
    SongMeasure sm = new SongMeasureImpl(measure.getNumber(), measureLength / PPQ_SCALE_FACTOR, ts);

    for (int trackIndex = 1; trackIndex <= tracks.size(); trackIndex++) {
      GPTrack track = tracks.get(trackIndex - 1);
      // TODO is12StringedGuitarTrack
      // TODO isBanjoTrack
      // TODO getter/setter for isDrumsTrack

      // TODO getChannelEffects
      // TODO getColor
      // TODO getName
      // TODO getNumberOfFrets
      // TODO getPort
      int capo = track.getCapo();
      int strings = track.getNumberOfStrings();
      int stringTuning[] = new int[strings];
      for (int i = 0; i < strings; i++) stringTuning[i] = track.getStringsTuning(i);

      // OLD  MGG logger.finer("Measure " + measure.getNumber() + " Track "+
      // trackIndex);
      GPMeasureTrackPair mtp = itMTP.next();
      SongMeasureTrack smt = new SongMeasureTrackImpl(song.getTrack(trackIndex));
      sm.addTrack(smt);

      List<GPBeat> beats = mtp.getBeats();
      int beatOffset = 0;
      for (Iterator<GPBeat> itBeat = beats.iterator(); itBeat.hasNext(); ) {
        GPBeat beat = itBeat.next();

        // TODO effects

        GPDuration duration = beat.getDuration();
        // TODO add getter and setter for GP4Beat.dottedNotes
        boolean dotted = beat.dottedNotes;
        int ntuplet = beat.getNTuplet();

        int beatDuration = calculateDuration(duration, dotted, ntuplet);

        if (beat.isNoteBeat()) {
          List<GPNote> notes = beat.getNotes();
          List<Integer> stringsPlayed = new LinkedList<Integer>();
          // TODO suggest an easier way of returning the played
          // string list
          for (int i = 6; i >= 0; i--) {
            if (beat.isStringPlayed(i)) {
              stringsPlayed.add(new Integer(i));
            }
          }

          Iterator<GPNote> itNotes = notes.iterator();
          Iterator<Integer> itStrings = stringsPlayed.iterator();

          while (itNotes.hasNext()) {

            //						OLD MGG Integer stringObject = (Integer) itStrings.next();
            // see TODO.TXT or NEWFEATURES.TXT
            //						this lines were added to fix the GTP playing error - BEGIN
            Integer stringObject;

            if (!itStrings.hasNext()) {
              // this error appears to happen when its *.GTP file
              // TODO show a friendly error
              break;
            }
            /*ELSE*/
            //						END

            stringObject = itStrings.next();
            // Note that the tuning array has the highest string
            // at index 0
            // but the track has the highest string at index 6.

            // TODO find out if this is correct. What about a
            // 4-string bass?
            int stringID = 6 - stringObject.intValue();

            GPNote note = itNotes.next();
            int noteDuration = beatDuration;

            // see if this note has time independent settings on
            // it
            // TODO getter/setter for GP4Note.duration
            GPDuration tiDuration = note.duration;
            if (tiDuration != null) {
              // TODO getter/setter for GP4Note.isDotted
              boolean tiDotted = note.isDotted;
              int tiTriplet = note.getNTuplet();
              noteDuration = calculateDuration(tiDuration, tiDotted, tiTriplet);
            }

            // TODO isDeadNote
            // TODO isGhostNote
            // TODO isTieNote
            // TODO effects

            // TODO Note effects are a little bit difficult.
            // Remember these are guitar effects
            // so we effectively need a 'virtual track' for
            // every string, so when we playback we
            // can assign a unique MIDI channel to that track
            // and so we can apply a channel-wide
            // controller to that effect (such as pitch bend).
            // Even the simple effect (let ring)
            // can't be done easily right now because we can't
            // tell when to really kill the note.
            // Of course if we don't need an effect, we should
            // try to use as few MIDI channels as
            // we can!

            int virtualTrackID = stringID;
            SongVirtualTrack svt = smt.getVirtualTrack(virtualTrackID);
            int noteStart = beatOffset / PPQ_SCALE_FACTOR;
            int noteEnd = (beatOffset + noteDuration) / PPQ_SCALE_FACTOR;

            // FIXME cover the tie note case by grabbing the
            // last fret
            if (note.isTieNote()) {
              svt.addEvent(new SongEventImpl(noteStart, new SongTieMessage(noteEnd - noteStart)));
            } else {
              int baseFret = note.getFretNumber(); // OLD
              // .getNumberOfFret();
              int fret = baseFret + capo;
              GPDynamic dynamic = note.getDynamic();
              int velocity = DynamicsMap.velocityOf(dynamic);
              int pitch = stringTuning[stringID] + fret;
              svt.addEvent(
                  new SongEventImpl(
                      noteStart,
                      new SongNoteOnMessage(pitch, velocity, noteEnd - noteStart, baseFret)));
            }
          }
        }
        beatOffset += beatDuration;
      }
      if (beatOffset != measureLength) {
        // an underfull one isn't fatal, but an overfull one is
        String reason =
            "Measure: "
                + measure.getNumber()
                + " track: "
                + trackIndex
                + " length mismatch, expected "
                + measureLength
                + ", got "
                + beatOffset;

        if (beatOffset > measureLength) {
          logger.fine(reason);
          System.err.println(reason);
        } else {
          logger.fine(reason);
        }
      }
    }
    return sm;
  }