Java Audio Playback, car elle doit s'appuyer sur l'environnement local, Java a peu d'avantage dans le traitement audio, ou en d'autres termes, il ne tient pas compte des facteurs de lecture audio lors du développement du système Java. Vous devez savoir que dans la première version Java 1.1, il n'y avait pas de package Javax.sound plus tard, et l'audio ne peut être récupéré que via le package d'applet ...
Malheureusement, dans le développement de programmes graphiques, nos programmes doivent inévitablement utiliser la musique de fond, les sons d'effet, etc. pour coopérer avec les opérations d'image. Hélas, c'est vraiment une blague que Master Sun a joué avec nous. Heureusement, Maître Sun a ouvert les yeux et a fourni le paquet Javax.sound pour nous sauver de Dire Straits ~
Mais le problème ultérieur est que dans l'utilisation du package Javax.sound, comme un problème commun dans la classe d'outils multimédias Java, il n'y a pas de mécanisme de libération très complet. Si nous faisons un développement de Windows, appeler MediaPlayer encore et encore ne peut pas être un gros problème, mais en Java, si le programme audio s'exécute à plusieurs reprises, il est très facile de ressentir une perte cumulative de mémoire, de sorte qu'un java.lang.outofMemoryError est lancé, puis ... le programme est accroché, l'utilisateur est stupide, et nous devons foularder ...
C'est déjà une question de "Est-ce tolérable"? Compte tenu de cela, dans mon développement de framework LoonFramework, j'ai intégré les méthodes pertinentes sous Sound, s'efforçant de créer la classe de contrôle audio la plus complète avec le code le plus simple. Maintenant que Loonframework-Game n'a pas encore réussi, nous extraitons d'abord certaines des méthodes pour que tout le monde les examine!
Correspondant aux appels de ressources réseau, notre propre classe URI est établie dans LoonFramework. Le contenu de base est le suivant:
(Lorsque StreamHelper est la propre classe de contrôle de streaming de LoonFramework, veuillez remplacer vous-même la méthode GethTTPSstream.)
Package org.loon.framework.game.net; import org.loon.framework.game.helper.streamhelper; / ** * // ** * <p> * Titre: loonframework * </p> * <p> * Description: LoonFramework dédié uri (Unified Resource Identifier) * </p> * <p> * Copyright: Copyright (C) 2007 * </p> * <p> * Copyright: Copyright (C) 2007 * </p> * <p> * <p> * Compagnie: loonframework * </p> * * @author ChenPeng * @email: [email protected] * @version 0.1 * / classe publique Uri ... {// Type de protocole de transport public Final statique int _L_URI_HTTP = 1; public static final int _l_uri_udp = 2; chaîne privée _uri; private int _type; / ** * // ** * Destructor, utilisé pour injecter URI et Type * * @param uri * @param type * / public uri (String uri, int type) ... {_uri = new String (uri); _Type = type; } / ** * // ** * Destructor, utilisé pour injecter uri * * @param type uri * / public uri (String uri) ... {_uri = new String (uri); _Type = uri._l_uri_http; } / ** * // ** * Renvoie le tableau d'octets de la ressource où se trouve l'URI. * * @return * / byte public [] getData () ... {if (_uri == null) ... {return null; } return streamHelper.gethttpStream (_uri); } public String getUri () ... {return _uri; } public int getType () ... {return _Type; }} Dans le framework LoonFramework, une classe SoundData de base est personnalisée pour gérer uniformément les sources de données audio. package org.loon.framework.game.sound; import org.loon.framework.game.helper.streamhelper; import org.loon.framework.game.net.uri; / ** * // ** * <p> * title: loonframework * </p> * <p> * Description) * </p> * <p> * Copyright: Copyright (C) 2007 * </p> * <p> * Compagnie: loonframework * </p> * * @author ChenPeng * @email: [email protected] * @version 0.1 * / public classe SoundData ... {Byte private [] _data; Boolean privé _loop; private int _type; public static final int _l_soundtype_midi = 1; public static final int _l_soundtype_wav = 2; / ** * // ** * Destructor, utilisé pour injecter uri, type, boucle * * @param uri * @param type * @param loop * / public sondata (uri uri, int type, booléan lobe) ... {if (uri! = Null) ... {_data = uri.getData (); } _type = type; _Loop = Loop; } / ** * // ** * Destructor, utilisé pour injecter des données, type, boucle * * @param data * @param type * @param loop * / public sondata (byte [] data, int type, booléan lobe) ... {if (data! = Null && data.length> 0) ... {_data = new Byte [data.Length]; // Copie Direct Copy Byte Array System.ArrayCopy (Data, 0, _data, 0, _data.Length); } _type = type; _Loop = Loop; } / ** * // ** * Destructor, utilisé pour injecter Resname, Type, Loop * @param Resname * @param Type * @param Loop * / public SoundData (String Resname, int type, Boolean Loop) ... {this (streamhelper.getDataSource (Resname), Type, Loop); } octet public [] getData () ... {return _data; } public boolean getloop () ... {return _loop; } public void setloop (Boolean Loop) ... {_loop = Loop; } public int getType () ... {return _Type; }}
LoonFramework résume les méthodes et le jeu sonore liés à la lecture audio. Les programmeurs peuvent ignorer les détails internes de Javax.sound et appeler directement Soundplay pour terminer les opérations connexes.
package org.loon.framework.game.sound; import java.io.bytearrayInputStream; import javax.sound.midi.metaeventListener; import javax.sound.midi.metaMessage; import javax.send javax.sound.midi.senshercer; import javax.sound.sampled.audiofileformat; import javax.sound.sampled.audiosystem; import javax.sound.sampled.clip; import javax.sound.sampled.dataline; import org.loon.framework.game.net.uri; / ** * * * <p> * LoonFramework * </p> * <p> * Description: Utilisé pour effectuer des opérations de fichiers sonores (seulement certaines méthodes dans LoonFramework, voir le framework LoonFramework-Game pour plus de détails) * </p> * <p> * Copyright: Copyright (C) 2007 * </p> * <p> * Company: LoonFramework * </p> * * @Author Chenpeng * @email: [email protected] * @version 0.1 * / classe publique Soundplay implémente MetaEventListener, Runnable ... {private int _sleeptime; Clip privé _Audio; séquenceur privé _midi; Boolean privé _loop; private int _soundType; Boolean privé _playing; thread privé _thread = null; Boolean privé _isrun = false; / ** * // ** * Destructor, Initialize Soundplay * * / public SoundPlay () ... {_loop = false; _SoundType = 0; _SleEptime = 1000; _playing = false; } // Chargez le fichier son public Boolean Load (SoundData Data) ... {reset (); if (data == null || data.getData () == null) ... {return false; } return init (data.getData (), data.getType (), data.getloop ()); } / ** * // ** * Perade directe du fichier URL * * @param uri * @param fType * @param Loop * @return * / public boolean charge (uri uri, int fType, Boolean Loop) ... {// Refresh data reset (); if (uri == null) ... {return false; } // Get SoundData SoundData Data = new SoundData (URI, FTYPE, LOOP); if (data == null || data.getData () == null) ... {return false; } return init (data.getData (), data.getType (), data.getloop ()); } / ** * // ** * Initialiser les données liées au son * * @param data * @param ftype * @param boucle * @return * / private booléen init (byte [] data, int fType, booléan lobe) ... {boolean result = false; BytearrayInputStream bis = null; essayez ... {bis = new bytearrayInputStream (data); } catch (exception e) ... {bis = null; } if (bis == null) ... {return false; } // Judging Type Switch (fType) ... {// midi case sounddata._l_soundtype_midi: // lorsque midi n'existe pas if (_midi == null) ... {try ... {// get séquencer _midi = midisystem.getSederer (); _midi.open (); } catch (exception ex) ... {_midi = null; } if (_midi! = null) ... {_midi.addMetaEventListener (this); }} // lorsque midi n'est toujours pas obtenu if (_midi! = Null) ... {// recréer la séquence de séquence sc = null; essayez ... {sc = midisystem.getSequence (bis); } catch (exception e) ... {sc = null; } if (sc! = null) ... {try ... {_midi.setSequence (sc); // obtenez si vous LOOP_LOOP = LOOP; // obtenez si le résultat de résultat = true; } catch (exception ee) ... {} // get son type_soundtype = sondata._l_soundtype_midi; }} essayez ... {bis.close (); } catch (exception ee) ... {} Break; // WAV Case SoundData._L_SOUNDTYPE_WAV: AudioFileFormat Type = NULL; // Obtenez un essai audio ... {type = Audiosystem.getAudioFileFormat (bis); } catch (exception e) ... {type = null; } // Fermer Stream Try ... {bis.close (); } catch (exception ex) ... {} if (type == null) ... {return false; } // Construisez l'objet d'information de la ligne de données en fonction de l'information spécifiée Dataline.info di = new Dataline.info (clip.class, type.getFormat ()); // Convertir en clip try ... {_audio = (clip) Audiosystem.getLine (di); } catch (exception e) ... {} // lecture de fichiers essai ... {_audio.open (type.getFormat (), data, 0, data.length); _Loop = Loop; résultat = true; } catch (exception e) ... {} // Get File Type _SoundType = SoundData._L_SOUNDTYPE_WAV; casser; } Retour Résultat; } public boolean play (SoundData data) ... {if (! Load (data)) ... {return false; } return play (); } public boolean play () ... {switch (_soundType) ... {case sondata._l_soundtype_midi: essayez ... {_midi.start (); _playing = true; _SoundType = SoundData._L_SOUNDTYPE_MIDI; } catch (exception ee) ... {} Break; Case SoundData._L_SOUNDTYPE_WAV: if (_Audio! = NULL) ... {if (_loop) ... {// set loop _audio.setlooppoints (0, -1); _audio.setFramePosition (0); _Audio.loop (clip.loop_continuly); } else ... {// Forcer la position de lecture à 0 _audio.setFramePosition (0); _audio.start (); } _playing = true; } casser; } return _playing; } / ** * // ** * La lecture automatique, la boucle se termine après l'arrêt. * * @param data * @return * / public boolean autoPlay (SoundData data) ... {if (! Load (data)) ... {return false; } return AutoPlay (); } / ** * // ** * La lecture automatique, la boucle se termine après l'arrêt. * * @return * / public boolean autoplay () ... {_isrun = true; _thread = nouveau thread (this); _thread.start (); return _playing; } / ** * // ** * arrête de jouer * / public void stop () ... {if (_audio! = Null && _audio.isactive ()) ... {try ... {_audio.stop (); } catch (exception e) ... {}} if (_midi! = null) ... {_midi.stop (); } _playing = false; _isrun = false; } / ** * // ** * Release Data * * / 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; } / ** * // ** * Définir MetaSessage * / public void Meta (MetaSSage Meta) ... {// Déterminez s'il faut jouer à Midi Loop if (_Loop && _SoundType == SoundData._L_SoundType_midi && Meta.getType () == 47) _midi.isopen ()) ... {_midi.setMicRoseCondPosition (0); _midi.start (); }}} public void run () ... {while (_isrun) ... {play (); // Parce que le type de lecture est unique, un seul résultat de jeu sera retourné pour le déterminer. if (_midi! = null) ... {_playing = _midi.isrunning (); } if (_audio! = null) ... {_playing = _audio.isrunning (); } // Lorsque la lecture s'arrête if (! _Playing) ... {// release reset (); } essayez ... {thread.sleep (_sleEptime); } catch (InterruptedException e) ... {e.printStackTrace (); }}} public int getleEptime () ... {return _sleEptime; } / ** * // ** * Définissez le temps de boucle de filetage de jeu automatique. * * @param time * / public void setsleeptime (int time) ... {_sleEptime = time; }}
À l'heure actuelle, ce dont nous devons faire face, ce ne sont que des données SoundData et des opérations de jeu sonore encapsulées comme des entités, sans avoir à traiter à nouveau le Javax.sound compliqué.
La méthode d'appel est la suivante:
package org.test; import org.loon.framework.game.helper.streamhelper; import org.loon.framework.game.net.uri; import org.loon.framework.game.sound.sounddata; import org.loon.framework.game.soundwork; / ** * // ** * * <p> Description: Soundplay Playback Test </p> * <p> Copyright: Copyright (C) 2007 </p> * <p> Company: loonframework </p> * @author ChenPeng * @email: [email protected] * @version 0.1 * / public class SoundplayTest ... {natic void seletsplay (int ftype). Switch (fType) .. {// jouer de la musique du réseau via l'URI sous le cas de loonframework 0: data = new SoundData (New Uri ("http://looframework.sourceforge.net/midi/who est le big héros.mid"), Sounddata._L_SoundType_midi, faux); casser; // Play Music via l'objet Byte [] du fichier musical dans le cas de ressources locales 1: Byte [] bytes = streamhelper.getResourcedata ("/ midi / who is the Big Hero.mid"); data = new SoundData (octets, sounddata._l_soundtype_midi, false); casser; // Play Music via le Cas de chemin de fichier musical 2: Data = new SoundData ("C: / Who Is the Big Hero.mid", Sounddata._L_SOUNDTYPE_MIDI, FAUX); casser; } SoundPlay play = new Soundlay (); // La différence entre les méthodes de lecture automatique et de lecture est que la lecture automatique s'arrêtera et publiera automatiquement les ressources après avoir joué, et la pièce doit être interrompue manuellement. //play.play(data); play.autoplay (données); } public static void main (String [] args) .. {selectPlay (2); }}
Une méthode plus détaillée sera expliquée après l'annonce du jeu LoonFramework.
De plus: puisque StreamHelper est associé à d'autres méthodes de loonframework, elle ne sera pas encore donnée. L'octise de l'octet [] peut être écrit comme suit:
// est le ByTeArraytStream OBTEATSTREAM obtenu ByteAutputStream ByteArrayOutputStream = new ByteArrayOutputStream (); // Utilisé pour entreprendre l'octet [] BYTE [] ArrayByte = NULL; Essayez ... {// La taille de chaque transfert est de 4096 octet [] octets = nouveau octet [4096]; Bytes = new Byte [is.Available ()]; int lic; while ((read = is.read (bytes))> = 0) ... {bytearrayoutputStream.write (bytes, 0, lecture); } arrayByte = bytearrayoutputStream.ToByTearray (); } catch (ioException e) ... {return null; } Enfin ... {Try ... {if (byTearRayOutputStream! = null) ... {bytearrayoutputStream.close (); byteArrayOutputStream = null; } if (is! = null) ... {is.close (); est = null; }} catch (ioexception e) ... {}}