Example #1
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseDuration(
      String s, int index, NoteContext noteContext, StaccatoParserContext parserContext) {
    if (index < s.length()) {
      switch (s.charAt(index)) {
        case '/':
          index = parseNumericDuration(s, index, noteContext);
          break;
        case 'W':
        case 'H':
        case 'Q':
        case 'I':
        case 'S':
        case 'T':
        case 'X':
        case 'O':
        case '-':
          index = parseLetterDuration(s, index, noteContext, parserContext);
          break;
        default:
          noteContext.decimalDuration =
              DefaultNoteSettingsManager.getInstance().getDefaultDuration();
          noteContext.isDurationExplicitlySet = false;
          break; // Could get here if the next character is a velocity char ("a" or "d")
      }
      index = parseTuplet(s, index, noteContext);
    } else {
      noteContext.decimalDuration = DefaultNoteSettingsManager.getInstance().getDefaultDuration();
      noteContext.isDurationExplicitlySet = false;
    }

    logger.info("Decimal duration is " + noteContext.decimalDuration);

    return index;
  }
Example #2
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseNumericDuration(String s, int index, NoteContext context) {
    // The duration has come in as a number, like 0.25 for a quarter note.
    // Advance pointer past the initial slash (/)
    index++;

    // If first character before the numeric value is a dash, we're ending a tie
    if (s.charAt(index) == '-') {
      context.isEndOfTie = true;
      index++;
    }

    context.isDurationExplicitlySet = true;

    // Get the duration value
    int endingIndex = seekToEndOfDecimal(s, index);
    String durationNumberString = s.substring(index, endingIndex);
    context.decimalDuration += Double.parseDouble(durationNumberString);
    logger.info("Decimal duration is " + context.decimalDuration);
    index = endingIndex;

    // If the character after all of the value parsing is a dash, we're starting a tie
    if ((index < s.length()) && (s.charAt(index) == '-')) {
      context.isStartOfTie = true;
      index++;
    }

    return index;
  }
Example #3
0
  private int parseNoteElement(String s, int index, StaccatoParserContext parserContext) {
    boolean repeat = false;
    NoteContext noteContext = new NoteContext();
    do {
      // Begin the voyage of creating a note by populating the NoteContext
      index = parseNoteElement(s, index, noteContext, parserContext);

      if (noteContext.isChord) {
        Chord chord = noteContext.createChord(parserContext);
        parserContext.getParser().fireChordParsed(chord);
      } else {
        Note note = noteContext.createNote(parserContext);
        parserContext.getParser().fireNoteParsed(note);
      }

      //            // If the note is a chord, fire all the note events for each note in the chord
      //            if (noteContext.isChord) {
      //            	Note[] notes = new Chord(note, noteContext.intervals).getNotes();
      //            	for (int i=1; i < notes.length; i++) {
      //            		NoteContext context2 = noteContext.createChordNoteContext();
      //            		context2.noteNumber = notes[i].getValue();
      //            		logger.info("Next note in chord is "+context2.noteNumber);
      //            		parserContext.fireNoteParsed(context2.createNote(parserContext));
      //            	}
      //            }

      // Determine if there is another note to parse, and set up the next NoteContext
      repeat = noteContext.thereIsAnother;
      noteContext = noteContext.createNextNoteContext();
    } while (repeat);
    return index;
  }
Example #4
0
 /**
  * Must be called (instead of the constructor) for notes other than the first note being parsed
  *
  * @return
  */
 public NoteContext createNextNoteContext() {
   NoteContext noteContext = new NoteContext();
   noteContext.isFirstNote = false;
   noteContext.isMelodicNote = anotherNoteIsMelodic;
   noteContext.isHarmonicNote = anotherNoteIsHarmonic;
   return noteContext;
 }
Example #5
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseChord(String s, int index, NoteContext context) {
    // Don't parse chord for a rest
    if (context.isRest) {
      return index;
    }

    int lengthOfChordString = 0;
    boolean chordFound = false;
    String[] chordNames = Chord.getChordNames();
    for (String chordName : chordNames) {
      if (!chordFound
          && (s.length() >= index + chordName.length())
          && chordName.equals(s.substring(index, index + chordName.length()))) {
        chordFound = true;
        lengthOfChordString = chordName.length();
        context.isChord = true;
        context.intervals = Chord.getIntervals(chordName);
        context.chordName = chordName;
        logger.info(
            "Chord: " + chordName + "   Interval Pattern: " + Chord.getIntervals(chordName));
        break;
      }
    }
    return index + lengthOfChordString;
  }
Example #6
0
 //
 // Methods from NoteProvider
 //
 @Override
 public Note createNote(String noteString) {
   StaccatoParserContext parserContext = new StaccatoParserContext(new StaccatoParser());
   NoteContext noteContext = new NoteContext();
   parseNoteElement(noteString, 0, noteContext, parserContext);
   return noteContext.createNote(parserContext);
 }
Example #7
0
 public NoteContext createChordNoteContext() {
   NoteContext noteContext = new NoteContext();
   noteContext.isFirstNote = false;
   noteContext.isMelodicNote = false;
   noteContext.isHarmonicNote = true;
   noteContext.decimalDuration = decimalDuration;
   return noteContext;
 }
Example #8
0
  private int parseBracketedNote(String s, int index, NoteContext context) {
    int indexOfEndBracket = s.indexOf(']', index);
    String stringInBrackets = s.substring(index + 1, indexOfEndBracket);
    context.noteValueAsString = stringInBrackets;
    context.isNumericNote = true;

    logger.info(
        "This note is a note represented by the dictionary value " + context.noteValueAsString);
    return indexOfEndBracket + 1;
  }
Example #9
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseOctave(String s, int index, NoteContext context) {
    context.isOctaveExplicitlySet = false;

    // Don't parse an octave for a rest or a numeric note
    if (context.isRest || context.isNumericNote) {
      return index;
    }

    // Check for octave.  Remember that octaves are optional.
    // Octaves can be two digits, which is what this next bit is testing for.
    // But, there could be no octave here as well.
    char possibleOctave1 = '.';
    char possibleOctave2 = '.';

    if (index < s.length()) {
      possibleOctave1 = s.charAt(index);
    }

    if (index + 1 < s.length()) {
      possibleOctave2 = s.charAt(index + 1);
    }

    byte definiteOctaveLength = 0;
    if ((possibleOctave1 >= '0') && (possibleOctave1 <= '9')) {
      definiteOctaveLength = 1;
      if (possibleOctave2 == '0') {
        definiteOctaveLength = 2;
      }
      //            if ((possibleOctave1 == '-') && (definiteOctaveLength == 1)) {
      //                // That '-' isn't representing a -1 octave, it's probably representing the
      // end of a tie!
      //                // It's a duration character, not an octave character!
      //                return index;
      //            }

      logger.info("Octave is " + definiteOctaveLength + " digits long");

      String octaveNumberString = s.substring(index, index + definiteOctaveLength);
      logger.info("Octave string value is " + octaveNumberString);
      try {
        context.octaveNumber = Integer.parseInt(octaveNumberString) + context.octaveBias;
        context.isOctaveExplicitlySet = true;
      } catch (NumberFormatException e) {
        throw new ParserException(StaccatoMessages.OCTAVE_OUT_OF_RANGE, s);
      }
      if (context.octaveNumber > Note.MAX_OCTAVE) {
        throw new ParserException(StaccatoMessages.OCTAVE_OUT_OF_RANGE, s);
      }
      if (context.octaveNumber < Note.MIN_OCTAVE) {
        throw new ParserException(StaccatoMessages.OCTAVE_OUT_OF_RANGE, s);
      }
      context.originalString = context.originalString + octaveNumberString;
    }
    return index + definiteOctaveLength;
  }
Example #10
0
  private void setDefaultOctave(NoteContext context) {
    logger.info("No octave string found, setting default octave");

    if (context.isChord) {
      context.octaveNumber =
          DefaultNoteSettingsManager.getInstance().getDefaultBassOctave() + context.octaveBias;
    } else {
      context.octaveNumber =
          DefaultNoteSettingsManager.getInstance().getDefaultOctave() + context.octaveBias;
    }
  }
Example #11
0
  public Chord createChord(String chordString) {
    // If the user requested a chord like "C" or "Ab" without providing any additional details,
    // assume it's MAJOR
    if (chordString.length() <= 2) {
      chordString = chordString + "MAJ";
    }

    StaccatoParserContext parserContext = new StaccatoParserContext(new StaccatoParser());
    NoteContext noteContext = new NoteContext();
    parseNoteElement(chordString, 0, noteContext, parserContext);
    return noteContext.createChord(parserContext);
  }
Example #12
0
  /** This method does a variety of calculations to get the actual value of the note. */
  private void computeNoteValue(NoteContext noteContext, StaccatoParserContext parserContext) {
    // Don't compute note value for a rest
    if (noteContext.isRest) {
      return;
    }

    // Adjust for Key Signature
    if (parserContext.getKey() != null) {
      int keySig = KeyProviderFactory.getKeyProvider().convertKeyToByte(parserContext.getKey());
      if ((keySig != 0) && (!noteContext.isNatural)) {
        if ((keySig <= -1) && (noteContext.noteNumber == 11)) noteContext.noteNumber = 10;
        if ((keySig <= -2) && (noteContext.noteNumber == 4)) noteContext.noteNumber = 3;
        if ((keySig <= -3) && (noteContext.noteNumber == 9)) noteContext.noteNumber = 8;
        if ((keySig <= -4) && (noteContext.noteNumber == 2)) noteContext.noteNumber = 1;
        if ((keySig <= -5) && (noteContext.noteNumber == 7)) noteContext.noteNumber = 6;
        if ((keySig <= -6) && (noteContext.noteNumber == 0)) {
          noteContext.noteNumber = 11;
          noteContext.octaveNumber--;
        }
        if ((keySig <= -7) && (noteContext.noteNumber == 5)) noteContext.noteNumber = 4;
        if ((keySig >= +1) && (noteContext.noteNumber == 5)) noteContext.noteNumber = 6;
        if ((keySig >= +2) && (noteContext.noteNumber == 0)) noteContext.noteNumber = 1;
        if ((keySig >= +3) && (noteContext.noteNumber == 7)) noteContext.noteNumber = 8;
        if ((keySig >= +4) && (noteContext.noteNumber == 2)) noteContext.noteNumber = 3;
        if ((keySig >= +5) && (noteContext.noteNumber == 9)) noteContext.noteNumber = 10;
        if ((keySig >= +6) && (noteContext.noteNumber == 4)) noteContext.noteNumber = 5;
        if ((keySig >= +7) && (noteContext.noteNumber == 11)) {
          noteContext.noteNumber = 0;
          noteContext.octaveNumber++;
        }
        logger.info(
            "After adjusting for Key Signature, noteNumber="
                + noteContext.noteNumber
                + " octave="
                + noteContext.octaveNumber);
      }
    }

    // Compute the actual note number, based on octave and note
    if (!noteContext.isNumericNote) {
      int intNoteNumber =
          ((noteContext.octaveNumber) * 12) + noteContext.noteNumber + noteContext.internalInterval;
      if (intNoteNumber > 127) {
        throw new ParserException(
            StaccatoMessages.CALCULATED_NOTE_OUT_OF_RANGE, Integer.toString(intNoteNumber));
      }
      noteContext.noteNumber = (byte) intNoteNumber;
      logger.info("Computed note number: " + noteContext.noteNumber);
    }
  }
Example #13
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseNumericNote(String s, int index, NoteContext context) {
    int numCharsInNumber = 0;
    while (numCharsInNumber < s.length()
        && (s.charAt(index + numCharsInNumber) >= '0')
        && (s.charAt(index + numCharsInNumber) <= '9')) {
      numCharsInNumber++;
    }
    String numericNoteString = s.substring(index, index + numCharsInNumber);
    context.noteNumber = Byte.parseByte(numericNoteString);
    context.isNumericNote = true;

    logger.info("This note is a numeric note with value " + context.noteNumber);
    return index + numCharsInNumber;
  }
Example #14
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseInternalInterval(String s, int index, NoteContext context) {
    if (context.isRest) {
      return index;
    }

    // An internal interval is indicated by a single quote
    if ((index < s.length()) && (s.charAt(index) == '\'')) {
      int intervalLength = 0;
      // Verify that index+1 is a number representing the interval.
      if (index + 1 < s.length()
          && ((s.charAt(index + 1) >= '0') && (s.charAt(index + 1) <= '9'))) {
        intervalLength = 1;
      }
      // We'll allow for the possibility of double-sharps and double-flats.
      if ((intervalLength == 1)
          && (index + 2 < s.length())
          && ((s.charAt(index + 2) == '#') || (s.charAt(index + 2) == 'B'))) {
        intervalLength = 2;
      }
      if ((intervalLength == 2)
          && (index + 3 < s.length())
          && ((s.charAt(index + 3) == '#') || (s.charAt(index + 3) == 'B'))) {
        intervalLength = 3;
      }
      context.internalInterval =
          Intervals.getHalfsteps(s.substring(index + 1, index + intervalLength + 1));
      return index + intervalLength + 1;
    } else {
      return index;
    }
  }
Example #15
0
 /**
  * Returns the String of the next sub-token (the parts after + or _), if one exists; otherwise,
  * returns null
  */
 private int parseConnector(String s, int index, NoteContext context) {
   context.thereIsAnother = false;
   // See if there's another note to process
   if ((index < s.length()) && ((s.charAt(index) == '+') || (s.charAt(index) == '_'))) {
     logger.info("Another note: string = " + s.substring(index, s.length() - 1));
     if (s.charAt(index) == '_') {
       context.anotherNoteIsMelodic = true;
       logger.info("Next note will be melodic");
     } else {
       context.anotherNoteIsHarmonic = true;
       logger.info("Next note will be harmonic");
     }
     index++;
     context.thereIsAnother = true;
   }
   return index;
 }
Example #16
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseTuplet(String s, int index, NoteContext context) {
    if (index < s.length()) {
      if (s.charAt(index) == '*') {
        logger.info("Note is a tuplet");
        index++;

        // Figure out tuplet ratio, or figure out when to stop looking for tuplet info
        boolean stopTupletParsing = false;
        int indexOfUnitsToMatch = 0;
        int indexOfNumNotes = 0;
        int counter = -1;
        while (!stopTupletParsing) {
          counter++;
          if (s.length() > index + counter) {
            if (s.charAt(index + counter) == ':') {
              indexOfNumNotes = index + counter + 1;
            } else if ((s.charAt(index + counter) >= '0') && (s.charAt(index + counter) <= '9')) {
              if (indexOfUnitsToMatch == 0) {
                indexOfUnitsToMatch = index + counter;
              }
            } else if ((s.charAt(index + counter) == '*')) {
              // no op... artifact of parsing
            } else {
              stopTupletParsing = true;
            }
          } else {
            stopTupletParsing = true;
          }
        }

        index += counter;

        double numerator = 2.0d;
        double denominator = 3.0d;
        if ((indexOfUnitsToMatch > 0) && (indexOfNumNotes > 0)) {
          numerator = Double.parseDouble(s.substring(indexOfUnitsToMatch, indexOfNumNotes - 1));
          denominator = Double.parseDouble(s.substring(indexOfNumNotes, index));
        }
        logger.info("Tuplet ratio is " + numerator + ":" + denominator);
        double tupletRatio = numerator / denominator;
        context.decimalDuration = context.decimalDuration * (1.0d / tupletRatio);
        logger.info("Decimal duration after tuplet is " + context.decimalDuration);
      }
    }

    return index;
  }
Example #17
0
 /**
  * Returns the index with which to start parsing the next part of the string, once this method is
  * done with its part
  */
 private int parseQuantityDuration(String s, int index, NoteContext context) {
   // A quantity is associated with the duration, like the '24' in "w24"
   int endingIndex = seekToEndOfDecimal(s, index);
   String quantityNumberString = s.substring(index, endingIndex);
   context.decimalDuration +=
       (1.0f / context.mostRecentDuration)
           * (Double.parseDouble(quantityNumberString)
               - 1.0D); // Subtract 1, because mostRecentDuration has already been added to the
                        // total duration
   logger.info(
       "Quantity duration calculation: Duration of 1/"
           + context.mostRecentDuration
           + " * "
           + quantityNumberString
           + " = "
           + (1.0 / context.mostRecentDuration) * Double.parseDouble(quantityNumberString));
   return endingIndex;
 }
Example #18
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseLetterNote(String s, int index, NoteContext context) {
    context.isNumericNote = false;
    int originalIndex = index;
    switch (s.charAt(index)) {
      case 'C':
        context.noteNumber = 0;
        break;
      case 'D':
        context.noteNumber = 2;
        break;
      case 'E':
        context.noteNumber = 4;
        break;
      case 'F':
        context.noteNumber = 5;
        break;
      case 'G':
        context.noteNumber = 7;
        break;
      case 'A':
        context.noteNumber = 9;
        break;
      case 'B':
        context.noteNumber = 11;
        break;
      default:
        break;
    }
    index++;

    // Check for #, b, or n (sharp, flat, or natural) modifier
    boolean checkForModifiers = true;
    while (checkForModifiers) {
      if (index < s.length()) {
        switch (s.charAt(index)) {
          case '#':
            index++;
            context.noteNumber++;
            if (context.noteNumber == 12) {
              context.noteNumber = 0;
              context.octaveBias++;
            }
            break;
          case 'B':
            index++;
            context.noteNumber--;
            if (context.noteNumber == -1) {
              context.noteNumber = 11;
              context.octaveBias--;
            }
            break;
          case 'N':
            index++;
            context.isNatural = true;
            checkForModifiers = false;
            break;
          default:
            checkForModifiers = false;
            break;
        }
      } else {
        checkForModifiers = false;
      }
    }

    context.originalString = s.substring(originalIndex, index);

    logger.info(
        "Note number within an octave (C=0, B=11): "
            + context.noteNumber
            + " (with octaveBias = "
            + context.octaveBias
            + ")");
    return index;
  }
Example #19
0
 /**
  * Returns the index with which to start parsing the next part of the string, once this method is
  * done with its part
  */
 private int parseRest(String s, int index, NoteContext context) {
   context.isRest = true;
   logger.info("This note is a Rest");
   return index + 1;
 }
Example #20
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseVelocity(String s, int index, NoteContext context) {
    // Don't compute note velocity for a rest
    if (context.isRest) {
      return index;
    }

    // Process velocity attributes, if they exist
    while (index < s.length()) {
      int startPoint = index + 1;
      int endPoint = startPoint;

      char velocityChar = s.charAt(index);
      int lengthOfByte = 0;
      if ((velocityChar == '+') || (velocityChar == '_') || (velocityChar == ' ')) break;
      logger.info("Identified Velocity character " + velocityChar);
      boolean byteDone = false;
      while (!byteDone && (index + lengthOfByte + 1 < s.length())) {
        char possibleByteChar = s.charAt(index + lengthOfByte + 1);
        if ((possibleByteChar >= '0') && (possibleByteChar <= '9')) {
          lengthOfByte++;
        } else {
          byteDone = true;
        }
      }
      endPoint = index + lengthOfByte + 1;

      if (startPoint == endPoint) {
        return endPoint;
      }

      byte velocityNumber = Byte.parseByte(s.substring(startPoint, endPoint));

      // Or maybe a bracketed string was passed in, instead of a byte
      String velocityString = null;
      if ((index + 1 < s.length()) && (s.charAt(index + 1) == '[')) {
        endPoint = s.indexOf(']', startPoint) + 1;
        velocityString = s.substring(startPoint, endPoint);
      }

      switch (velocityChar) {
        case 'A':
          if (velocityString == null) {
            context.noteOnVelocity = velocityNumber;
          } else {
            context.noteOnVelocityValueAsString = velocityString;
          }
          context.hasNoteOnVelocity = true;
          break;
        case 'D':
          if (velocityString == null) {
            context.noteOffVelocity = velocityNumber;
          } else {
            context.noteOffVelocityValueAsString = velocityString;
          }
          context.hasNoteOffVelocity = true;
          break;
        default:
          throw new ParserException(
              StaccatoMessages.VELOCITY_CHARACTER_NOT_RECOGNIZED,
              s.substring(startPoint, endPoint));
      }
      index = endPoint;
    }

    if (context.hasNoteOnVelocity) {
      logger.info("Attack velocity = " + context.noteOnVelocity);
    }
    if (context.hasNoteOffVelocity) {
      logger.info("Decay velocity = " + context.noteOffVelocity);
    }

    return index;
  }
Example #21
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseLetterDuration(
      String s, int index, NoteContext context, StaccatoParserContext parserContext) {
    boolean moreDurationCharsToParse = true;
    boolean isDotted = false;

    while (moreDurationCharsToParse == true) {
      int durationNumber = 0;
      // See if the note has a duration. Duration is optional for a note.
      if (index < s.length()) {
        char durationChar = s.charAt(index);
        switch (durationChar) {
          case '-':
            if ((context.decimalDuration == 0.0D) && (!context.isEndOfTie)) {
              context.isEndOfTie = true;
              logger.info("Note is end of tie");
            } else {
              context.isStartOfTie = true;
              logger.info("Note is start of tie");
            }
            break;
          case 'W':
            durationNumber = 1;
            break;
          case 'H':
            durationNumber = 2;
            break;
          case 'Q':
            durationNumber = 4;
            break;
          case 'I':
            durationNumber = 8;
            break;
          case 'S':
            durationNumber = 16;
            break;
          case 'T':
            durationNumber = 32;
            break;
          case 'X':
            durationNumber = 64;
            break;
          case 'O':
            durationNumber = 128;
            break;
          default:
            index--;
            moreDurationCharsToParse = false;
            break;
        }
        index++;
        if ((index < s.length()) && (s.charAt(index) == '.')) {
          isDotted = true;
          index++;
        }

        if (durationNumber > 0) {
          context.isDurationExplicitlySet = true;
          double d = 1.0 / durationNumber;
          if (isDotted) {
            context.decimalDuration += d + (d / 2.0);
          } else {
            context.decimalDuration += d;
          }
        }

        context.mostRecentDuration = durationNumber;

        if ((index < s.length()) && (s.charAt(index) >= '0') && (s.charAt(index) <= '9')) {
          index = parseQuantityDuration(s, index, context);
        }
      } else {
        moreDurationCharsToParse = false;
      }
    }

    return index;
  }
Example #22
0
  /**
   * Returns the index with which to start parsing the next part of the string, once this method is
   * done with its part
   */
  private int parseChordInversion(String s, int index, NoteContext context) {
    if (!context.isChord) {
      return index;
    }

    int inversionCount = 0;
    boolean bassNote = false;

    int startIndex = index;
    boolean checkForInversion = true;
    while (checkForInversion) {
      if (index < s.length()) {
        switch (s.charAt(index)) {
          case '^':
            index++;
            inversionCount++;
            break;
          case 'C':
            index++;
            bassNote = true;
            break;
          case 'D':
            index++;
            bassNote = true;
            break;
          case 'E':
            index++;
            bassNote = true;
            break;
          case 'F':
            index++;
            bassNote = true;
            break;
          case 'G':
            index++;
            bassNote = true;
            break;
          case 'A':
            index++;
            bassNote = true;
            break;
          case 'B':
            index++;
            bassNote = true;
            break;
          case '#':
            index++;
            break; // presumably the sharp mark followed a note
            // For '0', need to differentiate between initial 0 and 0 as a second digit (i.e., 10)
          case '0':
            index++;
            inversionCount = (inversionCount == -1) ? 0 : inversionCount + 10;
            break;
          case '1':
            index++;
            inversionCount = 1;
            break;
          case '2':
            index++;
            inversionCount = 2;
            break;
          case '3':
            index++;
            inversionCount = 3;
            break;
          case '4':
            index++;
            inversionCount = 4;
            break;
          case '5':
            index++;
            inversionCount = 5;
            break;
          case '6':
            index++;
            inversionCount = 6;
            break;
          case '7':
            index++;
            inversionCount = 7;
            break;
          case '8':
            index++;
            inversionCount = 8;
            break;
          case '9':
            index++;
            inversionCount = 9;
            break;
            // For '[', we're checking for a note number after the inversion marker
          case '[':
            int indexEndBracket = s.indexOf(']', index);
            context.inversionBassNote =
                Note.getToneString(Byte.parseByte(s.substring(index + 1, indexEndBracket - 1)));
            index = indexEndBracket + 1;
            break;
          default:
            checkForInversion = false;
            break;
        }
      } else {
        checkForInversion = false;
      }
    }

    // Modify the note values based on the inversion
    if (bassNote) {
      context.inversionBassNote = context.inversionBassNote = s.substring(startIndex + 1, index);
    } else if (inversionCount > 0) {
      context.inversionCount = inversionCount;
    }
    return index;
  }