Java 将Midi音符数字转换为名称和八度

Java 将Midi音符数字转换为名称和八度,java,audio,midi,javasound,Java,Audio,Midi,Javasound,有没有人知道Java世界中存在什么东西可以将midi音符编号映射到特定的音符名称和八度音阶编号。例如,请参见参考表: 我想将一个midi音符编号60映射到它在八度4中对应的音符名称(MIDLEC)。我可以为此编写一个实用程序类/枚举,但这将相当乏味。有人知道什么吗 我专门用它来用Java编写Tenori On/Monome克隆,到目前为止还不错 解决方案 这就是我最终使用的: String[] noteString = new String[] { "C", "C#", "D", "D#",

有没有人知道Java世界中存在什么东西可以将midi音符编号映射到特定的音符名称和八度音阶编号。例如,请参见参考表:

我想将一个midi音符编号60映射到它在八度4中对应的音符名称(MIDLEC)。我可以为此编写一个实用程序类/枚举,但这将相当乏味。有人知道什么吗

我专门用它来用Java编写Tenori On/Monome克隆,到目前为止还不错

解决方案

这就是我最终使用的:

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

我不相信你的建议那么乏味。这实际上只是一个除法和模运算,一个得到八度,另一个得到音符

octave = int (notenum / 12) - 1;
note = substring("C C#D D#E F F#G G#A A#B ",(notenum % 12) * 2, 2);
在真正的Java中,与上面的伪代码相反,您可以使用如下内容:

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);
    }
  }
}
公共课堂笔记{
公共静态void main(字符串[]args){
String notes=“C#D#E F F#G G#A A#B”;
int-octv;
字符串nt;
对于(int-noteNum=0;noteNum<128;noteNum++){
octv=noteNum/12-1;
nt=注释.子字符串((注释编号%12)*2,(注释编号%12)*2+2);
System.out.println(“Note#“+noteNum+”=倍频程“+octv+”,Note“+nt”);
}
}
}
在中,
Note
类有一个实用方法,可以实现这一点-请参阅
公共静态字符串getStringForNote(byte noteValue)

EDIT:从JFugue 5.0及更高版本开始,
Note
类有几种实用方法可用于从MIDI音符值获取字符串表示:

  • getToneString(byte noteValue)
    将值转换为
    60
    到字符串
    C5
  • getToneStringWithoutOctave(byte noteValue)
    60
    的值转换为字符串
    C
  • getStructionString(byte noteValue)
    字符串
    “[AGOGO]”
这些方法取代了原来的
getStringForNote()
方法

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;
}
说明:

  • midi中的A0是第一个音符,其编号为21。我们将索引调整为从0开始(因此
    noteNumber-=21;
    开始)。如果你的音符编号是以0为基础的,例如在钢琴中从0到88,那么你可以注释掉这一行

  • 请注意,在此解决方案中,数组中的注释名称从A到G开始

  • 八度音阶是
    noteNumber/12+1
    (或num/12的上限)

  • 注释名称索引为
    注释编号%12

    • 这是没有太多命名常量的最短形式。也不需要任何循环

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

      也许Jon在考虑为每个音符+八度组合创建一个枚举?这是最初的疯狂建议。我在找算法。。。我相信我能解决这个问题,我认为它在Java中是无效的。。。翻译不需要太长时间……而且,也许有人会希望有一个内置的com..Midi,它与Java一起“附带”,包含这样一个方法。然而,是否调用注释(61?)C#或Db仍然没有解决。如果一个人有一个密钥签名,他可以根据密钥签名来解决这个问题(在很多情况下)。也就是说,对于B的键,它将是B C#。Gb的键应该是Db。我需要在Lua中做同样的事情,但是从音符名称和八度到音符编号。Jon,我在我的答案中添加了一些真正的Java。太棒了,谢谢你的提示…很有趣。看起来jFugue 5不再具有
      org.jFugue.Note
      。它有
      org.jfugue.theory.Note
      ,但它似乎没有
      getStringForNote
      方法。不知道为什么人们决定拿走有用的功能(特别是因为它的成本没有那么高),尽管可能是他们把它移到了其他地方,但我并没有发现:-)事实上,新的Note类比旧版本有更多的实用功能。新的getStringForNote是getToneString(byte noteValue)——对于值60,它将返回“C5”。现在还有getToneStringWithoutOctave(byte noteValue),它将返回“C”60。您还可以找到GetStructionString(byte noteValue),对于60,它将返回“[AGOGO]”。新方法比原始方法更丰富,需要新的函数名来阐明它们的用途。这是错误的。如果给定69(A4的数字),代码返回A5。八度音程计算关闭。一旦你修正了一个错误,八度音程的计算将非常有效:在你调低21度之前,八度音程必须从原来的音符数开始计算。-因此,移动线与八度到顶部,它的作品优美!