Sequencer (midi)

0 respostas
S

Boa noite, eu estou com um problema utilizando um Sequencer.

Classe MusicPlayer

private static final MusicPlayer MUSIC_PLAYER = new MusicPlayer();
	private Thread player;
	private String currentMusic;
	private Sequencer sequencer;

	private MusicPlayer() {
		player = new Thread(this);
		try {
			sequencer = MidiSystem.getSequencer();
			player.start();
		} catch (MidiUnavailableException e) {
			// TODO
		}
	}

	public static MusicPlayer getInstance() {
		return MUSIC_PLAYER;
	}

	public void playMusic() throws Exception {
		sequencer.open();
		InputStream is = new BufferedInputStream(new FileInputStream(new File(
				currentMusic)));
		sequencer.setSequence(is);
		sequencer.start();
	}

	public void changeMusic(String newMusic) throws Exception {
		currentMusic = newMusic;
		if (sequencer.isRunning()) {
			sequencer.stop();
		}
	}

Main:

public static void main(String[] args) throws Exception {
		MUSIC_PLAYER.changeMusic("midi1.mid");
		Thread.sleep(2500);
		MUSIC_PLAYER.changeMusic("midi2.mid");
		Thread.sleep(2500);
		MUSIC_PLAYER.changeMusic("midi1.mid");
	}

Metodo run (a classe implements Runnable):

@Override
	public void run() {
		while (true) {
			if (currentMusic != null && !sequencer.isRunning()) {
				try {
					playMusic();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

Basicamente, eu instancio o MusicPlayer, no construtor eu instancio a Thread aponto o sequencer para o MidiSystem e começo a Thread. Na(s) primeira(s) vez(es) dentro do run() currentMusic será null até que MUSIC_PLAYER.changeMusic(“midi1.mid”) seja chamado.

A partir dai a String currentMusic será “midi1.mid” e ambas as condições do bloco if dentro do método run() válidas para chamar o metodo playMusic(). O !sequencer.isRunning() é necessário para evitar que a mesma música seja tocada milhares de vezes por segundo. Até ai tudo bem, a música toca sem problema até MUSIC_PLAYER.changeMusic(“midi2.mid”).

O método é chamado, interrompe a música que está tocando o que é o suficiente para satisfazer o if, já que sequencer.isRunning() retorna false e currentMusic não é null.

Ele simplesmente não entra mas a parte mais estranha é se eu chamo o método sequencer.isRunning() a partir de dentro de um System.out.println(); ele entra no if. Se eu invocar esse método sem o System.out.println() nada acontece.

Ou seja, se eu alterar o método run para:

@Override
	public void run() {
		while (true) {
			System.out.println(sequencer.isRunning());
			if (currentMusic != null && !sequencer.isRunning()) {
				try {
					playMusic();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

Ele reinicia a música assim que ela se encerra (que é o que eu quero). Qual a minha falha nesse código?

Criado 13 de outubro de 2013
Respostas 0
Participantes 1