/* * 21.04.2004 Original verion. davagin@udm.ru. *----------------------------------------------------------------------- * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *---------------------------------------------------------------------- */ package davaguine.jmac.prediction; import davaguine.jmac.info.CompressionLevel; import davaguine.jmac.tools.JMACException; import davaguine.jmac.tools.RollBufferFastInt; import java.util.Arrays; /** * Author: Dmitry Vaguine * Date: 04.03.2004 * Time: 14:51:31 */ public class PredictorDecompress3950toCurrent extends IPredictorDecompress { public final static int M_COUNT = 8; private final static int WINDOW_BLOCKS = 512; public PredictorDecompress3950toCurrent(int nCompressionLevel, int nVersion) { super(nCompressionLevel, nVersion); m_nVersion = nVersion; if (nCompressionLevel == CompressionLevel.COMPRESSION_LEVEL_FAST) { m_pNNFilter = null; m_pNNFilter1 = null; m_pNNFilter2 = null; } else if (nCompressionLevel == CompressionLevel.COMPRESSION_LEVEL_NORMAL) { m_pNNFilter = new NNFilter16(11, nVersion); m_pNNFilter1 = null; m_pNNFilter2 = null; } else if (nCompressionLevel == CompressionLevel.COMPRESSION_LEVEL_HIGH) { m_pNNFilter = new NNFilter64(11, nVersion); m_pNNFilter1 = null; m_pNNFilter2 = null; } else if (nCompressionLevel == CompressionLevel.COMPRESSION_LEVEL_EXTRA_HIGH) { m_pNNFilter = new NNFilter256(13, nVersion); m_pNNFilter1 = new NNFilter32(10, nVersion); m_pNNFilter2 = null; } else if (nCompressionLevel == CompressionLevel.COMPRESSION_LEVEL_INSANE) { m_pNNFilter = new NNFilter1280(15, nVersion); m_pNNFilter1 = new NNFilter256(13, nVersion); m_pNNFilter2 = new NNFilter16(11, nVersion); } else { throw new JMACException("Unknown Compression Type"); } } public int DecompressValue(int nA) { return DecompressValue(nA, 0); } public int DecompressValue(int nA, int nB) { if (m_nCurrentIndex == WINDOW_BLOCKS) { // copy forward and adjust pointers m_rbPredictionA.Roll(); m_rbPredictionB.Roll(); m_rbAdaptA.Roll(); m_rbAdaptB.Roll(); m_nCurrentIndex = 0; } // stage 2: NNFilter Object obj; if ((obj = m_pNNFilter2) != null) nA = ((NNFilter) (obj)).Decompress(nA); if ((obj = m_pNNFilter1) != null) nA = ((NNFilter) (obj)).Decompress(nA); if ((obj = m_pNNFilter) != null) nA = ((NNFilter) (obj)).Decompress(nA); // stage 1: multiple predictors (order 2 and offset 1) int indexA = ((RollBufferFastInt) (obj = m_rbPredictionA)).index; RollBufferFastInt predictB; int indexB = (predictB = m_rbPredictionB).index; int ai[]; int l; (ai = ((RollBufferFastInt) (obj)).m_pData)[indexA] = l = m_nLastValueA; int l1 = indexA - 1; ai[l1] = l - ai[l1]; int ai3[] = predictB.m_pData; ai3[indexB] = nB - ((scaledFilterBLV * 31) >> 5); scaledFilterBLV = nB; // ai3[indexB] = m_Stage1FilterB.Compress(nB); int k2 = indexB - 1; ai3[k2] = ai3[indexB] - ai3[k2]; int ai2[]; int ai4[]; int nPredictionA = (l * (ai2 = m_aryMA)[0]) + (ai[l1] * ai2[1]) + (ai[indexA - 2] * ai2[2]) + (ai[indexA - 3] * ai2[3]); int nPredictionB = (ai3[indexB] * (ai4 = m_aryMB)[0]) + (ai3[k2] * ai4[1]) + (ai3[indexB - 2] * ai4[2]) + (ai3[indexB - 3] * ai4[3]) + (ai3[indexB - 4] * ai4[4]); int nCurrentA = nA + ((nPredictionA + (nPredictionB >> 1)) >> 10); RollBufferFastInt adaptA; RollBufferFastInt adaptB; int indexAA = (adaptA = m_rbAdaptA).index; int indexAB = (adaptB = m_rbAdaptB).index; int ai1[]; (ai1 = m_rbAdaptA.m_pData)[indexAA] = (l != 0) ? ((l >> 30) & 2) - 1 : 0; ai1[indexAA - 1] = (ai[l1] != 0) ? ((ai[l1] >> 30) & 2) - 1 : 0; int ai5[]; (ai5 = m_rbAdaptB.m_pData)[indexAB] = (ai3[indexB] != 0) ? ((ai3[indexB] >> 30) & 2) - 1 : 0; ai5[indexAB - 1] = (ai3[k2] != 0) ? ((ai3[k2] >> 30) & 2) - 1 : 0; if (nA > 0) { ai2[0] -= ai1[indexAA]; ai2[1] -= ai1[indexAA - 1]; ai2[2] -= ai1[indexAA - 2]; ai2[3] -= ai1[indexAA - 3]; ai4[0] -= ai5[indexAB]; ai4[1] -= ai5[indexAB - 1]; ai4[2] -= ai5[indexAB - 2]; ai4[3] -= ai5[indexAB - 3]; ai4[4] -= ai5[indexAB - 4]; } else if (nA < 0) { ai2[0] += ai1[indexAA]; ai2[1] += ai1[indexAA - 1]; ai2[2] += ai1[indexAA - 2]; ai2[3] += ai1[indexAA - 3]; ai4[0] += ai5[indexAB]; ai4[1] += ai5[indexAB - 1]; ai4[2] += ai5[indexAB - 2]; ai4[3] += ai5[indexAB - 3]; ai4[4] += ai5[indexAB - 4]; } // int nRetVal = m_Stage1FilterA.Decompress(nCurrentA); scaledFilterALV = nCurrentA + ((scaledFilterALV * 31) >> 5); m_nLastValueA = nCurrentA; ((RollBufferFastInt) (obj)).index++; predictB.index++; adaptA.index++; adaptB.index++; m_nCurrentIndex++; return scaledFilterALV; } public void Flush() { NNFilter nnfilter; if ((nnfilter = m_pNNFilter) != null) nnfilter.Flush(); if ((nnfilter = m_pNNFilter1) != null) nnfilter.Flush(); if ((nnfilter = m_pNNFilter2) != null) nnfilter.Flush(); Arrays.fill(m_aryMA, 0); Arrays.fill(m_aryMB, 0); m_rbPredictionA.Flush(); m_rbPredictionB.Flush(); m_rbAdaptA.Flush(); m_rbAdaptB.Flush(); int ai[]; (ai = m_aryMA)[0] = 360; ai[1] = 317; ai[2] = -109; ai[3] = 98; // m_Stage1FilterA.Flush(); scaledFilterALV = 0; // m_Stage1FilterB.Flush(); scaledFilterBLV = 0; m_nLastValueA = 0; m_nCurrentIndex = 0; } // adaption protected int m_aryMA[] = new int[M_COUNT]; protected int m_aryMB[] = new int[M_COUNT]; // buffer pointers protected RollBufferFastInt m_rbPredictionA = new RollBufferFastInt(WINDOW_BLOCKS, 8); protected RollBufferFastInt m_rbPredictionB = new RollBufferFastInt(WINDOW_BLOCKS, 8); protected RollBufferFastInt m_rbAdaptA = new RollBufferFastInt(WINDOW_BLOCKS, 8); protected RollBufferFastInt m_rbAdaptB = new RollBufferFastInt(WINDOW_BLOCKS, 8); // protected ScaledFirstOrderFilter m_Stage1FilterA = new ScaledFirstOrderFilter(31, 5); protected int scaledFilterALV; // protected ScaledFirstOrderFilter m_Stage1FilterB = new ScaledFirstOrderFilter(31, 5); protected int scaledFilterBLV; // other protected int m_nCurrentIndex; protected int m_nLastValueA; protected int m_nVersion; protected NNFilter m_pNNFilter; protected NNFilter m_pNNFilter1; protected NNFilter m_pNNFilter2; }