Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
- package soundly.impl;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import javax.sound.sampled.AudioFormat;
- import paulscode.sound.Channel;
- import paulscode.sound.FilenameURL;
- import paulscode.sound.ListenerData;
- import paulscode.sound.MidiChannel;
- import paulscode.sound.SoundBuffer;
- import paulscode.sound.SoundSystemConfig;
- import paulscode.sound.SoundSystemException;
- import paulscode.sound.SoundSystemLogger;
- import paulscode.sound.Source;
- import paulscode.sound.StreamThread;
- import soundly.Sound;
- /**
- * A simple rework of Library which is more geared toward fast access and
- * modification of sources. Most of the code here was taken from Library.
- *
- * @author Paul, davedes
- */
- public class SimpleLibrary {
- private StreamThread streamThread;
- protected Sound[] sounds;
- /** A list of sounds representing those that are about to be played. */
- protected Sound[] queue;
- /** The actual list of channels. */
- protected Channel[] channels;
- /**
- * Processes status messages, warnings, and error messages.
- */
- protected SoundSystemLogger logger;
- /**
- * Position and orientation of the listener.
- */
- protected ListenerData listener;
- /**
- * Map containing sound file data for easy lookup by filename / identifier.
- */
- protected HashMap<String, SoundBuffer> bufferMap = null;
- /**
- * Interface through which MIDI files can be played.
- */
- private MidiChannel midiChannel;
- private int streamingCount;
- private int normalCount;
- private int channelCount;
- private List<Source> tempSources;
- public SimpleLibrary() {
- bufferMap = new HashMap<String, SoundBuffer>();
- tempSources = new ArrayList<Source>();
- listener = new ListenerData(0.0f, 0.0f, 0.0f, // position
- 0.0f, 0.0f, -1.0f, // look-at direction
- 0.0f, 1.0f, 0.0f, // up direction
- 0.0f); // angle
- streamThread = new StreamThread();
- streamThread.start();
- }
- /* ########################################################################## */
- /* BEGIN OVERRIDE METHODS */
- /* */
- /* The following methods should be overrided as required */
- /* ########################################################################## */
- /**
- * Initializes the sound library.
- */
- public void init() throws SoundSystemException {
- Channel channel = null;
- streamingCount = SoundSystemConfig.getNumberStreamingChannels();
- normalCount = SoundSystemConfig.getNumberNormalChannels();
- channelCount = streamingCount + normalCount;
- channels = new Channel[channelCount];
- sounds = new Sound[channelCount];
- queue = new Sound[channelCount];
- for (int i = 0; i < channelCount; i++) {
- channels[i] = createChannel(i < streamingCount
- ? SoundSystemConfig.TYPE_STREAMING
- : SoundSystemConfig.TYPE_NORMAL);
- }
- }
- /**
- * Stops all sources, shuts down sound library, and removes references to all
- * instantiated objects. This will not cleanup() individual sources; that
- * must be done through the Soundly engine.
- */
- public void cleanup() {
- streamThread.kill();
- streamThread.interrupt();
- // wait up to 5 seconds for stream thread to end:
- for (int i = 0; i < 50; i++) {
- if (!streamThread.alive()) {
- break;
- }
- try {
- Thread.sleep(100);
- } catch (Exception e) {
- }
- }
- if (streamThread.alive()) {
- message("Stream did not die... continuing cleanup");
- }
- if (midiChannel != null) {
- midiChannel.cleanup();
- midiChannel = null;
- }
- Channel channel = null;
- for (int i = 0; i < channels.length; i++) {
- if (channels[i] != null) {
- channels[i].close();
- channels[i].cleanup();
- channels[i] = null;
- }
- }
- listener = null;
- streamThread = null;
- //source.cleanup is handled elsewhere
- }
- /**
- * Creates a new channel of the specified type (normal or streaming). Possible
- * values for channel type can be found in the
- * {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} class.
- * @param type Type of channel.
- * @return The new channel.
- */
- public Channel createChannel(int type) {
- return new Channel(type);
- }
- /**
- * Checks if the no-sound library type is compatible.
- * @return True or false.
- */
- public static boolean libraryCompatible() {
- return true; // the no-sound library is always compatible.
- }
- /**
- * Pre-loads a sound into memory.
- * @param filenameURL Filename/URL of the sound file to load.
- * @return True if the sound loaded properly.
- */
- public boolean loadSound(FilenameURL filenameURL) {
- return true;
- }
- /**
- * Saves the specified sample data, under the specified identifier. This
- * identifier can be later used in place of 'filename' parameters to reference
- * the sample data.
- * @param buffer the sample data and audio format to save.
- * @param identifier What to call the sample.
- * @return True if there weren't any problems.
- */
- public boolean loadSound(SoundBuffer buffer, String identifier) {
- return true;
- }
- /**
- * Returns the filenames of all previously loaded sounds.
- * @return LinkedList of String filenames.
- */
- public String[] loadedFilenames() {
- Set<String> keys = bufferMap.keySet();
- return keys.toArray(new String[keys.size()]);
- }
- /**
- * Removes a pre-loaded sound from memory. This is a good method to use for
- * freeing up memory after a large sound file is no longer needed. NOTE: the
- * source will remain in memory after this method has been called, for as long
- * as the sound is attached to an existing source.
- * @param filename Filename/identifier of the sound file to unload.
- */
- public void unloadSound(String filename) {
- bufferMap.remove(filename);
- }
- public Source createSource(String name, FilenameURL url, boolean streaming, boolean temporary) {
- float r = SoundSystemConfig.getDefaultRolloff();
- int att = SoundSystemConfig.ATTENUATION_NONE;
- return new Source(false, streaming, false, name, url, null, 0, 0, 0, att, r, temporary);
- }
- public Source rawDataStream(AudioFormat audioFormat, String name, boolean streaming, boolean temporary) {
- float r = SoundSystemConfig.getDefaultRolloff();
- int att = SoundSystemConfig.ATTENUATION_NONE;
- Source s = new Source(audioFormat, false, name, 0, 0, 0, att, r);
- s.setTemporary(temporary);
- return s;
- }
- public MidiChannel getMidi() {
- return midiChannel;
- }
- protected int findBestChannel(Sound sound) {
- return 0;
- }
- /**
- * Feeds raw data through the specified source. The source must be a
- * streaming source and it can not be already associated with a file or URL to
- * stream from.
- * @param source Streaming source to play from.
- * @param buffer Byte buffer containing raw audio data to stream.
- * @return Number of prior buffers that have been processed, or -1 if unable to queue the buffer (if the source was culled, for example).
- */
- public int feedRawAudioData(Sound sound, byte[] buffer, int index) {
- Source source = sound.getSource();
- if (source == null) {
- throw new IllegalArgumentException("Source parameter null in method "
- + "'feedRawAudioData'");
- }
- if (!source.toStream) {
- throw new IllegalArgumentException("Only a streaming source may be specified in "
- + "method 'feedRawAudioData'");
- }
- if (!source.rawDataStream) {
- throw new IllegalArgumentException("Streaming source already associated with a "
- + "file or URL in method'feedRawAudioData'");
- }
- if (index > streamingCount) {
- throw new IllegalArgumentException("Given index for feedRawAudioData cannot be > streamingCount");
- }
- if (!source.playing() || source.channel == null) {
- Channel channel;
- if (source.channel != null && (source.channel.attachedSource
- == source)) {
- channel = source.channel;
- } else {
- int cInd = index >= 0 ? index : findBestChannel(sound);
- channel = channels[cInd];
- }
- int processed = source.feedRawAudioData(channel, buffer);
- channel.attachedSource = source;
- streamThread.watch(source);
- streamThread.interrupt();
- return processed;
- }
- return (source.feedRawAudioData(source.channel, buffer));
- }
- /**
- * Plays the specified source.
- * @param source The source to play.
- */
- public void play(Sound sound, int index) {
- Source source = sound.getSource();
- if (source == null) {
- return;
- }
- if (source.toStream && index > streamingCount) {
- throw new IllegalArgumentException("Given play() index for streaming sound must be <= streamCount");
- } else if (!source.toStream && index <= streamingCount) {
- throw new IllegalArgumentException("Given play() index for normal sound must be > streamCount");
- }
- // raw data streams will automatically play when data is sent to them,
- // so no need to do anything here.
- if (source.rawDataStream) {
- return;
- }
- if (!source.active()) {
- return;
- }
- if (!source.playing()) {
- int cInd = index >= 0 ? index : findBestChannel(sound);
- Channel channel = channels[cInd];
- if (channel != null) {
- if (source.channel != null
- && source.channel.attachedSource != source) {
- source.channel = null;
- }
- channel.attachedSource = source;
- source.play(channel);
- if (source.toStream) {
- streamThread.watch(source);
- streamThread.interrupt();
- }
- }
- }
- }
- /**
- * Sets the overall volume to the specified value, affecting all sources.
- * @param value New volume, float value ( 0.0f - 1.0f ).
- */
- public void setMasterVolume(float value) {
- SoundSystemConfig.setMasterGain(value);
- if (midiChannel != null) {
- midiChannel.resetGain();
- }
- }
- private void listenerChanged() {
- for (int i = 0; i < channelCount; i++) {
- if (queue[i] != null) {
- queue[i].listenerChanged();
- } else if (sounds[i] != null) {
- sounds[i].listenerChanged();
- }
- }
- }
- public void setListenerPosition(float x, float y, float z) {
- listener.setPosition(x, y, z);
- listenerChanged();
- }
- /**
- * Changes the listeners orientation to the specified 'angle' radians
- * counterclockwise around the y-Axis.
- * @param angle Angle in radians.
- */
- public void setListenerAngle(float angle) {
- listener.setAngle(angle);
- listenerChanged();
- }
- /**
- * Changes the listeners orientation using the specified coordinates.
- * @param lookX X element of the look-at direction.
- * @param lookY Y element of the look-at direction.
- * @param lookZ Z element of the look-at direction.
- * @param upX X element of the up direction.
- * @param upY Y element of the up direction.
- * @param upZ Z element of the up direction.
- */
- public void setListenerOrientation(float lookX, float lookY, float lookZ,
- float upX, float upY, float upZ) {
- listener.setOrientation(lookX, lookY, lookZ, upX, upY, upZ);
- listenerChanged();
- }
- /**
- * Changes the listeners position and orientation using the specified listener
- * data.
- * @param l Listener data to use.
- */
- public void setListenerData(ListenerData l) {
- listener.setData(l);
- }
- /**
- * Searches for and removes all temporary sources that have finished playing.
- */
- public void removeTemporarySources() {
- for (Source s : tempSources) {
- if (!s.playing()) {
- s.cleanup();
- }
- }
- tempSources.clear();
- }
- /**
- * Makes sure the current volume levels of streaming sources and MIDI are
- * correct. This method is designed to help reduce the "jerky" fading behavior
- * that happens when using some library and codec pluggins (such as
- * LibraryJavaSound and CodecJOrbis). This method has no effect on normal
- * "non-streaming" sources. It would normally be called somewhere in the main
- * "game loop". IMPORTANT: To optimize frame-rates, do not call this method
- * for every frame. It is better to just call this method at some acceptable
- * "granularity" (play around with different granularities to find what sounds
- * acceptable for a particular situation).
- */
- public void checkFadeVolumes() {
- if (midiChannel != null) {
- midiChannel.resetGain();
- }
- Channel c;
- Source s;
- for (int x = 0; x < streamingCount; x++) {
- c = channels[x];
- if (c != null) {
- s = c.attachedSource;
- if (s != null) {
- s.checkFadeOut();
- }
- }
- }
- c = null;
- s = null;
- }
- /**
- *
- * Specifies the MIDI channel to use.
- * @param c New MIDI channel.
- */
- public void setMidiChannel(MidiChannel c) {
- if (midiChannel != null && midiChannel != c) {
- midiChannel.cleanup();
- }
- midiChannel = c;
- }
- /**
- * Loads the specified MIDI file, and saves the source information about it.
- * @param toLoop Midi file should loop or play once.
- * @param sourcename Source identifier.
- * @param filenameURL Filename/URL of the MIDI file to load.
- * @return the newly created MidiChannel
- */
- public MidiChannel loadMidi(boolean toLoop, String sourcename,
- FilenameURL filenameURL) throws SoundSystemException {
- if (filenameURL == null) {
- throw new SoundSystemException("Filename/URL not specified in method 'loadMidi'.");
- }
- if (!filenameURL.getFilename().matches(
- SoundSystemConfig.EXTENSION_MIDI)) {
- throw new SoundSystemException("Filename/identifier doesn't end in '.mid' or"
- + "'.midi' in method loadMidi.");
- }
- if (midiChannel == null) {
- midiChannel = new MidiChannel(toLoop, sourcename, filenameURL);
- } else {
- midiChannel.switchSource(toLoop, sourcename, filenameURL);
- }
- return midiChannel;
- }
- /**
- * Notifies the underlying library that the Doppler parameters have changed.
- */
- public void dopplerChanged()
- {}
- /**
- * Unloads the current Midi file.
- */
- public void unloadMidi() {
- if (midiChannel != null) {
- midiChannel.cleanup();
- }
- midiChannel = null;
- }
- /**
- * Returns information about the listener.
- * @return A ListenerData object.
- */
- public ListenerData getListenerData() {
- return listener;
- }
- /**
- * Indicates whether or not this library requires some codecs to reverse-order
- * the audio data they generate.
- * @return True if audio data should be reverse-ordered.
- */
- public boolean reverseByteOrder() {
- return false;
- }
- /**
- * Returns the short title of this library type.
- * @return A short title.
- */
- public static String getTitle() {
- return "No Sound";
- }
- /**
- * Returns a longer description of this library type.
- * @return A longer description.
- */
- public static String getDescription() {
- return "Silent Mode";
- }
- /**
- * Prints a message.
- * @param message Message to print.
- */
- protected void message(String message) {
- logger.message(message, 0);
- }
- /**
- * Prints an important message.
- * @param message Message to print.
- */
- protected void importantMessage(String message) {
- logger.importantMessage(message, 0);
- }
- public String getClassName() {
- return getClass().getName();
- }
- }
Add Comment
Please, Sign In to add comment