OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
polyphase.c
Go to the documentation of this file.
1/* ***** BEGIN LICENSE BLOCK *****
2 * Version: RCSL 1.0/RPSL 1.0
3 *
4 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
5 *
6 * The contents of this file, and the files included with this file, are
7 * subject to the current version of the RealNetworks Public Source License
8 * Version 1.0 (the "RPSL") available at
9 * http://www.helixcommunity.org/content/rpsl unless you have licensed
10 * the file under the RealNetworks Community Source License Version 1.0
11 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
12 * in which case the RCSL will apply. You may also obtain the license terms
13 * directly from RealNetworks. You may not use this file except in
14 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
15 * applicable to this file, the RCSL. Please see the applicable RPSL or
16 * RCSL for the rights, obligations and limitations governing use of the
17 * contents of the file.
18 *
19 * This file is part of the Helix DNA Technology. RealNetworks is the
20 * developer of the Original Code and owns the copyrights in the portions
21 * it created.
22 *
23 * This file, and the files included with this file, is distributed and made
24 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
25 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
26 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
27 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
28 *
29 * Technology Compatibility Kit Test Suite(s) Location:
30 * http://www.helixcommunity.org/content/tck
31 *
32 * Contributor(s):
33 *
34 * ***** END LICENSE BLOCK ***** */
35
36/**************************************************************************************
37 * Fixed-point MP3 decoder
38 * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
39 * June 2003
40 *
41 * polyphase.c - final stage of subband transform (polyphase synthesis filter)
42 *
43 * This is the C reference version using __int64
44 * Look in the appropriate subdirectories for optimized asm implementations
45 * (e.g. arm/asmpoly.s)
46 **************************************************************************************/
47
48#include "coder.h"
49#include "assembly.h"
50
51/* input to Polyphase = Q(DQ_FRACBITS_OUT-2), gain 2 bits in convolution
52 * we also have the implicit bias of 2^15 to add back, so net fraction bits =
53 * DQ_FRACBITS_OUT - 2 - 2 - 15
54 * (see comment on Dequantize() for more info)
55 */
56#define DEF_NFRACBITS (DQ_FRACBITS_OUT - 2 - 2 - 15)
57#define CSHIFT 12 /* coefficients have 12 leading sign bits for early-terminating mulitplies */
58
59static __inline short ClipToShort(int x, int fracBits)
60{
61 int sign;
62
63 /* assumes you've already rounded (x += (1 << (fracBits-1))) */
64 x >>= fracBits;
65
66 /* Ken's trick: clips to [-32768, 32767] */
67 sign = x >> 31;
68 if (sign != (x >> 15))
69 x = sign ^ ((1 << 15) - 1);
70
71 return (short)x;
72}
73
74#define MC0M(x) { \
75 c1 = *coef; coef++; c2 = *coef; coef++; \
76 vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \
77 sum1L = MADD64(sum1L, vLo, c1); sum1L = MADD64(sum1L, vHi, -c2); \
78}
79
80#define MC1M(x) { \
81 c1 = *coef; coef++; \
82 vLo = *(vb1+(x)); \
83 sum1L = MADD64(sum1L, vLo, c1); \
84}
85
86#define MC2M(x) { \
87 c1 = *coef; coef++; c2 = *coef; coef++; \
88 vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \
89 sum1L = MADD64(sum1L, vLo, c1); sum2L = MADD64(sum2L, vLo, c2); \
90 sum1L = MADD64(sum1L, vHi, -c2); sum2L = MADD64(sum2L, vHi, c1); \
91}
92
93/**************************************************************************************
94 * Function: PolyphaseMono
95 *
96 * Description: filter one subband and produce 32 output PCM samples for one channel
97 *
98 * Inputs: pointer to PCM output buffer
99 * number of "extra shifts" (vbuf format = Q(DQ_FRACBITS_OUT-2))
100 * pointer to start of vbuf (preserved from last call)
101 * start of filter coefficient table (in proper, shuffled order)
102 * no minimum number of guard bits is required for input vbuf
103 * (see additional scaling comments below)
104 *
105 * Outputs: 32 samples of one channel of decoded PCM data, (i.e. Q16.0)
106 *
107 * Return: none
108 *
109 * TODO: add 32-bit version for platforms where 64-bit mul-acc is not supported
110 * (note max filter gain - see polyCoef[] comments)
111 **************************************************************************************/
112void PolyphaseMono(short *pcm, int *vbuf, const int *coefBase)
113{
114 int i;
115 const int *coef;
116 int *vb1;
117 int vLo, vHi, c1, c2;
118 Word64 sum1L, sum2L, rndVal;
119
120 rndVal = (Word64)( 1 << (DEF_NFRACBITS - 1 + (32 - CSHIFT)) );
121
122 /* special case, output sample 0 */
123 coef = coefBase;
124 vb1 = vbuf;
125 sum1L = rndVal;
126
127 MC0M(0)
128 MC0M(1)
129 MC0M(2)
130 MC0M(3)
131 MC0M(4)
132 MC0M(5)
133 MC0M(6)
134 MC0M(7)
135
136 *(pcm + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
137
138 /* special case, output sample 16 */
139 coef = coefBase + 256;
140 vb1 = vbuf + 64*16;
141 sum1L = rndVal;
142
143 MC1M(0)
144 MC1M(1)
145 MC1M(2)
146 MC1M(3)
147 MC1M(4)
148 MC1M(5)
149 MC1M(6)
150 MC1M(7)
151
152 *(pcm + 16) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
153
154 /* main convolution loop: sum1L = samples 1, 2, 3, ... 15 sum2L = samples 31, 30, ... 17 */
155 coef = coefBase + 16;
156 vb1 = vbuf + 64;
157 pcm++;
158
159 /* right now, the compiler creates bad asm from this... */
160 for (i = 15; i > 0; i--) {
161 sum1L = sum2L = rndVal;
162
163 MC2M(0)
164 MC2M(1)
165 MC2M(2)
166 MC2M(3)
167 MC2M(4)
168 MC2M(5)
169 MC2M(6)
170 MC2M(7)
171
172 vb1 += 64;
173 *(pcm) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
174 *(pcm + 2*i) = ClipToShort((int)SAR64(sum2L, (32-CSHIFT)), DEF_NFRACBITS);
175 pcm++;
176 }
177}
178
179#define MC0S(x) { \
180 c1 = *coef; coef++; c2 = *coef; coef++; \
181 vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \
182 sum1L = MADD64(sum1L, vLo, c1); sum1L = MADD64(sum1L, vHi, -c2); \
183 vLo = *(vb1+32+(x)); vHi = *(vb1+32+(23-(x))); \
184 sum1R = MADD64(sum1R, vLo, c1); sum1R = MADD64(sum1R, vHi, -c2); \
185}
186
187#define MC1S(x) { \
188 c1 = *coef; coef++; \
189 vLo = *(vb1+(x)); \
190 sum1L = MADD64(sum1L, vLo, c1); \
191 vLo = *(vb1+32+(x)); \
192 sum1R = MADD64(sum1R, vLo, c1); \
193}
194
195#define MC2S(x) { \
196 c1 = *coef; coef++; c2 = *coef; coef++; \
197 vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \
198 sum1L = MADD64(sum1L, vLo, c1); sum2L = MADD64(sum2L, vLo, c2); \
199 sum1L = MADD64(sum1L, vHi, -c2); sum2L = MADD64(sum2L, vHi, c1); \
200 vLo = *(vb1+32+(x)); vHi = *(vb1+32+(23-(x))); \
201 sum1R = MADD64(sum1R, vLo, c1); sum2R = MADD64(sum2R, vLo, c2); \
202 sum1R = MADD64(sum1R, vHi, -c2); sum2R = MADD64(sum2R, vHi, c1); \
203}
204
205/**************************************************************************************
206 * Function: PolyphaseStereo
207 *
208 * Description: filter one subband and produce 32 output PCM samples for each channel
209 *
210 * Inputs: pointer to PCM output buffer
211 * number of "extra shifts" (vbuf format = Q(DQ_FRACBITS_OUT-2))
212 * pointer to start of vbuf (preserved from last call)
213 * start of filter coefficient table (in proper, shuffled order)
214 * no minimum number of guard bits is required for input vbuf
215 * (see additional scaling comments below)
216 *
217 * Outputs: 32 samples of two channels of decoded PCM data, (i.e. Q16.0)
218 *
219 * Return: none
220 *
221 * Notes: interleaves PCM samples LRLRLR...
222 *
223 * TODO: add 32-bit version for platforms where 64-bit mul-acc is not supported
224 **************************************************************************************/
225void PolyphaseStereo(short *pcm, int *vbuf, const int *coefBase)
226{
227 int i;
228 const int *coef;
229 int *vb1;
230 int vLo, vHi, c1, c2;
231 Word64 sum1L, sum2L, sum1R, sum2R, rndVal;
232
233 rndVal = (Word64)( 1 << (DEF_NFRACBITS - 1 + (32 - CSHIFT)) );
234
235 /* special case, output sample 0 */
236 coef = coefBase;
237 vb1 = vbuf;
238 sum1L = sum1R = rndVal;
239
240 MC0S(0)
241 MC0S(1)
242 MC0S(2)
243 MC0S(3)
244 MC0S(4)
245 MC0S(5)
246 MC0S(6)
247 MC0S(7)
248
249 *(pcm + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
250 *(pcm + 1) = ClipToShort((int)SAR64(sum1R, (32-CSHIFT)), DEF_NFRACBITS);
251
252 /* special case, output sample 16 */
253 coef = coefBase + 256;
254 vb1 = vbuf + 64*16;
255 sum1L = sum1R = rndVal;
256
257 MC1S(0)
258 MC1S(1)
259 MC1S(2)
260 MC1S(3)
261 MC1S(4)
262 MC1S(5)
263 MC1S(6)
264 MC1S(7)
265
266 *(pcm + 2*16 + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
267 *(pcm + 2*16 + 1) = ClipToShort((int)SAR64(sum1R, (32-CSHIFT)), DEF_NFRACBITS);
268
269 /* main convolution loop: sum1L = samples 1, 2, 3, ... 15 sum2L = samples 31, 30, ... 17 */
270 coef = coefBase + 16;
271 vb1 = vbuf + 64;
272 pcm += 2;
273
274 /* right now, the compiler creates bad asm from this... */
275 for (i = 15; i > 0; i--) {
276 sum1L = sum2L = rndVal;
277 sum1R = sum2R = rndVal;
278
279 MC2S(0)
280 MC2S(1)
281 MC2S(2)
282 MC2S(3)
283 MC2S(4)
284 MC2S(5)
285 MC2S(6)
286 MC2S(7)
287
288 vb1 += 64;
289 *(pcm + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
290 *(pcm + 1) = ClipToShort((int)SAR64(sum1R, (32-CSHIFT)), DEF_NFRACBITS);
291 *(pcm + 2*2*i + 0) = ClipToShort((int)SAR64(sum2L, (32-CSHIFT)), DEF_NFRACBITS);
292 *(pcm + 2*2*i + 1) = ClipToShort((int)SAR64(sum2R, (32-CSHIFT)), DEF_NFRACBITS);
293 pcm += 2;
294 }
295}
UINT16 x
Definition BmfFile.h:83
INT64 Word64
Definition assembly.h:93
#define PolyphaseStereo
Definition coder.h:101
#define PolyphaseMono
Definition coder.h:100
#define MC2S(x)
Definition polyphase.c:195
#define MC1M(x)
Definition polyphase.c:80
#define DEF_NFRACBITS
Definition polyphase.c:56
#define MC0S(x)
Definition polyphase.c:179
#define MC0M(x)
Definition polyphase.c:74
#define CSHIFT
Definition polyphase.c:57
#define MC1S(x)
Definition polyphase.c:187
#define MC2M(x)
Definition polyphase.c:86