FastLED 3.9.15
Loading...
Searching...
No Matches
stproc.hpp
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 * stproc.c - mid-side and intensity (MPEG1 and MPEG2) stereo processing
42 **************************************************************************************/
43
44#include "coder.h"
45#include "fl/stl/stdint.h"
46#include "fl/stl/noexcept.h"
47#include "assembly.h"
48
49namespace fl {
50namespace third_party {
51
52
53
54/**************************************************************************************
55 * Function: MidSideProc
56 *
57 * Description: sum-difference stereo reconstruction
58 *
59 * Inputs: vector x with dequantized samples from left and right channels
60 * number of non-zero samples (MAX of left and right)
61 * assume 1 guard bit in input
62 * guard bit mask (left and right channels)
63 *
64 * Outputs: updated sample vector x
65 * updated guard bit mask
66 *
67 * Return: none
68 *
69 * Notes: assume at least 1 GB in input
70 **************************************************************************************/
72{
73 int32_t i, xr, xl, mOutL, mOutR;
74
75 /* L = (M+S)/sqrt(2), R = (M-S)/sqrt(2)
76 * NOTE: 1/sqrt(2) done in DequantChannel() - see comments there
77 */
78 mOutL = mOutR = 0;
79 for(i = 0; i < nSamps; i++) {
80 xl = x[0][i];
81 xr = x[1][i];
82 x[0][i] = xl + xr;
83 x[1][i] = xl - xr;
84 mOutL |= FASTABS(x[0][i]);
85 mOutR |= FASTABS(x[1][i]);
86 }
87 mOut[0] |= mOutL;
88 mOut[1] |= mOutR;
89}
90
91/**************************************************************************************
92 * Function: IntensityProcMPEG1
93 *
94 * Description: intensity stereo processing for MPEG1
95 *
96 * Inputs: vector x with dequantized samples from left and right channels
97 * number of non-zero samples in left channel
98 * valid FrameHeader struct
99 * two each of ScaleFactorInfoSub, CriticalBandInfo structs (both channels)
100 * flags indicating midSide on/off, mixedBlock on/off
101 * guard bit mask (left and right channels)
102 *
103 * Outputs: updated sample vector x
104 * updated guard bit mask
105 *
106 * Return: none
107 *
108 * Notes: assume at least 1 GB in input
109 *
110 * TODO: combine MPEG1/2 into one function (maybe)
111 * make sure all the mixed-block and IIP logic is right
112 **************************************************************************************/
114 CriticalBandInfo *cbi, int32_t midSideFlag, int32_t mixFlag, int32_t mOut[2]) FL_NOEXCEPT
115{
116 (void)mixFlag; // Unused parameter - reserved for future use
117 int32_t i=0, j=0, n=0, cb=0, w=0;
118 int32_t sampsLeft, isf, mOutL, mOutR, xl, xr;
119 int32_t fl, fr, fls[3], frs[3];
120 int32_t cbStartL=0, cbStartS=0, cbEndL=0, cbEndS=0;
121 int32_t *isfTab;
122
123 /* NOTE - this works fine for mixed blocks, as long as the switch point starts in the
124 * short block section (i.e. on or after sample 36 = sfBand->l[8] = 3*sfBand->s[3]
125 * is this a safe assumption?
126 * TODO - intensity + mixed not quite right (diff = 11 on he_mode)
127 * figure out correct implementation (spec ambiguous about when to do short block reorder)
128 */
129 if (cbi[1].cbType == 0) {
130 /* long block */
131 cbStartL = cbi[1].cbEndL + 1;
132 cbEndL = cbi[0].cbEndL + 1;
133 cbStartS = cbEndS = 0;
134 i = fh->sfBand->l[cbStartL];
135 } else if (cbi[1].cbType == 1 || cbi[1].cbType == 2) {
136 /* short or mixed block */
137 cbStartS = cbi[1].cbEndSMax + 1;
138 cbEndS = cbi[0].cbEndSMax + 1;
139 cbStartL = cbEndL = 0;
140 i = 3 * fh->sfBand->s[cbStartS];
141 }
142
143 sampsLeft = nSamps - i; /* process to length of left */
144 isfTab = (int32_t *)ISFMpeg1[midSideFlag];
145 mOutL = mOutR = 0;
146
147 /* long blocks */
148 for (cb = cbStartL; cb < cbEndL && sampsLeft > 0; cb++) {
149 isf = sfis->l[cb];
150 if (isf == 7) {
151 fl = ISFIIP[midSideFlag][0];
152 fr = ISFIIP[midSideFlag][1];
153 } else {
154 fl = isfTab[isf];
155 fr = isfTab[6] - isfTab[isf];
156 }
157
158 n = fh->sfBand->l[cb + 1] - fh->sfBand->l[cb];
159 for (j = 0; j < n && sampsLeft > 0; j++, i++) {
160 xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr);
161 xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl);
162 sampsLeft--;
163 }
164 }
165
166 /* short blocks */
167 for (cb = cbStartS; cb < cbEndS && sampsLeft >= 3; cb++) {
168 for (w = 0; w < 3; w++) {
169 isf = sfis->s[cb][w];
170 if (isf == 7) {
171 fls[w] = ISFIIP[midSideFlag][0];
172 frs[w] = ISFIIP[midSideFlag][1];
173 } else {
174 fls[w] = isfTab[isf];
175 frs[w] = isfTab[6] - isfTab[isf];
176 }
177 }
178
179 n = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb];
180 for (j = 0; j < n && sampsLeft >= 3; j++, i+=3) {
181 xr = MULSHIFT32(frs[0], x[0][i+0]) << 2; x[1][i+0] = xr; mOutR |= FASTABS(xr);
182 xl = MULSHIFT32(fls[0], x[0][i+0]) << 2; x[0][i+0] = xl; mOutL |= FASTABS(xl);
183 xr = MULSHIFT32(frs[1], x[0][i+1]) << 2; x[1][i+1] = xr; mOutR |= FASTABS(xr);
184 xl = MULSHIFT32(fls[1], x[0][i+1]) << 2; x[0][i+1] = xl; mOutL |= FASTABS(xl);
185 xr = MULSHIFT32(frs[2], x[0][i+2]) << 2; x[1][i+2] = xr; mOutR |= FASTABS(xr);
186 xl = MULSHIFT32(fls[2], x[0][i+2]) << 2; x[0][i+2] = xl; mOutL |= FASTABS(xl);
187 sampsLeft -= 3;
188 }
189 }
190 mOut[0] = mOutL;
191 mOut[1] = mOutR;
192
193 return;
194}
195
196/**************************************************************************************
197 * Function: IntensityProcMPEG2
198 *
199 * Description: intensity stereo processing for MPEG2
200 *
201 * Inputs: vector x with dequantized samples from left and right channels
202 * number of non-zero samples in left channel
203 * valid FrameHeader struct
204 * two each of ScaleFactorInfoSub, CriticalBandInfo structs (both channels)
205 * ScaleFactorJS struct with joint stereo info from UnpackSFMPEG2()
206 * flags indicating midSide on/off, mixedBlock on/off
207 * guard bit mask (left and right channels)
208 *
209 * Outputs: updated sample vector x
210 * updated guard bit mask
211 *
212 * Return: none
213 *
214 * Notes: assume at least 1 GB in input
215 *
216 * TODO: combine MPEG1/2 into one function (maybe)
217 * make sure all the mixed-block and IIP logic is right
218 * probably redo IIP logic to be simpler
219 **************************************************************************************/
221 CriticalBandInfo *cbi, ScaleFactorJS *sfjs, int32_t midSideFlag, int32_t mixFlag, int32_t mOut[2]) FL_NOEXCEPT
222{
223 (void)mixFlag; // Unused parameter - reserved for future use
224 int32_t i, j, k, n, r, cb, w;
225 int32_t fl, fr, mOutL, mOutR, xl, xr;
226 int32_t sampsLeft;
227 int32_t isf, sfIdx, tmp, il[23];
228 int32_t *isfTab;
229 int32_t cbStartL, cbStartS, cbEndL, cbEndS;
230
231 isfTab = (int32_t *)ISFMpeg2[sfjs->intensityScale][midSideFlag];
232 mOutL = mOutR = 0;
233
234 /* fill buffer with illegal intensity positions (depending on slen) */
235 for (k = r = 0; r < 4; r++) {
236 tmp = (1 << sfjs->slen[r]) - 1;
237 for (j = 0; j < sfjs->nr[r]; j++, k++)
238 il[k] = tmp;
239 }
240
241 if (cbi[1].cbType == 0) {
242 /* long blocks */
243 il[21] = il[22] = 1;
244 cbStartL = cbi[1].cbEndL + 1; /* start at end of right */
245 cbEndL = cbi[0].cbEndL + 1; /* process to end of left */
246 i = fh->sfBand->l[cbStartL];
247 sampsLeft = nSamps - i;
248
249 for(cb = cbStartL; cb < cbEndL; cb++) {
250 sfIdx = sfis->l[cb];
251 if (sfIdx == il[cb]) {
252 fl = ISFIIP[midSideFlag][0];
253 fr = ISFIIP[midSideFlag][1];
254 } else {
255 isf = (sfis->l[cb] + 1) >> 1;
256 fl = isfTab[(sfIdx & 0x01 ? isf : 0)];
257 fr = isfTab[(sfIdx & 0x01 ? 0 : isf)];
258 }
259 n = MIN(fh->sfBand->l[cb + 1] - fh->sfBand->l[cb], sampsLeft);
260
261 for(j = 0; j < n; j++, i++) {
262 xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr);
263 xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl);
264 }
265
266 /* early exit once we've used all the non-zero samples */
267 sampsLeft -= n;
268 if (sampsLeft == 0)
269 break;
270 }
271 } else {
272 /* short or mixed blocks */
273 il[12] = 1;
274
275 for(w = 0; w < 3; w++) {
276 cbStartS = cbi[1].cbEndS[w] + 1; /* start at end of right */
277 cbEndS = cbi[0].cbEndS[w] + 1; /* process to end of left */
278 i = 3 * fh->sfBand->s[cbStartS] + w;
279
280 /* skip through sample array by 3, so early-exit logic would be more tricky */
281 for(cb = cbStartS; cb < cbEndS; cb++) {
282 sfIdx = sfis->s[cb][w];
283 if (sfIdx == il[cb]) {
284 fl = ISFIIP[midSideFlag][0];
285 fr = ISFIIP[midSideFlag][1];
286 } else {
287 isf = (sfis->s[cb][w] + 1) >> 1;
288 fl = isfTab[(sfIdx & 0x01 ? isf : 0)];
289 fr = isfTab[(sfIdx & 0x01 ? 0 : isf)];
290 }
291 n = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb];
292
293 for(j = 0; j < n; j++, i+=3) {
294 xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr);
295 xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl);
296 }
297 }
298 }
299 }
300 mOut[0] = mOutL;
301 mOut[1] = mOutR;
302
303 return;
304}
305
306} // namespace third_party
307} // namespace fl
#define MIN(a, b)
Definition coder.h:64
#define MAX_NCHAN
Definition mp3dec.h:78
#define MAX_NSAMP
Definition mp3dec.h:79
void MidSideProc(int32_t x[MAX_NCHAN][MAX_NSAMP], int32_t nSamps, int32_t mOut[2]) FL_NOEXCEPT
Definition stproc.hpp:71
const int32_t ISFIIP[2][2]
Definition trigtabs.hpp:218
__inline int32_t MULSHIFT32(int32_t x, int32_t y) FL_NOEXCEPT
Multiply together two 32-bit numbers and return the top 32-bits of the result.
Definition assembly.h:503
__inline int32_t FASTABS(int32_t x) FL_NOEXCEPT
Absolute value of x.
Definition assembly.h:513
struct fl::third_party::_ScaleFactorInfoSub ScaleFactorInfoSub
struct fl::third_party::_FrameHeader FrameHeader
void IntensityProcMPEG1(int32_t x[MAX_NCHAN][MAX_NSAMP], int32_t nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis, CriticalBandInfo *cbi, int32_t midSideFlag, int32_t mixFlag, int32_t mOut[2]) FL_NOEXCEPT
Definition stproc.hpp:113
const int32_t ISFMpeg2[2][2][16]
Definition trigtabs.hpp:186
const int32_t ISFMpeg1[2][7]
Definition trigtabs.hpp:164
void IntensityProcMPEG2(int32_t x[MAX_NCHAN][MAX_NSAMP], int32_t nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis, CriticalBandInfo *cbi, ScaleFactorJS *sfjs, int32_t midSideFlag, int32_t mixFlag, int32_t mOut[2]) FL_NOEXCEPT
Definition stproc.hpp:220
fl::i32 int32_t
Definition coder.h:220
struct fl::third_party::_ScaleFactorJS ScaleFactorJS
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT