1 #ifndef APE_MULTICHANNEL_NNFILTER_H
2 #define APE_MULTICHANNEL_NNFILTER_H
3 
4 #include "NNFilter.h"
5 
6 class CMultichannelNNFilter
7 {
8 public:
9 
CMultichannelNNFilter(int nOrder1,int nOrder2,int nShift)10 	CMultichannelNNFilter(int nOrder1, int nOrder2, int nShift)
11 	{
12 		m_pNNFilterA = new CNNFilter(nOrder1 + nOrder2, 11, 3980);
13 		m_pNNFilterB = new CNNFilter(nOrder1 + nOrder2, 11, 3980);
14 
15 		m_rbA.Create(NN_WINDOW_ELEMENTS, nOrder1 + nOrder2 + 1);
16 		m_rbB.Create(NN_WINDOW_ELEMENTS, nOrder1 + nOrder2 + 1);
17 
18 		m_nShift = nShift;
19 
20 		m_nOrder1 = nOrder1;
21 	}
22 
23 
~CMultichannelNNFilter()24 	~CMultichannelNNFilter()
25 	{
26 		SAFE_DELETE(m_pNNFilterA)
27 		SAFE_DELETE(m_pNNFilterB)
28 	}
29 
Flush()30 	void Flush()
31 	{
32 		m_pNNFilterA->Flush();
33 		m_pNNFilterB->Flush();
34 
35 		m_rbA.Flush();
36 		m_rbB.Flush();
37 
38 	}
39 
Compress(int & nA,int & nB)40 	inline void Compress(int & nA, int & nB)
41 	{
42 		if (m_nShift <= 0)
43 			return;
44 
45 		m_rbA[0] = GetSaturatedShortFromInt(nA); m_rbB[0] = GetSaturatedShortFromInt(nB);
46 		m_rbA[-m_nOrder1 - 1] = m_rbB[-1]; m_rbB[-m_nOrder1 - 1] = m_rbA[0];
47 
48 		nA -= (m_pNNFilterA->GetPrediction(&m_rbA[-1]) >> m_nShift);
49 		nB -= (m_pNNFilterB->GetPrediction(&m_rbB[-1]) >> m_nShift);
50 
51 		m_pNNFilterA->AdaptAfterPrediction(&m_rbA[-1], -m_nOrder1, nA);
52 		m_pNNFilterB->AdaptAfterPrediction(&m_rbB[-1], -m_nOrder1, nB);
53 
54 		m_rbA.IncrementSafe(); m_rbB.IncrementSafe();
55 	}
56 
Decompress(int & nA,int & nB)57 	inline void Decompress(int & nA, int & nB)
58 	{
59 		if (m_nShift <= 0)
60 			return;
61 
62 		m_rbA[-m_nOrder1 - 1] = m_rbB[-1];
63 		int nOutputA = nA + (m_pNNFilterA->GetPrediction(&m_rbA[-1]) >> m_nShift);
64 		m_rbA[0] = GetSaturatedShortFromInt(nOutputA);
65 
66 		m_rbB[-m_nOrder1 - 1] = m_rbA[0];
67 		int nOutputB = nB + (m_pNNFilterB->GetPrediction(&m_rbB[-1]) >> m_nShift);
68 		m_rbB[0] = GetSaturatedShortFromInt(nOutputB);
69 
70 		m_pNNFilterA->AdaptAfterPrediction(&m_rbA[-1], -m_nOrder1, nA);
71 		m_pNNFilterB->AdaptAfterPrediction(&m_rbB[-1], -m_nOrder1, nB);
72 
73 		m_rbA.IncrementSafe(); m_rbB.IncrementSafe();
74 
75 		nA = nOutputA; nB = nOutputB;
76 	}
77 
78 protected:
79 
80 	CNNFilter * m_pNNFilterA;
81 	CNNFilter * m_pNNFilterB;
82 
83 	int m_nShift;
84 	int m_nOrder1;
85 
86 	CRollBuffer<short> m_rbA;
87 	CRollBuffer<short> m_rbB;
88 
GetSaturatedShortFromInt(int nValue)89 	inline short GetSaturatedShortFromInt(int nValue) const
90 	{
91 		return short((nValue == short(nValue)) ? nValue : (nValue >> 31) ^ 0x7FFF);
92 	}
93 };
94 
95 #endif // #ifndef APE_MULTICHANNEL_NNFILTER_H
96