- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
通过编写 MIDI 处理程序自学 Java。该程序需要能够做的一件事是在 MIDI 音符编号和它们相应的紧凑字符串表示之间来回转换。我查看了使用枚举设置,但由于命名限制,你不能做类似的事情
c-1, c#-1, ... g9;
因为升号和负号(是的,我遵循的惯例会让你以负 Octave 音阶结尾 :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 -> 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;
}
}
最佳答案
您可以使用枚举来表示音高,但我可能会尝试将音高封装在一个类中
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...) 将成为重复集之一的事实,但您可以拥有各种 Octave 音阶,在这种情况下由一个 int
。这将大大减少您的 enum
的大小。
编辑:我在这里添加了几行作为想法。您可以将第二个参数传递给枚举的构造函数,以允许您返回表示音高的 MIDI 数字。在这首轨道中,我假设 MIDI 代表的最小数字是 A,但我可能错了。此外,12*octave
旨在为每个增量添加一个完整的 Octave 音程。您可能需要稍微调整一下,因为我看到您使用的是一种奇怪的符号。
关于Java enum 的替代方法我是怎么做到的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10468436/
我是一名优秀的程序员,十分优秀!