#java #midi #terminate
#java #midi #завершить
Вопрос:
Я написал эту короткую программу, чтобы изучить систему javax.sound.midi. Для этого используется Java 6. Вывод соответствует ожиданиям (серия строк System.out.println (), которые запускаются событиями секвенсора), но проблема в том, что после последнего звукового эффекта программа остается в цикле и завершается не так, как ожидалось.
Кто-нибудь может сказать, как это исправить? Спасибо за вашу помощь:
import javax.sound.midi.MidiEvent;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.ControllerEventListener;
import javax.sound.midi.Sequencer;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Track;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiUnavailableException;
class MySound {
public static MidiEvent makeEvent(int comd, int chan, int one,
int two, int tick) {
MidiEvent event = null;
try {
ShortMessage a = new ShortMessage();
a.setMessage(comd, chan, one, two);
event = new MidiEvent(a, tick);
} catch (InvalidMidiDataException imde) {
imde.printStackTrace();
}
return event;
}
}
class MyControllerListener implements ControllerEventListener {
public void controlChange(ShortMessage event) {
System.out.println("la");
}
}
class SoundEffects {
public static void main(String[] args) {
try {
Sequencer seq = MidiSystem.getSequencer();
seq.open();
int[] events = { 127 };
MyControllerListener mcl = new MyControllerListener();
seq.addControllerEventListener(mcl, events);
Sequence s = new Sequence(Sequence.PPQ, 4);
Track t = s.createTrack();
for (int i = 5; i < 60; i = 4) {
t.add(MySound.makeEvent(144, 1, i, 100, i));
t.add(MySound.makeEvent(176, 1, 127, 0, i));
t.add(MySound.makeEvent(128, 1, i, 100, i 2));
}
seq.setSequence(s);
seq.setTempoInBPM(220);
seq.start();
} catch (InvalidMidiDataException imde) {
imde.printStackTrace();
} catch (MidiUnavailableException mue) {
mue.printStackTrace();
}
}
}
Ответ №1:
Вам нужно вызвать seq.close() после завершения воспроизведения трека. Способ сделать это — добавить прослушиватель мета-сообщений и вызвать close () при обнаружении сообщения типа 0x2F (которое является необязательным мета-сообщением «конец дорожки»). Ваш код будет выглядеть примерно так:
seq.addMetaEventListener(new MetaEventListener() {
@Override
public void meta(MetaMessage metaMsg) {
if (metaMsg.getType() == 0x2F) {
seq.close();
}
}
});
Обратите внимание, что вам нужно было бы добавить final
модификатор в seq
, чтобы ссылаться на него в реализации анонимного интерфейса.
Надеюсь, это поможет.