Jonathan Holloway
Jonathan Holloway

Reputation: 63672

Convert Midi Note Numbers To Name and Octave

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];

Upvotes: 20

Views: 16833

Answers (4)

Dezzo
Dezzo

Reputation: 210

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);
 }

Upvotes: 1

A-Sharabiani
A-Sharabiani

Reputation: 19329

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.

Upvotes: 2

David Koelle
David Koelle

Reputation: 20824

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.

Upvotes: 4

paxdiablo
paxdiablo

Reputation: 881403

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);
    }
  }
}

Upvotes: 20

Related Questions