mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 04:31:06 +00:00
c1a4db611b
Original commit message from CVS: Add monkeyaudio plugin
126 lines
3.6 KiB
C++
126 lines
3.6 KiB
C++
#include "All.h"
|
|
#include "APECompressCore.h"
|
|
|
|
#include "BitArray.h"
|
|
#include "Prepare.h"
|
|
#include "NewPredictor.h"
|
|
|
|
CAPECompressCore::CAPECompressCore(CIO * pIO, const WAVEFORMATEX * pwfeInput, int nMaxFrameBlocks, int nCompressionLevel)
|
|
{
|
|
m_spBitArray.Assign(new CBitArray(pIO));
|
|
m_spDataX.Assign(new int [nMaxFrameBlocks], TRUE);
|
|
m_spDataY.Assign(new int [nMaxFrameBlocks], TRUE);
|
|
m_spTempData.Assign(new int [nMaxFrameBlocks], TRUE);
|
|
m_spPrepare.Assign(new CPrepare);
|
|
m_spPredictorX.Assign(new CPredictorCompressNormal(nCompressionLevel));
|
|
m_spPredictorY.Assign(new CPredictorCompressNormal(nCompressionLevel));
|
|
|
|
memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX));
|
|
m_nPeakLevel = 0;
|
|
}
|
|
|
|
CAPECompressCore::~CAPECompressCore()
|
|
{
|
|
}
|
|
|
|
int CAPECompressCore::EncodeFrame(unsigned char * pInputData, int nInputBytes)
|
|
{
|
|
// variables
|
|
const int nInputBlocks = nInputBytes / m_wfeInput.nBlockAlign;
|
|
int nSpecialCodes = 0;
|
|
|
|
// always start a new frame on a byte boundary
|
|
m_spBitArray->AdvanceToByteBoundary();
|
|
|
|
// do the preparation stage
|
|
RETURN_ON_ERROR(Prepare(pInputData, nInputBytes, &nSpecialCodes))
|
|
|
|
m_spPredictorX->Flush();
|
|
m_spPredictorY->Flush();
|
|
|
|
m_spBitArray->FlushState(m_BitArrayStateX);
|
|
m_spBitArray->FlushState(m_BitArrayStateY);
|
|
|
|
m_spBitArray->FlushBitArray();
|
|
|
|
if (m_wfeInput.nChannels == 2)
|
|
{
|
|
BOOL bEncodeX = TRUE;
|
|
BOOL bEncodeY = TRUE;
|
|
|
|
if ((nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE) &&
|
|
(nSpecialCodes & SPECIAL_FRAME_RIGHT_SILENCE))
|
|
{
|
|
bEncodeX = FALSE;
|
|
bEncodeY = FALSE;
|
|
}
|
|
|
|
if (nSpecialCodes & SPECIAL_FRAME_PSEUDO_STEREO)
|
|
{
|
|
bEncodeY = FALSE;
|
|
}
|
|
|
|
if (bEncodeX && bEncodeY)
|
|
{
|
|
int nLastX = 0;
|
|
for (int z = 0; z < nInputBlocks; z++)
|
|
{
|
|
m_spBitArray->EncodeValue(m_spPredictorY->CompressValue(m_spDataY[z], nLastX), m_BitArrayStateY);
|
|
m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z], m_spDataY[z]), m_BitArrayStateX);
|
|
|
|
nLastX = m_spDataX[z];
|
|
}
|
|
}
|
|
else if (bEncodeX)
|
|
{
|
|
for (int z = 0; z < nInputBlocks; z++)
|
|
{
|
|
RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z]), m_BitArrayStateX))
|
|
}
|
|
}
|
|
else if (bEncodeY)
|
|
{
|
|
for (int z = 0; z < nInputBlocks; z++)
|
|
{
|
|
RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorY->CompressValue(m_spDataY[z]), m_BitArrayStateY))
|
|
}
|
|
}
|
|
}
|
|
else if (m_wfeInput.nChannels == 1)
|
|
{
|
|
if (!(nSpecialCodes & SPECIAL_FRAME_MONO_SILENCE))
|
|
{
|
|
for (int z = 0; z < nInputBlocks; z++)
|
|
{
|
|
RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z]), m_BitArrayStateX))
|
|
}
|
|
}
|
|
}
|
|
|
|
m_spBitArray->Finalize();
|
|
|
|
// return success
|
|
return 0;
|
|
}
|
|
|
|
int CAPECompressCore::Prepare(unsigned char * pInputData, int nInputBytes, int * pSpecialCodes)
|
|
{
|
|
// variable declares
|
|
*pSpecialCodes = 0;
|
|
unsigned int nCRC = 0;
|
|
|
|
// do the preparation
|
|
RETURN_ON_ERROR(m_spPrepare->Prepare(pInputData, nInputBytes, &m_wfeInput, m_spDataX, m_spDataY,
|
|
&nCRC, pSpecialCodes, &m_nPeakLevel))
|
|
|
|
// store the CRC
|
|
RETURN_ON_ERROR(m_spBitArray->EncodeUnsignedLong(nCRC))
|
|
|
|
// store any special codes
|
|
if (*pSpecialCodes != 0)
|
|
{
|
|
RETURN_ON_ERROR(m_spBitArray->EncodeUnsignedLong(*pSpecialCodes))
|
|
}
|
|
|
|
return 0;
|
|
}
|