jmac-1.74/ 0000755 0001750 0001750 00000000000 10451145164 012316 5 ustar twerner twerner jmac-1.74/build/ 0000755 0001750 0001750 00000000000 10451144640 013413 5 ustar twerner twerner jmac-1.74/build/build-core.xml 0000644 0001750 0001750 00000005564 10131471135 016171 0 ustar twerner twerner
jmac-1.74/build/build-spi.xml 0000644 0001750 0001750 00000007750 10131471135 016033 0 ustar twerner twerner
jmac-1.74/build/build-spi15.xml 0000644 0001750 0001750 00000005702 10131471135 016174 0 ustar twerner twerner
jmac-1.74/changelog.txt 0000644 0001750 0001750 00000005757 10451145121 015015 0 ustar twerner twerner JMAC Changelog
===================
version 1.0 (March 4, 2004)
-------------
Initial version
It supports the MAC format up to 3.97 version.
version 1.01 (March 8, 2004)
-------------
Small bug fixes with Player and file openings.
version 1.1 (March 14, 2004)
-------------
Support of playing/converting audio from stream (any InputStream) implemented.
Java Sound SPI for APE audio implemented.
version 1.11 (March 15, 2004)
-------------
Small performance improvements
version 1.12 (March 22, 2004)
-------------
The class CircularBuffer removed. Performance improvements.
version 1.13 (March 25, 2004)
-------------
Fixed bug with playing local files using jmacp.
version 1.14 (March 26, 2004)
-------------
Performance and reliability improvements.
version 1.15 (March 27, 2004)
-------------
More performance improvements.
version 1.16 (March 27, 2004)
-------------
Cleanup and bugfixing.
version 1.2 (April 2, 2004)
-------------
Java Sound SPI (based on Tritonus) for APE audio implemented.
version 1.3 (April 24, 2004)
-------------
The MAC format up to 3.98 version now supported. The ability to edit APE Tag info implemented.
version 1.4 (April 29, 2004)
-------------
The JNI wrapper around of original MAC library implemented. Now only Windows platform supported. Please, read readme.txt file for more details.
version 1.41 (April 30, 2004)
-------------
MD5 checking during file verification added.
version 1.5 (May 7, 2004)
-------------
The MAC format up to 3.99 version now supported.
version 1.6 (May 13, 2004)
-------------
The APE encoder (3.99) implemented, JNI wrapper updated and a lot of bug fixes.
version 1.61 (May 13, 2004)
-------------
Small bug fix in Tritonus based SPI.
version 1.62 (May 18, 2004)
-------------
Major bug fixing (generally in JNI wrapper). Small improvements.
version 1.63 (May 24, 2004)
-------------
Small improvements. Also, the ability to run jmac.jar as simple APE utility added.
version 1.64 (June 5, 2004)
-------------
The JNI wrapper around of original MAC library implemented (linux version).
version 1.65 (Jule 5, 2004)
-------------
Bug with compressing/decompressing of 24-bit audio fixed. There are several other small bug fixes.
version 1.70 (October 7, 2004)
-------------
Bug in compressing algorithm fixed (thanks to Dan). Also, the support of new features of JDK1.5 implemented.
version 1.71 (October 8, 2004)
-------------
The support both the JDK1.3 and JDK1.5 implemented. Code cleanup.
version 1.72 (January 16, 2005)
-------------
Some problems with closing output/input streams during compression where fixed (thanks again to Dan Rollo).
version 1.73 (November 8, 2005)
-------------
Some problems with correct identification of MAC format in SPI were fixed. Thanks to javazoom.
version 1.74 (June 30, 2005)
-------------
The SPI can freeze up in getAudioFileFormat if the target file represented as URL. Fixed.
JNI wrapper recompiled under MSVS 2005.
jmac-1.74/core/ 0000755 0001750 0001750 00000000000 10451144761 013250 5 ustar twerner twerner jmac-1.74/core/nativesrc/ 0000755 0001750 0001750 00000000000 10451144641 015243 5 ustar twerner twerner jmac-1.74/core/nativesrc/include/ 0000755 0001750 0001750 00000000000 10451144641 016666 5 ustar twerner twerner jmac-1.74/core/nativesrc/jmac/ 0000755 0001750 0001750 00000000000 10451144715 016157 5 ustar twerner twerner jmac-1.74/core/nativesrc/jmac/APEDecompressJMAC.cpp 0000644 0001750 0001750 00000034754 10131230056 021752 0 ustar twerner twerner /*
* 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.
*----------------------------------------------------------------------
*/
#include
#include
#include "APEDecompressJMAC.h"
#include "UnBitArrayJMAC.h"
#include
#include
#include
#include
#define DECODE_BLOCK_SIZE 4096
CAPEDecompressJMAC::CAPEDecompressJMAC(JNIEnv* aenv, jobject athisObject, jobject aioObject, int nVersion, int nCompressionLevel,
int nStartBlock, int nFinishBlock, int nTotalBlocks, int nBlockAlign, int nBlocksPerFrame,
int nSampleRate, int nBitsPerSample, int nChannels) {
SetRefs(aenv, athisObject, aioObject);
m_nVersion = nVersion;
m_nCompressionLevel = nCompressionLevel;
m_nBlockAlign = nBlockAlign;
m_nBlocksPerFrame = nBlocksPerFrame;
m_nBitsPerSample = nBitsPerSample;
FillWaveFormatEx(&m_wfeInput, nSampleRate, nBitsPerSample, nChannels);
// initialize other stuff
m_bDecompressorInitialized = FALSE;
m_nCurrentFrame = 0;
m_nRealFrame = 0;
m_nCurrentBlock = 0;
m_nCurrentFrameBufferBlock = 0;
m_nFrameBufferFinishedBlocks = 0;
m_bErrorDecodingCurrentFrame = FALSE;
// set the "real" start and finish blocks
m_nStartBlock = (nStartBlock < 0) ? 0 : min(nStartBlock, nTotalBlocks);
m_nFinishBlock = (nFinishBlock < 0) ? nTotalBlocks : min(nFinishBlock, nTotalBlocks);
m_bIsRanged = (m_nStartBlock != 0) || (m_nFinishBlock != nTotalBlocks);
}
CAPEDecompressJMAC::~CAPEDecompressJMAC() {
}
int CAPEDecompressJMAC::GetData(char* pBuffer, int nBlocks, int* pBlocksRetrieved) {
int nRetVal = ERROR_SUCCESS;
if (pBlocksRetrieved)
*pBlocksRetrieved = 0;
// make sure we're initialized
RETURN_ON_ERROR(InitializeDecompressor())
// cap
int nBlocksUntilFinish = m_nFinishBlock - m_nCurrentBlock;
const int nBlocksToRetrieve = min(nBlocks, nBlocksUntilFinish);
// get the data
unsigned char * pOutputBuffer = (unsigned char *) pBuffer;
int nBlocksLeft = nBlocksToRetrieve; int nBlocksThisPass = 1;
while ((nBlocksLeft > 0) && (nBlocksThisPass > 0)) {
// fill up the frame buffer
int nDecodeRetVal = FillFrameBuffer();
if (nDecodeRetVal != ERROR_SUCCESS)
nRetVal = nDecodeRetVal;
// analyze how much to remove from the buffer
const int nFrameBufferBlocks = m_nFrameBufferFinishedBlocks;
nBlocksThisPass = min(nBlocksLeft, nFrameBufferBlocks);
// remove as much as possible
if (nBlocksThisPass > 0) {
m_cbFrameBuffer.Get(pOutputBuffer, nBlocksThisPass * m_nBlockAlign);
pOutputBuffer += nBlocksThisPass * m_nBlockAlign;
nBlocksLeft -= nBlocksThisPass;
m_nFrameBufferFinishedBlocks -= nBlocksThisPass;
}
}
// calculate the blocks retrieved
int nBlocksRetrieved = nBlocksToRetrieve - nBlocksLeft;
// update position
m_nCurrentBlock += nBlocksRetrieved;
if (pBlocksRetrieved)
*pBlocksRetrieved = nBlocksRetrieved;
return nRetVal;
}
int CAPEDecompressJMAC::Seek(int nBlockOffset) {
RETURN_ON_ERROR(InitializeDecompressor())
// use the offset
nBlockOffset += m_nStartBlock;
// cap (to prevent seeking too far)
if (nBlockOffset >= m_nFinishBlock)
nBlockOffset = m_nFinishBlock - 1;
if (nBlockOffset < m_nStartBlock)
nBlockOffset = m_nStartBlock;
// seek to the perfect location
int nBaseFrame = nBlockOffset / m_nBlocksPerFrame;
int nBlocksToSkip = nBlockOffset % m_nBlocksPerFrame;
int nBytesToSkip = nBlocksToSkip* m_nBlockAlign;
m_nCurrentBlock = nBaseFrame * m_nBlocksPerFrame;
m_nCurrentFrameBufferBlock = nBaseFrame * m_nBlocksPerFrame;
m_nCurrentFrame = nBaseFrame;
m_nFrameBufferFinishedBlocks = 0;
m_cbFrameBuffer.Empty();
RETURN_ON_ERROR(SeekToFrame(m_nCurrentFrame));
// skip necessary blocks
CSmartPtr spTempBuffer(new char [nBytesToSkip], TRUE);
if (spTempBuffer == NULL)
return ERROR_INSUFFICIENT_MEMORY;
int nBlocksRetrieved = 0;
GetData(spTempBuffer, nBlocksToSkip, &nBlocksRetrieved);
if (nBlocksRetrieved != nBlocksToSkip)
return ERROR_UNDEFINED;
return ERROR_SUCCESS;
}
int CAPEDecompressJMAC::InitializeDecompressor() {
// check if we have anything to do
if (m_bDecompressorInitialized)
return ERROR_SUCCESS;
// update the initialized flag
m_bDecompressorInitialized = TRUE;
// create a frame buffer
m_cbFrameBuffer.CreateBuffer((m_nBlocksPerFrame + DECODE_BLOCK_SIZE) * m_nBlockAlign, m_nBlockAlign * 64);
// create decoding components
m_spUnBitArray.Assign((CUnBitArrayBase *) new CUnBitArrayJMAC(this, m_nVersion));
if (m_nVersion >= 3950) {
m_spNewPredictorX.Assign(new CPredictorDecompress3950toCurrent(m_nCompressionLevel, m_nVersion));
m_spNewPredictorY.Assign(new CPredictorDecompress3950toCurrent(m_nCompressionLevel, m_nVersion));
} else {
m_spNewPredictorX.Assign(new CPredictorDecompressNormal3930to3950(m_nCompressionLevel, m_nVersion));
m_spNewPredictorY.Assign(new CPredictorDecompressNormal3930to3950(m_nCompressionLevel, m_nVersion));
}
// seek to the beginning
return Seek(-1);
}
/*****************************************************************************************
Decodes blocks of data
*****************************************************************************************/
int CAPEDecompressJMAC::FillFrameBuffer() {
int nRetVal = ERROR_SUCCESS;
// determine the maximum blocks we can decode
// note that we won't do end capping because we can't use data
// until EndFrame(...) successfully handles the frame
// that means we may decode a little extra in end capping cases
// but this allows robust error handling of bad frames
int nMaxBlocks = m_cbFrameBuffer.MaxAdd() / m_nBlockAlign;
// loop and decode data
int nBlocksLeft = nMaxBlocks;
while (nBlocksLeft > 0) {
int nFrameBlocks = getApeInfoFrameBlocks(m_nCurrentFrame);
if (nFrameBlocks < 0)
break;
int nFrameOffsetBlocks = m_nCurrentFrameBufferBlock % m_nBlocksPerFrame;
int nFrameBlocksLeft = nFrameBlocks - nFrameOffsetBlocks;
int nBlocksThisPass = min(nFrameBlocksLeft, nBlocksLeft);
// start the frame if we need to
if (nFrameOffsetBlocks == 0)
StartFrame();
// store the frame buffer bytes before we start
int nFrameBufferBytes = m_cbFrameBuffer.MaxGet();
// decode data
DecodeBlocksToFrameBuffer(nBlocksThisPass);
// end the frame if we need to
if ((nFrameOffsetBlocks + nBlocksThisPass) >= nFrameBlocks) {
EndFrame();
if (m_bErrorDecodingCurrentFrame) {
// remove any decoded data from the buffer
m_cbFrameBuffer.RemoveTail(m_cbFrameBuffer.MaxGet() - nFrameBufferBytes);
// add silence
unsigned char cSilence = (m_nBitsPerSample == 8) ? 127 : 0;
for (int z = 0; z < nFrameBlocks*m_nBlockAlign; z++) {
*m_cbFrameBuffer.GetDirectWritePointer() = cSilence;
m_cbFrameBuffer.UpdateAfterDirectWrite(1);
}
// seek to try to synchronize after an error
SeekToFrame(m_nCurrentFrame);
// save the return value
nRetVal = ERROR_INVALID_CHECKSUM;
}
}
nBlocksLeft -= nBlocksThisPass;
}
return nRetVal;
}
void CAPEDecompressJMAC::DecodeBlocksToFrameBuffer(int nBlocks) {
// decode the samples
int nBlocksProcessed = 0;
try {
if (m_wfeInput.nChannels == 2) {
if ((m_nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE) && (m_nSpecialCodes & SPECIAL_FRAME_RIGHT_SILENCE))
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) {
m_Prepare.Unprepare(0, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
}
else if (m_nSpecialCodes & SPECIAL_FRAME_PSEUDO_STEREO)
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) {
int X = m_spNewPredictorX->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateX));
m_Prepare.Unprepare(X, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
}
else {
if (m_nVersion >= 3950)
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) {
int nY = m_spUnBitArray->DecodeValueRange(m_BitArrayStateY);
int nX = m_spUnBitArray->DecodeValueRange(m_BitArrayStateX);
int Y = m_spNewPredictorY->DecompressValue(nY, m_nLastX);
int X = m_spNewPredictorX->DecompressValue(nX, Y);
m_nLastX = X;
m_Prepare.Unprepare(X, Y, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
}
else
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) {
int X = m_spNewPredictorX->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateX));
int Y = m_spNewPredictorY->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateY));
m_Prepare.Unprepare(X, Y, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
}
}
} else {
if (m_nSpecialCodes & SPECIAL_FRAME_MONO_SILENCE)
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) {
m_Prepare.Unprepare(0, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
}
else
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) {
int X = m_spNewPredictorX->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateX));
m_Prepare.Unprepare(X, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
}
}
} catch (...) {
m_bErrorDecodingCurrentFrame = TRUE;
}
m_nCurrentFrameBufferBlock += nBlocks;
}
void CAPEDecompressJMAC::StartFrame() {
m_nCRC = 0xFFFFFFFF;
// get the frame header
m_nStoredCRC = m_spUnBitArray->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_INT);
m_bErrorDecodingCurrentFrame = FALSE;
// get any 'special' codes if the file uses them (for silence, FALSE stereo, etc.)
m_nSpecialCodes = 0;
if (m_nVersion > 3820) {
if (m_nStoredCRC & 0x80000000)
m_nSpecialCodes = m_spUnBitArray->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_INT);
m_nStoredCRC &= 0x7FFFFFFF;
}
m_spNewPredictorX->Flush();
m_spNewPredictorY->Flush();
m_spUnBitArray->FlushState(m_BitArrayStateX);
m_spUnBitArray->FlushState(m_BitArrayStateY);
m_spUnBitArray->FlushBitArray();
m_nLastX = 0;
}
void CAPEDecompressJMAC::EndFrame() {
m_nFrameBufferFinishedBlocks += getApeInfoFrameBlocks(m_nCurrentFrame);
m_nCurrentFrame++;
// finalize
m_spUnBitArray->Finalize();
// check the CRC
m_nCRC = m_nCRC ^ 0xFFFFFFFF;
m_nCRC >>= 1;
if (m_nCRC != m_nStoredCRC)
m_bErrorDecodingCurrentFrame = TRUE;
}
int CAPEDecompressJMAC::getApeInfoFrameBlocks(int nFrameIndex) {
jclass clazz = env->GetObjectClass(thisObject);
jmethodID method = env->GetMethodID(clazz, "getApeInfoFrameBlocks", "(I)I");
if (method == NULL) {
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
env->DeleteLocalRef(clazz);
return -1;
}
env->DeleteLocalRef(clazz);
return env->CallIntMethod(thisObject, method, (jint) nFrameIndex);
}
int CAPEDecompressJMAC::getApeInfoSeekByte(int nFrameIndex) {
jclass clazz = env->GetObjectClass(thisObject);
jmethodID method = env->GetMethodID(clazz, "getApeInfoSeekByte", "(I)I");
if (method == NULL) {
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
env->DeleteLocalRef(clazz);
return -1;
}
env->DeleteLocalRef(clazz);
return env->CallIntMethod(thisObject, method, (jint) nFrameIndex);
}
int CAPEDecompressJMAC::SeekToFrame(int nFrameIndex) {
int nSeekRemainder = (getApeInfoSeekByte(nFrameIndex) - getApeInfoSeekByte(0)) % 4;
int retVal = m_spUnBitArray->FillAndResetBitArray(m_nRealFrame == nFrameIndex ? -1 : getApeInfoSeekByte(nFrameIndex) - nSeekRemainder,
nSeekRemainder * 8);
m_nRealFrame = nFrameIndex;
return retVal;
}
int CAPEDecompressJMAC::GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1, int nParam2) {
return -1;
}
jmac-1.74/core/nativesrc/jmac/APEDecompressJMAC.h 0000644 0001750 0001750 00000006641 10131230056 021411 0 ustar twerner twerner /*
* 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.
*----------------------------------------------------------------------
*/
#ifndef JMAC_APEDECOMPRESS_H
#define JMAC_APEDECOMPRESS_H
class CUnBitArray;
class CPrepare;
class CAPEInfo;
class IPredictorDecompress;
#include
#include
#include
#include
#include "UnBitArrayJMAC.h"
class CAPEDecompressJMAC : public IAPEDecompress {
public:
CAPEDecompressJMAC(JNIEnv* aenv, jobject athisObject, jobject aioObject, int nVersion, int nCompressionLevel, int nStartBlock,
int nFinishBlock, int nTotalBlocks, int nBlockAlign, int nBlocksPerFrame, int nSampleRate, int nBitsPerSample,
int nChannels);
~CAPEDecompressJMAC();
inline void SetRefs(JNIEnv* aenv, jobject athisObject, jobject aioObject) {
env = aenv;
thisObject = athisObject;
ioObject = aioObject;
}
int getApeInfoFrameBlocks(int nFrameIndex);
int getApeInfoSeekByte(int nFrameIndex);
int GetData(char* pBuffer, int nBlocks, int* pBlocksRetrieved);
int Seek(int nBlockOffset);
int GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1 = 0, int nParam2 = 0);
protected:
// file info
int m_nBlockAlign;
int m_nCurrentFrame;
int m_nRealFrame;
// start / finish information
int m_nStartBlock;
int m_nFinishBlock;
int m_nCurrentBlock;
BOOL m_bIsRanged;
BOOL m_bDecompressorInitialized;
// decoding tools
CPrepare m_Prepare;
WAVEFORMATEX m_wfeInput;
unsigned int m_nCRC;
unsigned int m_nStoredCRC;
int m_nSpecialCodes;
int SeekToFrame(int nFrameIndex);
void DecodeBlocksToFrameBuffer(int nBlocks);
int FillFrameBuffer();
void StartFrame();
void EndFrame();
int InitializeDecompressor();
// more decoding components
CSmartPtr m_spAPEInfo;
CSmartPtr m_spUnBitArray;
UNBIT_ARRAY_STATE m_BitArrayStateX;
UNBIT_ARRAY_STATE m_BitArrayStateY;
CSmartPtr m_spNewPredictorX;
CSmartPtr m_spNewPredictorY;
int m_nLastX;
// decoding buffer
BOOL m_bErrorDecodingCurrentFrame;
int m_nCurrentFrameBufferBlock;
int m_nFrameBufferFinishedBlocks;
CCircleBuffer m_cbFrameBuffer;
int m_nVersion;
int m_nCompressionLevel;
int m_nBlocksPerFrame;
int m_nBitsPerSample;
friend class CUnBitArrayJMAC;
JNIEnv* env;
jobject ioObject;
jobject thisObject;
};
#endif // #ifndef JMAC_APEDECOMPRESS_H
jmac-1.74/core/nativesrc/jmac/jmac.cpp 0000644 0001750 0001750 00000012166 10131230056 017570 0 ustar twerner twerner /*
* 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.
*----------------------------------------------------------------------
*/
// jmac.cpp
//
#include
#include
#include "jmac.h"
#include "APEDecompressJMAC.h"
#define MAX_DECODERS 1024
CAPEDecompressJMAC* decoders[MAX_DECODERS];
typedef struct MAC_ERROR {
int nErrorCode;
char* spErrorExplanation;
} MAC_ERROR;
#define NUM_MAC_ERRORS 23
MAC_ERROR MAC_ERRORS[NUM_MAC_ERRORS] = {
ERROR_EXPLANATION
};
void ThrowError(JNIEnv* env, int nErrorCode) {
char* errorMessage = "Error Undefined";
for (int i = 0; i < NUM_MAC_ERRORS; i++) {
if (MAC_ERRORS[i].nErrorCode == nErrorCode) {
errorMessage = MAC_ERRORS[i].spErrorExplanation;
break;
}
}
jclass clazz = env->FindClass("davaguine/jmac/tools/JMACException");
if (clazz == NULL) {
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
} else
env->ThrowNew(clazz, errorMessage);
env->DeleteLocalRef(clazz);
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
memset(decoders, 0, sizeof(decoders));
return JNI_VERSION_1_4;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) {
for (jint i = 0; i < MAX_DECODERS; i++) {
if (decoders[i]) {
delete decoders[i];
decoders[i] = NULL;
}
}
}
JNIEXPORT jint JNICALL Java_davaguine_jmac_decoder_APEDecompressNative_registerDecoder(JNIEnv* env, jobject athisObject, jobject aioObject,
jint nVersion, jint nCompressionLevel,
jint nStartBlock, jint nFinishBlock,
jint nTotalBlocks, jint nBlockAlign,
jint nBlocksPerFrame, jint nSampleRate,
jint nBitsPerSample, jint nChannels) {
for (jint i = 0; i < MAX_DECODERS; i++) {
if (!decoders[i]) {
decoders[i] = new CAPEDecompressJMAC(env, athisObject, aioObject, nVersion, nCompressionLevel, nStartBlock, nFinishBlock,
nTotalBlocks, nBlockAlign, nBlocksPerFrame, nSampleRate, nBitsPerSample, nChannels);
return i;
}
}
return -1;
}
JNIEXPORT jint JNICALL Java_davaguine_jmac_decoder_APEDecompressNative_GetData(JNIEnv* env, jobject athisObject, jint ID, jobject aioObject,
jbyteArray pBuffer, jint nBlocks) {
if (decoders[ID] != NULL) {
decoders[ID]->SetRefs(env, athisObject, aioObject);
jbyte* elements = env->GetByteArrayElements(pBuffer, NULL);
if (elements != NULL) {
int nBlocksRetrieved;
int retValue = decoders[ID]->GetData((char*) elements, nBlocks, &nBlocksRetrieved);
env->ReleaseByteArrayElements(pBuffer, elements, 0);
if (retValue != ERROR_SUCCESS)
ThrowError(env, retValue);
return nBlocksRetrieved;
}
}
ThrowError(env, ERROR_UNDEFINED);
return -1;
};
JNIEXPORT void JNICALL Java_davaguine_jmac_decoder_APEDecompressNative_Seek(JNIEnv* env, jobject athisObject, jint ID, jobject aioObject,
jint nBlockOffset) {
if (decoders[ID] != NULL) {
decoders[ID]->SetRefs(env, athisObject, aioObject);
int retValue = decoders[ID]->Seek(nBlockOffset);
if (retValue != ERROR_SUCCESS)
ThrowError(env, retValue);
return;
}
ThrowError(env, ERROR_UNDEFINED);
};
JNIEXPORT void JNICALL Java_davaguine_jmac_decoder_APEDecompressNative_finalize(JNIEnv* env, jobject athisObject, jint ID, jobject aioObject) {
if (decoders[ID] != NULL) {
decoders[ID]->SetRefs(env, athisObject, aioObject);
delete decoders[ID];
decoders[ID] = NULL;
return;
}
ThrowError(env, ERROR_UNDEFINED);
};
jmac-1.74/core/nativesrc/jmac/jmac.def 0000644 0001750 0001750 00000000606 10131230056 017540 0 ustar twerner twerner ; jmac.def : Declares the module parameters for the DLL.
LIBRARY "jmac"
EXPORTS
; Explicit exports can go here
JNI_OnLoad
JNI_OnUnload
Java_davaguine_jmac_decoder_APEDecompressNative_registerDecoder
Java_davaguine_jmac_decoder_APEDecompressNative_GetData
Java_davaguine_jmac_decoder_APEDecompressNative_Seek
Java_davaguine_jmac_decoder_APEDecompressNative_finalize
jmac-1.74/core/nativesrc/jmac/jmac.h 0000644 0001750 0001750 00000005431 10131230056 017232 0 ustar twerner twerner /*
* 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.
*----------------------------------------------------------------------
*/
#ifndef _JMAC_H
#define _JMAC_H
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved);
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved);
JNIEXPORT jint JNICALL Java_davaguine_jmac_decoder_APEDecompressNative_registerDecoder(JNIEnv* env, jobject athisObject,
jobject aioObject, jint nVersion,
jint nCompressionLevel, jint nStartBlock,
jint nFinishBlock, jint nTotalBlocks,
jint nBlockAlign, jint nBlocksPerFrame,
jint nSampleRate, jint nBitsPerSample,
jint nChannels);
JNIEXPORT jint JNICALL Java_davaguine_jmac_decoder_APEDecompressNative_GetData(JNIEnv* env, jobject athisObject, jint ID,
jobject aioObject, jbyteArray pBuffer, jint nBlocks);
JNIEXPORT void JNICALL Java_davaguine_jmac_decoder_APEDecompressNative_Seek(JNIEnv* env, jobject athisObject, jint ID,
jobject aioObject, jint nBlockOffset);
JNIEXPORT void JNICALL Java_davaguine_jmac_decoder_APEDecompressNative_finalize(JNIEnv* env, jobject athisObject, jint ID,
jobject aioObject);
#ifdef __cplusplus
}
#endif
#endif //_JMAC_H
jmac-1.74/core/nativesrc/jmac/jmac.sln 0000644 0001750 0001750 00000001543 10451140437 017607 0 ustar twerner twerner Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jmac", "jmac.vcproj", "{E5C18EDC-7E7B-4EED-A810-4CC86D5D25F4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E5C18EDC-7E7B-4EED-A810-4CC86D5D25F4}.Debug|Win32.ActiveCfg = Debug|Win32
{E5C18EDC-7E7B-4EED-A810-4CC86D5D25F4}.Debug|Win32.Build.0 = Debug|Win32
{E5C18EDC-7E7B-4EED-A810-4CC86D5D25F4}.Release|Win32.ActiveCfg = Release|Win32
{E5C18EDC-7E7B-4EED-A810-4CC86D5D25F4}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
jmac-1.74/core/nativesrc/jmac/jmac.vcproj 0000644 0001750 0001750 00000012626 10451144232 020317 0 ustar twerner twerner
jmac-1.74/core/nativesrc/jmac/Makefile 0000644 0001750 0001750 00000001410 10131230056 017600 0 ustar twerner twerner TARGET = jmac
INCLUDES = -I/usr/local/java/include -I/usr/local/java/include/linux -I../mac/Source/MACLib -I../mac/Source/Shared
CPPOPT = -s -O3 -D__GNUC_IA32__ -DBUILD_CROSS_PLATFORM
COMPILER = gcc
SOURCEFILES = \
APEDecompressJMAC.o \
jmac.o \
UnBitArrayJMAC.o \
../mac/Shared/libmac.a
$(TARGET): $(SOURCEFILES)
$(COMPILER) -lstdc++ -shared $(CPPOPT) $(INCLUDES) -o lib$(TARGET).so $(SOURCEFILES)
APEDecompressJMAC.o: APEDecompressJMAC.cpp
$(COMPILER) -c $(CPPOPT) $(INCLUDES) -o APEDecompressJMAC.o APEDecompressJMAC.cpp
jmac.o: jmac.cpp
$(COMPILER) -c $(CPPOPT) $(INCLUDES) -o jmac.o jmac.cpp
UnBitArrayJMAC.o: UnBitArrayJMAC.cpp
$(COMPILER) -c $(CPPOPT) $(INCLUDES) -o UnBitArrayJMAC.o UnBitArrayJMAC.cpp
jmac-1.74/core/nativesrc/jmac/NULLIO.h 0000644 0001750 0001750 00000003755 10131230056 017331 0 ustar twerner twerner /*
* 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.
*----------------------------------------------------------------------
*/
#ifndef JMAC_NULLIO_H
#define JMAC_NULLIO_H
class CNULLIO : public CIO {
public:
// construction / destruction
CNULLIO() {
};
~CNULLIO() {
};
// open / close
int Open(const wchar_t* pName) {
return 0;
};
int Close() {
return 0;
};
// read / write
int Read(void* pBuffer, unsigned int nBytesToRead, unsigned int* pBytesRead) {
return 0;
};
int Write(const void* pBuffer, unsigned int nBytesToWrite, unsigned int* pBytesWritten) {
return 0;
};
// seek
int Seek(int nDistance, unsigned int nMoveMode) {
return 0;
};
// other functions
int SetEOF() {
return 0;
};
// creation / destruction
int Create(const wchar_t* pName) {
return 0;
};
int Delete() {
return 0;
};
// attributes
int GetPosition() {
return 0;
};
int GetSize() {
return 0;
};
int GetName(wchar_t* pBuffer) {
return 0;
};
};
#endif //JMAC_NULLIO_H
jmac-1.74/core/nativesrc/jmac/UnBitArrayJMAC.cpp 0000644 0001750 0001750 00000011306 10131230056 021324 0 ustar twerner twerner /*
* 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.
*----------------------------------------------------------------------
*/
#include
#include
#include
#include "UnBitArrayJMAC.h"
#include "APEDecompressJMAC.h"
#include "NULLIO.h"
CNULLIO m_IO;
/***********************************************************************************
Construction
***********************************************************************************/
CUnBitArrayJMAC::CUnBitArrayJMAC(CAPEDecompressJMAC* decoder, int nVersion) : CUnBitArray(&m_IO, nVersion) {
m_APEDecompress = decoder;
JNIEnv* env = m_APEDecompress->env;
jbyteArray ba = env->NewByteArray(m_nBytes);
if (ba != NULL) {
byteArray = (jbyteArray) env->NewGlobalRef(ba);
env->DeleteLocalRef(ba);
} else
byteArray = NULL;
}
CUnBitArrayJMAC::~CUnBitArrayJMAC() {
if (byteArray != NULL)
m_APEDecompress->env->DeleteGlobalRef(byteArray);
}
int CUnBitArrayJMAC::Seek(int nDistance) {
JNIEnv* env = m_APEDecompress->env;
jclass clazz = env->GetObjectClass(m_APEDecompress->ioObject);
jmethodID method = env->GetMethodID(clazz, "seek", "(J)V");
if (method == NULL) {
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
env->DeleteLocalRef(clazz);
return ERROR_IO_READ;
}
env->DeleteLocalRef(clazz);
env->CallVoidMethod(m_APEDecompress->ioObject, method, (jlong) nDistance);
if (env->ExceptionOccurred()) {
env->ExceptionClear();
return ERROR_IO_READ;
}
return ERROR_SUCCESS;
}
int CUnBitArrayJMAC::Read(void* pBuffer, unsigned int nBytesToRead, unsigned int* pBytesRead) {
JNIEnv* env = m_APEDecompress->env;
jclass clazz = env->GetObjectClass(m_APEDecompress->ioObject);
jmethodID method = env->GetMethodID(clazz, "read", "([BII)I");
if (method == NULL) {
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
env->DeleteLocalRef(clazz);
return ERROR_IO_READ;
}
env->DeleteLocalRef(clazz);
*pBytesRead = env->CallIntMethod(m_APEDecompress->ioObject, method, byteArray, 0, nBytesToRead);
if (env->ExceptionOccurred()) {
env->ExceptionClear();
return ERROR_IO_READ;
}
void* elements = env->GetPrimitiveArrayCritical(byteArray, NULL);
if (elements == NULL) {
if (env->ExceptionOccurred())
env->ExceptionClear();
return ERROR_IO_READ;
}
memcpy(pBuffer, elements, nBytesToRead);
env->ReleasePrimitiveArrayCritical(byteArray, elements, 0);
return ERROR_SUCCESS;
}
int CUnBitArrayJMAC::FillAndResetBitArray(int nFileLocation, int nNewBitIndex) {
// reset the bit index
m_nCurrentBitIndex = nNewBitIndex;
// seek if necessary
if (nFileLocation != -1) {
if (Seek(nFileLocation) != 0)
return ERROR_IO_READ;
}
// read the new data into the bit array
unsigned int nBytesRead = 0;
if (Read(((unsigned char *) m_pBitArray), m_nBytes, &nBytesRead) != ERROR_SUCCESS)
return ERROR_IO_READ;
return ERROR_SUCCESS;
}
int CUnBitArrayJMAC::FillBitArray() {
// get the bit array index
uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5;
// move the remaining data to the front
memmove((void *) (m_pBitArray), (const void *) (m_pBitArray + nBitArrayIndex), m_nBytes - (nBitArrayIndex * 4));
// read the new data
int nBytesToRead = nBitArrayIndex * 4;
unsigned int nBytesRead = 0;
int nRetVal = Read((unsigned char*) (m_pBitArray + m_nElements - nBitArrayIndex), nBytesToRead, &nBytesRead);
// adjust the m_Bit pointer
m_nCurrentBitIndex = m_nCurrentBitIndex & 31;
// return
return (nRetVal == ERROR_SUCCESS) ? ERROR_SUCCESS : ERROR_IO_READ;
}
jmac-1.74/core/nativesrc/jmac/UnBitArrayJMAC.h 0000644 0001750 0001750 00000003170 10131230056 020771 0 ustar twerner twerner /*
* 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.
*----------------------------------------------------------------------
*/
#ifndef JMAC_UNBITARRAY_H
#define JMAC_UNBITARRAY_H
#include
#include "UnBitArrayJMAC.h"
class CAPEDecompressJMAC;
class CUnBitArrayJMAC : public CUnBitArray {
public:
// construction/destruction
CUnBitArrayJMAC(CAPEDecompressJMAC* decoder, int nVersion);
~CUnBitArrayJMAC();
virtual int FillBitArray();
virtual int FillAndResetBitArray(int nFileLocation = -1, int nNewBitIndex = 0);
private:
int Seek(int nDistance);
int Read(void* pBuffer, unsigned int nBytesToRead, unsigned int* pBytesRead);
CAPEDecompressJMAC* m_APEDecompress;
jbyteArray byteArray;
friend class CAPEDecompressJMAC;
};
#endif // #ifndef JMAC_UNBITARRAY_H
jmac-1.74/core/nativesrc/mac/ 0000755 0001750 0001750 00000000000 10451144641 016003 5 ustar twerner twerner jmac-1.74/core/nativesrc/mac/Shared/ 0000755 0001750 0001750 00000000000 10451144641 017211 5 ustar twerner twerner jmac-1.74/core/nativesrc/mac/Shared/MACLib.lib 0000644 0001750 0001750 00001245562 10131230056 020736 0 ustar twerner twerner !
/ 1084342683 0 24022 `
1 ¼&