diff --git a/forge_client/src/ibxm/Channel.java b/client/ibxm/Channel.java similarity index 100% rename from forge_client/src/ibxm/Channel.java rename to client/ibxm/Channel.java diff --git a/forge_client/src/ibxm/Envelope.java b/client/ibxm/Envelope.java similarity index 100% rename from forge_client/src/ibxm/Envelope.java rename to client/ibxm/Envelope.java diff --git a/forge_client/src/ibxm/FastTracker2.java b/client/ibxm/FastTracker2.java similarity index 100% rename from forge_client/src/ibxm/FastTracker2.java rename to client/ibxm/FastTracker2.java diff --git a/forge_client/src/ibxm/IBXM.java b/client/ibxm/IBXM.java similarity index 100% rename from forge_client/src/ibxm/IBXM.java rename to client/ibxm/IBXM.java diff --git a/forge_client/src/ibxm/Instrument.java b/client/ibxm/Instrument.java similarity index 100% rename from forge_client/src/ibxm/Instrument.java rename to client/ibxm/Instrument.java diff --git a/forge_client/src/ibxm/LogTable.java b/client/ibxm/LogTable.java similarity index 100% rename from forge_client/src/ibxm/LogTable.java rename to client/ibxm/LogTable.java diff --git a/forge_client/src/ibxm/Module.java b/client/ibxm/Module.java similarity index 100% rename from forge_client/src/ibxm/Module.java rename to client/ibxm/Module.java diff --git a/forge_client/src/ibxm/Pattern.java b/client/ibxm/Pattern.java similarity index 100% rename from forge_client/src/ibxm/Pattern.java rename to client/ibxm/Pattern.java diff --git a/forge_client/src/ibxm/Player.java b/client/ibxm/Player.java similarity index 100% rename from forge_client/src/ibxm/Player.java rename to client/ibxm/Player.java diff --git a/forge_client/src/ibxm/ProTracker.java b/client/ibxm/ProTracker.java similarity index 100% rename from forge_client/src/ibxm/ProTracker.java rename to client/ibxm/ProTracker.java diff --git a/forge_client/src/ibxm/Sample.java b/client/ibxm/Sample.java similarity index 100% rename from forge_client/src/ibxm/Sample.java rename to client/ibxm/Sample.java diff --git a/forge_client/src/ibxm/ScreamTracker3.java b/client/ibxm/ScreamTracker3.java similarity index 100% rename from forge_client/src/ibxm/ScreamTracker3.java rename to client/ibxm/ScreamTracker3.java diff --git a/forge_client/src/paulscode/sound/codecs/CodecIBXM.java b/forge_client/src/paulscode/sound/codecs/CodecIBXM.java deleted file mode 100644 index 4bb032d8d8..0000000000 --- a/forge_client/src/paulscode/sound/codecs/CodecIBXM.java +++ /dev/null @@ -1,642 +0,0 @@ -package paulscode.sound.codecs; - -import java.io.DataInputStream; -import java.io.InputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ShortBuffer; -import javax.sound.sampled.AudioFormat; - -import paulscode.sound.ICodec; -import paulscode.sound.SoundBuffer; -import paulscode.sound.SoundSystemConfig; -import paulscode.sound.SoundSystemLogger; - -import ibxm.FastTracker2; -import ibxm.IBXM; -import ibxm.Module; -import ibxm.ProTracker; -import ibxm.ScreamTracker3; - -/** - * The CodecIBXM class provides an ICodec interface for reading from MOD/S3M/XM - * files via the IBXM library. - * SoundSystem CodecIBXM Class License:

- * You are free to use this class for any purpose, commercial or otherwise. - * You may modify this class or source code, and distribute it any way you - * like, provided the following conditions are met: - *
- * 1) You may not falsely claim to be the author of this class or any - * unmodified portion of it. - *
- * 2) You may not copyright this class or a modified version of it and then - * sue me for copyright infringement. - *
- * 3) If you modify the source code, you must clearly document the changes - * made before redistributing the modified source code, so other users know - * it is not the original code. - *
- * 4) You are not required to give me credit for this class in any derived - * work, but if you do, you must also mention my website: - * http://www.paulscode.com - *
- * 5) I the author will not be responsible for any damages (physical, - * financial, or otherwise) caused by the use if this class or any portion - * of it. - *
- * 6) I the author do not guarantee, warrant, or make any representations, - * either expressed or implied, regarding the use of this class or any - * portion of it. - *

- * Author: Paul Lamb - *
- * http://www.paulscode.com - *


- * - * This software is based on or using the IBXM library available from - * http://www.geocities.com/sunet2000/ - *

- *
- * IBXM is copyright (c) 2007, Martin Cameron, and is licensed under the BSD - * License. - *

- * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. Redistributions in binary - * form must reproduce the above copyright notice, this list of conditions and - * the following disclaimer in the documentation and/or other materials - * provided with the distribution. Neither the name of mumart nor the names of - * its contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *


- */ -public class CodecIBXM implements ICodec -{ -/** - * Used to return a current value from one of the synchronized - * boolean-interface methods. - */ - private static final boolean GET = false; - -/** - * Used to set the value in one of the synchronized boolean-interface methods. - */ - private static final boolean SET = true; - -/** - * Used when a parameter for one of the synchronized boolean-interface methods - * is not aplicable. - */ - private static final boolean XXX = false; - -/** - * True if there is no more data to read in. - */ - private boolean endOfStream = false; - -/** - * True if the stream has finished initializing. - */ - private boolean initialized = false; - -/** - * Format the converted audio will be in. - */ - private AudioFormat myAudioFormat = null; - -/** - * True if the using library requires data read by this codec to be - * reverse-ordered before returning it from methods read() and readAll(). - */ - private boolean reverseBytes = false; - -/** - * IBXM decoder. - */ - private IBXM ibxm; - -/** - * Module instance to be played. - */ - private Module module; - -/** - * Duration of the audio (in frames). - */ - private int songDuration; - -/** - * Audio read position (in frames). - */ - private int playPosition; - -/** - * Processes status messages, warnings, and error messages. - */ - private SoundSystemLogger logger; - -/** - * Constructor: Grabs a handle to the logger. - */ - public CodecIBXM() - { - logger = SoundSystemConfig.getLogger(); - } - -/** - * Tells this codec when it will need to reverse the byte order of - * the data before returning it in the read() and readAll() methods. The - * IBXM library produces audio data in a format that some external audio - * libraries require to be reversed. Derivatives of the Library and Source - * classes for audio libraries which require this type of data to be reversed - * will call the reverseByteOrder() method. - * @param b True if the calling audio library requires byte-reversal. - */ - public void reverseByteOrder( boolean b ) - { - reverseBytes = b; - } - -/** - * Prepares an audio stream to read from. If another stream is already opened, - * it will be closed and a new audio stream opened in its place. - * @param url URL to an audio file to stream from. - * @return False if an error occurred or if end of stream was reached. - */ - public boolean initialize( URL url ) - { - initialized( SET, false ); - cleanup(); - - if( url == null ) - { - errorMessage( "url null in method 'initialize'" ); - cleanup(); - return false; - } - - InputStream is = null; - - try - { - is = url.openStream(); - } - catch( IOException ioe ) - { - errorMessage( "Unable to open stream in method 'initialize'" ); - printStackTrace( ioe ); - return false; - } - - if( ibxm == null ) - ibxm = new IBXM( 48000 ); - if( myAudioFormat == null ) - myAudioFormat = new AudioFormat( 48000, 16, 2, true, true ); - - try - { - setModule( loadModule( is ) ); - } - catch( IllegalArgumentException iae ) - { - errorMessage( "Illegal argument in method 'initialize'" ); - printStackTrace( iae ); - if( is != null ) - { - try - { - is.close(); - } - catch( IOException ioe ) - {} - } - return false; - } - catch( IOException ioe ) - { - errorMessage( "Error loading module in method 'initialize'" ); - printStackTrace( ioe ); - if( is != null ) - { - try - { - is.close(); - } - catch( IOException ioe2 ) - {} - } - return false; - } - - if( is != null ) - { - try - { - is.close(); - } - catch( IOException ioe ) - {} - } - - endOfStream( SET, false ); - initialized( SET, true ); - return true; - } - -/** - * Returns false if the stream is busy initializing. - * @return True if steam is initialized. - */ - public boolean initialized() - { - return initialized( GET, XXX ); - } - -/** - * Reads in one stream buffer worth of audio data. See - * {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more - * information about accessing and changing default settings. - * @return The audio data wrapped into a SoundBuffer context. - */ - public SoundBuffer read() - { - if( endOfStream( GET, XXX ) ) - return null; - - if( module == null ) - { - errorMessage( "Module null in method 'read'" ); - return null; - } - - // Check to make sure there is an audio format: - if( myAudioFormat == null ) - { - errorMessage( "Audio Format null in method 'read'" ); - return null; - } - - int bufferFrameSize = (int) SoundSystemConfig.getStreamingBufferSize() - / 4; - - int frames = songDuration - playPosition; - if( frames > bufferFrameSize ) - frames = bufferFrameSize; - - if( frames <= 0 ) - { - endOfStream( SET, true ); - return null; - } - byte[] outputBuffer = new byte[ frames * 4 ]; - - ibxm.get_audio( outputBuffer, frames ); - - playPosition += frames; - if( playPosition >= songDuration ) - { - endOfStream( SET, true ); - } - - // Reverse the byte order if necessary: - if( reverseBytes ) - reverseBytes( outputBuffer, 0, frames * 4 ); - - // Wrap the data into a SoundBuffer: - SoundBuffer buffer = new SoundBuffer( outputBuffer, myAudioFormat ); - - return buffer; - } - -/** - * Reads in all the audio data from the stream (up to the default - * "maximum file size". See - * {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more - * information about accessing and changing default settings. - * @return the audio data wrapped into a SoundBuffer context. - */ - public SoundBuffer readAll() - { - if( module == null ) - { - errorMessage( "Module null in method 'readAll'" ); - return null; - } - - // Check to make sure there is an audio format: - if( myAudioFormat == null ) - { - errorMessage( "Audio Format null in method 'readAll'" ); - return null; - } - - int bufferFrameSize = (int) SoundSystemConfig.getFileChunkSize() - / 4; - - byte[] outputBuffer = new byte[ bufferFrameSize * 4 ]; - - // Buffer to contain the audio data: - byte[] fullBuffer = null; - // frames of audio data: - int frames; - // bytes of audio data: - int totalBytes = 0; - - while( (!endOfStream(GET, XXX)) && - (totalBytes < SoundSystemConfig.getMaxFileSize()) ) - { - frames = songDuration - playPosition; - if( frames > bufferFrameSize ) - frames = bufferFrameSize; - ibxm.get_audio( outputBuffer, frames ); - totalBytes += (frames * 4); - - fullBuffer = appendByteArrays( fullBuffer, outputBuffer, - frames * 4 ); - - playPosition += frames; - if( playPosition >= songDuration ) - { - endOfStream( SET, true ); - } - } - - // Reverse the byte order if necessary: - if( reverseBytes ) - reverseBytes( fullBuffer, 0, totalBytes ); - - // Wrap the data into a SoundBuffer: - SoundBuffer buffer = new SoundBuffer( fullBuffer, myAudioFormat ); - - return buffer; - } - -/** - * Returns false if there is still more data available to be read in. - * @return True if end of stream was reached. - */ - public boolean endOfStream() - { - return endOfStream( GET, XXX ); - } - -/** - * Closes the audio stream and remove references to all instantiated objects. - */ - public void cleanup() - { -// if( ibxm != null ) -// ibxm.seek( 0 ); - playPosition = 0; - } - -/** - * Returns the audio format of the data being returned by the read() and - * readAll() methods. - * @return Information wrapped into an AudioFormat context. - */ - public AudioFormat getAudioFormat() - { - return myAudioFormat; - } - -/** - * Decodes the data in the specified InputStream into an instance of - * ibxm.Module. - * @param input an InputStream containing the module file to be decoded. - * @throws IllegalArgumentException if the data is not recognised as a module file. - */ - private static Module loadModule( InputStream input ) - throws IllegalArgumentException, IOException - { - DataInputStream data_input_stream = new DataInputStream( input ); - - // Check if data is in XM format: - byte[] xm_header = new byte[ 60 ]; - data_input_stream.readFully( xm_header ); - if( FastTracker2.is_xm( xm_header ) ) - return FastTracker2.load_xm( xm_header, data_input_stream ); - - // Check if data is in ScreamTracker 3 format: - byte[] s3m_header = new byte[ 96 ]; - System.arraycopy( xm_header, 0, s3m_header, 0, 60 ); - data_input_stream.readFully( s3m_header, 60, 36 ); - if( ScreamTracker3.is_s3m( s3m_header ) ) - return ScreamTracker3.load_s3m( s3m_header, data_input_stream ); - - // Check if data is in ProTracker format: - byte[] mod_header = new byte[ 1084 ]; - System.arraycopy( s3m_header, 0, mod_header, 0, 96 ); - data_input_stream.readFully( mod_header, 96, 988 ); - return ProTracker.load_mod( mod_header, data_input_stream ); - } - -/** - * Sets the Module instance to be played. - */ - private void setModule( Module m ) - { - if( m != null ) - module = m; - ibxm.set_module( module ); - songDuration = ibxm.calculate_song_duration(); - } - -/** - * Internal method for synchronizing access to the boolean 'initialized'. - * @param action GET or SET. - * @param value New value if action == SET, or XXX if action == GET. - * @return True if steam is initialized. - */ - private synchronized boolean initialized( boolean action, boolean value ) - { - if( action == SET ) - initialized = value; - return initialized; - } - -/** - * Internal method for synchronizing access to the boolean 'endOfStream'. - * @param action GET or SET. - * @param value New value if action == SET, or XXX if action == GET. - * @return True if end of stream was reached. - */ - private synchronized boolean endOfStream( boolean action, boolean value ) - { - if( action == SET ) - endOfStream = value; - return endOfStream; - } - -/** - * Trims down the size of the array if it is larger than the specified - * maximum length. - * @param array Array containing audio data. - * @param maxLength Maximum size this array may be. - * @return New array. - */ - private static byte[] trimArray( byte[] array, int maxLength ) - { - byte[] trimmedArray = null; - if( array != null && array.length > maxLength ) - { - trimmedArray = new byte[maxLength]; - System.arraycopy( array, 0, trimmedArray, 0, maxLength ); - } - return trimmedArray; - } - -/** - * Reverse-orders all bytes contained in the specified array. - * @param buffer Array containing audio data. - */ - public static void reverseBytes( byte[] buffer ) - { - reverseBytes( buffer, 0, buffer.length ); - } - -/** - * Reverse-orders the specified range of bytes contained in the specified array. - * @param buffer Array containing audio data. - * @param offset Array index to begin. - * @param size number of bytes to reverse-order. - */ - public static void reverseBytes( byte[] buffer, int offset, int size ) - { - - byte b; - for( int i = offset; i < ( offset + size ); i += 2 ) - { - b = buffer[i]; - buffer[i] = buffer[i + 1]; - buffer[i + 1] = b; - } - } - -/** - * Converts sound bytes to little-endian format. - * @param audio_bytes The original wave data - * @param two_bytes_data For stereo sounds. - * @return byte array containing the converted data. - */ - private static byte[] convertAudioBytes( byte[] audio_bytes, - boolean two_bytes_data ) - { - ByteBuffer dest = ByteBuffer.allocateDirect( audio_bytes.length ); - dest.order( ByteOrder.nativeOrder() ); - ByteBuffer src = ByteBuffer.wrap( audio_bytes ); - src.order( ByteOrder.LITTLE_ENDIAN ); - if( two_bytes_data ) - { - ShortBuffer dest_short = dest.asShortBuffer(); - ShortBuffer src_short = src.asShortBuffer(); - while( src_short.hasRemaining() ) - { - dest_short.put(src_short.get()); - } - } - else - { - while( src.hasRemaining() ) - { - dest.put( src.get() ); - } - } - dest.rewind(); - - if( !dest.hasArray() ) - { - byte[] arrayBackedBuffer = new byte[dest.capacity()]; - dest.get( arrayBackedBuffer ); - dest.clear(); - - return arrayBackedBuffer; - } - - return dest.array(); - } - -/** - * Creates a new array with the second array appended to the end of the first - * array. - * @param arrayOne The first array. - * @param arrayTwo The second array. - * @param length How many bytes to append from the second array. - * @return Byte array containing information from both arrays. - */ - private static byte[] appendByteArrays( byte[] arrayOne, byte[] arrayTwo, - int length ) - { - byte[] newArray; - if( arrayOne == null && arrayTwo == null ) - { - // no data, just return - return null; - } - else if( arrayOne == null ) - { - // create the new array, same length as arrayTwo: - newArray = new byte[ length ]; - // fill the new array with the contents of arrayTwo: - System.arraycopy( arrayTwo, 0, newArray, 0, length ); - arrayTwo = null; - } - else if( arrayTwo == null ) - { - // create the new array, same length as arrayOne: - newArray = new byte[ arrayOne.length ]; - // fill the new array with the contents of arrayOne: - System.arraycopy( arrayOne, 0, newArray, 0, arrayOne.length ); - arrayOne = null; - } - else - { - // create the new array large enough to hold both arrays: - newArray = new byte[ arrayOne.length + length ]; - System.arraycopy( arrayOne, 0, newArray, 0, arrayOne.length ); - // fill the new array with the contents of both arrays: - System.arraycopy( arrayTwo, 0, newArray, arrayOne.length, - length ); - arrayOne = null; - arrayTwo = null; - } - - return newArray; - } - -/** - * Prints an error message. - * @param message Message to print. - */ - private void errorMessage( String message ) - { - logger.errorMessage( "CodecWav", message, 0 ); - } - -/** - * Prints an exception's error message followed by the stack trace. - * @param e Exception containing the information to print. - */ - private void printStackTrace( Exception e ) - { - logger.printStackTrace( e, 1 ); - } -}