편집 뭔가를 재생할 수 있도록 미디 시퀀서를 중지내가 다른
MidiLatte midiLatte = new MidiLatte();
for (int i = 60; i <= 72; i++) {
midiLatte.addNote(i, 4);
}
midiLatte.playAndRemove();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Field f = MidiLatte.class.getDeclaredField("player");
f.setAccessible(true);
Sequencer s = (Sequencer) f.get(midiLatte);
s.stop();
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
for (int i = 48; i <= 60; i++) {
midiLatte.addNote(i, 4);
}
midiLatte.playAndRemove();
내가 MidiLatte
here의 소스 코드를 찾을 수 있었다 : 다음은 자체에 포함 된 예입니다. 죄송합니다. 나는 그것을 수업에 사용해야한다. (내게 달린다면 javax.sound.midi
을 직접 사용합니다 ...) 이것은 12 개의 음표 (처음에는 for
루프)의 시퀀스를 시작하지만 3000 밀리 초 후에 멈춰서 다른 시퀀스를 재생할 수 있습니다. 두 번째 for
루프). 그러나 두 번째 시퀀스가 재생되기 시작하면 처음부터 그렇게하지 않습니다. 그것은 여러 노트를 시작합니다.
내가 javax.sound.midi
API를 사용하는 Java GUI 응용 프로그램을 만드는 중이라서. 특히, 사용자가 노트를 입력하고 순서대로 재생할 수있게 해주는 시퀀서입니다. 내가 가지고있는 이슈는 내가 미디 메시지를 보낸 후에 내가 다른 것을 할 수있게 그들을 막을 방법이 필요하다는 것이다. 예를 들어, 사용자가 게임을 친다 고 가정 해 봅시다. 그런 다음 분명히 프로그램에서 메모를 재생합니다. 내가 원하는 것은 시퀀스가 재생되는 동안 사용자가 재생을 누르면 현재 재생을 중지하고 다시 시작한다는 것입니다.
MIDI를 Swing과 함께 사용하는 방법은 이벤트 대기열을 손상시키지 않고 그렇게하는 것이 쉽지 않습니다. MIDI를 다루는 별도의 Thread
을 갖는 것입니다. 앞 단락에서 제시 한 문제 외에도이 방법이 정상적으로 작동합니다.
@Override
public void run() {
midiLatte = new MidiLatte();
//This loop waits for tasks to become available
while (true) {
try {
tasks.take().accept(midiLatte);
} catch (InterruptedException e) {
System.out.println("MPThread interrupted");
}
}
}
MidiLatte
가 쉽게 미디 메시지를 보낼 수와 Sequencer
을 래핑하는 유틸리티 클래스입니다 : 여기 내 Thread
구현의 run
방법이다. 기본적으로이 작동 방식은 tasks
이 LinkedBlockingQueue
이 Consumer<MidiLatte>
입니다. 이게 내가 할 수있는 것은 외부 클래스 (MPThread
, 내 사용자 정의 Thread
, 내부 클래스)에 Consumer<MidiLatte>
을 큐에 추가하는 메소드를 갖는 것입니다. 이것은 쉽게 다음과 같이 MIDI 작업을 예약 할 수 있습니다 : 위에서 언급 한 바와 같이
midiPlayer.addAction(midiLatte -> {
// do midi stuff
});
그러나, 나는이 작업을 취소하고 이미 전송 된 후 MIDI 재생을 정지 할 수 있어야합니다. 전자는 쉬운 나는 단지 큐를 지울 수 있습니다 : 미디 작업이 이미 전송되고 MIDI API의 손에 있기 때문에
tasks.clear();
그러나, 후자는 어렵다. 이 예에서 볼 수 있듯이, 나는 sequencer.stop()
를 사용하여 시도했지만 그에서 이상한 결과를 얻고있다 : cancelPending()
이 sequencer.stop()
를 호출하고 큐를 삭제
player.addAction(midiLatte -> {
//midi stuff
});
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
player.cancelPending();
player.addAction(midiLatte -> {
//Midi stuff
});
. 무슨 일이 일어나는지는 다음과 같습니다 (사용자가 버그를 분명하게 설명하지 않을 때 짜증나고 혼란 스러울 수 있음을 알고 있으므로 단계별로 설명해 드리겠습니다.) :
- 첫 번째 시퀀스가 올바르게 재생되기 시작합니다.
- 3000 (다소간) 밀리 초 후에 첫 번째 시퀀스가 중지됩니다.
- 두 번째 시퀀스는 즉시 재생을 시작하지만 처음부터 시작하지는 않습니다. 오히려 전체 시간을 연주 한 것처럼 연주하기 시작합니다.
첫 번째 시퀀스의 노트가 A B C D E F G A
이고 두 번째 시퀀스가 1 2 3 4 5 6 7 8
이라고 가정합니다. 일어날 일은 3000 밀이 첫 번째 시퀀스에서 C
과 D
사이에있는 경우 전체 재생은 A B C 1 2 3 4 5 6 7 8
입니다. 그러나 실제로는 A B C 4 5 6 7 8
입니다.
원하는 동작을 어떻게 얻을 수 있습니까? 동시성을 설정 한 방식에 고유 한 문제가있는 경우 알려주십시오. 내가 원하는 행동을 반복하기 만하면됩니다. 재생 버튼을 누르면 MIDI 시퀀스가 재생됩니다. 시퀀스가 계속 재생되는 동안 다시 누르면 처음 재생이 중지되고 시퀀스가 처음부터 다시 재생됩니다. 나는 어떤 식 으로든 불분명하다면 말해주십시오. 고맙습니다!
더 나은 도움을 받으려면 게시 a [MCVE] 또는 [Short, Self Contained, Correct Example] (http://www.sscce.org/). –
저는 @AndrewThompson과 함께합니다. 코드와 문제를 이해할 수있는 가장 좋은 방법은 [MCVE] (http://stackoverflow.com/help/mcve) 및/또는 [SSCCE] (http://www.sscce.org/)에 질문을 올리십시오. 그러나 우리가 접근 할 수없는 도서관을 조롱해야하기 때문에 쉬운 일이 아닙니다. 에. –
이것이 스윙과 관련이 있는지 확신 할 수 없으므로 사용자 정의 플레이어에서 예제를 생성 할 수 있습니다. – MadProgrammer