Convert Midi Note Numbers To Name and Octave
Asked Answered
A

4

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];
Alcala answered 3/4, 2009 at 5:44 Comment(1)
Jon, I added some real Java to my answer.Ruination
R
20

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);
    }
  }
}
Ruination answered 3/4, 2009 at 5:48 Comment(4)
Perhaps Jon was thinking of creating an enum for every single note+octave combination?Turdine
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...Alcala
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.Haroldharolda
I need to do the same in Lua but from note name and octave to note number.Ulphi
H
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.

Herold answered 5/1, 2010 at 18:59 Comment(2)
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 :-)Ruination
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.Herold
J
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.
Julee answered 6/2, 2019 at 3:34 Comment(2)
This is wrong. If given 69, (the number for A4), your code returns A5. The octave calculation is off.Pokpoke
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!Sides
A
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);
 }
Armagnac answered 18/10, 2020 at 1:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.