initial checkin

This commit is contained in:
chudov
2008-10-13 19:25:11 +00:00
parent 2e379c72e2
commit 36757fca7a
937 changed files with 184964 additions and 0 deletions

View File

@@ -0,0 +1,178 @@
#include "All.h"
#ifdef BACKWARDS_COMPATIBILITY
#include "UnMAC.h"
#include "APEDecompressCore.h"
#include "../APEInfo.h"
#include "GlobalFunctions.h"
#include "../UnBitArrayBase.h"
#include "Anti-Predictor.h"
#include "UnMAC.h"
#include "../Prepare.h"
#include "../UnBitArray.h"
#include "../Assembly/Assembly.h"
CAPEDecompressCore::CAPEDecompressCore(CIO * pIO, IAPEDecompress * pAPEDecompress)
{
m_pAPEDecompress = pAPEDecompress;
// initialize the bit array
m_pUnBitArray = CreateUnBitArray(pAPEDecompress, pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) >= 3930)
throw(0);
m_pAntiPredictorX = CreateAntiPredictor(pAPEDecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL), pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
m_pAntiPredictorY = CreateAntiPredictor(pAPEDecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL), pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
m_pDataX = new int [pAPEDecompress->GetInfo(APE_INFO_BLOCKS_PER_FRAME) + 16];
m_pDataY = new int [pAPEDecompress->GetInfo(APE_INFO_BLOCKS_PER_FRAME) + 16];
m_pTempData = new int [pAPEDecompress->GetInfo(APE_INFO_BLOCKS_PER_FRAME) + 16];
m_nBlocksProcessed = 0;
// check to see if MMX is available
m_bMMXAvailable = GetMMXAvailable();
}
CAPEDecompressCore::~CAPEDecompressCore()
{
SAFE_DELETE(m_pUnBitArray)
SAFE_DELETE(m_pAntiPredictorX)
SAFE_DELETE(m_pAntiPredictorY)
SAFE_ARRAY_DELETE(m_pDataX)
SAFE_ARRAY_DELETE(m_pDataY)
SAFE_ARRAY_DELETE(m_pTempData)
}
void CAPEDecompressCore::GenerateDecodedArrays(int nBlocks, int nSpecialCodes, int nFrameIndex, int nCPULoadBalancingFactor)
{
CUnBitArray * pBitArray = (CUnBitArray *) m_pUnBitArray;
if (m_pAPEDecompress->GetInfo(APE_INFO_CHANNELS) == 2)
{
if ((nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE) && (nSpecialCodes & SPECIAL_FRAME_RIGHT_SILENCE))
{
memset(m_pDataX, 0, nBlocks * 4);
memset(m_pDataY, 0, nBlocks * 4);
}
else if (nSpecialCodes & SPECIAL_FRAME_PSEUDO_STEREO)
{
GenerateDecodedArray(m_pDataX, nBlocks, nFrameIndex, m_pAntiPredictorX, nCPULoadBalancingFactor);
memset(m_pDataY, 0, nBlocks * 4);
}
else
{
GenerateDecodedArray(m_pDataX, nBlocks, nFrameIndex, m_pAntiPredictorX, nCPULoadBalancingFactor);
GenerateDecodedArray(m_pDataY, nBlocks, nFrameIndex, m_pAntiPredictorY, nCPULoadBalancingFactor);
}
}
else
{
if (nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE)
{
memset(m_pDataX, 0, nBlocks * 4);
}
else
{
GenerateDecodedArray(m_pDataX, nBlocks, nFrameIndex, m_pAntiPredictorX, nCPULoadBalancingFactor);
}
}
}
void CAPEDecompressCore::GenerateDecodedArray(int * Input_Array, uint32 Number_of_Elements, int Frame_Index, CAntiPredictor *pAntiPredictor, int CPULoadBalancingFactor)
{
const int nFrameBytes = m_pAPEDecompress->GetInfo(APE_INFO_FRAME_BYTES, Frame_Index);
// run the prediction sequence
switch (m_pAPEDecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL))
{
#ifdef ENABLE_COMPRESSION_MODE_FAST
case COMPRESSION_LEVEL_FAST:
if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) < 3320)
{
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
pAntiPredictor->AntiPredict(m_pTempData, Input_Array, Number_of_Elements);
}
else
{
m_pUnBitArray->GenerateArray(Input_Array, Number_of_Elements, nFrameBytes);
pAntiPredictor->AntiPredict(Input_Array, NULL, Number_of_Elements);
}
break;
#endif // #ifdef ENABLE_COMPRESSION_MODE_FAST
#ifdef ENABLE_COMPRESSION_MODE_NORMAL
case COMPRESSION_LEVEL_NORMAL:
{
// get the array from the bitstream
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
pAntiPredictor->AntiPredict(m_pTempData, Input_Array, Number_of_Elements);
break;
}
#endif // #ifdef ENABLE_COMPRESSION_MODE_NORMAL
#ifdef ENABLE_COMPRESSION_MODE_HIGH
case COMPRESSION_LEVEL_HIGH:
// get the array from the bitstream
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
pAntiPredictor->AntiPredict(m_pTempData, Input_Array, Number_of_Elements);
break;
#endif // #ifdef ENABLE_COMPRESSION_MODE_HIGH
#ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
case COMPRESSION_LEVEL_EXTRA_HIGH:
unsigned int aryCoefficientsA[64], aryCoefficientsB[64], nNumberOfCoefficients;
#define GET_COEFFICIENTS(NumberOfCoefficientsBits, ValueBits) \
nNumberOfCoefficients = m_pUnBitArray->DecodeValue(DECODE_VALUE_METHOD_X_BITS, NumberOfCoefficientsBits); \
for (unsigned int z = 0; z <= nNumberOfCoefficients; z++) \
{ \
aryCoefficientsA[z] = m_pUnBitArray->DecodeValue(DECODE_VALUE_METHOD_X_BITS, ValueBits); \
aryCoefficientsB[z] = m_pUnBitArray->DecodeValue(DECODE_VALUE_METHOD_X_BITS, ValueBits); \
} \
if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) < 3320)
{
GET_COEFFICIENTS(4, 6)
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
((CAntiPredictorExtraHigh0000To3320 *) pAntiPredictor)->AntiPredict(m_pTempData, Input_Array, Number_of_Elements, nNumberOfCoefficients, &aryCoefficientsA[0], &aryCoefficientsB[0]);
}
else if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) < 3600)
{
GET_COEFFICIENTS(3, 5)
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
((CAntiPredictorExtraHigh3320To3600 *) pAntiPredictor)->AntiPredict(m_pTempData, Input_Array, Number_of_Elements, nNumberOfCoefficients, &aryCoefficientsA[0], &aryCoefficientsB[0]);
}
else if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) < 3700)
{
GET_COEFFICIENTS(3, 6)
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
((CAntiPredictorExtraHigh3600To3700 *) pAntiPredictor)->AntiPredict(m_pTempData, Input_Array, Number_of_Elements, nNumberOfCoefficients, &aryCoefficientsA[0], &aryCoefficientsB[0]);
}
else if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) < 3800)
{
GET_COEFFICIENTS(3, 6)
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
((CAntiPredictorExtraHigh3700To3800 *) pAntiPredictor)->AntiPredict(m_pTempData, Input_Array, Number_of_Elements, nNumberOfCoefficients, &aryCoefficientsA[0], &aryCoefficientsB[0]);
}
else
{
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
((CAntiPredictorExtraHigh3800ToCurrent *) pAntiPredictor)->AntiPredict(m_pTempData, Input_Array, Number_of_Elements, m_bMMXAvailable, CPULoadBalancingFactor, m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
}
break;
#endif // #ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
}
}
#endif // #ifdef BACKWARDS_COMPATIBILITY

View File

@@ -0,0 +1,37 @@
#ifndef APE_DECOMPRESS_CORE_H
#define APE_DECOMPRESS_CORE_H
class CAPEDecompressCore
{
public:
CAPEDecompressCore(CIO * pIO, IAPEDecompress * pAPEDecompress);
~CAPEDecompressCore();
void GenerateDecodedArrays(int nBlocks, int nSpecialCodes, int nFrameIndex, int nCPULoadBalancingFactor);
void GenerateDecodedArray(int *Input_Array, uint32 Number_of_Elements, int Frame_Index, CAntiPredictor *pAntiPredictor, int CPULoadBalancingFactor = 0);
int * GetDataX() { return m_pDataX; }
int * GetDataY() { return m_pDataY; }
CUnBitArrayBase * GetUnBitArrray() { return m_pUnBitArray; }
int * m_pTempData;
int * m_pDataX;
int * m_pDataY;
CAntiPredictor * m_pAntiPredictorX;
CAntiPredictor * m_pAntiPredictorY;
CUnBitArrayBase * m_pUnBitArray;
BIT_ARRAY_STATE m_BitArrayStateX;
BIT_ARRAY_STATE m_BitArrayStateY;
IAPEDecompress * m_pAPEDecompress;
BOOL m_bMMXAvailable;
int m_nBlocksProcessed;
};
#endif // #ifndef APE_DECOMPRESS_CORE_H

View File

@@ -0,0 +1,279 @@
#include "All.h"
#ifdef BACKWARDS_COMPATIBILITY
#include "UnMAC.h"
#include "APEDecompressOld.h"
#include "../APEInfo.h"
CAPEDecompressOld::CAPEDecompressOld(int * pErrorCode, CAPEInfo * pAPEInfo, int nStartBlock, int nFinishBlock)
{
*pErrorCode = ERROR_SUCCESS;
// open / analyze the file
m_spAPEInfo.Assign(pAPEInfo);
// version check (this implementation only works with 3.92 and earlier files)
if (GetInfo(APE_INFO_FILE_VERSION) > 3920)
{
*pErrorCode = ERROR_UNDEFINED;
return;
}
// create the buffer
m_nBlockAlign = GetInfo(APE_INFO_BLOCK_ALIGN);
// initialize other stuff
m_nBufferTail = 0;
m_bDecompressorInitialized = FALSE;
m_nCurrentFrame = 0;
m_nCurrentBlock = 0;
// set the "real" start and finish blocks
m_nStartBlock = (nStartBlock < 0) ? 0 : min(nStartBlock, GetInfo(APE_INFO_TOTAL_BLOCKS));
m_nFinishBlock = (nFinishBlock < 0) ? GetInfo(APE_INFO_TOTAL_BLOCKS) : min(nFinishBlock, GetInfo(APE_INFO_TOTAL_BLOCKS));
m_bIsRanged = (m_nStartBlock != 0) || (m_nFinishBlock != GetInfo(APE_INFO_TOTAL_BLOCKS));
}
CAPEDecompressOld::~CAPEDecompressOld()
{
}
int CAPEDecompressOld::InitializeDecompressor()
{
// check if we have anything to do
if (m_bDecompressorInitialized)
return ERROR_SUCCESS;
// initialize the decoder
RETURN_ON_ERROR(m_UnMAC.Initialize(this))
int nMaximumDecompressedFrameBytes = m_nBlockAlign * GetInfo(APE_INFO_BLOCKS_PER_FRAME);
int nTotalBufferBytes = max(65536, (nMaximumDecompressedFrameBytes + 16) * 2);
m_spBuffer.Assign(new char [nTotalBufferBytes], TRUE);
if (m_spBuffer == NULL)
return ERROR_INSUFFICIENT_MEMORY;
// update the initialized flag
m_bDecompressorInitialized = TRUE;
// seek to the beginning
return Seek(0);
}
int CAPEDecompressOld::GetData(char * pBuffer, int nBlocks, int * pBlocksRetrieved)
{
if (pBlocksRetrieved) *pBlocksRetrieved = 0;
RETURN_ON_ERROR(InitializeDecompressor())
// cap
int nBlocksUntilFinish = m_nFinishBlock - m_nCurrentBlock;
nBlocks = min(nBlocks, nBlocksUntilFinish);
int nBlocksRetrieved = 0;
// fulfill as much of the request as possible
int nTotalBytesNeeded = nBlocks * m_nBlockAlign;
int nBytesLeft = nTotalBytesNeeded;
int nBlocksDecoded = 1;
while (nBytesLeft > 0 && nBlocksDecoded > 0)
{
// empty the buffer
int nBytesAvailable = m_nBufferTail;
int nIntialBytes = min(nBytesLeft, nBytesAvailable);
if (nIntialBytes > 0)
{
memcpy(&pBuffer[nTotalBytesNeeded - nBytesLeft], &m_spBuffer[0], nIntialBytes);
if ((m_nBufferTail - nIntialBytes) > 0)
memmove(&m_spBuffer[0], &m_spBuffer[nIntialBytes], m_nBufferTail - nIntialBytes);
nBytesLeft -= nIntialBytes;
m_nBufferTail -= nIntialBytes;
}
// decode more
if (nBytesLeft > 0)
{
nBlocksDecoded = m_UnMAC.DecompressFrame((unsigned char *) &m_spBuffer[m_nBufferTail], m_nCurrentFrame++, 0);
if (nBlocksDecoded == -1)
{
return -1;
}
m_nBufferTail += (nBlocksDecoded * m_nBlockAlign);
}
}
nBlocksRetrieved = (nTotalBytesNeeded - nBytesLeft) / m_nBlockAlign;
// update the position
m_nCurrentBlock += nBlocksRetrieved;
if (pBlocksRetrieved) *pBlocksRetrieved = nBlocksRetrieved;
return ERROR_SUCCESS;
}
int CAPEDecompressOld::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;
// flush the buffer
m_nBufferTail = 0;
// seek to the perfect location
int nBaseFrame = nBlockOffset / GetInfo(APE_INFO_BLOCKS_PER_FRAME);
int nBlocksToSkip = nBlockOffset % GetInfo(APE_INFO_BLOCKS_PER_FRAME);
int nBytesToSkip = nBlocksToSkip * m_nBlockAlign;
// skip necessary blocks
int nMaximumDecompressedFrameBytes = m_nBlockAlign * GetInfo(APE_INFO_BLOCKS_PER_FRAME);
char *pTempBuffer = new char [nMaximumDecompressedFrameBytes + 16];
ZeroMemory(pTempBuffer, nMaximumDecompressedFrameBytes + 16);
m_nCurrentFrame = nBaseFrame;
int nBlocksDecoded = m_UnMAC.DecompressFrame((unsigned char *) pTempBuffer, m_nCurrentFrame++, 0);
if (nBlocksDecoded == -1)
{
return -1;
}
int nBytesToKeep = (nBlocksDecoded * m_nBlockAlign) - nBytesToSkip;
memcpy(&m_spBuffer[m_nBufferTail], &pTempBuffer[nBytesToSkip], nBytesToKeep);
m_nBufferTail += nBytesToKeep;
delete [] pTempBuffer;
m_nCurrentBlock = nBlockOffset;
return ERROR_SUCCESS;
}
int CAPEDecompressOld::GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1, int nParam2)
{
int nRetVal = 0;
BOOL bHandled = TRUE;
switch (Field)
{
case APE_DECOMPRESS_CURRENT_BLOCK:
nRetVal = m_nCurrentBlock - m_nStartBlock;
break;
case APE_DECOMPRESS_CURRENT_MS:
{
int nSampleRate = m_spAPEInfo->GetInfo(APE_INFO_SAMPLE_RATE, 0, 0);
if (nSampleRate > 0)
nRetVal = int((double(m_nCurrentBlock) * double(1000)) / double(nSampleRate));
break;
}
case APE_DECOMPRESS_TOTAL_BLOCKS:
nRetVal = m_nFinishBlock - m_nStartBlock;
break;
case APE_DECOMPRESS_LENGTH_MS:
{
int nSampleRate = m_spAPEInfo->GetInfo(APE_INFO_SAMPLE_RATE, 0, 0);
if (nSampleRate > 0)
nRetVal = int((double(m_nFinishBlock - m_nStartBlock) * double(1000)) / double(nSampleRate));
break;
}
case APE_DECOMPRESS_CURRENT_BITRATE:
nRetVal = GetInfo(APE_INFO_FRAME_BITRATE, m_nCurrentFrame);
break;
case APE_DECOMPRESS_AVERAGE_BITRATE:
{
if (m_bIsRanged)
{
// figure the frame range
const int nBlocksPerFrame = GetInfo(APE_INFO_BLOCKS_PER_FRAME);
int nStartFrame = m_nStartBlock / nBlocksPerFrame;
int nFinishFrame = (m_nFinishBlock + nBlocksPerFrame - 1) / nBlocksPerFrame;
// get the number of bytes in the first and last frame
int nTotalBytes = (GetInfo(APE_INFO_FRAME_BYTES, nStartFrame) * (m_nStartBlock % nBlocksPerFrame)) / nBlocksPerFrame;
if (nFinishFrame != nStartFrame)
nTotalBytes += (GetInfo(APE_INFO_FRAME_BYTES, nFinishFrame) * (m_nFinishBlock % nBlocksPerFrame)) / nBlocksPerFrame;
// get the number of bytes in between
const int nTotalFrames = GetInfo(APE_INFO_TOTAL_FRAMES);
for (int nFrame = nStartFrame + 1; (nFrame < nFinishFrame) && (nFrame < nTotalFrames); nFrame++)
nTotalBytes += GetInfo(APE_INFO_FRAME_BYTES, nFrame);
// figure the bitrate
int nTotalMS = int((double(m_nFinishBlock - m_nStartBlock) * double(1000)) / double(GetInfo(APE_INFO_SAMPLE_RATE)));
if (nTotalMS != 0)
nRetVal = (nTotalBytes * 8) / nTotalMS;
}
else
{
nRetVal = GetInfo(APE_INFO_AVERAGE_BITRATE);
}
break;
}
default:
bHandled = FALSE;
}
if (!bHandled && m_bIsRanged)
{
bHandled = TRUE;
switch (Field)
{
case APE_INFO_WAV_HEADER_BYTES:
nRetVal = sizeof(WAVE_HEADER);
break;
case APE_INFO_WAV_HEADER_DATA:
{
char * pBuffer = (char *) nParam1;
int nMaxBytes = nParam2;
if (sizeof(WAVE_HEADER) > nMaxBytes)
{
nRetVal = -1;
}
else
{
WAVEFORMATEX wfeFormat; GetInfo(APE_INFO_WAVEFORMATEX, (int) &wfeFormat, 0);
WAVE_HEADER WAVHeader; FillWaveHeader(&WAVHeader,
(m_nFinishBlock - m_nStartBlock) * GetInfo(APE_INFO_BLOCK_ALIGN),
&wfeFormat, 0);
memcpy(pBuffer, &WAVHeader, sizeof(WAVE_HEADER));
nRetVal = 0;
}
break;
}
case APE_INFO_WAV_TERMINATING_BYTES:
nRetVal = 0;
break;
case APE_INFO_WAV_TERMINATING_DATA:
nRetVal = 0;
break;
default:
bHandled = FALSE;
}
}
if (bHandled == FALSE)
nRetVal = m_spAPEInfo->GetInfo(Field, nParam1, nParam2);
return nRetVal;
}
#endif // #ifdef BACKWARDS_COMPATIBILITY

View File

@@ -0,0 +1,43 @@
#ifndef _apedecompressold_h_
#define _apedecompressold_h_
#include "../APEDecompress.h"
#include "UnMAC.h"
class CAPEDecompressOld : public IAPEDecompress
{
public:
CAPEDecompressOld(int * pErrorCode, CAPEInfo * pAPEInfo, int nStartBlock = -1, int nFinishBlock = -1);
~CAPEDecompressOld();
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:
// buffer
CSmartPtr<char> m_spBuffer;
int m_nBufferTail;
// file info
int m_nBlockAlign;
int m_nCurrentFrame;
// start / finish information
int m_nStartBlock;
int m_nFinishBlock;
int m_nCurrentBlock;
BOOL m_bIsRanged;
// decoding tools
CUnMAC m_UnMAC;
CSmartPtr<CAPEInfo> m_spAPEInfo;
BOOL m_bDecompressorInitialized;
int InitializeDecompressor();
};
#endif //_apedecompressold_h_

View File

@@ -0,0 +1,394 @@
#include "All.h"
#ifdef BACKWARDS_COMPATIBILITY
#include "../MACLib.h"
#include "Anti-Predictor.h"
CAntiPredictor * CreateAntiPredictor(int nCompressionLevel, int nVersion)
{
CAntiPredictor *pAntiPredictor = NULL;
switch (nCompressionLevel)
{
#ifdef ENABLE_COMPRESSION_MODE_FAST
case COMPRESSION_LEVEL_FAST:
if (nVersion < 3320)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorFast0000To3320;
}
else
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorFast3320ToCurrent;
}
break;
#endif //ENABLE_COMPRESSION_MODE_FAST
#ifdef ENABLE_COMPRESSION_MODE_NORMAL
case COMPRESSION_LEVEL_NORMAL:
if (nVersion < 3320)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorNormal0000To3320;
}
else if (nVersion < 3800)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorNormal3320To3800;
}
else
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorNormal3800ToCurrent;
}
break;
#endif //ENABLE_COMPRESSION_MODE_NORMAL
#ifdef ENABLE_COMPRESSION_MODE_HIGH
case COMPRESSION_LEVEL_HIGH:
if (nVersion < 3320)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorHigh0000To3320;
}
else if (nVersion < 3600)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorHigh3320To3600;
}
else if (nVersion < 3700)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorHigh3600To3700;
}
else if (nVersion < 3800)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorHigh3700To3800;
}
else
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorHigh3800ToCurrent;
}
break;
#endif //ENABLE_COMPRESSION_MODE_HIGH
#ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
case COMPRESSION_LEVEL_EXTRA_HIGH:
if (nVersion < 3320)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorExtraHigh0000To3320;
}
else if (nVersion < 3600)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorExtraHigh3320To3600;
}
else if (nVersion < 3700)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorExtraHigh3600To3700;
}
else if (nVersion < 3800)
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorExtraHigh3700To3800;
}
else
{
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorExtraHigh3800ToCurrent;
}
break;
#endif //ENABLE_COMPRESSION_MODE_EXTRA_HIGH
}
return pAntiPredictor;
}
CAntiPredictor::CAntiPredictor()
{
}
CAntiPredictor::~CAntiPredictor()
{
}
void CAntiPredictor::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
{
return;
}
void CAntiPredictorOffset::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Offset, int DeltaM)
{
memcpy(pOutputArray, pInputArray, Offset * 4);
int *ip = &pInputArray[Offset];
int *ipo = &pOutputArray[0];
int *op = &pOutputArray[Offset];
int m = 0;
for (; op < &pOutputArray[NumberOfElements]; ip++, ipo++, op++)
{
*op = *ip + ((*ipo * m) >> 12);
(*ipo ^ *ip) > 0 ? m += DeltaM : m -= DeltaM;
}
}
#ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
int CAntiPredictorExtraHighHelper::ConventionalDotProduct(short *bip, short *bbm, short *pIPAdaptFactor, int op, int nNumberOfIterations)
{
// dot product
int nDotProduct = 0;
short *pMaxBBM = &bbm[nNumberOfIterations];
if (op == 0)
{
while(bbm < pMaxBBM)
{
EXPAND_32_TIMES(nDotProduct += *bip++ * *bbm++;)
}
}
else if (op > 0)
{
while(bbm < pMaxBBM)
{
EXPAND_32_TIMES(nDotProduct += *bip++ * *bbm; *bbm++ += *pIPAdaptFactor++;)
}
}
else
{
while(bbm < pMaxBBM)
{
EXPAND_32_TIMES(nDotProduct += *bip++ * *bbm; *bbm++ -= *pIPAdaptFactor++;)
}
}
// use the dot product
return nDotProduct;
}
#ifdef ENABLE_ASSEMBLY
#define MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_HEAD \
__asm movq mm0, [esi] \
__asm add esi, 8 \
__asm movq mm1, [esi] \
__asm add esi, 8 \
__asm movq mm2, [esi] \
__asm add esi, 8 \
\
__asm movq mm3, [edi] \
__asm add edi, 8 \
__asm movq mm4, [edi] \
__asm add edi, 8 \
__asm movq mm5, [edi] \
__asm sub edi, 16 \
\
__asm pmaddwd mm0, mm3 \
__asm pmaddwd mm1, mm4 \
__asm pmaddwd mm2, mm5 \
\
__asm paddd mm7, mm0 \
__asm paddd mm7, mm1 \
__asm paddd mm7, mm2 \
#define MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD \
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_HEAD \
\
__asm paddw mm3, DWORD PTR [eax] \
__asm movq [edi], mm3 \
__asm add eax, 8 \
__asm add edi, 8 \
__asm paddw mm4, DWORD PTR [eax] \
__asm movq [edi], mm4 \
__asm add eax, 8 \
__asm add edi, 8 \
__asm paddw mm5, DWORD PTR [eax] \
__asm movq [edi], mm5 \
__asm add eax, 8 \
__asm add edi, 8
#define MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT \
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_HEAD \
\
__asm psubw mm3, DWORD PTR [eax] \
__asm movq [edi], mm3 \
__asm add eax, 8 \
__asm add edi, 8 \
__asm psubw mm4, DWORD PTR [eax] \
__asm movq [edi], mm4 \
__asm add eax, 8 \
__asm add edi, 8 \
__asm psubw mm5, DWORD PTR [eax] \
__asm movq [edi], mm5 \
__asm add eax, 8 \
__asm add edi, 8
int CAntiPredictorExtraHighHelper::MMXDotProduct(short *bip, short *bbm, short *pIPAdaptFactor, int op, int nNumberOfIterations)
{
int nDotProduct;
nNumberOfIterations = (nNumberOfIterations / 128);
if (op > 0)
{
__asm
{
push eax
mov eax, DWORD PTR [pIPAdaptFactor]
push esi
push edi
mov esi, DWORD PTR bip[0]
mov edi, DWORD PTR bbm[0]
pxor mm7, mm7
LBL_ADD_AGAIN:
/////////////////////////////////////////////////////////
// process 8 mm registers full
/////////////////////////////////////////////////////////
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
// fill the registers
movq mm0, [esi]
add esi, 8
movq mm1, [esi]
add esi, 8
movq mm3, [edi]
add edi, 8
movq mm4, [edi]
sub edi, 8
pmaddwd mm0, mm3
pmaddwd mm1, mm4
paddd mm7, mm0
paddd mm7, mm1
paddw mm3, DWORD PTR [eax]
movq [edi], mm3
add eax, 8
add edi, 8
paddw mm4, DWORD PTR [eax]
movq [edi], mm4
add eax, 8
add edi, 8
sub nNumberOfIterations, 1
cmp nNumberOfIterations, 0
jg LBL_ADD_AGAIN
///////////////////////////////////////////////////////////////
// clean-up
///////////////////////////////////////////////////////////////
// mm7 has the final dot-product (split into two dwords)
movq mm6, mm7
psrlq mm7, 32
paddd mm6, mm7
movd nDotProduct, mm6
pop edi
pop esi
pop eax
emms
}
}
else
{
__asm
{
push eax
mov eax, DWORD PTR [pIPAdaptFactor]
push esi
push edi
mov esi, DWORD PTR bip[0]
mov edi, DWORD PTR bbm[0]
pxor mm7, mm7
LBL_SUBTRACT_AGAIN:
/////////////////////////////////////////////////////////
// process 8 mm registers full
/////////////////////////////////////////////////////////
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
// fill the registers
movq mm0, [esi]
add esi, 8
movq mm1, [esi]
add esi, 8
movq mm3, [edi]
add edi, 8
movq mm4, [edi]
sub edi, 8
pmaddwd mm0, mm3
pmaddwd mm1, mm4
paddd mm7, mm0
paddd mm7, mm1
psubw mm3, DWORD PTR [eax]
movq [edi], mm3
add eax, 8
add edi, 8
psubw mm4, DWORD PTR [eax]
movq [edi], mm4
add eax, 8
add edi, 8
sub nNumberOfIterations, 1
cmp nNumberOfIterations, 0
jg LBL_SUBTRACT_AGAIN
///////////////////////////////////////////////////////////////
// clean-up
///////////////////////////////////////////////////////////////
// mm7 has the final dot-product (split into two dwords)
movq mm6, mm7
psrlq mm7, 32
paddd mm6, mm7
movd nDotProduct, mm6
pop edi
pop esi
pop eax
emms
}
}
return nDotProduct;
}
#endif // #ifdef ENABLE_ASSEMBLY
#endif // #ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
#endif // #ifdef BACKWARDS_COMPATIBILITY

View File

@@ -0,0 +1,253 @@
#ifndef APE_ANTIPREDICTOR_H
#define APE_ANTIPREDICTOR_H
class CAntiPredictor;
CAntiPredictor * CreateAntiPredictor(int nCompressionLevel, int nVersion);
/*****************************************************************************************
Base class for all anti-predictors
*****************************************************************************************/
class CAntiPredictor
{
public:
// construction/destruction
CAntiPredictor();
~CAntiPredictor();
// functions
virtual void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
/*****************************************************************************************
Offset anti-predictor
*****************************************************************************************/
class CAntiPredictorOffset : public CAntiPredictor
{
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Offset, int DeltaM);
};
#ifdef ENABLE_COMPRESSION_MODE_FAST
/*****************************************************************************************
Fast anti-predictor (from original 'fast' mode...updated for version 3.32)
*****************************************************************************************/
class CAntiPredictorFast0000To3320 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
/*****************************************************************************************
Fast anti-predictor (new 'fast' mode release with version 3.32)
*****************************************************************************************/
class CAntiPredictorFast3320ToCurrent : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
#endif // #ifdef ENABLE_COMPRESSION_MODE_FAST
#ifdef ENABLE_COMPRESSION_MODE_NORMAL
/*****************************************************************************************
Normal anti-predictor
*****************************************************************************************/
class CAntiPredictorNormal0000To3320 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
/*****************************************************************************************
Normal anti-predictor
*****************************************************************************************/
class CAntiPredictorNormal3320To3800 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
/*****************************************************************************************
Normal anti-predictor
*****************************************************************************************/
class CAntiPredictorNormal3800ToCurrent : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
#endif // #ifdef ENABLE_COMPRESSION_MODE_NORMAL
#ifdef ENABLE_COMPRESSION_MODE_HIGH
/*****************************************************************************************
High anti-predictor
*****************************************************************************************/
class CAntiPredictorHigh0000To3320 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
/*****************************************************************************************
High anti-predictor
*****************************************************************************************/
class CAntiPredictorHigh3320To3600 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
/*****************************************************************************************
High anti-predictor
*****************************************************************************************/
class CAntiPredictorHigh3600To3700 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
/*****************************************************************************************
High anti-predictor
*****************************************************************************************/
class CAntiPredictorHigh3700To3800 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
/*****************************************************************************************
High anti-predictor
*****************************************************************************************/
class CAntiPredictorHigh3800ToCurrent : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
};
#endif // #ifdef ENABLE_COMPRESSION_MODE_HIGH
#ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
/*****************************************************************************************
Extra high helper
*****************************************************************************************/
class CAntiPredictorExtraHighHelper
{
public:
int ConventionalDotProduct(short *bip, short *bbm, short *pIPAdaptFactor, int op, int nNumberOfIterations);
#ifdef ENABLE_ASSEMBLY
int MMXDotProduct(short *bip, short *bbm, short *pIPAdaptFactor, int op, int nNumberOfIterations);
#endif // #ifdef ENABLE_ASSEMBLY
};
/*****************************************************************************************
Extra high anti-predictor
*****************************************************************************************/
class CAntiPredictorExtraHigh0000To3320 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB);
private:
void AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g, int dm, int Max_Order);
};
/*****************************************************************************************
Extra high anti-predictor
*****************************************************************************************/
class CAntiPredictorExtraHigh3320To3600 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB);
private:
void AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g, int dm, int Max_Order);
};
/*****************************************************************************************
Extra high anti-predictor
*****************************************************************************************/
class CAntiPredictorExtraHigh3600To3700 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB);
private:
void AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g1, int g2, int Max_Order);
};
/*****************************************************************************************
Extra high anti-predictor
*****************************************************************************************/
class CAntiPredictorExtraHigh3700To3800 : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB);
private:
void AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g1, int g2, int Max_Order);
};
/*****************************************************************************************
Extra high anti-predictor
*****************************************************************************************/
class CAntiPredictorExtraHigh3800ToCurrent : public CAntiPredictor {
public:
// functions
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, BOOL bMMXAvailable, int CPULoadBalancingFactor, int nVersion);
};
#endif // #ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
#endif // #ifndef APE_ANTIPREDICTOR_H

View File

@@ -0,0 +1,330 @@
#include "All.h"
#ifdef BACKWARDS_COMPATIBILITY
#include "Anti-Predictor.h"
#ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
/*****************************************************************************************
Extra high 0000 to 3320 implementation
*****************************************************************************************/
void CAntiPredictorExtraHigh0000To3320::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB) {
for (int z = Iterations; z >= 0; z--){
AntiPredictorOffset(pInputArray, pOutputArray, NumberOfElements, pOffsetValueArrayB[z], -1, 64);
AntiPredictorOffset(pOutputArray, pInputArray, NumberOfElements, pOffsetValueArrayA[z], 1, 64);
}
CAntiPredictorHigh0000To3320 AntiPredictor;
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
}
void CAntiPredictorExtraHigh0000To3320::AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g, int dm, int Max_Order)
{
int q;
if ((g==0) || (Number_of_Elements <= Max_Order)) {
memcpy(Output_Array, Input_Array, Number_of_Elements * 4);
return;
}
memcpy(Output_Array, Input_Array, Max_Order * 4);
int m = 512;
if (dm > 0)
for (q = Max_Order; q < Number_of_Elements; q++) {
Output_Array[q] = Input_Array[q] + (Output_Array[q - g] >> 3);
}
else
for (q = Max_Order; q < Number_of_Elements; q++) {
Output_Array[q] = Input_Array[q] - (Output_Array[q - g] >> 3);
}
}
/*****************************************************************************************
Extra high 3320 to 3600 implementation
*****************************************************************************************/
void CAntiPredictorExtraHigh3320To3600::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB)
{
for (int z = Iterations; z >= 0; z--)
{
AntiPredictorOffset(pInputArray, pOutputArray, NumberOfElements, pOffsetValueArrayB[z], -1, 32);
AntiPredictorOffset(pOutputArray, pInputArray, NumberOfElements, pOffsetValueArrayA[z], 1, 32);
}
CAntiPredictorHigh0000To3320 AntiPredictor;
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
}
void CAntiPredictorExtraHigh3320To3600::AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g, int dm, int Max_Order)
{
int q;
if ((g==0) || (Number_of_Elements <= Max_Order)) {
memcpy(Output_Array, Input_Array, Number_of_Elements * 4);
return;
}
memcpy(Output_Array, Input_Array, Max_Order * 4);
int m = 512;
if (dm > 0)
for (q = Max_Order; q < Number_of_Elements; q++) {
Output_Array[q] = Input_Array[q] + ((Output_Array[q - g] * m) >> 12);
(Input_Array[q] ^ Output_Array[q - g]) > 0 ? m += 8 : m -= 8;
}
else
for (q = Max_Order; q < Number_of_Elements; q++) {
Output_Array[q] = Input_Array[q] - ((Output_Array[q - g] * m) >> 12);
(Input_Array[q] ^ Output_Array[q - g]) > 0 ? m -= 8 : m += 8;
}
}
/*****************************************************************************************
Extra high 3600 to 3700 implementation
*****************************************************************************************/
void CAntiPredictorExtraHigh3600To3700::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB) {
for (int z = Iterations; z >= 0; ){
AntiPredictorOffset(pInputArray, pOutputArray, NumberOfElements, pOffsetValueArrayA[z], pOffsetValueArrayB[z], 64);
z--;
if (z >= 0) {
AntiPredictorOffset(pOutputArray, pInputArray, NumberOfElements, pOffsetValueArrayA[z], pOffsetValueArrayB[z], 64);
z--;
}
else {
memcpy(pInputArray, pOutputArray, NumberOfElements * 4);
goto Exit_Loop;
z--;
}
}
Exit_Loop:
CAntiPredictorHigh3600To3700 AntiPredictor;
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
}
void CAntiPredictorExtraHigh3600To3700::AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g1, int g2, int Max_Order) {
int q;
if ((g1==0) || (g2==0) || (Number_of_Elements <= Max_Order)) {
memcpy(Output_Array, Input_Array, Number_of_Elements * 4);
return;
}
memcpy(Output_Array, Input_Array, Max_Order * 4);
int m = 64;
int m2 = 64;
for (q = Max_Order; q < Number_of_Elements; q++) {
Output_Array[q] = Input_Array[q] + ((Output_Array[q - g1] * m) >> 9) - ((Output_Array[q - g2] * m2) >> 9);
(Input_Array[q] ^ Output_Array[q - g1]) > 0 ? m++ : m--;
(Input_Array[q] ^ Output_Array[q - g2]) > 0 ? m2-- : m2++;
}
}
/*****************************************************************************************
Extra high 3700 to 3800 implementation
*****************************************************************************************/
void CAntiPredictorExtraHigh3700To3800::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB) {
for (int z = Iterations; z >= 0; ) {
AntiPredictorOffset(pInputArray, pOutputArray, NumberOfElements, pOffsetValueArrayA[z], pOffsetValueArrayB[z], 64);
z--;
if (z >= 0) {
AntiPredictorOffset(pOutputArray, pInputArray, NumberOfElements, pOffsetValueArrayA[z], pOffsetValueArrayB[z], 64);
z--;
}
else {
memcpy(pInputArray, pOutputArray, NumberOfElements * 4);
goto Exit_Loop;
z--;
}
}
Exit_Loop:
CAntiPredictorHigh3700To3800 AntiPredictor;
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
}
void CAntiPredictorExtraHigh3700To3800::AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g1, int g2, int Max_Order) {
int q;
if ((g1==0) || (g2==0) || (Number_of_Elements <= Max_Order)) {
memcpy(Output_Array, Input_Array, Number_of_Elements * 4);
return;
}
memcpy(Output_Array, Input_Array, Max_Order * 4);
int m = 64;
int m2 = 64;
for (q = Max_Order; q < Number_of_Elements; q++) {
Output_Array[q] = Input_Array[q] + ((Output_Array[q - g1] * m) >> 9) - ((Output_Array[q - g2] * m2) >> 9);
(Input_Array[q] ^ Output_Array[q - g1]) > 0 ? m++ : m--;
(Input_Array[q] ^ Output_Array[q - g2]) > 0 ? m2-- : m2++;
}
}
/*****************************************************************************************
Extra high 3800 to Current
*****************************************************************************************/
void CAntiPredictorExtraHigh3800ToCurrent::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, BOOL bMMXAvailable, int CPULoadBalancingFactor, int nVersion)
{
const int nFilterStageElements = (nVersion < 3830) ? 128 : 256;
const int nFilterStageShift = (nVersion < 3830) ? 11 : 12;
const int nMaxElements = (nVersion < 3830) ? 134 : 262;
const int nFirstElement = (nVersion < 3830) ? 128 : 256;
const int nStageCShift = (nVersion < 3830) ? 10 : 11;
//short frame handling
if (NumberOfElements < nMaxElements) {
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
return;
}
//make the first five samples identical in both arrays
memcpy(pOutputArray, pInputArray, nFirstElement * 4);
//variable declares and initializations
//short bm[nFirstElement]; memset(bm, 0, nFirstElement * 2);
short bm[256]; memset(bm, 0, 256 * 2);
int m2 = 64, m3 = 115, m4 = 64, m5 = 740, m6 = 0;
int p4 = pInputArray[nFirstElement - 1];
int p3 = (pInputArray[nFirstElement - 1] - pInputArray[nFirstElement - 2]) << 1;
int p2 = pInputArray[nFirstElement - 1] + ((pInputArray[nFirstElement - 3] - pInputArray[nFirstElement - 2]) << 3);// - pInputArray[3] + pInputArray[2];
int *op = &pOutputArray[nFirstElement];
int *ip = &pInputArray[nFirstElement];
int IPP2 = ip[-2];
int IPP1 = ip[-1];
int p7 = 2 * ip[-1] - ip[-2];
int opp = op[-1];
int Original;
CAntiPredictorExtraHighHelper Helper;
//undo the initial prediction stuff
int q; // loop variable
for (q = 1; q < nFirstElement; q++) {
pOutputArray[q] += pOutputArray[q - 1];
}
//pump the primary loop
short *IPAdaptFactor = (short *) calloc(NumberOfElements, 2);
short *IPShort = (short *) calloc(NumberOfElements, 2);
for (q = 0; q < nFirstElement; q++) {
IPAdaptFactor[q] = ((pInputArray[q] >> 30) & 2) - 1;
IPShort[q] = short(pInputArray[q]);
}
int FM[9]; memset(&FM[0], 0, 9 * 4);
int FP[9]; memset(&FP[0], 0, 9 * 4);
for (q = nFirstElement; op < &pOutputArray[NumberOfElements]; op++, ip++, q++) {
//CPU load-balancing
if (CPULoadBalancingFactor > 0) {
if ((q % CPULoadBalancingFactor) == 0) { SLEEP(1); }
}
if (nVersion >= 3830)
{
int *pFP = &FP[8];
int *pFM = &FM[8];
int nDotProduct = 0;
FP[0] = ip[0];
if (FP[0] == 0)
{
EXPAND_8_TIMES(nDotProduct += *pFP * *pFM--; *pFP-- = *(pFP - 1);)
}
else if (FP[0] > 0)
{
EXPAND_8_TIMES(nDotProduct += *pFP * *pFM; *pFM-- += ((*pFP >> 30) & 2) - 1; *pFP-- = *(pFP - 1);)
}
else
{
EXPAND_8_TIMES(nDotProduct += *pFP * *pFM; *pFM-- -= ((*pFP >> 30) & 2) - 1; *pFP-- = *(pFP - 1);)
}
*ip -= nDotProduct >> 9;
}
Original = *ip;
IPShort[q] = short(*ip);
IPAdaptFactor[q] = ((ip[0] >> 30) & 2) - 1;
#ifdef ENABLE_ASSEMBLY
if (bMMXAvailable && (Original != 0))
{
*ip -= (Helper.MMXDotProduct(&IPShort[q-nFirstElement], &bm[0], &IPAdaptFactor[q-nFirstElement], Original, nFilterStageElements) >> nFilterStageShift);
}
else
{
*ip -= (Helper.ConventionalDotProduct(&IPShort[q-nFirstElement], &bm[0], &IPAdaptFactor[q-nFirstElement], Original, nFilterStageElements) >> nFilterStageShift);
}
#else
*ip -= (Helper.ConventionalDotProduct(&IPShort[q-nFirstElement], &bm[0], &IPAdaptFactor[q-nFirstElement], Original, nFilterStageElements) >> nFilterStageShift);
#endif
IPShort[q] = short(*ip);
IPAdaptFactor[q] = ((ip[0] >> 30) & 2) - 1;
/////////////////////////////////////////////
*op = *ip + (((p2 * m2) + (p3 * m3) + (p4 * m4)) >> 11);
if (*ip > 0) {
m2 -= ((p2 >> 30) & 2) - 1;
m3 -= ((p3 >> 28) & 8) - 4;
m4 -= ((p4 >> 28) & 8) - 4;
}
else if (*ip < 0) {
m2 += ((p2 >> 30) & 2) - 1;
m3 += ((p3 >> 28) & 8) - 4;
m4 += ((p4 >> 28) & 8) - 4;
}
p2 = *op + ((IPP2 - p4) << 3);
p3 = (*op - p4) << 1;
IPP2 = p4;
p4 = *op;
/////////////////////////////////////////////
*op += (((p7 * m5) - (opp * m6)) >> nStageCShift);
if (p4 > 0) {
m5 -= ((p7 >> 29) & 4) - 2;
m6 += ((opp >> 30) & 2) - 1;
}
else if (p4 < 0) {
m5 += ((p7 >> 29) & 4) - 2;
m6 -= ((opp >> 30) & 2) - 1;
}
p7 = 2 * *op - opp;
opp = *op;
/////////////////////////////////////////////
*op += ((op[-1] * 31) >> 5);
}
free(IPAdaptFactor);
free(IPShort);
}
#endif // #ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
#endif // #ifdef BACKWARDS_COMPATIBILITY

View File

@@ -0,0 +1,88 @@
#include "All.h"
#ifdef BACKWARDS_COMPATIBILITY
#include "Anti-Predictor.h"
#ifdef ENABLE_COMPRESSION_MODE_FAST
void CAntiPredictorFast0000To3320::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements) {
//short frame handling
if (NumberOfElements < 32) {
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
return;
}
//the initial
pOutputArray[0] = pInputArray[0];
pOutputArray[1] = pInputArray[1] + pOutputArray[0];
pOutputArray[2] = pInputArray[2] + pOutputArray[1];
pOutputArray[3] = pInputArray[3] + pOutputArray[2];
pOutputArray[4] = pInputArray[4] + pOutputArray[3];
pOutputArray[5] = pInputArray[5] + pOutputArray[4];
pOutputArray[6] = pInputArray[6] + pOutputArray[5];
pOutputArray[7] = pInputArray[7] + pOutputArray[6];
//the rest
int p, pw;
int m = 4000;
int *ip, *op, *op1;
op1 = &pOutputArray[7];
p = (*op1 * 2) - pOutputArray[6];
pw = (p * m) >> 12;
for (op = &pOutputArray[8], ip = &pInputArray[8]; ip < &pInputArray[NumberOfElements]; ip++, op++, op1++) {
*op = *ip + pw;
//adjust m
if (*ip > 0)
m += (p > 0) ? 4 : -4;
else if (*ip < 0)
m += (p > 0) ? -4 : 4;
p = (*op * 2) - *op1;
pw = (p * m) >> 12;
}
}
///////note: no output - overwrites input/////////////////
void CAntiPredictorFast3320ToCurrent::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements) {
//short frame handling
if (NumberOfElements < 3) {
return;
}
//variable declares
int p;
int m = 375;
int *ip;
int IP2 = pInputArray[1];
int IP3 = pInputArray[0];
int OP1 = pInputArray[1];
//the decompression loop (order 2 followed by order 1)
for (ip = &pInputArray[2]; ip < &pInputArray[NumberOfElements]; ip++) {
//make a prediction for order 2
p = IP2 + IP2 - IP3;
//rollback the values
IP3 = IP2;
IP2 = *ip + ((p * m) >> 9);
//adjust m for the order 2
(*ip ^ p) > 0 ? m++ : m--;
//set the output value
*ip = IP2 + OP1;
OP1 = *ip;
}
}
#endif // #ifdef ENABLE_COMPRESSION_MODE_FAST
#endif // #ifdef BACKWARDS_COMPATIBILITY

View File

@@ -0,0 +1,484 @@
#include "All.h"
#ifdef BACKWARDS_COMPATIBILITY
#include "Anti-Predictor.h"
#ifdef ENABLE_COMPRESSION_MODE_HIGH
void CAntiPredictorHigh0000To3320::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
{
// variable declares
int p, pw;
int q;
int m;
// short frame handling
if (NumberOfElements < 32)
{
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
return;
}
////////////////////////////////////////
// order 5
////////////////////////////////////////
memcpy(pOutputArray, pInputArray, 32);
// initialize values
m = 0;
for (q = 8; q < NumberOfElements; q++)
{
p = (5 * pOutputArray[q - 1]) - (10 * pOutputArray[q - 2]) + (12 * pOutputArray[q - 3]) - (7 * pOutputArray[q - 4]) + pOutputArray[q - 5];
pw = (p * m) >> 12;
pOutputArray[q] = pInputArray[q] + pw;
// adjust m
if (pInputArray[q] > 0)
(p > 0) ? m += 1 : m -= 1;
else if (pInputArray[q] < 0)
(p > 0) ? m -= 1 : m += 1;
}
///////////////////////////////////////
// order 4
///////////////////////////////////////
memcpy(pInputArray, pOutputArray, 32);
m = 0;
for (q = 8; q < NumberOfElements; q++)
{
p = (4 * pInputArray[q - 1]) - (6 * pInputArray[q - 2]) + (4 * pInputArray[q - 3]) - pInputArray[q - 4];
pw = (p * m) >> 12;
pInputArray[q] = pOutputArray[q] + pw;
// adjust m
if (pOutputArray[q] > 0)
(p > 0) ? m += 2 : m -= 2;
else if (pOutputArray[q] < 0)
(p > 0) ? m -= 2 : m += 2;
}
CAntiPredictorNormal0000To3320 AntiPredictor;
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
}
void CAntiPredictorHigh3320To3600::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
{
// short frame handling
if (NumberOfElements < 8)
{
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
return;
}
// do the offset anti-prediction
CAntiPredictorOffset AntiPredictorOffset;
AntiPredictorOffset.AntiPredict(pInputArray, pOutputArray, NumberOfElements, 2, 12);
AntiPredictorOffset.AntiPredict(pOutputArray, pInputArray, NumberOfElements, 3, 12);
AntiPredictorOffset.AntiPredict(pInputArray, pOutputArray, NumberOfElements, 4, 12);
AntiPredictorOffset.AntiPredict(pOutputArray, pInputArray, NumberOfElements, 5, 12);
AntiPredictorOffset.AntiPredict(pInputArray, pOutputArray, NumberOfElements, 6, 12);
AntiPredictorOffset.AntiPredict(pOutputArray, pInputArray, NumberOfElements, 7, 12);
// use the normal mode
CAntiPredictorNormal3320To3800 AntiPredictor;
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
}
void CAntiPredictorHigh3600To3700::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
{
// variable declares
int q;
// short frame handling
if (NumberOfElements < 16)
{
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
return;
}
// make the first five samples identical in both arrays
memcpy(pOutputArray, pInputArray, 13 * 4);
// initialize values
int bm1 = 0;
int bm2 = 0;
int bm3 = 0;
int bm4 = 0;
int bm5 = 0;
int bm6 = 0;
int bm7 = 0;
int bm8 = 0;
int bm9 = 0;
int bm10 = 0;
int bm11 = 0;
int bm12 = 0;
int bm13 = 0;
int m2 = 64;
int m3 = 28;
int m4 = 16;
int OP0;
int OP1 = pOutputArray[12];
int p4 = pInputArray[12];
int p3 = (pInputArray[12] - pInputArray[11]) << 1;
int p2 = pInputArray[12] + ((pInputArray[10] - pInputArray[11]) << 3);// - pInputArray[3] + pInputArray[2];
int bp1 = pOutputArray[12];
int bp2 = pOutputArray[11];
int bp3 = pOutputArray[10];
int bp4 = pOutputArray[9];
int bp5 = pOutputArray[8];
int bp6 = pOutputArray[7];
int bp7 = pOutputArray[6];
int bp8 = pOutputArray[5];
int bp9 = pOutputArray[4];
int bp10 = pOutputArray[3];
int bp11 = pOutputArray[2];
int bp12 = pOutputArray[1];
int bp13 = pOutputArray[0];
for (q = 13; q < NumberOfElements; q++)
{
pInputArray[q] = pInputArray[q] - 1;
OP0 = (pInputArray[q] - ((bp1 * bm1) >> 8) + ((bp2 * bm2) >> 8) - ((bp3 * bm3) >> 8) - ((bp4 * bm4) >> 8) - ((bp5 * bm5) >> 8) - ((bp6 * bm6) >> 8) - ((bp7 * bm7) >> 8) - ((bp8 * bm8) >> 8) - ((bp9 * bm9) >> 8) + ((bp10 * bm10) >> 8) + ((bp11 * bm11) >> 8) + ((bp12 * bm12) >> 8) + ((bp13 * bm13) >> 8));
if (pInputArray[q] > 0)
{
bm1 -= bp1 > 0 ? 1 : -1;
bm2 += bp2 >= 0 ? 1 : -1;
bm3 -= bp3 > 0 ? 1 : -1;
bm4 -= bp4 >= 0 ? 1 : -1;
bm5 -= bp5 > 0 ? 1 : -1;
bm6 -= bp6 >= 0 ? 1 : -1;
bm7 -= bp7 > 0 ? 1 : -1;
bm8 -= bp8 >= 0 ? 1 : -1;
bm9 -= bp9 > 0 ? 1 : -1;
bm10 += bp10 >= 0 ? 1 : -1;
bm11 += bp11 > 0 ? 1 : -1;
bm12 += bp12 >= 0 ? 1 : -1;
bm13 += bp13 > 0 ? 1 : -1;
}
else if (pInputArray[q] < 0)
{
bm1 -= bp1 <= 0 ? 1 : -1;
bm2 += bp2 < 0 ? 1 : -1;
bm3 -= bp3 <= 0 ? 1 : -1;
bm4 -= bp4 < 0 ? 1 : -1;
bm5 -= bp5 <= 0 ? 1 : -1;
bm6 -= bp6 < 0 ? 1 : -1;
bm7 -= bp7 <= 0 ? 1 : -1;
bm8 -= bp8 < 0 ? 1 : -1;
bm9 -= bp9 <= 0 ? 1 : -1;
bm10 += bp10 < 0 ? 1 : -1;
bm11 += bp11 <= 0 ? 1 : -1;
bm12 += bp12 < 0 ? 1 : -1;
bm13 += bp13 <= 0 ? 1 : -1;
}
bp13 = bp12;
bp12 = bp11;
bp11 = bp10;
bp10 = bp9;
bp9 = bp8;
bp8 = bp7;
bp7 = bp6;
bp6 = bp5;
bp5 = bp4;
bp4 = bp3;
bp3 = bp2;
bp2 = bp1;
bp1 = OP0;
pInputArray[q] = OP0 + ((p2 * m2) >> 11) + ((p3 * m3) >> 9) + ((p4 * m4) >> 9);
if (OP0 > 0)
{
m2 -= p2 > 0 ? -1 : 1;
m3 -= p3 > 0 ? -1 : 1;
m4 -= p4 > 0 ? -1 : 1;
}
else if (OP0 < 0)
{
m2 -= p2 > 0 ? 1 : -1;
m3 -= p3 > 0 ? 1 : -1;
m4 -= p4 > 0 ? 1 : -1;
}
p2 = pInputArray[q] + ((pInputArray[q - 2] - pInputArray[q - 1]) << 3);
p3 = (pInputArray[q] - pInputArray[q - 1]) << 1;
p4 = pInputArray[q];
pOutputArray[q] = pInputArray[q];// + ((p3 * m3) >> 9);
}
m4 = 370;
int m5 = 3900;
pOutputArray[1] = pInputArray[1] + pOutputArray[0];
pOutputArray[2] = pInputArray[2] + pOutputArray[1];
pOutputArray[3] = pInputArray[3] + pOutputArray[2];
pOutputArray[4] = pInputArray[4] + pOutputArray[3];
pOutputArray[5] = pInputArray[5] + pOutputArray[4];
pOutputArray[6] = pInputArray[6] + pOutputArray[5];
pOutputArray[7] = pInputArray[7] + pOutputArray[6];
pOutputArray[8] = pInputArray[8] + pOutputArray[7];
pOutputArray[9] = pInputArray[9] + pOutputArray[8];
pOutputArray[10] = pInputArray[10] + pOutputArray[9];
pOutputArray[11] = pInputArray[11] + pOutputArray[10];
pOutputArray[12] = pInputArray[12] + pOutputArray[11];
p4 = (2 * pInputArray[12]) - pInputArray[11];
int p6 = 0;
int p5 = pOutputArray[12];
int IP0, IP1;
int m6 = 0;
IP1 = pInputArray[12];
for (q = 13; q < NumberOfElements; q++)
{
IP0 = pOutputArray[q] + ((p4 * m4) >> 9) - ((p6 * m6) >> 10);
(pOutputArray[q] ^ p4) >= 0 ? m4++ : m4--;
(pOutputArray[q] ^ p6) >= 0 ? m6-- : m6++;
p4 = (2 * IP0) - IP1;
p6 = IP0;
pOutputArray[q] = IP0 + ((p5 * 31) >> 5);
p5 = pOutputArray[q];
IP1 = IP0;
}
}
void CAntiPredictorHigh3700To3800::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
{
// the frame to start prediction on
#define FIRST_ELEMENT 16
int x = 100;
int y = -25;
// short frame handling
if (NumberOfElements < 20)
{
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
return;
}
// make the first five samples identical in both arrays
memcpy(pOutputArray, pInputArray, FIRST_ELEMENT * 4);
// variable declares and initializations
int bm[FIRST_ELEMENT]; memset(bm, 0, FIRST_ELEMENT * 4);
int m2 = 64, m3 = 115, m4 = 64, m5 = 740, m6 = 0;
int p4 = pInputArray[FIRST_ELEMENT - 1];
int p3 = (pInputArray[FIRST_ELEMENT - 1] - pInputArray[FIRST_ELEMENT - 2]) << 1;
int p2 = pInputArray[FIRST_ELEMENT - 1] + ((pInputArray[FIRST_ELEMENT - 3] - pInputArray[FIRST_ELEMENT - 2]) << 3);// - pInputArray[3] + pInputArray[2];
int *op = &pOutputArray[FIRST_ELEMENT];
int *ip = &pInputArray[FIRST_ELEMENT];
int IPP2 = ip[-2];
int IPP1 = ip[-1];
int p7 = 2 * ip[-1] - ip[-2];
int opp = op[-1];
int Original;
// undo the initial prediction stuff
for (int q = 1; q < FIRST_ELEMENT; q++) {
pOutputArray[q] += pOutputArray[q - 1];
}
// pump the primary loop
for (;op < &pOutputArray[NumberOfElements]; op++, ip++) {
Original = *ip - 1;
*ip = Original - (((ip[-1] * bm[0]) + (ip[-2] * bm[1]) + (ip[-3] * bm[2]) + (ip[-4] * bm[3]) + (ip[-5] * bm[4]) + (ip[-6] * bm[5]) + (ip[-7] * bm[6]) + (ip[-8] * bm[7]) + (ip[-9] * bm[8]) + (ip[-10] * bm[9]) + (ip[-11] * bm[10]) + (ip[-12] * bm[11]) + (ip[-13] * bm[12]) + (ip[-14] * bm[13]) + (ip[-15] * bm[14]) + (ip[-16] * bm[15])) >> 8);
if (Original > 0)
{
bm[0] -= ip[-1] > 0 ? 1 : -1;
bm[1] += ((unsigned int(ip[-2]) >> 30) & 2) - 1;
bm[2] -= ip[-3] > 0 ? 1 : -1;
bm[3] += ((unsigned int(ip[-4]) >> 30) & 2) - 1;
bm[4] -= ip[-5] > 0 ? 1 : -1;
bm[5] += ((unsigned int(ip[-6]) >> 30) & 2) - 1;
bm[6] -= ip[-7] > 0 ? 1 : -1;
bm[7] += ((unsigned int(ip[-8]) >> 30) & 2) - 1;
bm[8] -= ip[-9] > 0 ? 1 : -1;
bm[9] += ((unsigned int(ip[-10]) >> 30) & 2) - 1;
bm[10] -= ip[-11] > 0 ? 1 : -1;
bm[11] += ((unsigned int(ip[-12]) >> 30) & 2) - 1;
bm[12] -= ip[-13] > 0 ? 1 : -1;
bm[13] += ((unsigned int(ip[-14]) >> 30) & 2) - 1;
bm[14] -= ip[-15] > 0 ? 1 : -1;
bm[15] += ((unsigned int(ip[-16]) >> 30) & 2) - 1;
}
else if (Original < 0)
{
bm[0] -= ip[-1] <= 0 ? 1 : -1;
bm[1] -= ((unsigned int(ip[-2]) >> 30) & 2) - 1;
bm[2] -= ip[-3] <= 0 ? 1 : -1;
bm[3] -= ((unsigned int(ip[-4]) >> 30) & 2) - 1;
bm[4] -= ip[-5] <= 0 ? 1 : -1;
bm[5] -= ((unsigned int(ip[-6]) >> 30) & 2) - 1;
bm[6] -= ip[-7] <= 0 ? 1 : -1;
bm[7] -= ((unsigned int(ip[-8]) >> 30) & 2) - 1;
bm[8] -= ip[-9] <= 0 ? 1 : -1;
bm[9] -= ((unsigned int(ip[-10]) >> 30) & 2) - 1;
bm[10] -= ip[-11] <= 0 ? 1 : -1;
bm[11] -= ((unsigned int(ip[-12]) >> 30) & 2) - 1;
bm[12] -= ip[-13] <= 0 ? 1 : -1;
bm[13] -= ((unsigned int(ip[-14]) >> 30) & 2) - 1;
bm[14] -= ip[-15] <= 0 ? 1 : -1;
bm[15] -= ((unsigned int(ip[-16]) >> 30) & 2) - 1;
}
/////////////////////////////////////////////
*op = *ip + (((p2 * m2) + (p3 * m3) + (p4 * m4)) >> 11);
if (*ip > 0)
{
m2 -= p2 > 0 ? -1 : 1;
m3 -= p3 > 0 ? -4 : 4;
m4 -= p4 > 0 ? -4 : 4;
}
else if (*ip < 0)
{
m2 -= p2 > 0 ? 1 : -1;
m3 -= p3 > 0 ? 4 : -4;
m4 -= p4 > 0 ? 4 : -4;
}
p4 = *op;
p2 = p4 + ((IPP2 - IPP1) << 3);
p3 = (p4 - IPP1) << 1;
IPP2 = IPP1;
IPP1 = p4;
/////////////////////////////////////////////
*op += (((p7 * m5) - (opp * m6)) >> 10);
(IPP1 ^ p7) >= 0 ? m5+=2 : m5-=2;
(IPP1 ^ opp) >= 0 ? m6-- : m6++;
p7 = 2 * *op - opp;
opp = *op;
/////////////////////////////////////////////
*op += ((op[-1] * 31) >> 5);
}
}
void CAntiPredictorHigh3800ToCurrent::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
{
// the frame to start prediction on
#define FIRST_ELEMENT 16
// short frame handling
if (NumberOfElements < 20)
{
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
return;
}
// make the first five samples identical in both arrays
memcpy(pOutputArray, pInputArray, FIRST_ELEMENT * 4);
// variable declares and initializations
int bm[FIRST_ELEMENT]; memset(bm, 0, FIRST_ELEMENT * 4);
int m2 = 64, m3 = 115, m4 = 64, m5 = 740, m6 = 0;
int p4 = pInputArray[FIRST_ELEMENT - 1];
int p3 = (pInputArray[FIRST_ELEMENT - 1] - pInputArray[FIRST_ELEMENT - 2]) << 1;
int p2 = pInputArray[FIRST_ELEMENT - 1] + ((pInputArray[FIRST_ELEMENT - 3] - pInputArray[FIRST_ELEMENT - 2]) << 3);// - pInputArray[3] + pInputArray[2];
int *op = &pOutputArray[FIRST_ELEMENT];
int *ip = &pInputArray[FIRST_ELEMENT];
int IPP2 = ip[-2];
int IPP1 = ip[-1];
int p7 = 2 * ip[-1] - ip[-2];
int opp = op[-1];
// undo the initial prediction stuff
for (int q = 1; q < FIRST_ELEMENT; q++)
{
pOutputArray[q] += pOutputArray[q - 1];
}
// pump the primary loop
for (;op < &pOutputArray[NumberOfElements]; op++, ip++)
{
unsigned int *pip = (unsigned int *) &ip[-FIRST_ELEMENT];
int *pbm = &bm[0];
int nDotProduct = 0;
if (*ip > 0)
{
EXPAND_16_TIMES(nDotProduct += *pip * *pbm; *pbm++ += ((*pip++ >> 30) & 2) - 1;)
}
else if (*ip < 0)
{
EXPAND_16_TIMES(nDotProduct += *pip * *pbm; *pbm++ -= ((*pip++ >> 30) & 2) - 1;)
}
else
{
EXPAND_16_TIMES(nDotProduct += *pip++ * *pbm++;)
}
*ip -= (nDotProduct >> 9);
/////////////////////////////////////////////
*op = *ip + (((p2 * m2) + (p3 * m3) + (p4 * m4)) >> 11);
if (*ip > 0)
{
m2 -= ((p2 >> 30) & 2) - 1;
m3 -= ((p3 >> 28) & 8) - 4;
m4 -= ((p4 >> 28) & 8) - 4;
}
else if (*ip < 0)
{
m2 += ((p2 >> 30) & 2) - 1;
m3 += ((p3 >> 28) & 8) - 4;
m4 += ((p4 >> 28) & 8) - 4;
}
p2 = *op + ((IPP2 - p4) << 3);
p3 = (*op - p4) << 1;
IPP2 = p4;
p4 = *op;
/////////////////////////////////////////////
*op += (((p7 * m5) - (opp * m6)) >> 10);
if (p4 > 0)
{
m5 -= ((p7 >> 29) & 4) - 2;
m6 += ((opp >> 30) & 2) - 1;
}
else if (p4 < 0)
{
m5 += ((p7 >> 29) & 4) - 2;
m6 -= ((opp >> 30) & 2) - 1;
}
p7 = 2 * *op - opp;
opp = *op;
/////////////////////////////////////////////
*op += ((op[-1] * 31) >> 5);
}
#undef FIRST_ELEMENT
}
#endif // #ifdef ENABLE_COMPRESSION_MODE_HIGH
#endif // #ifdef BACKWARDS_COMPATIBILITY

View File

@@ -0,0 +1,262 @@
#include "All.h"
#ifdef BACKWARDS_COMPATIBILITY
#include "Anti-Predictor.h"
#ifdef ENABLE_COMPRESSION_MODE_NORMAL
void CAntiPredictorNormal0000To3320::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
{
// variable declares
int *ip, *op, *op1, *op2;
int p, pw;
int m;
// short frame handling
if (NumberOfElements < 32)
{
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
return;
}
////////////////////////////////////////
// order 3
////////////////////////////////////////
memcpy(pOutputArray, pInputArray, 32);
// initialize values
m = 300;
op = &pOutputArray[8];
op1 = &pOutputArray[7];
op2 = &pOutputArray[6];
// make the first prediction
p = (pOutputArray[7] * 3) - (pOutputArray[6] * 3) + pOutputArray[5];
pw = (p * m) >> 12;
// loop through the array
for (ip = &pInputArray[8]; ip < &pInputArray[NumberOfElements]; ip++, op++, op1++, op2++) {
// figure the output value
*op = *ip + pw;
// adjust m
if (*ip > 0)
m += (p > 0) ? 4 : -4;
else if (*ip < 0)
m += (p > 0) ? -4 : 4;
// make the next prediction
p = (*op * 3) - (*op1 * 3) + *op2;
pw = (p * m) >> 12;
}
///////////////////////////////////////
// order 2
///////////////////////////////////////
memcpy(pInputArray, pOutputArray, 32);
m = 3000;
op1 = &pInputArray[7];
p = (*op1 * 2) - pInputArray[6];
pw = (p * m) >> 12;
for (op = &pInputArray[8], ip = &pOutputArray[8]; ip < &pOutputArray[NumberOfElements]; ip++, op++, op1++)
{
*op = *ip + pw;
// adjust m
if (*ip > 0)
m += (p > 0) ? 12 : -12;
else if (*ip < 0)
m += (p > 0) ? -12 : 12;
p = (*op * 2) - *op1;
pw = (p * m) >> 12;
}
///////////////////////////////////////
// order 1
///////////////////////////////////////
pOutputArray[0] = pInputArray[0];
pOutputArray[1] = pInputArray[1] + pOutputArray[0];
pOutputArray[2] = pInputArray[2] + pOutputArray[1];
pOutputArray[3] = pInputArray[3] + pOutputArray[2];
pOutputArray[4] = pInputArray[4] + pOutputArray[3];
pOutputArray[5] = pInputArray[5] + pOutputArray[4];
pOutputArray[6] = pInputArray[6] + pOutputArray[5];
pOutputArray[7] = pInputArray[7] + pOutputArray[6];
m = 3900;
p = pOutputArray[7];
pw = (p * m) >> 12;
for (op = &pOutputArray[8], ip = &pInputArray[8]; ip < &pInputArray[NumberOfElements]; ip++, op++) {
*op = *ip + pw;
// adjust m
if (*ip > 0)
m += (p > 0) ? 1 : -1;
else if (*ip < 0)
m += (p > 0) ? -1 : 1;
p = *op;
pw = (p * m) >> 12;
}
}
void CAntiPredictorNormal3320To3800::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
{
// variable declares
int q;
// short frame handling
if (NumberOfElements < 8)
{
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
return;
}
// make the first five samples identical in both arrays
memcpy(pOutputArray, pInputArray, 20);
// initialize values
int m1 = 0;
int m2 = 64;
int m3 = 28;
int OP0;
int OP1 = pOutputArray[4];
int p3 = (3 * (pOutputArray[4] - pOutputArray[3])) + pOutputArray[2];
int p2 = pInputArray[4] + ((pInputArray[2] - pInputArray[3]) << 3) - pInputArray[1] + pInputArray[0];
int p1 = pOutputArray[4];
for (q = 5; q < NumberOfElements; q++)
{
OP0 = pInputArray[q] + ((p1 * m1) >> 8);
(pInputArray[q] ^ p1) > 0 ? m1++ : m1--;
p1 = OP0;
pInputArray[q] = OP0 + ((p2 * m2) >> 11);
(OP0 ^ p2) > 0 ? m2++ : m2--;
p2 = pInputArray[q] + ((pInputArray[q - 2] - pInputArray[q - 1]) << 3) - pInputArray[q - 3] + pInputArray[q - 4];
pOutputArray[q] = pInputArray[q] + ((p3 * m3) >> 9);
(pInputArray[q] ^ p3) > 0 ? m3++ : m3--;
p3 = (3 * (pOutputArray[q] - pOutputArray[q - 1])) + pOutputArray[q - 2];
}
int m4 = 370;
int m5 = 3900;
pOutputArray[1] = pInputArray[1] + pOutputArray[0];
pOutputArray[2] = pInputArray[2] + pOutputArray[1];
pOutputArray[3] = pInputArray[3] + pOutputArray[2];
pOutputArray[4] = pInputArray[4] + pOutputArray[3];
int p4 = (2 * pInputArray[4]) - pInputArray[3];
int p5 = pOutputArray[4];
int IP0, IP1;
IP1 = pInputArray[4];
for (q = 5; q < NumberOfElements; q++)
{
IP0 = pOutputArray[q] + ((p4 * m4) >> 9);
(pOutputArray[q] ^ p4) > 0 ? m4++ : m4--;
p4 = (2 * IP0) - IP1;
pOutputArray[q] = IP0 + ((p5 * m5) >> 12);
(IP0 ^ p5) > 0 ? m5++ : m5--;
p5 = pOutputArray[q];
IP1 = IP0;
}
}
void CAntiPredictorNormal3800ToCurrent::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
{
// the frame to start prediction on
#define FIRST_ELEMENT 4
// short frame handling
if (NumberOfElements < 8)
{
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
return;
}
// make the first five samples identical in both arrays
memcpy(pOutputArray, pInputArray, FIRST_ELEMENT * 4);
// variable declares and initializations
int m2 = 64, m3 = 115, m4 = 64, m5 = 740, m6 = 0;
int p4 = pInputArray[FIRST_ELEMENT - 1];
int p3 = (pInputArray[FIRST_ELEMENT - 1] - pInputArray[FIRST_ELEMENT - 2]) << 1;
int p2 = pInputArray[FIRST_ELEMENT - 1] + ((pInputArray[FIRST_ELEMENT - 3] - pInputArray[FIRST_ELEMENT - 2]) << 3);// - pInputArray[3] + pInputArray[2];
int *op = &pOutputArray[FIRST_ELEMENT];
int *ip = &pInputArray[FIRST_ELEMENT];
int IPP2 = ip[-2];
int p7 = 2 * ip[-1] - ip[-2];
int opp = op[-1];
// undo the initial prediction stuff
for (int q = 1; q < FIRST_ELEMENT; q++) {
pOutputArray[q] += pOutputArray[q - 1];
}
// pump the primary loop
for (; op < &pOutputArray[NumberOfElements]; op++, ip++) {
register int o = *op, i = *ip;
/////////////////////////////////////////////
o = i + (((p2 * m2) + (p3 * m3) + (p4 * m4)) >> 11);
if (i > 0)
{
m2 -= ((p2 >> 30) & 2) - 1;
m3 -= ((p3 >> 28) & 8) - 4;
m4 -= ((p4 >> 28) & 8) - 4;
}
else if (i < 0)
{
m2 += ((p2 >> 30) & 2) - 1;
m3 += ((p3 >> 28) & 8) - 4;
m4 += ((p4 >> 28) & 8) - 4;
}
p2 = o + ((IPP2 - p4) << 3);
p3 = (o - p4) << 1;
IPP2 = p4;
p4 = o;
/////////////////////////////////////////////
o += (((p7 * m5) - (opp * m6)) >> 10);
if (p4 > 0)
{
m5 -= ((p7 >> 29) & 4) - 2;
m6 += ((opp >> 30) & 2) - 1;
}
else if (p4 < 0)
{
m5 += ((p7 >> 29) & 4) - 2;
m6 -= ((opp >> 30) & 2) - 1;
}
p7 = 2 * o - opp;
opp = o;
/////////////////////////////////////////////
*op = o + ((op[-1] * 31) >> 5);
}
}
#endif // #ifdef ENABLE_COMPRESSION_MODE_NORMAL
#endif // #ifdef BACKWARDS_COMPATIBILITY

View File

@@ -0,0 +1,353 @@
#include "All.h"
#ifdef BACKWARDS_COMPATIBILITY
#include "../APEInfo.h"
#include "UnBitarrayOld.h"
#include "../BitArray.h"
const uint32 K_SUM_MIN_BOUNDARY_OLD[32] = {0,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,0,0,0,0,0,0};
const uint32 K_SUM_MAX_BOUNDARY_OLD[32] = {128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,0,0,0,0,0,0,0};
const uint32 Powers_of_Two[32] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648};
const uint32 Powers_of_Two_Reversed[32] = {2147483648,1073741824,536870912,268435456,134217728,67108864,33554432,16777216,8388608,4194304,2097152,1048576,524288,262144,131072,65536,32768,16384,8192,4096,2048,1024,512,256,128,64,32,16,8,4,2,1};
const uint32 Powers_of_Two_Minus_One[33] = {0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535,131071,262143,524287,1048575,2097151,4194303,8388607,16777215,33554431,67108863,134217727,268435455,536870911,1073741823,2147483647,4294967295};
const uint32 Powers_of_Two_Minus_One_Reversed[33] = {4294967295,2147483647,1073741823,536870911,268435455,134217727,67108863,33554431,16777215,8388607,4194303,2097151,1048575,524287,262143,131071,65535,32767,16383,8191,4095,2047,1023,511,255,127,63,31,15,7,3,1,0};
const uint32 K_SUM_MIN_BOUNDARY[32] = {0,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,0,0,0,0};
const uint32 K_SUM_MAX_BOUNDARY[32] = {32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,0,0,0,0,0};
/***********************************************************************************
Construction
***********************************************************************************/
CUnBitArrayOld::CUnBitArrayOld(IAPEDecompress * pAPEDecompress, int nVersion)
{
int nBitArrayBytes = 262144;
// calculate the bytes
if (nVersion <= 3880)
{
int nMaxFrameBytes = (pAPEDecompress->GetInfo(APE_INFO_BLOCKS_PER_FRAME) * 50) / 8;
nBitArrayBytes = 65536;
while (nBitArrayBytes < nMaxFrameBytes)
{
nBitArrayBytes <<= 1;
}
nBitArrayBytes = max(nBitArrayBytes, 262144);
}
else if (nVersion <= 3890)
{
nBitArrayBytes = 65536;
}
else
{
// error
}
CreateHelper(GET_IO(pAPEDecompress), nBitArrayBytes, nVersion);
// set the refill threshold
if (m_nVersion <= 3880)
m_nRefillBitThreshold = (m_nBits - (16384 * 8));
else
m_nRefillBitThreshold = (m_nBits - 512);
}
CUnBitArrayOld::~CUnBitArrayOld()
{
SAFE_ARRAY_DELETE(m_pBitArray)
}
////////////////////////////////////////////////////////////////////////////////////
// Gets the number of m_nBits of data left in the m_nCurrentBitIndex array
////////////////////////////////////////////////////////////////////////////////////
uint32 CUnBitArrayOld::GetBitsRemaining()
{
return (m_nElements * 32 - m_nCurrentBitIndex);
}
////////////////////////////////////////////////////////////////////////////////////
// Gets a rice value from the array
////////////////////////////////////////////////////////////////////////////////////
uint32 CUnBitArrayOld::DecodeValueRiceUnsigned(uint32 k)
{
// variable declares
uint32 v;
// plug through the string of 0's (the overflow)
uint32 BitInitial = m_nCurrentBitIndex;
while (!(m_pBitArray[m_nCurrentBitIndex >> 5] & Powers_of_Two_Reversed[m_nCurrentBitIndex++ & 31])) {}
// if k = 0, your done
if (k == 0)
return (m_nCurrentBitIndex - BitInitial - 1);
// put the overflow value into v
v = (m_nCurrentBitIndex - BitInitial - 1) << k;
return v | DecodeValueXBits(k);
}
////////////////////////////////////////////////////////////////////////////////////
// Get the optimal k for a given value
////////////////////////////////////////////////////////////////////////////////////
__inline uint32 CUnBitArrayOld::Get_K(uint32 x)
{
if (x == 0) return 0;
uint32 k = 0;
while (x >= Powers_of_Two[++k]) {}
return k;
}
unsigned int CUnBitArrayOld::DecodeValue(DECODE_VALUE_METHOD DecodeMethod, int nParam1, int nParam2)
{
switch (DecodeMethod)
{
case DECODE_VALUE_METHOD_UNSIGNED_INT:
return DecodeValueXBits(32);
case DECODE_VALUE_METHOD_UNSIGNED_RICE:
return DecodeValueRiceUnsigned(nParam1);
case DECODE_VALUE_METHOD_X_BITS:
return DecodeValueXBits(nParam1);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////
// Generates an array from the m_nCurrentBitIndexarray
////////////////////////////////////////////////////////////////////////////////////
void CUnBitArrayOld::GenerateArrayOld(int* Output_Array, uint32 Number_of_Elements, int Minimum_nCurrentBitIndex_Array_Bytes) {
//variable declarations
uint32 K_Sum;
uint32 q;
uint32 kmin, kmax;
uint32 k;
uint32 Max;
int *p1, *p2;
// fill bit array if necessary
// could use seek information to determine what the max was...
uint32 Max_Bits_Needed = Number_of_Elements * 50;
if (Minimum_nCurrentBitIndex_Array_Bytes > 0)
{
// this is actually probably double what is really needed
// we can only calculate the space needed for both arrays in multichannel
Max_Bits_Needed = ((Minimum_nCurrentBitIndex_Array_Bytes + 4) * 8);
}
if (Max_Bits_Needed > GetBitsRemaining())
FillBitArray();
// decode the first 5 elements (all k = 10)
Max = (Number_of_Elements < 5) ? Number_of_Elements : 5;
for (q = 0; q < Max; q++)
{
Output_Array[q] = DecodeValueRiceUnsigned(10);
}
// quit if that was all
if (Number_of_Elements <= 5)
{
for (p2 = &Output_Array[0]; p2 < &Output_Array[Number_of_Elements]; p2++)
*p2 = (*p2 & 1) ? (*p2 >> 1) + 1 : -(*p2 >> 1);
return;
}
// update k and K_Sum
K_Sum = Output_Array[0] + Output_Array[1] + Output_Array[2] + Output_Array[3] + Output_Array[4];
k = Get_K(K_Sum / 10);
// work through the rest of the elements before the primary loop
Max = (Number_of_Elements < 64) ? Number_of_Elements : 64;
for (q = 5; q < Max; q++)
{
Output_Array[q] = DecodeValueRiceUnsigned(k);
K_Sum += Output_Array[q];
k = Get_K(K_Sum / (q + 1) / 2);
}
// quit if that was all
if (Number_of_Elements <= 64)
{
for (p2 = &Output_Array[0]; p2 < &Output_Array[Number_of_Elements]; p2++)
*p2 = (*p2 & 1) ? (*p2 >> 1) + 1 : -(*p2 >> 1);
return;
}
// set all of the variables up for the primary loop
uint32 v, Bit_Array_Index;
k = Get_K(K_Sum >> 7);
kmin = K_SUM_MIN_BOUNDARY_OLD[k];
kmax = K_SUM_MAX_BOUNDARY_OLD[k];
p1 = &Output_Array[64]; p2 = &Output_Array[0];
// the primary loop
for (p1 = &Output_Array[64], p2 = &Output_Array[0]; p1 < &Output_Array[Number_of_Elements]; p1++, p2++)
{
// plug through the string of 0's (the overflow)
uint32 Bit_Initial = m_nCurrentBitIndex;
while (!(m_pBitArray[m_nCurrentBitIndex >> 5] & Powers_of_Two_Reversed[m_nCurrentBitIndex++ & 31])) {}
// if k = 0, your done
if (k == 0)
{
v = (m_nCurrentBitIndex - Bit_Initial - 1);
}
else
{
// put the overflow value into v
v = (m_nCurrentBitIndex - Bit_Initial - 1) << k;
// store the bit information and incement the bit pointer by 'k'
Bit_Array_Index = m_nCurrentBitIndex >> 5;
unsigned int Bit_Index = m_nCurrentBitIndex & 31;
m_nCurrentBitIndex += k;
// figure the extra bits on the left and the left value
int Left_Extra_Bits = (32 - k) - Bit_Index;
unsigned int Left_Value = m_pBitArray[Bit_Array_Index] & Powers_of_Two_Minus_One_Reversed[Bit_Index];
if (Left_Extra_Bits >= 0)
v |= (Left_Value >> Left_Extra_Bits);
else
v |= (Left_Value << -Left_Extra_Bits) | (m_pBitArray[Bit_Array_Index + 1] >> (32 + Left_Extra_Bits));
}
*p1 = v;
K_Sum += *p1 - *p2;
// convert *p2 to unsigned
*p2 = (*p2 % 2) ? (*p2 >> 1) + 1 : -(*p2 >> 1);
// adjust k if necessary
if ((K_Sum < kmin) || (K_Sum >= kmax))
{
if (K_Sum < kmin)
while (K_Sum < K_SUM_MIN_BOUNDARY_OLD[--k]) {}
else
while (K_Sum >= K_SUM_MAX_BOUNDARY_OLD[++k]) {}
kmax = K_SUM_MAX_BOUNDARY_OLD[k];
kmin = K_SUM_MIN_BOUNDARY_OLD[k];
}
}
for (; p2 < &Output_Array[Number_of_Elements]; p2++)
*p2 = (*p2 & 1) ? (*p2 >> 1) + 1 : -(*p2 >> 1);
}
void CUnBitArrayOld::GenerateArray(int *pOutputArray, int nElements, int nBytesRequired)
{
if (m_nVersion < 3860)
{
GenerateArrayOld(pOutputArray, nElements, nBytesRequired);
}
else if (m_nVersion <= 3890)
{
GenerateArrayRice(pOutputArray, nElements, nBytesRequired);
}
else
{
// error
}
}
void CUnBitArrayOld::GenerateArrayRice(int* Output_Array, uint32 Number_of_Elements, int Minimum_nCurrentBitIndex_Array_Bytes)
{
/////////////////////////////////////////////////////////////////////////////
// decode the bit array
/////////////////////////////////////////////////////////////////////////////
k = 10;
K_Sum = 1024 * 16;
if (m_nVersion <= 3880)
{
// the primary loop
for (int *p1 = &Output_Array[0]; p1 < &Output_Array[Number_of_Elements]; p1++)
{
*p1 = DecodeValueNew(FALSE);
}
}
else
{
// the primary loop
for (int *p1 = &Output_Array[0]; p1 < &Output_Array[Number_of_Elements]; p1++)
{
*p1 = DecodeValueNew(TRUE);
}
}
}
__inline int CUnBitArrayOld::DecodeValueNew(BOOL bCapOverflow)
{
// make sure there is room for the data
// this is a little slower than ensuring a huge block to start with, but it's safer
if (m_nCurrentBitIndex > m_nRefillBitThreshold)
{
FillBitArray();
}
unsigned int v;
// plug through the string of 0's (the overflow)
uint32 Bit_Initial = m_nCurrentBitIndex;
while (!(m_pBitArray[m_nCurrentBitIndex >> 5] & Powers_of_Two_Reversed[m_nCurrentBitIndex++ & 31])) {}
int nOverflow = (m_nCurrentBitIndex - Bit_Initial - 1);
if (bCapOverflow)
{
while (nOverflow >= 16)
{
k += 4;
nOverflow -= 16;
}
}
// if k = 0, your done
if (k != 0)
{
// put the overflow value into v
v = nOverflow << k;
// store the bit information and incement the bit pointer by 'k'
unsigned int Bit_Array_Index = m_nCurrentBitIndex >> 5;
unsigned int Bit_Index = m_nCurrentBitIndex & 31;
m_nCurrentBitIndex += k;
// figure the extra bits on the left and the left value
int Left_Extra_Bits = (32 - k) - Bit_Index;
unsigned int Left_Value = m_pBitArray[Bit_Array_Index] & Powers_of_Two_Minus_One_Reversed[Bit_Index];
if (Left_Extra_Bits >= 0)
{
v |= (Left_Value >> Left_Extra_Bits);
}
else
{
v |= (Left_Value << -Left_Extra_Bits) | (m_pBitArray[Bit_Array_Index + 1] >> (32 + Left_Extra_Bits));
}
}
else
{
v = nOverflow;
}
// update K_Sum
K_Sum += v - ((K_Sum + 8) >> 4);
// update k
if (K_Sum < K_SUM_MIN_BOUNDARY[k])
k--;
else if (K_Sum >= K_SUM_MAX_BOUNDARY[k])
k++;
// convert to unsigned and save
return (v & 1) ? (v >> 1) + 1 : -(int(v >> 1));
}
#endif // #ifdef BACKWARDS_COMPATIBILITY

View File

@@ -0,0 +1,46 @@
#ifndef APE_UNBITARRAY_OLD_H
#define APE_UNBITARRAY_OLD_H
#include "All.h"
#ifdef BACKWARDS_COMPATIBILITY
#include "../UnBitArrayBase.h"
class IAPEDecompress;
// decodes 0000 up to and including 3890
class CUnBitArrayOld : public CUnBitArrayBase
{
public:
// construction/destruction
CUnBitArrayOld(IAPEDecompress *pAPEDecompress, int nVersion);
~CUnBitArrayOld();
// functions
void GenerateArray(int *pOutputArray, int nElements, int nBytesRequired = -1);
unsigned int DecodeValue(DECODE_VALUE_METHOD DecodeMethod, int nParam1 = 0, int nParam2 = 0);
private:
void GenerateArrayOld(int* pOutputArray, uint32 NumberOfElements, int MinimumBitArrayBytes);
void GenerateArrayRice(int* pOutputArray, uint32 NumberOfElements, int MinimumBitArrayBytes);
uint32 DecodeValueRiceUnsigned(uint32 k);
// data
uint32 k;
uint32 K_Sum;
uint32 m_nRefillBitThreshold;
// functions
__inline int DecodeValueNew(BOOL bCapOverflow);
uint32 GetBitsRemaining();
__inline uint32 Get_K(uint32 x);
};
#endif
#endif // #ifndef APE_UNBITARRAY_OLD_H

View File

@@ -0,0 +1,261 @@
/*****************************************************************************************
UnMAC.cpp
Copyright (C) 2000-2001 by Matthew T. Ashland All Rights Reserved.
CUnMAC - the main hub for decompression (manages all of the other components)
Notes:
-none
*****************************************************************************************/
/*****************************************************************************************
Includes
*****************************************************************************************/
#include "All.h"
#ifdef BACKWARDS_COMPATIBILITY
#include "../APEInfo.h"
#include "UnMAC.h"
#include "GlobalFunctions.h"
#include "../UnBitArrayBase.h"
#include "Anti-Predictor.h"
#include "../Prepare.h"
#include "../UnBitArray.h"
#include "../NewPredictor.h"
#include "APEDecompressCore.h"
/*****************************************************************************************
CUnMAC class construction
*****************************************************************************************/
CUnMAC::CUnMAC()
{
// initialize member variables
m_bInitialized = FALSE;
m_LastDecodedFrameIndex = -1;
m_pAPEDecompress = NULL;
m_pAPEDecompressCore = NULL;
m_pPrepare = NULL;
m_nBlocksProcessed = 0;
m_nCRC = 0;
}
/*****************************************************************************************
CUnMAC class destruction
*****************************************************************************************/
CUnMAC::~CUnMAC()
{
// uninitialize the decoder in case it isn't already
Uninitialize();
}
/*****************************************************************************************
Initialize
*****************************************************************************************/
int CUnMAC::Initialize(IAPEDecompress *pAPEDecompress)
{
// uninitialize if it is currently initialized
if (m_bInitialized)
Uninitialize();
if (pAPEDecompress == NULL)
{
Uninitialize();
return ERROR_INITIALIZING_UNMAC;
}
// set the member pointer to the IAPEDecompress class
m_pAPEDecompress = pAPEDecompress;
// set the last decode frame to -1 so it forces a seek on start
m_LastDecodedFrameIndex = -1;
m_pAPEDecompressCore = new CAPEDecompressCore(GET_IO(pAPEDecompress), pAPEDecompress);
m_pPrepare = new CPrepare;
// set the initialized flag to TRUE
m_bInitialized = TRUE;
m_pAPEDecompress->GetInfo(APE_INFO_WAVEFORMATEX, (int) &m_wfeInput);
// return a successful value
return ERROR_SUCCESS;
}
/*****************************************************************************************
Uninitialize
*****************************************************************************************/
int CUnMAC::Uninitialize()
{
if (m_bInitialized)
{
SAFE_DELETE(m_pAPEDecompressCore)
SAFE_DELETE(m_pPrepare)
// clear the APE info pointer
m_pAPEDecompress = NULL;
// set the last decoded frame again
m_LastDecodedFrameIndex = -1;
// set the initialized flag to FALSE
m_bInitialized = FALSE;
}
return ERROR_SUCCESS;
}
/*****************************************************************************************
Decompress frame
*****************************************************************************************/
int CUnMAC::DecompressFrame(unsigned char *pOutputData, int32 FrameIndex, int CPULoadBalancingFactor)
{
return DecompressFrameOld(pOutputData, FrameIndex, CPULoadBalancingFactor);
}
/*****************************************************************************************
Seek to the proper frame (if necessary) and do any alignment of the bit array
*****************************************************************************************/
int CUnMAC::SeekToFrame(int FrameIndex)
{
if (GET_FRAMES_START_ON_BYTES_BOUNDARIES(m_pAPEDecompress))
{
if ((m_LastDecodedFrameIndex == -1) || ((FrameIndex - 1) != m_LastDecodedFrameIndex))
{
int SeekRemainder = (m_pAPEDecompress->GetInfo(APE_INFO_SEEK_BYTE, FrameIndex) - m_pAPEDecompress->GetInfo(APE_INFO_SEEK_BYTE, 0)) % 4;
m_pAPEDecompressCore->GetUnBitArrray()->FillAndResetBitArray(m_pAPEDecompress->GetInfo(APE_INFO_SEEK_BYTE, FrameIndex) - SeekRemainder, SeekRemainder * 8);
}
else
{
m_pAPEDecompressCore->GetUnBitArrray()->AdvanceToByteBoundary();
}
}
else
{
if ((m_LastDecodedFrameIndex == -1) || ((FrameIndex - 1) != m_LastDecodedFrameIndex))
{
m_pAPEDecompressCore->GetUnBitArrray()->FillAndResetBitArray(m_pAPEDecompress->GetInfo(APE_INFO_SEEK_BYTE, FrameIndex), m_pAPEDecompress->GetInfo(APE_INFO_SEEK_BIT, FrameIndex));
}
}
return ERROR_SUCCESS;
}
/*****************************************************************************************
Old code for frame decompression
*****************************************************************************************/
int CUnMAC::DecompressFrameOld(unsigned char *pOutputData, int32 FrameIndex, int CPULoadBalancingFactor)
{
// error check the parameters (too high of a frame index, etc.)
if (FrameIndex >= m_pAPEDecompress->GetInfo(APE_INFO_TOTAL_FRAMES)) { return ERROR_SUCCESS; }
// get the number of samples in the frame
int nBlocks = 0;
nBlocks = ((FrameIndex + 1) >= m_pAPEDecompress->GetInfo(APE_INFO_TOTAL_FRAMES)) ? m_pAPEDecompress->GetInfo(APE_INFO_FINAL_FRAME_BLOCKS) : m_pAPEDecompress->GetInfo(APE_INFO_BLOCKS_PER_FRAME);
if (nBlocks == 0)
return -1; // nothing to do (file must be zero length) (have to return error)
// take care of seeking and frame alignment
if (SeekToFrame(FrameIndex) != 0) { return -1; }
// get the checksum
unsigned int nSpecialCodes = 0;
uint32 nStoredCRC = 0;
if (GET_USES_CRC(m_pAPEDecompress) == FALSE)
{
nStoredCRC = m_pAPEDecompressCore->GetUnBitArrray()->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_RICE, 30);
if (nStoredCRC == 0)
{
nSpecialCodes = SPECIAL_FRAME_LEFT_SILENCE | SPECIAL_FRAME_RIGHT_SILENCE;
}
}
else
{
nStoredCRC = m_pAPEDecompressCore->GetUnBitArrray()->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_INT);
// get any 'special' codes if the file uses them (for silence, FALSE stereo, etc.)
nSpecialCodes = 0;
if (GET_USES_SPECIAL_FRAMES(m_pAPEDecompress))
{
if (nStoredCRC & 0x80000000)
{
nSpecialCodes = m_pAPEDecompressCore->GetUnBitArrray()->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_INT);
}
nStoredCRC &= 0x7FFFFFFF;
}
}
// the CRC that will be figured during decompression
uint32 CRC = 0xFFFFFFFF;
// decompress and convert from (x,y) -> (l,r)
// sort of int and ugly.... sorry
if (m_pAPEDecompress->GetInfo(APE_INFO_CHANNELS) == 2)
{
m_pAPEDecompressCore->GenerateDecodedArrays(nBlocks, nSpecialCodes, FrameIndex, CPULoadBalancingFactor);
WAVEFORMATEX WaveFormatEx; m_pAPEDecompress->GetInfo(APE_INFO_WAVEFORMATEX, (int) &WaveFormatEx);
m_pPrepare->UnprepareOld(m_pAPEDecompressCore->GetDataX(), m_pAPEDecompressCore->GetDataY(), nBlocks, &WaveFormatEx,
pOutputData, (unsigned int *) &CRC, (int *) &nSpecialCodes, m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
}
else if (m_pAPEDecompress->GetInfo(APE_INFO_CHANNELS) == 1)
{
m_pAPEDecompressCore->GenerateDecodedArrays(nBlocks, nSpecialCodes, FrameIndex, CPULoadBalancingFactor);
WAVEFORMATEX WaveFormatEx; m_pAPEDecompress->GetInfo(APE_INFO_WAVEFORMATEX, (int) &WaveFormatEx);
m_pPrepare->UnprepareOld(m_pAPEDecompressCore->GetDataX(), NULL, nBlocks, &WaveFormatEx,
pOutputData, (unsigned int *) &CRC, (int *) &nSpecialCodes, m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
}
if (GET_USES_SPECIAL_FRAMES(m_pAPEDecompress))
{
CRC >>= 1;
}
// check the CRC
if (GET_USES_CRC(m_pAPEDecompress) == FALSE)
{
uint32 nChecksum = CalculateOldChecksum(m_pAPEDecompressCore->GetDataX(), m_pAPEDecompressCore->GetDataY(), m_pAPEDecompress->GetInfo(APE_INFO_CHANNELS), nBlocks);
if (nChecksum != nStoredCRC)
return -1;
}
else
{
if (CRC != nStoredCRC)
return -1;
}
m_LastDecodedFrameIndex = FrameIndex;
return nBlocks;
}
/*****************************************************************************************
Figures the old checksum using the X,Y data
*****************************************************************************************/
uint32 CUnMAC::CalculateOldChecksum(int *pDataX, int *pDataY, int nChannels, int nBlocks)
{
uint32 nChecksum = 0;
if (nChannels == 2)
{
for (int z = 0; z < nBlocks; z++)
{
int R = pDataX[z] - (pDataY[z] / 2);
int L = R + pDataY[z];
nChecksum += (labs(R) + labs(L));
}
}
else if (nChannels == 1)
{
for (int z = 0; z < nBlocks; z++)
nChecksum += labs(pDataX[z]);
}
return nChecksum;
}
#endif // #ifdef BACKWARDS_COMPATIBILITY

View File

@@ -0,0 +1,69 @@
/*****************************************************************************************
UnMAC.h
Copyright (C) 2000-2001 by Matthew T. Ashland All Rights Reserved.
Methods for decompressing or verifying APE files
Notes:
-none
*****************************************************************************************/
#ifndef APE_UNMAC_H
#define APE_UNMAC_H
#include "../BitArray.h"
#include "../UnBitArrayBase.h"
class CAntiPredictor;
class CPrepare;
class CAPEDecompressCore;
class CPredictorBase;
class IPredictorDecompress;
class IAPEDecompress;
/*****************************************************************************************
CUnMAC class... a class that allows decoding on a frame-by-frame basis
*****************************************************************************************/
class CUnMAC
{
public:
// construction/destruction
CUnMAC();
~CUnMAC();
// functions
int Initialize(IAPEDecompress *pAPEDecompress);
int Uninitialize();
int DecompressFrame(unsigned char *pOutputData, int32 FrameIndex, int CPULoadBalancingFactor = 0);
int SeekToFrame(int FrameIndex);
private:
// data members
BOOL m_bInitialized;
int m_LastDecodedFrameIndex;
IAPEDecompress * m_pAPEDecompress;
CPrepare * m_pPrepare;
CAPEDecompressCore * m_pAPEDecompressCore;
// functions
void GenerateDecodedArrays(int nBlocks, int nSpecialCodes, int nFrameIndex, int nCPULoadBalancingFactor);
void GenerateDecodedArray(int *Input_Array, uint32 Number_of_Elements, int Frame_Index, CAntiPredictor *pAntiPredictor, int CPULoadBalancingFactor = 0);
int CreateAntiPredictors(int nCompressionLevel, int nVersion);
int DecompressFrameOld(unsigned char *pOutputData, int32 FrameIndex, int CPULoadBalancingFactor);
uint32 CalculateOldChecksum(int *pDataX, int *pDataY, int nChannels, int nBlocks);
public:
int m_nBlocksProcessed;
unsigned int m_nCRC;
unsigned int m_nStoredCRC;
WAVEFORMATEX m_wfeInput;
};
#endif // #ifndef APE_UNMAC_H