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