Java Audio Playback, porque deve confiar no ambiente local, o Java tem pouca vantagem no processamento de áudio ou, em outras palavras, não considera os fatores de reprodução de áudio ao desenvolver o sistema Java. Você deve saber que, na versão mais antiga do Java 1.1, não havia pacote Javax.Sound posterior, e o áudio só pode ser recuperado através do pacote de applet ...
Infelizmente, no desenvolvimento de programas gráficos, nossos programas precisam inevitavelmente usar música de fundo, sons de efeito etc. para cooperar com as operações de imagem. Infelizmente, isso é realmente uma piada que o mestre Sun jogou conosco. Felizmente, Mestre Sun abriu os olhos e forneceu o pacote Javax.Sound para nos salvar de Dire Straits ~
Mas o problema subsequente é que, no uso do pacote Javax.Sound, como um problema comum na classe de ferramentas Java Multimedia, não há mecanismo de liberação muito completo. Se fizermos o desenvolvimento do Windows, chamando o MediaPlayer repetidamente pode não ser um grande negócio, mas em Java, se o programa de áudio funcionar repetidamente, é muito fácil experimentar a perda cumulativa de memória, de modo que um java.lang.OutofMemoryError é jogado, e então ... o programa está pendurado, o usuário é estúpido e ficamos loucos ...
Isso já é uma questão de "é tolerável"? Em vista disso, no meu desenvolvimento da estrutura da LoonFramework, integrei secundamente os métodos relevantes em som, esforçando -se para criar a classe de controle de áudio mais completa com o código mais simples. Agora que o jogo do Loonframework ainda não alcançou grande sucesso, primeiro extrairei alguns métodos para você dar uma olhada neles!
Correspondendo às chamadas de recursos de rede, nossa própria classe URI é estabelecida no LoonFramework. O conteúdo básico é o seguinte:
(Onde Streamhelper é a classe de controle de streaming da Loonframework, substitua o método GethttpStream.)
pacote org.loon.framework.game.net; importar org.loon.framework.game.helper.streamhelper;/** ** // ** ** <p> * título: loonframework * </p> * <p> * descrição: uri dedicado de pupla e pup (p. * <p> * Empresa: Loonframework * </p> * * @author chenpeng * @email: [email protected] * @version 0.1 */public class Uri ... {// Tipo de protocolo de transporte public static final int _l_uri_http = 1; public static final int _l_uri_udp = 2; String privada _uri; private int _type; /** * // ** * Destrutor, usado para injetar URI e digitar * * @param uri * @param tipo */public URI (String Uri, int tipo) ... {_uri = new String (URI); _type = tipo; }/** * // ** * Destrutor, usado para injetar Uri * * @param tipo Uri */public URI (String Uri) ... {_uri = new String (URI); _type = uri._l_uri_http; }/*** // *** Retorna a matriz de bytes do recurso em que o URI está localizado. * * @return */ public byte [] getData () ... {if (_uri == null) ... {return null; } retornar streamhelper.gethttpStream (_uri); } public string geturi () ... {return _uri; } public int getType () ... {return _type; }} Na estrutura LoonFramework, uma classe Basic SoundData é personalizada para gerenciar uniformemente fontes de dados de áudio. pacote org.loon.framework.game.sound; importar org.loon.framework.game.helper.streamhelper; importar org.loon.framework.game.net.uri;/** ** // ** * <p> * title: lOONFROWWORK * </p> * <p> * descrição: para obter o FILETROTWATHON: estrutura) * </p> * <p> * direitos autorais: direitos autorais (c) 2007 * </p> * <p> * Empresa: Loonframework * </p> * * @author chenpeng * @email: [email protected] * @version 0.1 */public Class Sounddata ... {privado por [] Private boolean _loop; private int _type; public static final int _l_soundType_midi = 1; public static final int _l_soundType_wav = 2; /** * // ** * destruidor, usado para injetar Uri, tipo, loop * * @param uri * @param tipo * @param loop */public SoundData (Uri Uri, tipo int, loop boolean) ... {if (uri! = Null) ... {_data = urri.getData (); } _type = type; _loop = loop; }/** * // ** * Destutor, usado para injetar dados, digitar, loop * * @param dados * @param tipo * @param loop */public SoundData (byte [] dados, tipo int, tipo booleano) ... {if (dados! // Direct Copy Byte Array System.arraycopy (dados, 0, _data, 0, _data.length); } _type = type; _loop = loop; }/** * // ** * Destutor, usado para injetar resname, tipo, loop * @param resname * @param tipo * @param loop */public SoundData (string resname, int tipo, loop booleano) ... {this (streamhelper.getDatasource (resname), tipo, loop); } public byte [] getData () ... {return _data; } public boolean getloop () ... {return _loop; } public void setLoop (loop booleano) ... {_loop = loop; } public int getType () ... {return _type; }}
O LoonFramework encapsula os métodos relacionados à reprodução de áudio e o SoundPlay. Os programadores podem ignorar os detalhes internos do Javax.Sound e chamar diretamente o SoundPlay para concluir operações relacionadas.
pacote org.loon.framework.game.sound; importar java.io.byteArrayInputStream; importar javax.sound.midi.metaEventListener; importar javax.sidishismi.metamessage; importação javax.midi.midiStemstem; javax.sound.midi.sequenciador; importar javax.sound.sampled.audiofileFileFile; importar javax.sound.sampled.audiosystem; import javax.sound.sampled.clip; import javax.sound.sampled.dataline; import.; <p> * Título: Loonframework * </p> * <p> * Descrição: Usado para executar operações de arquivo de som (apenas alguns métodos no LoonFramework, consulte a estrutura Loonframework-Game para obter mais detalhes) * </p> * <p> * * Copyright: Copyright (c) 2007 * </p> * <p> @email: [email protected] * @version 0.1 */public class Soundplay implementa MetaventListener, Runnable ... {private int _sleeptime; clipe privado _audio; sequenciador privado _midi; Private boolean _loop; private int _SoundType; Private Boolean _playing; thread privado _thread = null; Privado booleano _isrun = false; /** * // ** * destruidor, inicialize o Soundplay * */public Soundplay () ... {_loop = false; _SoundType = 0; _sleeptime = 1000; _playing = false; } // Carregar o arquivo de som public boolean load (dados do som do som) ... {redet (); if (data == null || data.getData () == null) ... {return false; } retornar init (data.getData (), data.gettype (), data.getloop ()); }/** * // ** * reprodução direta do arquivo URL * * @param uri * @param ftype * @param loop * @return */public boolean load (uri uri, int ftype, loop booleano) ... {// Refresh Data RESET (); if (uri == null) ... {return false; } // Obtenha dados de dados sonoros SoundData = new SoundData (URI, FTYPE, LOOP); if (data == null || data.getData () == null) ... {return false; } retornar init (data.getData (), data.gettype (), data.getloop ()); }/** * // ** * Inicialize dados relacionados ao som * * @param dados * @param ftype * @param loop * @return */private boolean init (byte [] dados, int ftype, loop booleano) ... {resultado booleano = false; ByteArrayInputStream bis = null; tente ... {bis = new ByteArrayInputStream (dados); } catch (Exceção e) ... {bis = null; } if (bis == null) ... {return false; } // Switch de tipo de julgamento (ftype) ... {// midi case Sounddata._l_soundtype_midi: // Quando o MIDI não existe se (_midi == null) ... {tente ... {// obtenha sequenciador _midi = midisystem.getSequescher (); _midi.open (); } catch (exceção ex) ... {_midi = null; } if (_midi! = null) ... {_midi.addMetaEventListener (this); }} // Quando o MIDI ainda não é obtido se (_midi! = Null) ... {// recriar sequência de sequência sc = null; tente ... {sc = midisystem.getSequence (bis); } catch (Exceção e) ... {sc = null; } if (sc! = null) ... {tente ... {_midi.setSequence (sc); // obtenha se deve loop_loop = loop; // obtenha se deve carregar resultado = true; } catch (exceção ee) ... {} // obtenha som type_soundType = sounddata._l_soundtype_midi; }} tente ... {bis.close (); } catch (exceção ee) ... {} break; // WAV Case SoundData._L_SoundType_wav: AudiofileFormat Type = null; // Obtenha o áudio Tente ... {type = Audiosystem.GetAudioFileFormat (BIS); } catch (Exceção e) ... {type = null; } // Fechar o fluxo tente ... {bis.close (); } catch (exceção ex) ... {} if (type == null) ... {return false; } // Construa o objeto de informação da linha de dados com base na informação especificada dataline.info di = new Dataline.info (clip.class, type.getFormat ()); // converte em clipe, tente ... {_audio = (clip) audiosystem.getline (di); } catch (Exceção e) ... {} // Play File Try ... {_Audio.open (type.getFormat (), dados, 0, data.length); _loop = loop; resultado = true; } catch (Exceção e) ... {} // Obtenha tipo de arquivo _SoundType = SoundData._L_SoundType_wav; quebrar; } resultado de retorno; } public boolean play (dados do som do som) ... {if (! carregar (dados)) ... {return false; } retornar play (); } public boolean play () ... {switch (_soundType) ... {case SoundData._l_soundType_midi: tente ... {_midi.start (); _playing = true; _SoundType = SoundData._L_SOUNDTYPE_MIDI; } catch (exceção ee) ... {} break; case SoundData._l_soundType_wav: if (_audio! = null) ... {if (_loop) ... {// Definir loop _Audio.SetloopPoints (0, -1); _AUDIO.SETFAMEPOSIÇÃO (0); _audio.loop (clip.loop_continuouly); } else ... {// Forçar a posição de reprodução a 0 _AUDIO.SETFAMEPOSIÇÃO (0); _audio.start (); } _playing = true; } quebrar; } retornar _playing; }/*** // *** reprodução automática, o loop termina após a parada. * * @Param Data * @return */ public boolean AutoPlay (dados do som do som) ... {if (! load (dados)) ... {return false; } return AutoPlay (); }/*** // *** A reprodução automática termina após a parada do loop. * * @return */ public boolean AutoPlay () ... {_isrun = true; _thread = novo thread (this); _thread.start (); retornar _playing; }/***// ***Pare de tocar*/public void stop () ... {if (_audio! = Null && _audio.isactive ()) ... {tente ... {_audio.stop (); } catch (Exceção e) ... {}} if (_midi! = null) ... {_midi.stop (); } _playing = false; _isrun = false; }/*** // *** Dados de liberação**/public void reset () ... {stop (); _loop = false; _SoundType = 0; if (_midi! = null) ... {_midi.close (); _midi = null; } if (_audio! = null && _audio.isopen ()) ... {_audio.close (); _AUDIO = NULL; } _isrun = false; _thread = null; }/***// ***Definir metamessage*/public void meta (meta de metamessage) ... {// Determine se deve jogar o loop midi if (_loop && _soundType == SoundData._l_l_soundtype_midi && meta.gettype () ==7) _midi.isopen ()) ... {_midi.setMicrosecondPosition (0); _midi.start (); }}} public void run () ... {while (_isrun) ... {play (); // Como o tipo de reprodução é exclusivo, apenas um resultado de jogo será retornado para determinar isso. if (_midi! = null) ... {_playing = _midi.isrunning (); } if (_audio! = null) ... {_playing = _audio.isrunning (); } // Quando a reprodução para if (! _Playing) ... {// release reset (); } tente ... {thread.sleep (_sleeptime); } catch (interruptedException e) ... {e.printStackTrace (); }}} public int getSleeptime () ... {return _sleeptime; }/*** // *** Defina o tempo de loop de encadeamento do AutoPlay. * * @param time */ public void Setsleeptime (int time) ... {_sleeptime = time; }}
Neste momento, o que precisamos enfrentar são apenas os dados do SoundData e as operações do SoundPlay encapsuladas como entidades, sem ter que lidar com o complicado javax.Sound novamente.
O método de chamada é o seguinte:
pacote org.test; importar org.loon.framework.game.helper.streamhelper; importar org.loon.framework.game.net.uri; importar org.loon.framework.game.sound.soundData; importar org.loon.framework.game.soundplyPlay; Loonframework </p> * <p> Descrição: Teste de reprodução do Soundplay </p> * <p> Copyright: Copyright (c) 2007 </p> * <p> Empresa: loonframework </p> * @Author ChenPeng * @Email: [email protected] * * version 0.1 */Publict */Publics SOLTLINATINE… @AOLTRSOY11 */PUBLIONAY (CEPONLINACOLOME.COY.CNAYMALAY (@AIATRSILAY (CEPON.CNAYMOLAY (@AutsLAY (@AutsLatation ftype) .. {Dados do som do som = null; switch (ftype) .. {// toca música da rede através do URI sob o caso de Loonframework 0: Data = new SoundData (new Uri ("http://looframework.sourceforge.net/midi/who é o grande herói.mid"), sounddata._l_soundtypen_mid; quebrar; // toca música através do objeto byte [] do arquivo de música no caso de recurso local 1: byte [] bytes = streamhelper.getResourcedata ("/midi/quem é o grande herói.mid"); Data = novo SoundData (bytes, SoundData._L_SoundType_Midi, false); quebrar; // Toque música através do Caso 2 do Caminho do Arquivo de Música: Data = novo SoundData ("C:/quem é o grande herói.mid", SoundData._L_SoundType_Midi, false); quebrar; } Soundplay play = new Soundplay (); // A diferença entre os métodos de AutoPlay e Play é que o AutoPlay interrompe automaticamente e liberará recursos após o jogo, e a peça precisa ser abortada manualmente. //play.play(data); play.autoPlay (dados); } public static void main (string [] args) .. {selectPlay (2); }}
Um método mais detalhado será explicado depois que o jogo do LoonFramework for totalmente anunciado.
Além disso: como o StreamHelper está associado a outros métodos de Loonframework, ele ainda não será fornecido. O InputStream para Byte [] pode ser escrito da seguinte maneira:
// é o inputStream obtido byteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); // usado para realizar byte [] byte [] Arraybyte = null; tente ... {// O tamanho de cada transferência é 4096 byte [] bytes = new Byte [4096]; bytes = novo byte [is.Available ()]; int leia; while ((read = is.read (bytes))> = 0) ... {bytearrayoutputStream.write (bytes, 0, leia); } ArrayByte = byteArrayOutputStream.tobyteArray (); } catch (ioexception e) ... {return null; } finalmente ... {tente ... {if (byteArrayOutputStream! = null) ... {byteArrayOutputStream.close (); byteArrayOutputStream = null; } if (is! = null) ... {is.close (); é = nulo; }} catch (ioexception e) ... {}}