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 }