1 #include "All.h"
2 #include "APECompressCore.h"
3 #include "BitArray.h"
4 #include "Prepare.h"
5 #include "NewPredictor.h"
6
7 namespace APE
8 {
9
CAPECompressCore(CIO * pIO,const WAVEFORMATEX * pwfeInput,intn nMaxFrameBlocks,intn nCompressionLevel)10 CAPECompressCore::CAPECompressCore(CIO * pIO, const WAVEFORMATEX * pwfeInput, intn nMaxFrameBlocks, intn nCompressionLevel)
11 {
12 m_spBitArray.Assign(new CBitArray(pIO));
13 m_spDataX.Assign(new int [nMaxFrameBlocks], true);
14 m_spDataY.Assign(new int [nMaxFrameBlocks], true);
15 m_spTempData.Assign(new int [nMaxFrameBlocks], true);
16 m_spPrepare.Assign(new CPrepare);
17 m_spPredictorX.Assign(new CPredictorCompressNormal(nCompressionLevel));
18 m_spPredictorY.Assign(new CPredictorCompressNormal(nCompressionLevel));
19
20 memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX));
21 m_nPeakLevel = 0;
22 }
23
~CAPECompressCore()24 CAPECompressCore::~CAPECompressCore()
25 {
26 }
27
EncodeFrame(const void * pInputData,intn nInputBytes)28 int CAPECompressCore::EncodeFrame(const void * pInputData, intn nInputBytes)
29 {
30 // variables
31 const intn nInputBlocks = nInputBytes / m_wfeInput.nBlockAlign;
32 int nSpecialCodes = 0;
33
34 // always start a new frame on a byte boundary
35 m_spBitArray->AdvanceToByteBoundary();
36
37 // do the preparation stage
38 RETURN_ON_ERROR(Prepare(pInputData, (int) nInputBytes, &nSpecialCodes))
39
40 m_spPredictorX->Flush();
41 m_spPredictorY->Flush();
42
43 m_spBitArray->FlushState(m_BitArrayStateX);
44 m_spBitArray->FlushState(m_BitArrayStateY);
45
46 m_spBitArray->FlushBitArray();
47
48 if (m_wfeInput.nChannels == 2)
49 {
50 bool bEncodeX = true;
51 bool bEncodeY = true;
52
53 if ((nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE) &&
54 (nSpecialCodes & SPECIAL_FRAME_RIGHT_SILENCE))
55 {
56 bEncodeX = false;
57 bEncodeY = false;
58 }
59
60 if (nSpecialCodes & SPECIAL_FRAME_PSEUDO_STEREO)
61 {
62 bEncodeY = false;
63 }
64
65 if (bEncodeX && bEncodeY)
66 {
67 int nLastX = 0;
68 for (int z = 0; z < nInputBlocks; z++)
69 {
70 m_spBitArray->EncodeValue(m_spPredictorY->CompressValue(m_spDataY[z], nLastX), m_BitArrayStateY);
71 m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z], m_spDataY[z]), m_BitArrayStateX);
72
73 nLastX = m_spDataX[z];
74 }
75 }
76 else if (bEncodeX)
77 {
78 for (int z = 0; z < nInputBlocks; z++)
79 {
80 RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z]), m_BitArrayStateX))
81 }
82 }
83 else if (bEncodeY)
84 {
85 for (int z = 0; z < nInputBlocks; z++)
86 {
87 RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorY->CompressValue(m_spDataY[z]), m_BitArrayStateY))
88 }
89 }
90 }
91 else if (m_wfeInput.nChannels == 1)
92 {
93 if (!(nSpecialCodes & SPECIAL_FRAME_MONO_SILENCE))
94 {
95 for (int z = 0; z < nInputBlocks; z++)
96 {
97 RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z]), m_BitArrayStateX))
98 }
99 }
100 }
101
102 m_spBitArray->Finalize();
103
104 // return success
105 return 0;
106 }
107
Prepare(const void * pInputData,int nInputBytes,int * pSpecialCodes)108 int CAPECompressCore::Prepare(const void * pInputData, int nInputBytes, int * pSpecialCodes)
109 {
110 // variable declares
111 *pSpecialCodes = 0;
112 unsigned int nCRC = 0;
113
114 // do the preparation
115 RETURN_ON_ERROR(m_spPrepare->Prepare((unsigned char *) pInputData, nInputBytes, &m_wfeInput, m_spDataX, m_spDataY,
116 &nCRC, pSpecialCodes, &m_nPeakLevel))
117
118 // store the CRC
119 RETURN_ON_ERROR(m_spBitArray->EncodeUnsignedLong(nCRC))
120
121 // store any special codes
122 if (*pSpecialCodes != 0)
123 {
124 RETURN_ON_ERROR(m_spBitArray->EncodeUnsignedLong(*pSpecialCodes))
125 }
126
127 return 0;
128 }
129
130 }