我已经搜索了一段时间,并且找不到我想要做的答案。Java Midi - 如何从midi中弹出音符
我想播放MIDI文件,并在播放时在屏幕上显示注释。当一个音符停止播放时,它应该从屏幕上消失。
我可以用音序器演奏MIDI,但不知道如何获得音符的演奏,或者当它停止演奏音符时。
我已经看着ControllerEventListeners和MetaEventListeners,但仍不知道如何做到这一点。
任何帮助,将不胜感激。
我已经搜索了一段时间,并且找不到我想要做的答案。Java Midi - 如何从midi中弹出音符
我想播放MIDI文件,并在播放时在屏幕上显示注释。当一个音符停止播放时,它应该从屏幕上消失。
我可以用音序器演奏MIDI,但不知道如何获得音符的演奏,或者当它停止演奏音符时。
我已经看着ControllerEventListeners和MetaEventListeners,但仍不知道如何做到这一点。
任何帮助,将不胜感激。
这是一个FAQ。
将您自己的Receiver连接到音序器的变送器。
查看MidiPlayer中的DumpReceiver示例。
这已经证明是非常有用的,但你会知道如何获得一个笔记的持续时间?我想制作一个基本的MIDI可视化工具,随着笔记淡出,它将淡出一个正方形。 – user228856 2014-10-30 12:59:59
当您收到音符关闭事件时,音符停止。 – 2014-10-30 13:34:29
我不确定我是否清楚了我的观点。此刻,当笔记播放时,我正在显示彩色方块。当我收到音符关闭事件时,我已使其消失。随着钞票消失,我想使彩色正方形慢慢淡出。我认为接受者不知道一张音符将播放多久会是对的吗?如果是这样,我想我必须在播放之前以某种方式读取MIDI文件,并使用它来计算时间。感谢你的帮助,你真的很有帮助。 – user228856 2014-10-30 16:10:25
这是你应该做的:
您必须实现Receiver
,然后
sequencer = MidiSystem.getSequencer();
sequencer.open();
transmitter = sequencer.getTransmitter();
transmitter.setReceiver(this);
,并在此之后,下一个方法将每一个事件发生时触发:
@Override
public void send(MidiMessage message, long timeStamp) {
if(message instanceof ShortMessage) {
ShortMessage sm = (ShortMessage) message;
int channel = sm.getChannel();
if (sm.getCommand() == NOTE_ON) {
int key = sm.getData1();
int velocity = sm.getData2();
Note note = new Note(key);
System.out.println(note);
} else if (sm.getCommand() == NOTE_OFF) {
int key = sm.getData1();
int velocity = sm.getData2();
Note note = new Note(key);
System.out.println(note);
} else {
System.out.println("Command:" + sm.getCommand());
}
}
}
如果你愿意,你也可以使用这个类:
public class Note {
private static final String[] NOTE_NAMES = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
private String name;
private int key;
private int octave;
public Note(int key) {
this.key = key;
this.octave = (key/12)-1;
int note = key % 12;
this.name = NOTE_NAMES[note];
}
@Override
public boolean equals(Object obj) {
return obj instanceof Note && this.key == ((Note) obj).key;
}
@Override
public String toString() {
return "Note -> " + this.name + this.octave + " key=" + this.key;
}
}
解决方案之一是读取midi文件,获取所有笔记及其持续时间,然后运行另一个线程来显示笔记?如果有一些延迟,这会不会变得不同步? – user228856 2014-10-08 21:22:01