예제 #1
0
 /**
  * saves settings object to a file
  *
  * @param settings settings to save
  * @param file file to write
  */
 public static void settingsToFile(AutomaticVoicingSettings settings, File file) {
   try {
     PrintWriter writer = new PrintWriter(file, "UTF-8");
     writer.println(
         "(comments \"Auto Voicing Preset File. Please check parameter limits (in Impro-visor) before modifying.\")");
     writer.println("(LH-lower-limit " + settings.getLeftHandLowerLimit() + ")");
     writer.println("(RH-lower-limit " + settings.getRightHandLowerLimit() + ")");
     writer.println("(LH-upper-limit " + settings.getLeftHandUpperLimit() + ")");
     writer.println("(RH-upper-limit " + settings.getRightHandUpperLimit() + ")");
     writer.println("(LH-spread " + settings.getLeftHandSpread() + ")");
     writer.println("(RH-spread " + settings.getRightHandSpread() + ")");
     writer.println("(LH-min-notes " + settings.getLeftHandMinNotes() + ")");
     writer.println("(LH-max-notes " + settings.getLeftHandMaxNotes() + ")");
     writer.println("(RH-min-notes " + settings.getRightHandMinNotes() + ")");
     writer.println("(RH-max-notes " + settings.getRightHandMaxNotes() + ")");
     // voice leading controls
     writer.println("(pref-motion " + settings.getPreferredMotion() + ")");
     writer.println("(pref-motion-range " + settings.getPreferredMotionRange() + ")");
     writer.println(
         "(prev-voicing-multiplier "
             + (int) (settings.getPreviousVoicingMultiplier() * 10)
             + ")"); // multiplier for notes used in previous voicing
     writer.println(
         "(half-step-multiplier " + (int) (settings.getHalfStepAwayMultiplier() * 10) + ")");
     writer.println(
         "(full-step-multiplier " + (int) (settings.getFullStepAwayMultiplier() * 10) + ")");
     // voicing control
     writer.println(
         "(LH-color-priority "
             + settings.getLeftColorPriority()
             + ")"); // priority of any color note
     writer.println(
         "(RH-color-priority "
             + settings.getRightColorPriority()
             + ")"); // priority of any color note
     writer.println(
         "(max-priority "
             + settings.getMaxPriority()
             + ")"); // max priority a note in the priority array can have
     writer.println(
         "(priority-multiplier "
             + (int) (+settings.getPriorityMultiplier() * 10)
             + ")"); // should be between 0 and 1, multiply this by the index in priority array,
     // subtract result from max priority to get note priority
     writer.println("(repeat-multiplier " + (int) (settings.getRepeatMultiplier() * 10) + ")");
     writer.println("(half-step-reducer " + (int) (settings.getHalfStepReducer() * 10) + ")");
     writer.println("(full-step-reducer " + (int) (settings.getFullStepReducer() * 10) + ")");
     writer.println("(left-min-interval " + (int) (settings.getLeftMinInterval()) + ")");
     writer.println("(right-min-interval " + (int) (settings.getRightMinInterval()) + ")");
     if (settings.getInvertM9()) writer.println("(invert-9th on)");
     else writer.println("(invert-9th off)");
     if (settings.getVoiceAll()) writer.println("(voice-all on)");
     else writer.println("(voice-all off)");
     if (settings.getRootless()) writer.println("(rootless on)");
     else writer.println("(rootless off)");
     writer.close();
   } catch (Exception f) {
     ErrorLog.log(ErrorLog.SEVERE, "Error writing Voicing File: " + file.getName());
   }
 }
예제 #2
0
  /**
   * Creates a Part with the specified number of slots and a rest in the first slot.
   *
   * @param size the number of slots to create in the Part
   */
  public Part(int size) {
    title = DEFAULT_TITLE;
    volume = DEFAULT_VOLUME;
    instrument = DEFAULT_INSTRUMENT;

    setMetre(DEFAULT_METRE[0], DEFAULT_METRE[1]);

    keySig = DEFAULT_KEYSIG;
    swing = DEFAULT_SWING;
    composer = DEFAULT_COMPOSER;

    this.size = size;
    try {
      slots = new ArrayList<Unit>(size);
      for (int k = 0; k < size; k++) {
        slots.add(null);
      }
      // slots.setSize(size);
      if (size != 0) {
        slots.set(0, new Rest(size)); // empty Part has one long rest
        unitCount = 1;
      }
    } catch (OutOfMemoryError e) {
      ErrorLog.log(ErrorLog.SEVERE, "Not enough memory to create part of size " + size);
    }
  }
예제 #3
0
  /**
   * Gets the closest match Note to a given pitchName, from a polylist of NoteSymbols
   *
   * @param pitch
   * @param tonesPL
   * @return Note an instance of the 'closest' note in list from the pitchName
   */
  public static Note getClosestMatch(int pitch, Polylist tonesPL) {
    int originalPitch = pitch;
    // System.out.println("getClosestMatch to " + pitchName + " " + tonesPL);

    if (!tonesPL.nonEmpty()) {
      ErrorLog.log(ErrorLog.WARNING, "*** Error: No tones list to match against.");
    }

    Polylist list = tonesPL;
    int[] tones = new int[list.length()];

    /* Make an array of pitches of all acceptable tones to match to */
    for (int i = 0; list.nonEmpty(); i++) {
      try {
        tones[i] = ((NoteSymbol) list.first()).getMIDI() % OCTAVE;
        list = list.rest();
      } catch (Exception ep) {
        // ep.printStackTrace();
      }
    }

    /* Search incrementally within the tones list for the 'closest'
     * acceptable pitchName.  This will fit our contour best.
     */
    int stepSearch = 0;
    int indexMatch;

    while ((indexMatch = arrayContains((pitch % OCTAVE), tones)) == OUT_OF_BOUNDS) {
      stepSearch++;
      if (stepSearch % 2 == 0) {
        pitch -= stepSearch;
      } else {
        pitch += stepSearch;
      }
    }

    Note note = ((NoteSymbol) tonesPL.nth(indexMatch)).toNote();
    note.setPitch(pitch);
    /*
    if( pitchName != originalPitch )
    {
        System.out.println("closest match to " + new Note(originalPitch).toLeadsheet() + " is " + note.toLeadsheet() + " among " + tonesPL);
    }
     */
    return note;
  }
예제 #4
0
  /**
   * Gets the closest match Note at or above a given pitchName, from a polylist of NoteSymbols
   *
   * @param pitch
   * @param tonesPL
   * @param upward
   * @return Note an instance of the 'closest' note in list from the pitchName
   */
  public static Note getClosestMatchDirectional(int pitch, Polylist tonesPL, boolean upward) {
    // System.out.println("getClosestMatchDirectional to " + pitchName + " " + tonesPL);
    if (!tonesPL.nonEmpty()) {
      ErrorLog.log(ErrorLog.WARNING, "*** Error: No tones list to match against.");
    }

    Polylist list = tonesPL;
    int[] tones = new int[tonesPL.length()];

    /* Make an array of pitches of all acceptable tones to match to */
    for (int i = 0; i < tones.length; i++) {
      try {
        tones[i] = ((NoteSymbol) tonesPL.first()).getMIDI() % OCTAVE;
        tonesPL = tonesPL.rest();
      } catch (Exception ep) {
        // ep.printStackTrace();
      }
    }

    /* Search incrementally within the tones list for the 'closest'
     * acceptable pitchName.  This will fit our contour best.
     */

    int indexMatch;

    if (upward) {
      pitch++;
    } else {
      pitch--;
    }
    while ((indexMatch = arrayContains((pitch % OCTAVE), tones)) == OUT_OF_BOUNDS) {
      if (upward) {
        pitch++;
      } else {
        pitch--;
      }
    }

    Note note = ((NoteSymbol) list.nth(indexMatch)).toNote();
    note.setPitch(pitch);
    return note;
  }
예제 #5
0
  /**
   * addSubBlocks / 3 Constructs the subblocks of a brick by reading in a PolyList and using a
   * BrickLibrary to convert it to bricks with appropriate subbricks.
   *
   * @param contents, a PolyList of subbricks
   * @param bricks, a BrickLibrary
   */
  private void addSubBlocks(
      Polylist contents, BrickLibrary bricks, LinkedHashMap<String, LinkedList<Polylist>> polymap) {

    List<Block> subBlockList = new ArrayList<Block>();

    while (contents.nonEmpty()) {
      Object obj = contents.first();
      contents = contents.rest();
      if (obj instanceof Polylist) {
        Polylist pList = (Polylist) obj;
        String blockType = pList.first().toString();
        pList = pList.rest();

        // If a subblock is a brick, split it into components and then
        // look up the corresponding brick in the library to construct
        // the necessary new brick.
        if (blockType.equals(BRICK_KEYWORD) && (pList.length() == 3 || pList.length() == 4)) {
          // determine the information about the name, variant, etc.
          String subBrickName = BrickLibrary.dashless(pList.first().toString());
          pList = pList.rest();

          String subBrickVariant = "";
          if (pList.first() instanceof Polylist) {
            subBrickVariant = ((Polylist) pList.first()).toStringSansParens();
            pList = pList.rest();
          }

          String subBrickKeyString = pList.first().toString();
          pList = pList.rest();

          // Workaround added by RK for error reporting
          // in case of missing duration in sub-brick

          Object durObj = DEFAULT_SUBRICK_DURATION;

          if (pList.isEmpty()) {
            ErrorLog.log(
                ErrorLog.WARNING, "Missing Sub-Brick Duration in " + subBrickName + ", using 1");
          } else {
            durObj = pList.first();
            // pList = pList.rest();
          }

          // when all data members are initialized, find the correct
          // brick scaled appropriately
          boolean starFlag = isStar(durObj);
          if (durObj instanceof Long || starFlag) {
            int dur = starFlag ? 0 : Arith.long2int((Long) durObj);
            long subBrickKeyNum = BrickLibrary.keyNameToNum(subBrickKeyString);
            Brick subBrick = null;

            // if the subbrick already exists in the dictionary
            if (bricks.hasBrick(subBrickName)) {
              if (!subBrickVariant.equals("")) {
                subBrick = bricks.getBrick(subBrickName, subBrickVariant, subBrickKeyNum, dur);
              } else {
                subBrick = bricks.getBrick(subBrickName, subBrickKeyNum, dur);
              }
            }

            // if the subbrick has yet to be initialized in the
            // dictionary, make one to use for now
            else if (polymap.containsKey(subBrickName)) {

              // find the appropriate definition to use to assemble
              // the subbrick
              LinkedList<Polylist> tokenList = polymap.get(subBrickName);
              Polylist tokens = null;
              if (subBrickVariant.equals("")) {
                tokens = tokenList.getFirst();
              } else {
                for (Polylist p : tokenList) {
                  Object variant = p.rest().rest().first();
                  if (variant instanceof Polylist
                      && ((Polylist) variant).toStringSansParens().equals(subBrickVariant)) {
                    tokens = p;
                    break;
                  }
                }
                if (tokens == null) {
                  ErrorLog.log(
                      ErrorLog.SEVERE,
                      "Dictionary does not contain " + subBrickName + subBrickVariant);
                }
              }

              // find the elements of the subbrick
              String brickName = BrickLibrary.dashless(subBrickName);
              tokens = tokens.rest();
              tokens = tokens.rest();

              String brickVariant = "";
              if (tokens.first() instanceof Polylist) {
                brickVariant = ((Polylist) tokens.first()).toStringSansParens();
                tokens = tokens.rest();
              }
              String brickMode = tokens.first().toString();
              tokens = tokens.rest();
              String brickType = tokens.first().toString();
              tokens = tokens.rest();
              String brickKeyString = tokens.first().toString();
              tokens = tokens.rest();
              long brickKeyNum = BrickLibrary.keyNameToNum(brickKeyString);

              // construct the subbrick
              subBrick =
                  new Brick(
                      brickName,
                      brickVariant,
                      brickKeyNum,
                      brickType,
                      tokens,
                      bricks,
                      brickMode,
                      polymap);
              subBrick.transpose(Arith.long2int(subBrickKeyNum - brickKeyNum));
              subBrick.setDuration(dur);
            } else {
              ErrorLog.log(
                  ErrorLog.SEVERE, "Dictionary does " + "not contain " + subBrickName, true);
            }

            subBlockList.add(subBrick);
          } else {
            ErrorLog.log(
                ErrorLog.FATAL, subBrickName + ": " + "Duration not of type long: " + obj, true);
          }
        }

        // If a subblock is a chord, make an appropriate Chord object
        else if (blockType.equals(CHORD_KEYWORD) && pList.length() == 2) {
          String chordName = pList.first().toString();
          pList = pList.rest();
          Object durObj = pList.first();
          // pList = pList.rest();
          boolean starFlag = isStar(durObj);
          if (durObj instanceof Long || starFlag) {
            int dur = starFlag ? 0 : Arith.long2int((Long) durObj);
            ChordBlock subBlockChord = new ChordBlock(chordName, dur);
            subBlockList.add(subBlockChord);
          } else {
            ErrorLog.log(
                ErrorLog.FATAL, chordName + ": " + "Duration not of type long: " + durObj, true);
          }
        } else {
          ErrorLog.log(
              ErrorLog.WARNING,
              "Incorrect subblock of "
                  + name
                  + ": "
                  + blockType
                  + " "
                  + pList.toStringSansParens());
        }
      }
    }

    subBlocks.addAll(subBlockList);
  }
예제 #6
0
  /**
   * addSubBlocks / 2 Constructs the subblocks of a brick by reading in a PolyList and using a
   * BrickLibrary to convert it to bricks with appropriate subbricks.
   *
   * @param contents, a PolyList of subbricks
   * @param bricks, a BrickLibrary
   */
  private void addSubBlocks(Polylist contents, BrickLibrary bricks) {

    List<Block> subBlockList = new ArrayList<Block>();

    while (contents.nonEmpty()) {
      Object obj = contents.first();
      contents = contents.rest();
      if (obj instanceof Polylist) {
        Polylist pList = (Polylist) obj;
        String blockType = pList.first().toString();
        pList = pList.rest();

        // If a subblock is a brick, split it into components and then
        // look up the corresponding brick in the library to construct
        // the necessary new brick.
        if (blockType.equals(BRICK_KEYWORD)) {
          String brickName = BrickLibrary.dashless(pList.first().toString());
          pList = pList.rest();
          String brickVariant = "";
          if (pList.first() instanceof Polylist) {
            brickVariant = ((Polylist) pList.first()).toStringSansParens();
            pList = pList.rest();
          }
          String brickKeyString = pList.first().toString();
          pList = pList.rest();
          Object durObj = pList.first();
          // pList = pList.rest();
          boolean starFlag = isStar(durObj);
          if (durObj instanceof Long || starFlag) {
            int dur = starFlag ? 0 : Arith.long2int((Long) durObj);
            long brickKeyNum = BrickLibrary.keyNameToNum(brickKeyString);
            Brick subBrick;
            if (brickVariant.equals("")) {
              subBrick =
                  bricks.getBrick(
                      brickName, brickVariant,
                      brickKeyNum, dur);
            } else {
              subBrick = bricks.getBrick(brickName, brickKeyNum, dur);
            }
            subBlockList.add(subBrick);
          } else {
            ErrorLog.log(
                ErrorLog.FATAL, brickName + ": " + "Duration not of type long: " + obj, true);
          }
        }

        // If a subblock is a chord, make an appropriate Chord object
        else if (blockType.equals(CHORD_KEYWORD)) {
          String chordName = pList.first().toString();
          pList = pList.rest();
          Object durObj = pList.first();
          boolean starFlag = isStar(durObj);
          if (durObj instanceof Long || starFlag) {
            int dur = starFlag ? 0 : Arith.long2int((Long) durObj);
            ChordBlock subBlockChord = new ChordBlock(chordName, dur);
            subBlockList.add(subBlockChord);
          } else {
            ErrorLog.log(
                ErrorLog.FATAL, chordName + ": " + "Duration not of type long: " + obj, true);
          }
        }
      }
    }

    subBlocks.addAll(subBlockList);
  }
예제 #7
0
 public static void fileToSettings(File file, AutomaticVoicingSettings settings) {
   lastFileName = file.getName();
   try {
     Scanner sc = new Scanner(file);
     while (sc.hasNextLine()) {
       String line = sc.nextLine();
       // System.out.println(line);
       if (line.contains("Auto Voicing Preset File.")) ;
       else if (!line.contains("(")) throw new Exception();
       else if (line.contains("LH-lower-limit")) {
         line =
             line.substring(
                 line.indexOf("LH-lower-limit") + "LH-lower-limit".length() + 1,
                 line.indexOf(")"));
         settings.setLeftHandLowerLimit(Integer.parseInt(line));
       } else if (line.contains("RH-lower-limit")) {
         line =
             line.substring(
                 line.indexOf("RH-lower-limit") + "RH-lower-limit".length() + 1,
                 line.indexOf(")"));
         settings.setRightHandLowerLimit(Integer.parseInt(line));
       } else if (line.contains("LH-upper-limit")) {
         line =
             line.substring(
                 line.indexOf("LH-upper-limit") + "LH-upper-limit".length() + 1,
                 line.indexOf(")"));
         settings.setLeftHandUpperLimit(Integer.parseInt(line));
       } else if (line.contains("RH-upper-limit")) {
         line =
             line.substring(
                 line.indexOf("RH-upper-limit") + "RH-upper-limit".length() + 1,
                 line.indexOf(")"));
         settings.setRightHandUpperLimit(Integer.parseInt(line));
       } else if (line.contains("LH-spread")) {
         line =
             line.substring(
                 line.indexOf("LH-spread") + "LH-spread".length() + 1, line.indexOf(")"));
         settings.setLeftHandSpread(Integer.parseInt(line));
       } else if (line.contains("RH-spread")) {
         line =
             line.substring(
                 line.indexOf("RH-spread") + "RH-spread".length() + 1, line.indexOf(")"));
         settings.setRightHandSpread(Integer.parseInt(line));
       } else if (line.contains("LH-min-notes")) {
         line =
             line.substring(
                 line.indexOf("LH-min-notes") + "LH-min-notes".length() + 1, line.indexOf(")"));
         settings.setLeftHandMinNotes(Integer.parseInt(line));
       } else if (line.contains("RH-min-notes")) {
         line =
             line.substring(
                 line.indexOf("RH-min-notes") + "RH-min-notes".length() + 1, line.indexOf(")"));
         settings.setRightHandMinNotes(Integer.parseInt(line));
       } else if (line.contains("LH-max-notes")) {
         line =
             line.substring(
                 line.indexOf("LH-max-notes") + "LH-max-notes".length() + 1, line.indexOf(")"));
         settings.setLeftHandMaxNotes(Integer.parseInt(line));
       } else if (line.contains("RH-max-notes")) {
         line =
             line.substring(
                 line.indexOf("RH-max-notes") + "RH-max-notes".length() + 1, line.indexOf(")"));
         settings.setRightHandMaxNotes(Integer.parseInt(line));
       } else if (line.contains("pref-motion-range")) {
         line =
             line.substring(
                 line.indexOf("pref-motion-range") + "pref-motion-range".length() + 1,
                 line.indexOf(")"));
         settings.setPreferredMotionRange(Integer.parseInt(line));
       } else if (line.contains("pref-motion")) {
         line =
             line.substring(
                 line.indexOf("pref-motion") + "pref-motion".length() + 1, line.indexOf(")"));
         settings.setPreferredMotion(Integer.parseInt(line));
       } else if (line.contains("prev-voicing-multiplier")) {
         line =
             line.substring(
                 line.indexOf("prev-voicing-multiplier") + "prev-voicing-multiplier".length() + 1,
                 line.indexOf(")"));
         settings.setPreviousVoicingMultiplier(Integer.parseInt(line) / 10.0);
       } else if (line.contains("half-step-multiplier")) {
         line =
             line.substring(
                 line.indexOf("half-step-multiplier") + "half-step-multiplier".length() + 1,
                 line.indexOf(")"));
         settings.setHalfStepAwayMultiplier(Integer.parseInt(line) / 10.0);
       } else if (line.contains("full-step-multiplier")) {
         line =
             line.substring(
                 line.indexOf("full-step-multiplier") + "full-step-multiplier".length() + 1,
                 line.indexOf(")"));
         settings.setFullStepAwayMultiplier(Integer.parseInt(line) / 10.0);
       } else if (line.contains("LH-color-priority")) {
         line =
             line.substring(
                 line.indexOf("LH-color-priority") + "LH-color-priority".length() + 1,
                 line.indexOf(")"));
         settings.setLeftColorPriority(Integer.parseInt(line));
       } else if (line.contains("RH-color-priority")) {
         line =
             line.substring(
                 line.indexOf("RH-color-priority") + "RH-color-priority".length() + 1,
                 line.indexOf(")"));
         settings.setRightColorPriority(Integer.parseInt(line));
       } else if (line.contains("max-priority")) {
         line =
             line.substring(
                 line.indexOf("max-priority") + "max-priority".length() + 1, line.indexOf(")"));
         settings.setMaxPriority(Integer.parseInt(line));
       } else if (line.contains("priority-multiplier")) {
         line =
             line.substring(
                 line.indexOf("priority-multiplier") + "priority-multiplier".length() + 1,
                 line.indexOf(")"));
         settings.setPriorityMultiplier(Integer.parseInt(line) / 10.0);
       } else if (line.contains("repeat-multiplier")) {
         line =
             line.substring(
                 line.indexOf("repeat-multiplier") + "repeat-multiplier".length() + 1,
                 line.indexOf(")"));
         settings.setRepeatMultiplier(Integer.parseInt(line) / 10.0);
       } else if (line.contains("half-step-reducer")) {
         line =
             line.substring(
                 line.indexOf("half-step-reducer") + "half-step-reducer".length() + 1,
                 line.indexOf(")"));
         settings.setHalfStepReducer(Integer.parseInt(line) / 10.0);
       } else if (line.contains("full-step-reducer")) {
         line =
             line.substring(
                 line.indexOf("full-step-reducer") + "full-step-reducer".length() + 1,
                 line.indexOf(")"));
         settings.setFullStepReducer(Integer.parseInt(line) / 10.0);
       } else if (line.contains("left-min-interval")) {
         line =
             line.substring(
                 line.indexOf("min-interval") + "min-interval".length() + 1, line.indexOf(")"));
         settings.setLeftMinInterval(Integer.parseInt(line));
       } else if (line.contains("right-min-interval")) {
         line =
             line.substring(
                 line.indexOf("min-interval") + "min-interval".length() + 1, line.indexOf(")"));
         settings.setRightMinInterval(Integer.parseInt(line));
       } else if (line.contains("invert-9th")) {
         if (line.contains("on")) settings.setInvertM9(true);
         if (line.contains("off")) settings.setInvertM9(false);
       } else if (line.contains("voice-all")) {
         if (line.contains("on")) settings.setVoiceAll(true);
         if (line.contains("off")) settings.setVoiceAll(false);
       } else if (line.contains("rootless")) {
         if (line.contains("on")) settings.setRootless(true);
         if (line.contains("off")) settings.setRootless(false);
       }
     }
   } catch (Exception ex) {
     ErrorLog.log(ErrorLog.SEVERE, "Error finding or reading Voicing File: " + lastFileName);
   }
 }
예제 #8
0
  public void makeSwing(SectionInfo sectionInfo) {
    // The index here iterates through the start of every beat

    Style previousStyle = Style.getStyle("swing"); // TEMP: FIX!
    for (int i = 0; i + beatValue - 1 < size; i += beatValue) {
      SectionRecord record = sectionInfo.getSectionRecordBySlot(i);

      Style s;
      if (record.getUsePreviousStyle()) {
        s = previousStyle;
      } else {
        s = record.getStyle();
        previousStyle = s;
      }

      if (s == null) {
        ErrorLog.log(ErrorLog.FATAL, "It will not be possible to continue");
      }

      double swingValue = s.getSwing();

      // System.out.println("i = " + i + ", style = " + s + " swing = " + swingValue);

      // FIX: Notice the problem here when i < size, the original condition, is used.

      // we get the Units where a second sixteenth note would fall,
      // an eighth note, and a fourth sixteenth note

      Unit unit1 = slots.get(i + 1 * beatValue / 4);
      Unit unit2 = slots.get(i + 1 * beatValue / 2);
      Unit unit3 = slots.get(i + 3 * beatValue / 4);

      // we only use swingValue if there is no second sixteenth note
      // (we don't want to swingValue a beat of four sixteenths)

      if (unit1 == null && unit2 != null) {

        /* formerly:
        // swingValue if there is a second eighth note
        if(unit2.getRhythmValue() == beatValue/2) {
            slots.set(i+beatValue/2, null);
            slots.set(i+(int)(beatValue*swingValue), unit2);
        }
        */

        int trailingRhythm = unit2.getRhythmValue();

        // swingValue if there is a second eighth note or longer
        if (trailingRhythm >= beatValue / 2) {

          int offset = (int) (beatValue * swingValue);
          Unit unit2mod = unit2.copy();
          unit2mod.setRhythmValue(unit2.getRhythmValue() - offset);
          slots.set(i + beatValue / 2, null);
          slots.set(i + offset, unit2mod);
        }
      }
    }

    try {
      // After the Units are shifted, go through and reset each rhythm value
      Part.PartIterator i = iterator();
      while (i.hasNext()) {
        int index = i.nextIndex();
        slots.get(index).setRhythmValue(getUnitRhythmValue(index));
        i.next();
      }
    } catch (Exception e) {

    }
  }