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