有这样一个简单的代码可以工作(但直到我用^-c终止它,它才结束):
import javax.sound.midi.*;
public class Foo {
public void play(int instrument, int note) {
try {
Sequencer player = MidiSystem.getSequencer();
player.open();
Sequence seq = new Sequence(Sequence.PPQ, 4);
Track track = seq.createTrack();
ShortMessage first = new ShortMessage();
first.setMessage(192, 1, instrument, 0);
MidiEvent changeInstrument = new MidiEvent(first, 1);
track.add(changeInstrument);
ShortMessage a = new ShortMessage();
a.setMessage(144, 1, note, 100);
MidiEvent noteOn = new MidiEvent(a, 1); //fired on "tick 1"
track.add(noteOn);
ShortMessage b = new ShortMessage();
b.setMessage(128, 1, note, 100);
MidiEvent noteOff = new MidiEvent(b, 8); //fired on "tick 8"
track.add(noteOff);
player.setSequence(seq);
player.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Foo foo = new Foo();
foo.play(0, 42);
}
}
这个
noteOn MidiEvent
向…开火 1 tick
(第二个论点) MidiEvent
构造函数)。这个
noteOff MidiEvent
向…开火 8 tick
,也就是说。应该有7个刻度。但我永远看不到结局。当从cmd触发时,提示永远不会返回,除非我强制进程终止(使用 <ctrl-c>
). 为什么?音序器什么时候结束,程序什么时候结束?
编辑:这可能是由于打开序列器,但没有关闭它。所以我想在最后关闭它,但它不能立即跟随 player.start()
声明,否则立即结束。所以一定有耽搁。不过,这是一个笨拙的解决方案
...
player.setSequence(seq);
player.start();
TimeUnit.SECONDS.sleep(3);
player.close();
之后,提示返回。但是有更好的解决办法吗?
2条答案
按热度按时间rkkpypqq1#
当sequencer#isrunning()等于
false
. 我想你应该先关闭sequencer对象再开始另一个序列。将sequence对象声明为类成员可以提供更多的灵活性:lnxxn5zx2#
您需要添加metaeventlistener来捕获“序列结束”事件:
如果您只想在序列结束时退出程序,只需直接调用侦听器中的system.exit()。
请注意,如果使用sequencer.setloopcount(x)且x>0,则永远不会调用序列结束侦听器,您将需要一个ui按钮(或计时器)来触发对sequencer.stop()的调用。
在使用java sequencer时,有一些技巧需要了解,如果您需要示例代码,请查看我在github上的应用程序jjazzlab-x,尤其是
MusicController.java
在MusicController
模块。