La reproducción de audio de Java, debido a que debe confiar en el entorno local, Java tiene poca ventaja en el procesamiento de audio, o en otras palabras, no considera los factores de reproducción de audio al desarrollar el sistema Java. Debe saber que en la primera versión de Java 1.1, no hubo un paquete Javax.Sound más tarde, y el audio solo se puede recuperar a través del paquete de applet ...
Desafortunadamente, en el desarrollo de programas de gráficos, nuestros programas inevitablemente necesitan usar música de fondo, sonidos de efectos, etc. para cooperar con las operaciones de imagen. Por desgracia, esta es realmente una broma que el Maestro Sun nos ha jugado. Afortunadamente, el maestro Sun abrió los ojos y proporcionó el paquete Javax. Sound para salvarnos de Dire Straits ~
Pero el problema posterior es que en el uso del paquete Javax.Sound, como un problema común en la clase de herramientas multimedia Java, no hay un mecanismo de liberación muy completo. Si hacemos el desarrollo de Windows, llamar a MediaPlayer una y otra vez puede no ser un gran problema, pero en Java, si el programa de audio se ejecuta repetidamente, es muy fácil experimentar la pérdida acumulada de la memoria, de modo que un java.lang.outofMemoryError se lanza, y luego ... el programa cuelga, el usuario es estúpido y nos volvemos locos ...
Esta ya es una cuestión de "¿Es tolerable"? En vista de esto, en mi desarrollo del marco de LoonFramework, he integrado secundariamente los métodos relevantes bajo sonido, esforzándose por crear la clase de control de audio más completa con el código más simple. Ahora que LoonFramework-Game aún no ha logrado un gran éxito, ¡primero extraeré algunos métodos para que los eche un vistazo!
En correspondencia con las llamadas de recursos de red, nuestra propia clase URI se establece en LoonFramework. El contenido básico es el siguiente:
(Donde StreamHelper es la clase de control de transmisión de Loonframework, reemplace el método GethttpStream usted mismo).
paquete org.loon.framework.game.net; import org.loon.framework.game.helper.streamHelper;/** * // ** * <p> * title: loonframework * </p> * <p> * Descripción: LoonFramework Uri (Identificador de recursos unificado) * </p> * <P> * Copyright: Copyright (c) 2007 * <p> * Company: Loonframework * </p> * * @author Chenpeng * @email: [email protected] * @version 0.1 */public class Uri ... {// Protocolo de transporte Tipo de protocolo público estático final int _l_http = 1; Public static final int _l_uri_udp = 2; cadena privada _uri; privado int _type; /** * // ** * destructor, utilizado para inyectar URI y tipo * * @param uri * @param type */public uri (string uri, int type) ... {_uri = new String (uri); _type = type; }/** * // ** * destructor, utilizado para inyectar uri * * @param type uri */public uri (string uri) ... {_uri = new String (uri); _type = uri._l_uri_http; }/*** // *** Devuelve la matriz de bytes del recurso donde se encuentra el URI. * * @return */ public byte [] getData () ... {if (_uri == null) ... {return null; } return streamHelper.gethttpStream (_uri); } public String geturi () ... {return _uri; } public int getType () ... {return _type; }} En el marco LoonFramework, se personaliza una clase básica de Data para administrar uniformemente las fuentes de datos de audio. paquete org.loon.framework.game.sound; import org.loon.framework.game.helper.streamhelper; importar org.loon.framework.game.net.uri;/** * // ** * <p> * Título: Loonframework * </p> * <p> * Descripción: Usado para obtener y cache Sound Data (para obtener datos de archivos de sonido adicional, vea la información de LOONFRAME * </p> * <p> * Descripción: Usado para obtener y cache Sound Data (para obtener datos de archivos de sonido adicional, vea el Título: Framework) * </p> * <p> * Copyright: Copyright (c) 2007 * </p> * * <p> * Company: Loonframework * </p> * * @author Chenpeng * @email: [email protected] * @version 0.1 */public class Sounddata ... {byte privado [] _data; booleano privado _loop; privado int _type; Public static final int _l_soundType_midi = 1; Public static final int _l_soundType_wav = 2; /** * // ** * destructor, utilizado para inyectar Uri, tipo, bucle * * @param uri * @param type * @param loop */public soundData (uri uri, int type, boolean loop) ... {if (uri! = Null) ... {_data = uri.getData (); } _type = type; _loop = loop; }/** * // ** * Destructor, utilizado para inyectar datos, tipo, bucle * * @param data * @param type * @param bucle */public soundData (byte [] data, int type, boolean loop) ... {if (data! = Null && data.length> 0) ... {_data = new Byte [data.lengthing]; // Copia directa Byte Array System.ArrayCopy (datos, 0, _data, 0, _data.length); } _type = type; _loop = loop; }/** * // ** * destructor, utilizado para inyectar resname, type, bucle * @param resname * @param type * @param loop */public soundData (string resname, int type, boolean loop) ... {this (streamHelper.getDataSource (resname), type, bucle); } public byte [] getData () ... {return _data; } public boolean getLoop () ... {return _loop; } public void setloop (boolean loop) ... {_loop = loop; } public int getType () ... {return _type; }}
LoonFramework encapsula los métodos relacionados con la reproducción de audio y el juego de sonido. Los programadores pueden ignorar los detalles internos de Javax.Sound y llamar directamente a SoundPlay para completar las operaciones relacionadas.
paquete org.loon.framework.game.sound; import java.io.bytearrayInputStream; import javax.Sound.Midi.MetaEventListener; import javax.sound.midi.metAmessage; import javax.sound.midi.midisystem; import javax.sound.midi.shusion; import; importar; import javax.Sound.Midi.Sequencer; import javax.Sound.Sampled.audiofileFormat; import javax.sound.sampleed.audiosystem; import javax.sound.samppled.clip; import javax.sound.sampled.dataline; import org.loon.framework.game.netnet; * Título: LoonFramework * </p> * <p> * Descripción: Se usa para realizar operaciones de archivos de sonido (solo algunos métodos en LoonFramework, consulte el marco LoonFramework-Game para obtener más detalles) * </p> * <p> * Copyright: Copyright (c) 2007 * </p> * <p> * Compañía: Loonframework * </p> * * @Author Chenpeng * @email: [email protected] * @version 0.1 */public class SoundPlay implementa metaeventListener, runnable ... {private int _sleeptime; clip privado _audio; secuenciador privado _midi; booleano privado _loop; privado int _soundType; booleano privado _laying; hilo privado _thread = null; booleano privado _isrun = false; /** * // ** * Destructor, inicializar SoundPlay * */public SoundPlay () ... {_loop = false; _soundType = 0; _Sleeptime = 1000; _playing = false; } // Cargue el archivo de sonido Public boolean Load (soundData data) ... {reset (); if (data == null || data.getData () == null) ... {return false; } return init (data.getData (), data.gettype (), data.getloop ()); }/** * // ** * Reproducción directa del archivo URL * * @param uri * @param ftype * @param bucle * @return */public boolean load (uri uri, int ftype, boolean loop) ... {// actualizar el reajuste de datos (); if (uri == null) ... {return false; } // Obtener data SoundData SoundData = nuevo SoundData (URI, FTYPE, Loop); if (data == null || data.getData () == null) ... {return false; } return init (data.getData (), data.gettype (), data.getloop ()); }/** * // ** * Inicializar datos relacionados con el sonido * * @param data * @param ftype * @param loop * @return */private boolean init (byte [] data, int ftype, boolean loop) ... {resultado boolean = falso; BytearrayInputStream bis = null; intente ... {bis = new bytearrayInputStream (datos); } capt (excepción e) ... {bis = null; } if (bis == null) ... {return false; } // Switch de tipo de juicio (ftype) ... {// midi case soundData._l_soundtype_midi: // Cuando MIDI no existe si (_midi == null) ... {try ... {// get secuencer _midi = mid midmidystem.getSeSeSequeSer (); _midi.open (); } capt (excepción ex) ... {_midi = null; } if (_midi! = null) ... {_midi.addmetaeventListener (this); }} // Cuando MIDI todavía no se obtiene si (_midi! = NULL) ... {// Recree secuencia secuencia sc = null; intente ... {sc = midisystem.getSequence (bis); } capt (excepción e) ... {sc = null; } if (sc! = null) ... {try ... {_midi.setSequence (sc); // Obtener si a bucle_loop = loop; // Obtener si cargar resultado = true; } catch (Exception ee) ... {} // Get Sound type_soundType = SoundData._L_SoundType_Midi; }} try ... {bis.close (); } catch (excepción ee) ... {} ruptura; // WAV Case SoundData._L_SoundType_wav: AudiofileFormat type = null; // Get Audio intenta ... {type = audiosystem.getAudiofileFormat (bis); } capt (excepción e) ... {type = null; } // Cerrar flujo intente ... {bis.close (); } catch (excepción ex) ... {} if (type == null) ... {return false; } // Construye el objeto de información de la fila de datos en función de la información especificada dataLine.info di = new DataLine.info (clip.class, type.getformat ()); // Convertir a clip inty ... {_audio = (clip) audiosystem.getline (di); } catch (Exception e) ... {} // Play File intente ... {_audio.open (type.getformat (), data, 0, data.length); _loop = loop; resultado = verdadero; } catch (Exception e) ... {} // Obtener tipo de archivo _SoundType = SoundData._L_SoundType_wav; romper; } resultado de retorno; } Public Boolean Play (SoundData Data) ... {if (! Load (data)) ... {return false; } return play (); } public boolean Play () ... {switch (_soundType) ... {case SoundData._l_SoundType_Midi: intente ... {_midi.start (); _playing = true; _soundType = SoundData._L_SoundType_Midi; } catch (excepción ee) ... {} ruptura; caso SoundData._l_SoundType_wav: if (_audio! = NULL) ... {if (_loop) ... {// establecer el bucle _audio.setloopPoints (0, -1); _audio.setFramePosition (0); _audio.loop (clip.loop_continuously); } else ... {// Forzar la posición de reproducción a 0 _audio.setFramePosition (0); _audio.start (); } _playing = true; } romper; } return _playing; }/*** // *** Reproducción automática, el bucle termina después de la parada. * * @param data * @return */ public boolean autoplay (data soundData) ... {if (! Load (data)) ... {return false; } return autoplay (); }/*** // *** reproducción automática, termina después de que se detiene el bucle. * * @return */ public boolean autoplay () ... {_isrun = true; _thread = nuevo hilo (this); _thread.start (); return _ playing; }/***// ***Deja de jugar*/public void stop () ... {if (_audio! = Null && _audio.isactive ()) ... {try ... {_audio.stop (); } catch (excepción e) ... {}} if (_midi! = null) ... {_midi.stop (); } _playing = false; _isrun = false; }/*** // *** DATOS DE LA REPARACIÓN**/public void Reset () ... {stop (); _loop = falso; _soundType = 0; if (_midi! = null) ... {_midi.close (); _midi = nulo; } if (_audio! = null && _audio.isopen ()) ... {_audio.close (); _audio = nulo; } _isrun = false; _thread = nulo; }/***// ***Establezca metamessage*/public void meta (metamessage meta) _midi.isopen ()) ... {_midi.setmicrosecondPosition (0); _midi.start (); }}} public void run () ... {while (_isrun) ... {play (); // Debido a que el tipo de reproducción es único, solo se devolverá un resultado de juego para determinar esto. if (_midi! = null) ... {_playing = _midi.isrunning (); } if (_audio! = null) ... {_playing = _audio.isrunning (); } // Cuando la reproducción se detiene si (! _Playing) ... {// libere reset (); } try ... {thread.sleep (_sleeptime); } catch (InterruptedException e) ... {E.PrintStackTrace (); }}} public int getSleepTime () ... {return _sleeptime; }/*** // *** Establezca el tiempo de bucle de subprocesos automático. * * @param time */ public void setSleepTime (int tiempo) ... {_sleeptime = time; }}
En este momento, lo que necesitamos enfrentar son solo datos de datos de sonido y operaciones de juego de sonido encapsulado como entidades, sin tener que lidiar con el complicado Javax. Sound nuevamente.
El método de llamada es el siguiente:
paquete org.test; import org.loon.framework.game.helper.streamHelper; import org.loon.framework.game.net.uri; importar org.loon.framework.game.sound.sounddata; import org.loon.framework.game.sound.soundplay;/** ** *** <pil. <P> Descripción: prueba de reproducción de SoundPlay </p> * <p> Copyright: Copyright (c) 2007 </p> * <p> Company: Loonframework </p> * @author Chenpeng * @email: [email protected] * @version 0.1 */public class SoundPlayTest ... {static void SelectPlay (int ftype) ... datos = nulo; switch (ftype) .. {// reproduce música desde la red a través del URI bajo el caso de loonframework 0: data = new SoundData (new Uri ("http://looframework.sourceforge.net/midi/who es el gran héroe.mid"), SoundData._l_soundtype_midi, false); romper; // reproducir música a través del objeto Byte [] del archivo de música en el caso de recursos locales 1: byte [] bytes = streamHelper.getResourcedata ("/Midi/quién es el gran héroe.mid"); data = new SoundData (bytes, SoundData._l_SoundType_Midi, falso); romper; // reproducir música a través de la ruta del archivo de música Caso 2: data = new SoundData ("C:/quién es el Big Hero.Mid", SoundData._L_SoundType_Midi, falso); romper; } SoundPlay Play = new SoundPlay (); // La diferencia entre los métodos de reproducción automática y reproducción es que Autoplay detendrá y liberará automáticamente los recursos después de reproducir, y la obra debe ser abortada manualmente. //play.play(data); Play.auToPlay (datos); } public static void main (string [] args) .. {selectPlay (2); }}
Se explicará un método más detallado después de anunciar completamente el juego Loonframework.
Además: dado que StreamHelper se asocia con otros métodos de trabajo de loon, aún no se dará. El InputStream a Byte [] se puede escribir de la siguiente manera:
// es el InputStream BytearRauteutputStream ByteArRauteutputStream de inputStream obtenido de InputStream. intente ... {// El tamaño de cada transferencia es 4096 byte [] bytes = new byte [4096]; bytes = new byte [is.available ()]; int. while ((read = is.read (bytes))> = 0) ... {bytearRayOutputStream.write (bytes, 0, read); } arrayByte = byteArRAyOutputStream.tobyTearray (); } catch (ioException e) ... {return null; } Finalmente ... {try ... {if (bytearRayOutputStream! = NULL) ... {bytearRayOutputStream.close (); bytearRayOutputStream = null; } if (is! = null) ... {is.close (); es = nulo; }} catch (ioException e) ... {}}