3

MIDI 処理プログラムをコーディングして Java を独学しています。プログラムができる必要があることの 1 つは、MIDI ノート番号とそれに対応するコンパクトな文字列表現との間で相互に変換することです。列挙型のセットアップを使用して見ましたが、命名の制約により、次のようなことはできません

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 -> name の変換は非常に簡単で、name -> note_num のようなものは、古き良き文字列解析の楽しみです。

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

2 に答える 2

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...) が繰り返しセットの 1 つになるという事実を説明しますが、この場合はint. のサイズを大幅に縮小しますenum

編集: アイデアとしてここに数行追加しました。列挙型のコンストラクターに 2 番目のパラメーターを渡して、ピッチを表す MIDI 番号を返すことができます。この例では、MIDI で表される最小の数字は A であると仮定しましたが、それは間違っている可能性があります。また、12*octave各インクリメントに 1 オクターブのピッチを追加することも目的としています。奇妙な表記法を使用しているように見えるので、おそらくこれを少し調整する必要があります。

于 2012-05-06T06:03:45.737 に答える
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;
    }
}

列挙型には必要な数のパラメーターを含めることができるため、トニックとオクターブを分離する必要がある場合は、そうすることができます。

于 2012-05-06T05:49:40.287 に答える