/* * 21.04.2004 Original verion. davagin@udm.ru. *----------------------------------------------------------------------- * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *---------------------------------------------------------------------- */ package davaguine.jmac.encoder; import davaguine.jmac.info.CompressionLevel; import davaguine.jmac.info.InputSource; import davaguine.jmac.info.WaveFormat; import davaguine.jmac.tools.ByteBuffer; import davaguine.jmac.tools.File; import davaguine.jmac.tools.IntegerPointer; import java.io.IOException; /** * Author: Dmitry Vaguine * Date: 07.05.2004 * Time: 13:10:46 */ public abstract class IAPECompress { public final static int CREATE_WAV_HEADER_ON_DECOMPRESSION = -1; public final static int MAX_AUDIO_BYTES_UNKNOWN = -1; /** * ****************************************************************************************** * Start * ******************************************************************************************* */ ////////////////////////////////////////////////////////////////////////////////////////////// // Start(...) / StartEx(...) - starts encoding // // Parameters: // CIO * pioOutput / const wchar_t * pFilename // the output... either a filename or an I/O source // WAVEFORMATEX * pwfeInput // format of the audio to encode (use FillWaveFormatEx() if necessary) // int nMaxAudioBytes // the absolute maximum audio bytes that will be encoded... encoding fails with a // ERROR_APE_COMPRESS_TOO_MUCH_DATA if you attempt to encode more than specified here // (if unknown, use MAX_AUDIO_BYTES_UNKNOWN to allocate as much storage in the seek table as // possible... limit is then 2 GB of data (~4 hours of CD music)... this wastes around // 30kb, so only do it if completely necessary) // int nCompressionLevel // the compression level for the APE file (fast - extra high) // (note: extra-high is much slower for little gain) // const unsigned char * pHeaderData // a pointer to a buffer containing the WAV header (data before the data block in the WAV) // (note: use NULL for on-the-fly encoding... see next parameter) // int nHeaderBytes // number of bytes in the header data buffer (use CREATE_WAV_HEADER_ON_DECOMPRESSION and // NULL for the pHeaderData and MAC will automatically create the appropriate WAV header // on decompression) ////////////////////////////////////////////////////////////////////////////////////////////// public void Start(String pOutputFilename, WaveFormat pwfeInput) throws IOException { Start(pOutputFilename, pwfeInput, MAX_AUDIO_BYTES_UNKNOWN, CompressionLevel.COMPRESSION_LEVEL_NORMAL, null, CREATE_WAV_HEADER_ON_DECOMPRESSION); } public void Start(String pOutputFilename, WaveFormat pwfeInput, int nMaxAudioBytes) throws IOException { Start(pOutputFilename, pwfeInput, nMaxAudioBytes, CompressionLevel.COMPRESSION_LEVEL_NORMAL, null, CREATE_WAV_HEADER_ON_DECOMPRESSION); } public void Start(String pOutputFilename, WaveFormat pwfeInput, int nMaxAudioBytes, int nCompressionLevel) throws IOException { Start(pOutputFilename, pwfeInput, nMaxAudioBytes, nCompressionLevel, null, CREATE_WAV_HEADER_ON_DECOMPRESSION); } public void Start(String pOutputFilename, WaveFormat pwfeInput, int nMaxAudioBytes, int nCompressionLevel, byte[] pHeaderData) throws IOException { Start(pOutputFilename, pwfeInput, nMaxAudioBytes, nCompressionLevel, pHeaderData, CREATE_WAV_HEADER_ON_DECOMPRESSION); } public abstract void Start(String pOutputFilename, WaveFormat pwfeInput, int nMaxAudioBytes, int nCompressionLevel, byte[] pHeaderData, int nHeaderBytes) throws IOException; public void StartEx(File pioOutput, WaveFormat pwfeInput) throws IOException { StartEx(pioOutput, pwfeInput, MAX_AUDIO_BYTES_UNKNOWN, CompressionLevel.COMPRESSION_LEVEL_NORMAL, null, CREATE_WAV_HEADER_ON_DECOMPRESSION); } public void StartEx(File pioOutput, WaveFormat pwfeInput, int nMaxAudioBytes) throws IOException { StartEx(pioOutput, pwfeInput, nMaxAudioBytes, CompressionLevel.COMPRESSION_LEVEL_NORMAL, null, CREATE_WAV_HEADER_ON_DECOMPRESSION); } public void StartEx(File pioOutput, WaveFormat pwfeInput, int nMaxAudioBytes, int nCompressionLevel) throws IOException { StartEx(pioOutput, pwfeInput, nMaxAudioBytes, nCompressionLevel, null, CREATE_WAV_HEADER_ON_DECOMPRESSION); } public void StartEx(File pioOutput, WaveFormat pwfeInput, int nMaxAudioBytes, int nCompressionLevel, byte[] pHeaderData) throws IOException { StartEx(pioOutput, pwfeInput, nMaxAudioBytes, nCompressionLevel, pHeaderData, CREATE_WAV_HEADER_ON_DECOMPRESSION); } public abstract void StartEx(File pioOutput, WaveFormat pwfeInput, int nMaxAudioBytes, int nCompressionLevel, byte[] pHeaderData, int nHeaderBytes) throws IOException; /** * ****************************************************************************************** * Add / Compress Data * - there are 3 ways to add data: * 1) simple call AddData(...) * 2) lock MAC's buffer, copy into it, and unlock (LockBuffer(...) / UnlockBuffer(...)) * 3) from an I/O source (AddDataFromInputSource(...)) * ******************************************************************************************* */ ////////////////////////////////////////////////////////////////////////////////////////////// // AddData(...) - adds data to the encoder // // Parameters: // unsigned char * pData // a pointer to a buffer containing the raw audio data // int nBytes // the number of bytes in the buffer ////////////////////////////////////////////////////////////////////////////////////////////// public abstract void AddData(byte[] pData, int nBytes) throws IOException; ////////////////////////////////////////////////////////////////////////////////////////////// // GetBufferBytesAvailable(...) - returns the number of bytes available in the buffer // (helpful when locking) ////////////////////////////////////////////////////////////////////////////////////////////// public abstract int GetBufferBytesAvailable(); ////////////////////////////////////////////////////////////////////////////////////////////// // LockBuffer(...) - locks MAC's buffer so we can copy into it // // Parameters: // int * pBytesAvailable // returns the number of bytes available in the buffer (DO NOT COPY MORE THAN THIS IN) // // Return: // pointer to the buffer (add at that location) ////////////////////////////////////////////////////////////////////////////////////////////// public abstract ByteBuffer LockBuffer(IntegerPointer pBytesAvailable); ////////////////////////////////////////////////////////////////////////////////////////////// // UnlockBuffer(...) - releases the buffer // // Parameters: // int nBytesAdded // the number of bytes copied into the buffer // BOOL bProcess // whether MAC should process as much as possible of the buffer ////////////////////////////////////////////////////////////////////////////////////////////// public void UnlockBuffer(int nBytesAdded) throws IOException { UnlockBuffer(nBytesAdded, true); } public abstract void UnlockBuffer(int nBytesAdded, boolean bProcess) throws IOException; ////////////////////////////////////////////////////////////////////////////////////////////// // AddDataFromInputSource(...) - use a CInputSource (input source) to add data // // Parameters: // CInputSource * pInputSource // a pointer to the input source // int nMaxBytes // the maximum number of bytes to let MAC add (-1 if MAC can add any amount) // int * pBytesAdded // returns the number of bytes added from the I/O source ////////////////////////////////////////////////////////////////////////////////////////////// public int AddDataFromInputSource(InputSource pInputSource) throws IOException { return AddDataFromInputSource(pInputSource, -1); } public abstract int AddDataFromInputSource(InputSource pInputSource, int nMaxBytes) throws IOException; /** * ****************************************************************************************** * Finish / Kill * ******************************************************************************************* */ ////////////////////////////////////////////////////////////////////////////////////////////// // Finish(...) - ends encoding and finalizes the file // // Parameters: // unsigned char * pTerminatingData // a pointer to a buffer containing the information to place at the end of the APE file // (comprised of the WAV terminating data (data after the data block in the WAV) followed // by any tag information) // int nTerminatingBytes // number of bytes in the terminating data buffer // int nWAVTerminatingBytes // the number of bytes of the terminating data buffer that should be appended to a decoded // WAV file (it's basically nTerminatingBytes - the bytes that make up the tag) ////////////////////////////////////////////////////////////////////////////////////////////// public abstract void Finish(byte[] pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes) throws IOException; ////////////////////////////////////////////////////////////////////////////////////////////// // Kill(...) - stops encoding and deletes the output file // --- NOT CURRENTLY IMPLEMENTED --- ////////////////////////////////////////////////////////////////////////////////////////////// public abstract void Kill(); public static IAPECompress CreateIAPECompress() { return new APECompress(); } }