Piano em Java usando Synthesizer: som não sai

18 respostas
Giacaboy

Estou fazendo um piano em java e eu estou com um problema para tocar os sons. O código para tocar uma nota é simples.

Primeiro eu declaro um Synthesizer.

private Synthesizer synth;

Depois, no construtor da interface gráfica do piano, eu inicializo ele e o abro.

this.synth = MidiSystem.getSynthesizer(); this.synth.open();

Quando aperto uma tecla do piano, simplesmente é chamada a função abaixo.

private void tocaNota(int nota) { MidiChannel channel = synth.getChannels()[0]; channel.noteOn(nota,90); channel.noteOff(nota,90); }

O prolema é que aqui em casa ele está funcionando PERFEITAMENTE. Porém, em outros computadores, não sai o som. Meu amigo começou a testar, e em notebooks (como é o caso daqui de casa) o som sai. Em computadores gabinete, o som não sai. APARENTEMENTE é isso que acontece.

Alguém poderia me ajudar com esse problema? Obrigado.

18 Respostas

E

Por acaso esses tais computadores têm caixinhas de som? O som MIDI não sai pelo alto-falante embutido do computador (aquele que mal e mal bipa, e olhe lá) a menos que o computador já tenha a fiação adequada (que é o caso de alguns computadores “de marca”).

gomesrod

O problema que eu tive não tem nada a ver com Java, mas o motivo pode estar relacionado:

Eu costumava utilizar um software para gravação de música pelo computador, mas em algumas máquinas ele não tocava MIDI. Isso tinha a ver com a placa de som, se tivesse o recurso de MIDI embutido funcionava, senão não.
Nas máquinas cuja placa de som não tem o sintetizador de MIDI só dá pra tocar pelo Media Player mesmo, ele deve fazer algum tipo de emulação.

Infelizmente não conheço essa API de som e por isso não sei se ela pode sofrer o mesmo efeito, mas talvez seja uma pista.

Marky.Vasconcelos

Cara testei esse código aqui e não tocou também não em um gabinete.

Alias qual o paramametro que voce passa como nota? eu Testei os valores de 1 a 255 em todos os canais (16 pra ser mais exato) e nao foi tocado nenhum som.

Giacaboy

Mark_Ameba:
Cara testei esse código aqui e não tocou também não em um gabinete.

Alias qual o paramametro que voce passa como nota? eu Testei os valores de 1 a 255 em todos os canais (16 pra ser mais exato) e nao foi tocado nenhum som.

nota é um numero inteiro msm. use 60, por exemplo. é um dó de piano.

os canais não precisa mudar. é só pra vc usar cada instrumento em um canal. nesse caso tô usando o piano no canal 0. se eu for usar outro instrumento, usaria outro canal

Marky.Vasconcelos

Hmm… mesmo com 60 não funcionou.

Vou ver se acho um projeto que eu vi uma vez que voce passa notas de piano como “D, D#, A” e etc e ele toca e te mostro. Aquele eu vi que funcionava.

Depois vou testar em um notbook pra ver se funciona com o MidiChannel.

Giacaboy

Mark_Ameba:
Hmm… mesmo com 60 não funcionou.

Vou ver se acho um projeto que eu vi uma vez que voce passa notas de piano como “D, D#, A” e etc e ele toca e te mostro. Aquele eu vi que funcionava.

Depois vou testar em um notbook pra ver se funciona com o MidiChannel.

mt obrigado, Mark. tô precisando mt disso até pq é meu projeto de graduação. tem q sair som. hahahahaha

abraço

gomesrod
Cara, assim funcionou aqui na minha máquina:
channel.noteOn(nota, 90);
Thread.sleep(1000);
channel.noteOff(nota, 90);
Entendi que é preciso um tempo entre ligar e desligar a nota. No caso do seu piano, pode dar o noteOn quando apertar a tecla e noteOff quando soltar. Só não entendi porque é que no notebook funciona!!

E finalizando, uma observação: que negócio da hora!
Queria agradecer ao autor do tópico por ter me apresentado essa API :D

De quebra, segue minha obra-prima:

private static void playSong() throws MidiUnavailableException, InterruptedException {
 Synthesizer synth;
 synth = MidiSystem.getSynthesizer();

 synth.open();
 MidiChannel channel = synth.getChannels()[1];
 
 int doo = 60;
 int re = 62;
 int mi = 64;
 int fa = 65;
 int sol = 67;
 int silencio = 0;
 
 int umtempo = 250;
 int doistempos = 500;
 
 playNote(channel, doo, umtempo); 
 playNote(channel, re, umtempo);
 playNote(channel, mi, umtempo);
 playNote(channel, fa, doistempos);
 playNote(channel, fa, umtempo);
 playNote(channel, fa, umtempo);
 playNote(channel, silencio, umtempo);
 
 playNote(channel, doo, umtempo); 
 playNote(channel, re, umtempo);
 playNote(channel, doo, umtempo); 
 playNote(channel, re, doistempos);
 playNote(channel, re, umtempo);
 playNote(channel, re, umtempo);
 playNote(channel, silencio, umtempo);
 
 playNote(channel, doo, umtempo); 
 playNote(channel, sol, umtempo);
 playNote(channel, fa, umtempo);
 playNote(channel, mi, doistempos);
 playNote(channel, mi, umtempo);
 playNote(channel, mi, umtempo);
 playNote(channel, silencio, umtempo);
 
 playNote(channel, doo, umtempo); 
 playNote(channel, re, umtempo);
 playNote(channel, mi, umtempo);
 playNote(channel, fa, doistempos);
 playNote(channel, fa, umtempo);
 playNote(channel, fa, doistempos);
 
 synth.close();
	}

	private static void playNote(MidiChannel channel, int nota, int tempo) throws InterruptedException {
 channel.noteOn(nota, 90);
 Thread.sleep(tempo);
 channel.noteOff(nota, 90);
	}
Marky.Vasconcelos

Não achei exatamente o que eu procurava mas lembro que é um desses projetos de som.

http://www.softsynth.com/links/java_music.html

Marky.Vasconcelos

Verdade… com Thread.sleep ele funciona mesmo.

E esse seu tópico me lembro esse site:

Giacaboy

gomesrod:
Cara, assim funcionou aqui na minha máquina:

channel.noteOn(nota, 90); Thread.sleep(1000); channel.noteOff(nota, 90);
Entendi que é preciso um tempo entre ligar e desligar a nota.
No caso do seu piano, pode dar o noteOn quando apertar a tecla e noteOff quando soltar.
Só não entendi porque é que no notebook funciona!!

sim, eu tava usando esse sleep, mas tava dando um probleminha com o acendimento do botão do piano qd eu usava. aí como tava funcionando sem ela, tirei… então se colocar funciona em computadores gabinete? pq em note funciona sem o sleep!!! hahaha mt estranho

Giacaboy

gomesrod:
E finalizando, uma observação: que negócio da hora!
Queria agradecer ao autor do tópico por ter me apresentado essa API :D

mt obrigado pela ajuda. vô dar uma olhada no seu programa. essa api é legal =]

Giacaboy

Mark_Ameba:
Não achei exatamente o que eu procurava mas lembro que é um desses projetos de som.

http://www.softsynth.com/links/java_music.html

mt obrigado pela ajuda Mark

Giacaboy

é. nos testes aqui nem colocando o sleep funcionou

F

Galera, to precisando de ajuda pra um problema parecido.

Estou criando um sequenciador midi para a monografia da facul. Porém não sei como criar a parte gráfica do sequenciador. Queria algo parecido com isso.

Onde daria pra mexer na duração das notas.

Alguém tem alguma sugestão de como posso fazer isso?

Abraço!

gomesrod

Dando uma voltada ao assunto principal do tópico (não sai som), eu estava dando uma fuçada e aconteceu uma coisa terrível:

O som do MIDI não sai quando o programa executa no Java 1.6 (JRE 1.6.0_06), mas no 1.5 funciona normal…

Se o Giacaboy por acaso ainda estiver com o problema, dê uma olhada nisso!

M

O MIDI, caso o dispositivo não seja apropriado para reprodução via hardware, é “renderizado” via software (por programas sequenciadores) para ser reproduzido pelos alto-falantes comuns do computador.

Acontece que, para essa sequenciação ser bem sucedida é preciso ter um conjunto de bibliotecas específicas. Por exemplo, no caso do Ubuntu, um pacote chamado ‘freepats’ é responsável por essa função. Sem ele, nem os reprodutores de áudio nativos, nem a API do Java conseguirá reproduzir sons. Com ele instalado, tudo funciona perfeitamente.

Ou seja, são necessários alto-falantes e toda a parte de software devidamente configurada.

Garanta que isso está OK, pois deve estar relacionado com isso o problema (tente reproduzir um arquivo .mid nos computadores nos quais o programa não funcionou, por exemplo).

Giacaboy

marcobiscaro2112:
O MIDI, caso o dispositivo não seja apropriado para reprodução via hardware, é “renderizado” via software (por programas sequenciadores) para ser reproduzido pelos alto-falantes comuns do computador.

Acontece que, para essa sequenciação ser bem sucedida é preciso ter um conjunto de bibliotecas específicas. Por exemplo, no caso do Ubuntu, um pacote chamado ‘freepats’ é responsável por essa função. Sem ele, nem os reprodutores de áudio nativos, nem a API do Java conseguirá reproduzir sons. Com ele instalado, tudo funciona perfeitamente.

Ou seja, são necessários alto-falantes e toda a parte de software devidamente configurada.

Garanta que isso está OK, pois deve estar relacionado com isso o problema (tente reproduzir um arquivo .mid nos computadores nos quais o programa não funcionou, por exemplo).

É… acho q será mais complicado do q eu imaginava… queria saber como esses programas reproduzem sons facilmente…

será q tem algum jeito mais simples do q usar o midi?

Giacaboy

Essa é a classe piano. Ela simplesmente toca uma nota usando o método toca(nota), sendo que nota é um inteiro que vai de 0 a 255. Ela não é nada complicada, mas o som só sai em alguns computadores (principalmente notebooks). Notei que se uso um JOptionPane para criar uma mensagem usando algum parâmetro de synth ou canal (synth.toString() ou canal.toString(), por exemplo), nos computadores nos quais o som não sai a mensagem não é exibida. Nos computadores nos quais o som sai a mensagem é exibida normalmente. Então não está achando o canal? Talvez, não sei. O negócio é que já fiz de tudo e nada.

public class Piano
{
    public Piano()
    {

    }

    public void toca(final int nota)
    {
        new Thread()
        {
            @Override
            public void run()
            {
                Synthesizer synth = null;

                try
                {
                    synth = MidiSystem.getSynthesizer();
                } catch (MidiUnavailableException ex)
                {
                    Logger.getLogger(Piano.class.getName()).log(Level.SEVERE, null, ex);
                }

                try
                {
                    synth.open();
                } catch (MidiUnavailableException ex)
                {
                    Logger.getLogger(InterfaceTecladoVirtual.class.getName()).log(Level.SEVERE, null, ex);
                }

                MidiChannel canal = synth.getChannels()[0];

                canal.noteOn(nota,100);

                try
                {
                    Thread.sleep(1000);
                } catch (InterruptedException ex)
                {
                    Logger.getLogger(InterfaceTecladoVirtual.class.getName()).log(Level.SEVERE, null, ex);
                }

                canal.noteOff(nota,100);

                synth.close();
            }
        }.start();
    }
}
Criado 10 de fevereiro de 2010
Ultima resposta 30 de set. de 2010
Respostas 18
Participantes 6