Convert Midi Note Numbers To Name and Octave

13,878

Solution 1

I'm not convinced your suggestion is that tedious. It's really just a divide-and-modulo operation, one gets the octave, the other gets the note.

octave = int (notenum / 12) - 1;
note = substring("C C#D D#E F F#G G#A A#B ",(notenum % 12) * 2, 2);

In real Java, as opposed to that pseudo-code above, you can use something like:

public class Notes {
  public static void main(String [] args) {
    String notes = "C C#D D#E F F#G G#A A#B ";
    int octv;
    String nt;
    for (int noteNum = 0; noteNum < 128; noteNum++) {
      octv = noteNum / 12 - 1;
      nt = notes.substring((noteNum % 12) * 2, (noteNum % 12) * 2 + 2);
      System.out.println("Note # " + noteNum + " = octave " + octv + ", note " + nt);
    }
  }
}

Solution 2

In JFugue, the Note class has a utility method that does exactly this - see public static String getStringForNote(byte noteValue).

EDIT: As of JFugue 5.0 and later, the Note class has several utility methods for getting a string representation from a MIDI note value:

  • getToneString(byte noteValue) converts a value of 60 to the string C5
  • getToneStringWithoutOctave(byte noteValue) converts a value of 60 to the string C
  • getPercussionString(byte noteValue) converts a value of 60 to the string "[AGOGO]"

These replace the original getStringForNote() method.

Solution 3

public static String getNoteName(int noteNumber){
    noteNumber -= 21; // see the explanation below.
    String[] notes = new String[] {"A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"};
    int octave = noteNumber / 12 + 1;
    String name = notes[noteNumber % 12];
    return name + octave;
}

Explanation:

  • A0 in midi is the first note and its number is 21. We adjust the index to start from 0 (hence noteNumber -= 21; at the beginning). If your note numbers are 0 based, for example in piano from 0 to 88, then you can comment this line out.

  • Note that in this solution, the note names in the array start from A to G.

  • Octave is noteNumber / 12 + 1 (Or ceiling of num / 12).

  • Note name index is noteNumber % 12.

Solution 4

This is the shortest form without too many named constants. No need for any loops as well.

public static String getNoteFromMidiNumber(int midiNote){
    String[] note_names = {"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
    return note_names[midiNote % 12] + ((midiNote / 12) - 1);
 }
Share:
13,878

Related videos on Youtube

Jonathan Holloway
Author by

Jonathan Holloway

Consultant CTO and Architect with expertise in Java, Python, Ruby and Javascript http://www.jonathanholloway.co.uk/

Updated on October 18, 2020

Comments

  • Jonathan Holloway
    Jonathan Holloway over 3 years

    Does anybody know of anything that exists in the Java world to map midi note numbers to specific note names and octave numbers. For example, see the reference table:

    http://www.harmony-central.com/MIDI/Doc/table2.html

    I want to map a midi note number 60 to it's corresponding note name (MiddleC) in octave 4. I could write a utility class/enum for this, but it would be rather tedious. Does anybody know of anything?

    I'm specifically using this to write a Tenori-On/Monome clone in Java, so far so good...

    Solution

    This was what I ended up using:

    String[] noteString = new String[] { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
    
    int octave = (initialNote / 12) - 1;
    int noteIndex = (initialNote % 12);
    String note = noteString[noteIndex];
    
    • paxdiablo
      paxdiablo over 15 years
      Jon, I added some real Java to my answer.
    • Jonathan Holloway
      Jonathan Holloway over 15 years
      awesome, thanks for the pointers...
  • Smashery
    Smashery over 15 years
    Perhaps Jon was thinking of creating an enum for every single note+octave combination?
  • Jonathan Holloway
    Jonathan Holloway over 15 years
    That was the initial crazy suggestion. I was looking for the algorithm... I'm sure I can work something out given this, I don't think it's valid in Java... shouldn't take long to translate...
  • David Elson
    David Elson almost 9 years
    Also, perhaps one might hope for an intrinsic com.<whatever>.Midi, that "ships" with Java, that contains such a method. However, it would still leave unresolved whether to call a note (61?) C# or Db. If one had a key signature, one could resolve that (for many cases) according to key signature. I.e., for the key of B, it would b C#. For the key of Gb it would be Db.
  • paxdiablo
    paxdiablo almost 8 years
    Interesting. It looks like jFugue 5 no longer has org.jfugue.Note. It has org.jfugue.theory.Note but that one appears not to have the getStringForNote method. Not sure why people decide to take away useful functionality (especially since the cost of it wasn't that high) though it may be they're moved it somewhere else, not that I could find it though :-)
  • David Koelle
    David Koelle almost 8 years
    Actually, the new Note class has several more utility functions than the older version. The new getStringForNote is getToneString(byte noteValue) - for a value of 60, this would return "C5". There is now also getToneStringWithoutOctave(byte noteValue), which will return "C" for 60. You can also find getPercussionString(byte noteValue), which for 60 will return "[AGOGO]". The new methods are richer than the originals, and required new function names to clarify their purpose.
  • LuaStart
    LuaStart about 5 years
    I need to do the same in Lua but from note name and octave to note number.
  • Cerin
    Cerin about 4 years
    This is wrong. If given 69, (the number for A4), your code returns A5. The octave calculation is off.
  • col000r
    col000r almost 4 years
    Works great once you fix one error: the octave has to be calculated from the original noteNumber before you adjust down by 21. - So move the line with the octave to the top and it works beautifully!