2012-05-06 22 views
3

通過編寫MIDI處理程序來自學Java。程序需要做的一件事就是在MIDI音符數字和它們相應的緊湊字符串表示之間來回轉換。我看着使用枚舉設置,但由於命名約束你不能這樣做Java枚舉替代我如何做到這一點?

c-1, c#-1, ... g9; 
因爲銳器和底片的

(是的,我下面,讓你最終有一個負的約定八度:P)。

看起來很笨重,必須在允許的和我想要的之間進行轉換。

CNEG1("c-1"), 
CSNEG1("c#-1"), 
DNEG1("d-1"), 
... 
G9("g9"); 

所以我想出了下面的靜態導入方案,它工作正常。但是,我想了解更多關於如何使用枚舉的知識,並且我有一種預感,他們可能實際上更適合於這項任務 - 只要我能更好地理解這些細節。所以這是我的問題:任何人都可以想出一個優雅的方式來使用枚舉方案提供相同的功能嗎?而且,這樣做會有強有力的論據嗎?

public abstract class MethodsAndConstants { 

    public static final String TONICS[] = {"c","c#","d","d#","e","f","f#","g","g#","a","a#","b"}; 
    static final NoteMap notemap = new NoteMap(); 

    static class NoteMap{ 
     static String map[] = new String[128]; 

     NoteMap() { 
      for (int i = 0; i < 128; i++){ 
       int octave = i/12 - 1; 
       String tonic = MethodsAndConstants.TONICS[i%12]; 
       map[i] = tonic + octave; 
      } 
     } 
    } 

    public static int convert_midi_note(String name){ 
     return indexOf(NoteMap.map, name); 
    } 

    public static String convert_midi_note(int note_num){ 
     return NoteMap.map[note_num]; 
    } 

    public static int indexOf(String[] a, String item){ 
     return java.util.Arrays.asList(a).indexOf(item); 
    }  
} 

編輯------------------------------------------

經過沉重的考慮,我認爲在這種特殊情況下,枚舉可能是矯枉過正的。我可能最終只是在這裏使用這個代碼,同樣的靜態導入方法,但不再需要像上面的NoteMap業務那樣的任何東西。

note_num - >名稱轉換非常簡單,名稱 - > note_num stuff只是很好的字符串解析樂趣。

public abstract class MethodsAndConstants { 
    public static final String[] TONICS = {"c","c#","d","d#","e","f","f#","g","g#","a","a#","b"}; 

    static String convert(int i) { 
     String tonic = MethodsAndConstants.TONICS[i%12]; 
     int octave = (i/12) - 1; 
     return tonic + octave; 
    } 

    static int convert(String s) { 
     int tonic = java.util.Arrays.asList(MethodsAndConstants.TONICS).indexOf(s.substring(0,1)); 
     if (s.contains("#")) tonic += 1; 
     int octave = Integer.parseInt(s.substring(s.length()-1)); 
     if (s.contains("-")) octave -= 2; // case octave = -1 
     int note_num = ((octave + 1) * 12) + tonic; 
     return note_num; 
    } 
} 
+0

['Note'](http://stackoverflow.com/a/2065693/230513)是一個相關示例。 – trashgod

回答

1

類似的東西:

public enum Note { 
    CNEG1("c-1"), CSNEG1("c#-1"), DNEG1("d-1"); 

    private final String tonicOctave; 

    private Note(final String tonicOctave) { 
     this.tonicOctave = tonicOctave; 
    } 

    public String getTonicOctave() { 
     return this.tonicOctave; 
    } 

    public static Note fromTonicOctave(final String val) { 
     for (final Note note: Note.values()) { 
      if (note.getTonicOctave().equals(val)) { 
       return note; 
      } 
     } 
     return null; 
    } 
} 

注意,當你在你的枚舉需要你可以有很多的參數,所以如果你需要單獨的滋補和倍頻程,就可以了。

+0

看起來很有趣。現在只能勉強開始解析它,但我會進行一些研究。 編輯*只能開始... – TOZ

+0

我想我知道你的意思是有能力分開滋補和ocatve,順便說一句。 沿着CNEG1(「c」, - 1)等行嗎?不知何故可能有用。 – TOZ

+0

@TOZ,是的,'CNEG1(「c」, - 1)'是可能的 – 2012-05-06 06:20:51

3

你可以使用一個枚舉來表示間距,但我可能會嘗試在一個類封裝節距

public class Pitch { 

    private final int octave; 
    private final Note note; 

    public enum Note { 
     C("C",4), CSHARP("C#/Db",5), DFLAT("C#/Db",5), //and so on 

     private final String thePitch; 
     private final int midiAdjust; 

     private Note(final String thePitch, final int midiAdjust) { 
      this.thePitch = thePitch; 
      this.midiAdjust = midiAdjust; 
     } 

     String getThePitch() { 
      return thePitch; 
     } 

     int getMidiAdjust() { 
      return midiAdjust; 
     } 
    } 

    public Pitch(Note note, int octave) { 
     this.note = note; 
     this.octave = octave; 
    } 

    public int getMidiNumber(){ 
     return 12*octave + note.getMidiAdjust(); 
    } 

} 

這將佔到事實音符(C,C#,d,d#,E ...)將會成爲一個重複組合,但是您可以有各種八度音,在這種情況下可以通過int來處理。這將大大減少您的enum的大小。

編輯:我在這裏添加了幾行作爲一個想法。您可以將第二個參數傳遞給枚舉的構造函數,以允許您返回表示音高的MIDI數字。在這一個中,我認爲由MIDI表示的最低數字是A,但我可能是錯誤的。此外,12*octave旨在爲每個增量添加整個八度音高。你可能需要稍微調整一下,因爲我看到你正在使用這種奇怪的符號。

+0

感謝您的回覆。我也會給這個研究。 – TOZ

+0

我很欣賞其他編輯 - 將對其進行更多的研究。 – TOZ