20

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];
Jonathan Holloway
  • 62,090
  • 32
  • 125
  • 150

4 Answers4

19

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);
    }
  }
}
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Perhaps Jon was thinking of creating an enum for every single note+octave combination? – Smashery Apr 03 '09 at 05:50
  • 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... – Jonathan Holloway Apr 03 '09 at 06:00
  • Also, perhaps one might hope for an intrinsic com..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. – David Elson Aug 20 '15 at 16:01
  • I need to do the same in Lua but from note name and octave to note number. – LuaStart Jun 06 '19 at 19:53
4

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.

David Koelle
  • 20,726
  • 23
  • 93
  • 130
  • 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 :-) – paxdiablo Aug 20 '16 at 12:32
  • 1
    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. – David Koelle Aug 31 '16 at 04:01
2
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.
A-Sharabiani
  • 17,750
  • 17
  • 113
  • 128
  • This is wrong. If given 69, (the number for A4), your code returns A5. The octave calculation is off. – Cerin May 21 '20 at 20:44
  • 2
    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! – col000r Sep 03 '20 at 03:52
1

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);
 }
Dezzo
  • 170
  • 1
  • 2
  • 9