将音符弦乐转换为MIDI音高编号

时间:2016-02-29 00:15:51

标签: java algorithm midi data-conversion

我编写了以下方法将音符(附加到结尾的八度)转换为相应的MIDI音高:

// Converts a note string (MUST HAVE OCTAVE) to an integer pitch.
public static int convertToPitch(String note) {
    String sym = "";
    int oct = 0;

    String[] notes = { "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B" };

    char[] splitNote = note.toCharArray();

    // If the length is two, then grab the symbol and number.
    // Otherwise, it must be a two-char note.
    if (splitNote.length == 2) {
        sym += splitNote[0];
        oct = splitNote[1];
    } else if (splitNote.length == 3) {
        sym += Character.toString(splitNote[0]);
        sym += Character.toString(splitNote[1]);
        oct = splitNote[2];
    }

    // Find the corresponding note in the array.
    for (int i = 0; i < notes.length; i++) {
        if (notes[i].equals(sym)) {
            return Character.getNumericValue(oct) * 12 + i;
        }
    }

    // If nothing was found, we return -1.
    return -1;
}

它的效果非常好。但是,我还希望能够使用备用名称的每个音符将convertToPitch()与备用音符值(Db变为C#等)一起使用。有没有办法在不撕裂我的方法的情况下做到这一点?

3 个答案:

答案 0 :(得分:2)

你可以从&#34;正常化&#34;开始输入预期输入的注释。即初始化字符串 - &gt;包含所有可能的注释和规范化映射的字符串映射。应该只在构造函数中导致一些map初始化,并在convertToPitch的开头调用map方法。

答案 1 :(得分:1)

你可以这样做

public static int convertToPitch(String note) {
  String sym = "";
  int oct = 0;
  String[][] notes = { {"C"}, {"Db", "C#"}, {"D"}, {"Eb", "D#"}, {"E"},
    {"F"}, {"Gb", "F#"}, {"G"}, {"Ab", "G#"}, {"A"}, {"Bb", "A#"}, {"B"} };

  char[] splitNote = note.toCharArray();

  // If the length is two, then grab the symbol and number.
  // Otherwise, it must be a two-char note.
  if (splitNote.length == 2) {
    sym += splitNote[0];
    oct = splitNote[1];
  } else if (splitNote.length == 3) {
    sym += Character.toString(splitNote[0]);
    sym += Character.toString(splitNote[1]);
    oct = splitNote[2];
  }

  // Find the corresponding note in the array.
  for (int i = 0; i < notes.length; i++)
  for (int j = 0; j < notes[i].length; j++) {
    if (notes[i][j].equals(sym)) {
        return Character.getNumericValue(oct) * 12 + i;
    }
  }

  // If nothing was found, we return -1.
  return -1;
}

答案 2 :(得分:0)

您可以单独处理意外事件。因此,对代码的修改最少:

TypeError

但是,在我看来,使用数组索引作为映射并不是最好的方法。根据您的输入格式,这不起作用,因为Cb是有效音符但没有数组索引-1。您可以创建[...] String sym = ""; int oct = 0; int accidental = 0; // initialize with default value 0 (i.e. no accidental) [...] } else if (splitNote.length == 3) { sym += Character.toString(splitNote[0]); switch (splitNote[1]){ case '#': accidental = 1; break; case 'b': accidental = -1; break; default: return -1; // you should really use Exceptions instead } // don't concat accidental to sym oct = splitNote[2]; [...] return Character.getNumericValue(oct) * 12 + i + accidental; // !! read the documentation of Character#getNumericValue !! [...] (如“C”映射到0,“D”映射到2等)或使用split() method。您还应该使用enumeration而不是返回-1;通过这种方式,您可以区分格式错误的字符串(“abbc123”)和超出范围的值(“B#9”)。
最后,如果我没记错的话,MIDI音高有一个偏移(比如C0不是0而是12)。