1 #include "All.h"
2 #include "APECompress.h"
3 #include "NewPredictor.h"
4 
5 namespace APE
6 {
7 
8 /*****************************************************************************************
9 CPredictorCompressNormal
10 *****************************************************************************************/
CPredictorCompressNormal(intn nCompressionLevel)11 CPredictorCompressNormal::CPredictorCompressNormal(intn nCompressionLevel)
12     : IPredictorCompress(nCompressionLevel)
13 {
14     if (nCompressionLevel == COMPRESSION_LEVEL_FAST)
15     {
16         m_pNNFilter = NULL;
17         m_pNNFilter1 = NULL;
18         m_pNNFilter2 = NULL;
19     }
20     else if (nCompressionLevel == COMPRESSION_LEVEL_NORMAL)
21     {
22         m_pNNFilter = new CNNFilter(16, 11, MAC_FILE_VERSION_NUMBER);
23         m_pNNFilter1 = NULL;
24         m_pNNFilter2 = NULL;
25     }
26     else if (nCompressionLevel == COMPRESSION_LEVEL_HIGH)
27     {
28         m_pNNFilter = new CNNFilter(64, 11, MAC_FILE_VERSION_NUMBER);
29         m_pNNFilter1 = NULL;
30         m_pNNFilter2 = NULL;
31     }
32     else if (nCompressionLevel == COMPRESSION_LEVEL_EXTRA_HIGH)
33     {
34         m_pNNFilter = new CNNFilter(256, 13, MAC_FILE_VERSION_NUMBER);
35         m_pNNFilter1 = new CNNFilter(32, 10, MAC_FILE_VERSION_NUMBER);
36         m_pNNFilter2 = NULL;
37     }
38     else if (nCompressionLevel == COMPRESSION_LEVEL_INSANE)
39     {
40         m_pNNFilter = new CNNFilter(1024 + 256, 15, MAC_FILE_VERSION_NUMBER);
41         m_pNNFilter1 = new CNNFilter(256, 13, MAC_FILE_VERSION_NUMBER);
42         m_pNNFilter2 = new CNNFilter(16, 11, MAC_FILE_VERSION_NUMBER);
43     }
44     else
45     {
46         throw(1);
47     }
48 }
49 
~CPredictorCompressNormal()50 CPredictorCompressNormal::~CPredictorCompressNormal()
51 {
52     SAFE_DELETE(m_pNNFilter)
53     SAFE_DELETE(m_pNNFilter1)
54     SAFE_DELETE(m_pNNFilter2)
55 }
56 
Flush()57 int CPredictorCompressNormal::Flush()
58 {
59     if (m_pNNFilter) m_pNNFilter->Flush();
60     if (m_pNNFilter1) m_pNNFilter1->Flush();
61     if (m_pNNFilter2) m_pNNFilter2->Flush();
62 
63     m_rbPrediction.Flush();
64     m_rbAdapt.Flush();
65     m_Stage1FilterA.Flush(); m_Stage1FilterB.Flush();
66 
67     memset(m_aryM, 0, sizeof(m_aryM));
68 
69     int * paryM = &m_aryM[8];
70     paryM[0] = 360;
71     paryM[-1] = 317;
72     paryM[-2] = -109;
73     paryM[-3] = 98;
74 
75     m_nCurrentIndex = 0;
76 
77     return ERROR_SUCCESS;
78 }
79 
CompressValue(int nA,int nB)80 int CPredictorCompressNormal::CompressValue(int nA, int nB)
81 {
82     // roll the buffers if necessary
83     if (m_nCurrentIndex == WINDOW_BLOCKS)
84     {
85         m_rbPrediction.Roll(); m_rbAdapt.Roll();
86         m_nCurrentIndex = 0;
87     }
88 
89     // stage 1: simple, non-adaptive order 1 prediction
90     nA = m_Stage1FilterA.Compress(nA);
91     nB = m_Stage1FilterB.Compress(nB);
92 
93     // stage 2: adaptive offset filter(s)
94     m_rbPrediction[0] = nA;
95     m_rbPrediction[-2] = m_rbPrediction[-1] - m_rbPrediction[-2];
96 
97     m_rbPrediction[-5] = nB;
98     m_rbPrediction[-6] = m_rbPrediction[-5] - m_rbPrediction[-6];
99 
100     int * paryM = &m_aryM[8];
101 
102     int nPredictionA = (m_rbPrediction[-1] * paryM[0]) + (m_rbPrediction[-2] * paryM[-1]) + (m_rbPrediction[-3] * paryM[-2]) + (m_rbPrediction[-4] * paryM[-3]);
103     int nPredictionB = (m_rbPrediction[-5] * paryM[-4]) + (m_rbPrediction[-6] * paryM[-5]) + (m_rbPrediction[-7] * paryM[-6]) + (m_rbPrediction[-8] * paryM[-7]) + (m_rbPrediction[-9] * paryM[-8]);
104 
105     int nOutput = nA - ((nPredictionA + (nPredictionB >> 1)) >> 10);
106 
107     // adapt
108     m_rbAdapt[0] = (m_rbPrediction[-1]) ? ((m_rbPrediction[-1] >> 30) & 2) - 1 : 0;
109     m_rbAdapt[-1] = (m_rbPrediction[-2]) ? ((m_rbPrediction[-2] >> 30) & 2) - 1 : 0;
110     m_rbAdapt[-4] = (m_rbPrediction[-5]) ? ((m_rbPrediction[-5] >> 30) & 2) - 1 : 0;
111     m_rbAdapt[-5] = (m_rbPrediction[-6]) ? ((m_rbPrediction[-6] >> 30) & 2) - 1 : 0;
112 
113     if (nOutput > 0)
114     {
115         int * pM = &paryM[-8]; int * pAdapt = &m_rbAdapt[-8];
116         EXPAND_9_TIMES(*pM++ -= *pAdapt++;)
117     }
118     else if (nOutput < 0)
119     {
120         int * pM = &paryM[-8]; int * pAdapt = &m_rbAdapt[-8];
121         EXPAND_9_TIMES(*pM++ += *pAdapt++;)
122     }
123 
124     // stage 3: NNFilters
125     if (m_pNNFilter)
126     {
127         nOutput = m_pNNFilter->Compress(nOutput);
128 
129         if (m_pNNFilter1)
130         {
131             nOutput = m_pNNFilter1->Compress(nOutput);
132 
133             if (m_pNNFilter2)
134                 nOutput = m_pNNFilter2->Compress(nOutput);
135         }
136     }
137 
138     m_rbPrediction.IncrementFast();    m_rbAdapt.IncrementFast();
139     m_nCurrentIndex++;
140 
141     return nOutput;
142 }
143 
144 /*****************************************************************************************
145 CPredictorDecompressNormal3930to3950
146 *****************************************************************************************/
CPredictorDecompressNormal3930to3950(intn nCompressionLevel,intn nVersion)147 CPredictorDecompressNormal3930to3950::CPredictorDecompressNormal3930to3950(intn nCompressionLevel, intn nVersion)
148     : IPredictorDecompress(nCompressionLevel, nVersion)
149 {
150     m_pBuffer[0] = new int [HISTORY_ELEMENTS + WINDOW_BLOCKS];
151 
152     if (nCompressionLevel == COMPRESSION_LEVEL_FAST)
153     {
154         m_pNNFilter = NULL;
155         m_pNNFilter1 = NULL;
156     }
157     else if (nCompressionLevel == COMPRESSION_LEVEL_NORMAL)
158     {
159         m_pNNFilter = new CNNFilter(16, 11, nVersion);
160         m_pNNFilter1 = NULL;
161     }
162     else if (nCompressionLevel == COMPRESSION_LEVEL_HIGH)
163     {
164         m_pNNFilter = new CNNFilter(64, 11, nVersion);
165         m_pNNFilter1 = NULL;
166     }
167     else if (nCompressionLevel == COMPRESSION_LEVEL_EXTRA_HIGH)
168     {
169         m_pNNFilter = new CNNFilter(256, 13, nVersion);
170         m_pNNFilter1 = new CNNFilter(32, 10, nVersion);
171     }
172     else
173     {
174         throw(1);
175     }
176 }
177 
~CPredictorDecompressNormal3930to3950()178 CPredictorDecompressNormal3930to3950::~CPredictorDecompressNormal3930to3950()
179 {
180     SAFE_DELETE(m_pNNFilter)
181     SAFE_DELETE(m_pNNFilter1)
182     SAFE_ARRAY_DELETE(m_pBuffer[0])
183 }
184 
Flush()185 int CPredictorDecompressNormal3930to3950::Flush()
186 {
187     if (m_pNNFilter) m_pNNFilter->Flush();
188     if (m_pNNFilter1) m_pNNFilter1->Flush();
189 
190     ZeroMemory(m_pBuffer[0], (HISTORY_ELEMENTS + 1) * sizeof(int));
191     ZeroMemory(&m_aryM[0], M_COUNT * sizeof(int));
192 
193     m_aryM[0] = 360;
194     m_aryM[1] = 317;
195     m_aryM[2] = -109;
196     m_aryM[3] = 98;
197 
198     m_pInputBuffer = &m_pBuffer[0][HISTORY_ELEMENTS];
199 
200     m_nLastValue = 0;
201     m_nCurrentIndex = 0;
202 
203     return ERROR_SUCCESS;
204 }
205 
DecompressValue(int nInput,int)206 int CPredictorDecompressNormal3930to3950::DecompressValue(int nInput, int)
207 {
208     if (m_nCurrentIndex == WINDOW_BLOCKS)
209     {
210         // copy forward and adjust pointers
211         memcpy(&m_pBuffer[0][0], &m_pBuffer[0][WINDOW_BLOCKS], HISTORY_ELEMENTS * sizeof(int));
212         m_pInputBuffer = &m_pBuffer[0][HISTORY_ELEMENTS];
213 
214         m_nCurrentIndex = 0;
215     }
216 
217     // stage 2: NNFilter
218     if (m_pNNFilter1)
219         nInput = m_pNNFilter1->Decompress(nInput);
220     if (m_pNNFilter)
221         nInput = m_pNNFilter->Decompress(nInput);
222 
223     // stage 1: multiple predictors (order 2 and offset 1)
224 
225     int p1 = m_pInputBuffer[-1];
226     int p2 = m_pInputBuffer[-1] - m_pInputBuffer[-2];
227     int p3 = m_pInputBuffer[-2] - m_pInputBuffer[-3];
228     int p4 = m_pInputBuffer[-3] - m_pInputBuffer[-4];
229 
230     m_pInputBuffer[0] = nInput + (((p1 * m_aryM[0]) + (p2 * m_aryM[1]) + (p3 * m_aryM[2]) + (p4 * m_aryM[3])) >> 9);
231 
232     if (nInput > 0)
233     {
234         m_aryM[0] -= ((p1 >> 30) & 2) - 1;
235         m_aryM[1] -= ((p2 >> 30) & 2) - 1;
236         m_aryM[2] -= ((p3 >> 30) & 2) - 1;
237         m_aryM[3] -= ((p4 >> 30) & 2) - 1;
238     }
239     else if (nInput < 0)
240     {
241         m_aryM[0] += ((p1 >> 30) & 2) - 1;
242         m_aryM[1] += ((p2 >> 30) & 2) - 1;
243         m_aryM[2] += ((p3 >> 30) & 2) - 1;
244         m_aryM[3] += ((p4 >> 30) & 2) - 1;
245     }
246 
247     int nResult = m_pInputBuffer[0] + ((m_nLastValue * 31) >> 5);
248     m_nLastValue = nResult;
249 
250     m_nCurrentIndex++;
251     m_pInputBuffer++;
252 
253     return nResult;
254 }
255 
256 /*****************************************************************************************
257 CPredictorDecompress3950toCurrent
258 *****************************************************************************************/
CPredictorDecompress3950toCurrent(intn nCompressionLevel,intn nVersion)259 CPredictorDecompress3950toCurrent::CPredictorDecompress3950toCurrent(intn nCompressionLevel, intn nVersion)
260     : IPredictorDecompress(nCompressionLevel, nVersion)
261 {
262     m_nVersion = nVersion;
263 
264     if (nCompressionLevel == COMPRESSION_LEVEL_FAST)
265     {
266         m_pNNFilter = NULL;
267         m_pNNFilter1 = NULL;
268         m_pNNFilter2 = NULL;
269     }
270     else if (nCompressionLevel == COMPRESSION_LEVEL_NORMAL)
271     {
272         m_pNNFilter = new CNNFilter(16, 11, nVersion);
273         m_pNNFilter1 = NULL;
274         m_pNNFilter2 = NULL;
275     }
276     else if (nCompressionLevel == COMPRESSION_LEVEL_HIGH)
277     {
278         m_pNNFilter = new CNNFilter(64, 11, nVersion);
279         m_pNNFilter1 = NULL;
280         m_pNNFilter2 = NULL;
281     }
282     else if (nCompressionLevel == COMPRESSION_LEVEL_EXTRA_HIGH)
283     {
284         m_pNNFilter = new CNNFilter(256, 13, nVersion);
285         m_pNNFilter1 = new CNNFilter(32, 10, nVersion);
286         m_pNNFilter2 = NULL;
287     }
288     else if (nCompressionLevel == COMPRESSION_LEVEL_INSANE)
289     {
290         m_pNNFilter = new CNNFilter(1024 + 256, 15, MAC_FILE_VERSION_NUMBER);
291         m_pNNFilter1 = new CNNFilter(256, 13, MAC_FILE_VERSION_NUMBER);
292         m_pNNFilter2 = new CNNFilter(16, 11, MAC_FILE_VERSION_NUMBER);
293 
294     }
295     else
296     {
297         throw(1);
298     }
299 }
300 
~CPredictorDecompress3950toCurrent()301 CPredictorDecompress3950toCurrent::~CPredictorDecompress3950toCurrent()
302 {
303     SAFE_DELETE(m_pNNFilter)
304     SAFE_DELETE(m_pNNFilter1)
305     SAFE_DELETE(m_pNNFilter2)
306 }
307 
Flush()308 int CPredictorDecompress3950toCurrent::Flush()
309 {
310     if (m_pNNFilter) m_pNNFilter->Flush();
311     if (m_pNNFilter1) m_pNNFilter1->Flush();
312     if (m_pNNFilter2) m_pNNFilter2->Flush();
313 
314     ZeroMemory(m_aryMA, sizeof(m_aryMA));
315     ZeroMemory(m_aryMB, sizeof(m_aryMB));
316 
317     m_rbPredictionA.Flush();
318     m_rbPredictionB.Flush();
319     m_rbAdaptA.Flush();
320     m_rbAdaptB.Flush();
321 
322     m_aryMA[0] = 360;
323     m_aryMA[1] = 317;
324     m_aryMA[2] = -109;
325     m_aryMA[3] = 98;
326 
327     m_Stage1FilterA.Flush();
328     m_Stage1FilterB.Flush();
329 
330     m_nLastValueA = 0;
331 
332     m_nCurrentIndex = 0;
333 
334     return ERROR_SUCCESS;
335 }
336 
DecompressValue(int nA,int nB)337 int CPredictorDecompress3950toCurrent::DecompressValue(int nA, int nB)
338 {
339     if (m_nCurrentIndex == WINDOW_BLOCKS)
340     {
341         // copy forward and adjust pointers
342         m_rbPredictionA.Roll();    m_rbPredictionB.Roll();
343         m_rbAdaptA.Roll(); m_rbAdaptB.Roll();
344 
345         m_nCurrentIndex = 0;
346     }
347 
348     // stage 2: NNFilter
349     if (m_pNNFilter2)
350         nA = m_pNNFilter2->Decompress(nA);
351     if (m_pNNFilter1)
352         nA = m_pNNFilter1->Decompress(nA);
353     if (m_pNNFilter)
354         nA = m_pNNFilter->Decompress(nA);
355 
356     // stage 1: multiple predictors (order 2 and offset 1)
357     m_rbPredictionA[0] = m_nLastValueA;
358     m_rbPredictionA[-1] = m_rbPredictionA[0] - m_rbPredictionA[-1];
359 
360     m_rbPredictionB[0] = m_Stage1FilterB.Compress(nB);
361     m_rbPredictionB[-1] = m_rbPredictionB[0] - m_rbPredictionB[-1];
362 
363     int nPredictionA = (m_rbPredictionA[0] * m_aryMA[0]) + (m_rbPredictionA[-1] * m_aryMA[1]) + (m_rbPredictionA[-2] * m_aryMA[2]) + (m_rbPredictionA[-3] * m_aryMA[3]);
364     int nPredictionB = (m_rbPredictionB[0] * m_aryMB[0]) + (m_rbPredictionB[-1] * m_aryMB[1]) + (m_rbPredictionB[-2] * m_aryMB[2]) + (m_rbPredictionB[-3] * m_aryMB[3]) + (m_rbPredictionB[-4] * m_aryMB[4]);
365 
366     int nCurrentA = nA + ((nPredictionA + (nPredictionB >> 1)) >> 10);
367 
368     m_rbAdaptA[0] = (m_rbPredictionA[0]) ? ((m_rbPredictionA[0] >> 30) & 2) - 1 : 0;
369     m_rbAdaptA[-1] = (m_rbPredictionA[-1]) ? ((m_rbPredictionA[-1] >> 30) & 2) - 1 : 0;
370 
371     m_rbAdaptB[0] = (m_rbPredictionB[0]) ? ((m_rbPredictionB[0] >> 30) & 2) - 1 : 0;
372     m_rbAdaptB[-1] = (m_rbPredictionB[-1]) ? ((m_rbPredictionB[-1] >> 30) & 2) - 1 : 0;
373 
374     if (nA > 0)
375     {
376         m_aryMA[0] -= m_rbAdaptA[0];
377         m_aryMA[1] -= m_rbAdaptA[-1];
378         m_aryMA[2] -= m_rbAdaptA[-2];
379         m_aryMA[3] -= m_rbAdaptA[-3];
380 
381         m_aryMB[0] -= m_rbAdaptB[0];
382         m_aryMB[1] -= m_rbAdaptB[-1];
383         m_aryMB[2] -= m_rbAdaptB[-2];
384         m_aryMB[3] -= m_rbAdaptB[-3];
385         m_aryMB[4] -= m_rbAdaptB[-4];
386     }
387     else if (nA < 0)
388     {
389         m_aryMA[0] += m_rbAdaptA[0];
390         m_aryMA[1] += m_rbAdaptA[-1];
391         m_aryMA[2] += m_rbAdaptA[-2];
392         m_aryMA[3] += m_rbAdaptA[-3];
393 
394         m_aryMB[0] += m_rbAdaptB[0];
395         m_aryMB[1] += m_rbAdaptB[-1];
396         m_aryMB[2] += m_rbAdaptB[-2];
397         m_aryMB[3] += m_rbAdaptB[-3];
398         m_aryMB[4] += m_rbAdaptB[-4];
399     }
400 
401     int nResult = m_Stage1FilterA.Decompress(nCurrentA);
402     m_nLastValueA = nCurrentA;
403 
404     m_rbPredictionA.IncrementFast(); m_rbPredictionB.IncrementFast();
405     m_rbAdaptA.IncrementFast(); m_rbAdaptB.IncrementFast();
406 
407     m_nCurrentIndex++;
408 
409     return nResult;
410 }
411 
412 }