1 /******************************************************************************
2  *
3  *  Copyright (C) 2014 The Android Open Source Project
4  *  Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at:
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  ******************************************************************************/
19 
20 /**********************************************************************************
21   $Revision: #1 $
22 ***********************************************************************************/
23 
24 /** @file
25 
26 This file, along with synthesis-generated.c, contains the synthesis
27 filterbank routines. The operations performed correspond to the
28 operations described in A2DP Appendix B, Figure 12.3. Several
29 mathematical optimizations are performed, particularly for the
30 8-subband case.
31 
32 One important optimization is to note that the "matrixing" operation
33 can be decomposed into the product of a type II discrete cosine kernel
34 and another, sparse matrix.
35 
36 According to Fig 12.3, in the 8-subband case,
37 @code
38     N[k][i] = cos((i+0.5)*(k+4)*pi/8), k = 0..15 and i = 0..7
39 @endcode
40 
41 N can be factored as R * C2, where C2 is an 8-point type II discrete
42 cosine kernel given by
43 @code
44     C2[k][i] = cos((i+0.5)*k*pi/8)), k = 0..7 and i = 0..7
45 @endcode
46 
47 R turns out to be a sparse 16x8 matrix with the following non-zero
48 entries:
49 @code
50     R[k][k+4]        =  1,   k = 0..3
51     R[k][abs(12-k)]  = -1,   k = 5..15
52 @endcode
53 
54 The spec describes computing V[0..15] as N * R.
55 @code
56     V[0..15] = N * R = (R * C2) * R = R * (C2 * R)
57 @endcode
58 
59 C2 * R corresponds to computing the discrete cosine transform of R, so
60 V[0..15] can be computed by taking the DCT of R followed by assignment
61 and selective negation of the DCT result into V.
62 
63         Although this was derived empirically using GNU Octave, it is
64         formally demonstrated in, e.g., Liu, Chi-Min and Lee,
65         Wen-Chieh. "A Unified Fast Algorithm for Cosine Modulated
66         Filter Banks in Current Audio Coding Standards." Journal of
67         the AES 47 (December 1999): 1061.
68 
69 Given the shift operation performed prior to computing V[0..15], it is
70 clear that V[0..159] represents a rolling history of the 10 most
71 recent groups of blocks input to the synthesis operation. Interpreting
72 the matrix N in light of its factorization into C2 and R, R's
73 sparseness has implications for interpreting the values in V. In
74 particular, there is considerable redundancy in the values stored in
75 V. Furthermore, since R[4][0..7] are all zeros, one out of every 16
76 values in V will be zero regardless of the input data. Within each
77 block of 16 values in V, fully half of them are redundant or
78 irrelevant:
79 
80 @code
81     V[ 0] =  DCT[4]
82     V[ 1] =  DCT[5]
83     V[ 2] =  DCT[6]
84     V[ 3] =  DCT[7]
85     V[ 4] = 0
86     V[ 5] = -DCT[7] = -V[3] (redundant)
87     V[ 6] = -DCT[6] = -V[2] (redundant)
88     V[ 7] = -DCT[5] = -V[1] (redundant)
89     V[ 8] = -DCT[4] = -V[0] (redundant)
90     V[ 9] = -DCT[3]
91     V[10] = -DCT[2]
92     V[11] = -DCT[1]
93     V[12] = -DCT[0]
94     V[13] = -DCT[1] = V[11] (redundant)
95     V[14] = -DCT[2] = V[10] (redundant)
96     V[15] = -DCT[3] = V[ 9] (redundant)
97 @endcode
98 
99 Since the elements of V beyond 15 were originally computed the same
100 way during a previous run, what holds true for V[x] also holds true
101 for V[x+16]. Thus, so long as care is taken to maintain the mapping,
102 we need only actually store the unique values, which correspond to the
103 output of the DCT, in some cases inverted. In fact, instead of storing
104 V[0..159], we could store DCT[0..79] which would contain a history of
105 DCT results. More on this in a bit.
106 
107 Going back to figure 12.3 in the spec, it should be clear that the
108 vector U need not actually be explicitly constructed, but that with
109 suitable indexing into V during the window operation, the same end can
110 be accomplished. In the same spirit of the pseudocode shown in the
111 figure, the following is the construction of W without using U:
112 
113 @code
114     for i=0 to 79 do
115         W[i] = D[i]*VSIGN(i)*V[remap_V(i)] where remap_V(i) = 32*(int(i/16)) + (i % 16) + (i % 16 >= 8 ? 16 : 0)
116                                              and VSIGN(i) maps i%16 into {1, 1, 1, 1, 0, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1 }
117                                              These values correspond to the
118                                              signs of the redundant values as
119                                              shown in the explanation three
120                                              paragraphs above.
121 @endcode
122 
123 We saw above how V[4..8,13..15] (and by extension
124 V[(4..8,13..15)+16*n]) can be defined in terms of other elements
125 within the subblock of V. V[0..3,9..12] correspond to DCT elements.
126 
127 @code
128     for i=0 to 79 do
129         W[i] = D[i]*DSIGN(i)*DCT[remap_DCT(i)]
130 @endcode
131 
132 The DCT is calculated using the Arai-Agui-Nakajima factorization,
133 which saves some computation by producing output that needs to be
134 multiplied by scaling factors before being used.
135 
136 @code
137     for i=0 to 79 do
138         W[i] = D[i]*SCALE[i%8]*AAN_DCT[remap_DCT(i)]
139 @endcode
140 
141 D can be premultiplied with the DCT scaling factors to yield
142 
143 @code
144     for i=0 to 79 do
145         W[i] = DSCALED[i]*AAN_DCT[remap_DCT(i)] where DSCALED[i] = D[i]*SCALE[i%8]
146 @endcode
147 
148 The output samples X[0..7] are defined as sums of W:
149 
150 @code
151         X[j] = sum{i=0..9}(W[j+8*i])
152 @endcode
153 
154 @ingroup codec_internal
155 */
156 
157 /**
158 @addtogroup codec_internal
159 @{
160 */
161 #include "common/bt_target.h"
162 #include "oi_codec_sbc_private.h"
163 
164 #if (defined(SBC_DEC_INCLUDED) && SBC_DEC_INCLUDED == TRUE)
165 
166 const OI_INT32 dec_window_4[21] = {
167     0,        /* +0.00000000E+00 */
168     97,        /* +5.36548976E-04 */
169     270,        /* +1.49188357E-03 */
170     495,        /* +2.73370904E-03 */
171     694,        /* +3.83720193E-03 */
172     704,        /* +3.89205149E-03 */
173     338,        /* +1.86581691E-03 */
174     -554,        /* -3.06012286E-03 */
175     1974,        /* +1.09137620E-02 */
176     3697,        /* +2.04385087E-02 */
177     5224,        /* +2.88757392E-02 */
178     5824,        /* +3.21939290E-02 */
179     4681,        /* +2.58767811E-02 */
180     1109,        /* +6.13245186E-03 */
181     -5214,        /* -2.88217274E-02 */
182     -14047,        /* -7.76463494E-02 */
183     24529,        /* +1.35593274E-01 */
184     35274,        /* +1.94987841E-01 */
185     44618,        /* +2.46636662E-01 */
186     50984,        /* +2.81828203E-01 */
187     53243,        /* +2.94315332E-01 */
188 };
189 
190 #define DCTII_4_K06_FIX ( 11585)/* S1.14      11585   0.707107*/
191 
192 #define DCTII_4_K08_FIX ( 21407)/* S1.14      21407   1.306563*/
193 
194 #define DCTII_4_K09_FIX (-15137)/* S1.14     -15137  -0.923880*/
195 
196 #define DCTII_4_K10_FIX ( -8867)/* S1.14      -8867  -0.541196*/
197 
198 /** Scales x by y bits to the right, adding a rounding factor.
199  */
200 #ifndef SCALE
201 #define SCALE(x, y) (((x) + (1 <<((y)-1))) >> (y))
202 #endif
203 
204 #ifndef CLIP_INT16
205 #define CLIP_INT16(x) do { if (x > OI_INT16_MAX) { x = OI_INT16_MAX; } else if (x < OI_INT16_MIN) { x = OI_INT16_MIN; } } while (0)
206 #endif
207 
208 /**
209  * Default C language implementation of a 16x32->32 multiply. This function may
210  * be replaced by a platform-specific version for speed.
211  *
212  * @param u A signed 16-bit multiplicand
213  * @param v A signed 32-bit multiplier
214 
215  * @return  A signed 32-bit value corresponding to the 32 most significant bits
216  * of the 48-bit product of u and v.
217  */
default_mul_16s_32s_hi(OI_INT16 u,OI_INT32 v)218 static INLINE OI_INT32 default_mul_16s_32s_hi(OI_INT16 u, OI_INT32 v)
219 {
220     OI_UINT16 v0;
221     OI_INT16 v1;
222 
223     OI_INT32 w, x;
224 
225     v0 = (OI_UINT16)(v & 0xffff);
226     v1 = (OI_INT16) (v >> 16);
227 
228     w = v1 * u;
229     x = u * v0;
230 
231     return w + (x >> 16);
232 }
233 
234 #define MUL_16S_32S_HI(_x, _y) default_mul_16s_32s_hi(_x, _y)
235 
236 #define LONG_MULT_DCT(K, sample) (MUL_16S_32S_HI(K, sample)<<2)
237 
238 PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const *RESTRICT buffer, OI_UINT strideShift);
239 PRIVATE void SynthWindow112_generated(OI_INT16 *pcm, SBC_BUFFER_T const *RESTRICT buffer, OI_UINT strideShift);
240 PRIVATE void dct2_8(SBC_BUFFER_T *RESTRICT out, OI_INT32 const *RESTRICT x);
241 
242 typedef void (*SYNTH_FRAME)(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT blkstart, OI_UINT blkcount);
243 
244 #ifndef COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS
245 #define COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(dest, src) do { shift_buffer(dest, src, 72); } while (0)
246 #endif
247 
248 #ifndef DCT2_8
249 #define DCT2_8(dst, src) dct2_8(dst, src)
250 #endif
251 
252 #ifndef SYNTH80
253 #define SYNTH80 SynthWindow80_generated
254 #endif
255 
256 #ifndef SYNTH112
257 #define SYNTH112 SynthWindow112_generated
258 #endif
259 
OI_SBC_SynthFrame_80(OI_CODEC_SBC_DECODER_CONTEXT * context,OI_INT16 * pcm,OI_UINT blkstart,OI_UINT blkcount)260 PRIVATE void OI_SBC_SynthFrame_80(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT blkstart, OI_UINT blkcount)
261 {
262     OI_UINT blk;
263     OI_UINT ch;
264     OI_UINT nrof_channels = context->common.frameInfo.nrof_channels;
265     OI_UINT pcmStrideShift = context->common.pcmStride == 1 ? 0 : 1;
266     OI_UINT offset = context->common.filterBufferOffset;
267     OI_INT32 *s = context->common.subdata + 8 * nrof_channels * blkstart;
268     OI_UINT blkstop = blkstart + blkcount;
269 
270     for (blk = blkstart; blk < blkstop; blk++) {
271         if (offset == 0) {
272             COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(context->common.filterBuffer[0] + context->common.filterBufferLen - 72, context->common.filterBuffer[0]);
273             if (nrof_channels == 2) {
274                 COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(context->common.filterBuffer[1] + context->common.filterBufferLen - 72, context->common.filterBuffer[1]);
275             }
276             offset = context->common.filterBufferLen - 80;
277         } else {
278             offset -= 1 * 8;
279         }
280 
281         for (ch = 0; ch < nrof_channels; ch++) {
282             DCT2_8(context->common.filterBuffer[ch] + offset, s);
283             SYNTH80(pcm + ch, context->common.filterBuffer[ch] + offset, pcmStrideShift);
284             s += 8;
285         }
286         pcm += (8 << pcmStrideShift);
287     }
288     context->common.filterBufferOffset = offset;
289 }
290 
OI_SBC_SynthFrame_4SB(OI_CODEC_SBC_DECODER_CONTEXT * context,OI_INT16 * pcm,OI_UINT blkstart,OI_UINT blkcount)291 PRIVATE void OI_SBC_SynthFrame_4SB(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT blkstart, OI_UINT blkcount)
292 {
293     OI_UINT blk;
294     OI_UINT ch;
295     OI_UINT nrof_channels = context->common.frameInfo.nrof_channels;
296     OI_UINT pcmStrideShift = context->common.pcmStride == 1 ? 0 : 1;
297     OI_UINT offset = context->common.filterBufferOffset;
298     OI_INT32 *s = context->common.subdata + 8 * nrof_channels * blkstart;
299     OI_UINT blkstop = blkstart + blkcount;
300 
301     for (blk = blkstart; blk < blkstop; blk++) {
302         if (offset == 0) {
303             COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(context->common.filterBuffer[0] + context->common.filterBufferLen - 72, context->common.filterBuffer[0]);
304             if (nrof_channels == 2) {
305                 COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(context->common.filterBuffer[1] + context->common.filterBufferLen - 72, context->common.filterBuffer[1]);
306             }
307             offset = context->common.filterBufferLen - 80;
308         } else {
309             offset -= 8;
310         }
311         for (ch = 0; ch < nrof_channels; ch++) {
312             cosineModulateSynth4(context->common.filterBuffer[ch] + offset, s);
313             SynthWindow40_int32_int32_symmetry_with_sum(pcm + ch,
314                     context->common.filterBuffer[ch] + offset,
315                     pcmStrideShift);
316             s += 4;
317         }
318         pcm += (4 << pcmStrideShift);
319     }
320     context->common.filterBufferOffset = offset;
321 }
322 
323 #ifdef SBC_ENHANCED
324 
OI_SBC_SynthFrame_Enhanced(OI_CODEC_SBC_DECODER_CONTEXT * context,OI_INT16 * pcm,OI_UINT blkstart,OI_UINT blkcount)325 PRIVATE void OI_SBC_SynthFrame_Enhanced(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT blkstart, OI_UINT blkcount)
326 {
327     OI_UINT blk;
328     OI_UINT ch;
329     OI_UINT nrof_channels = context->common.frameInfo.nrof_channels;
330     OI_UINT pcmStrideShift = context->common.pcmStride == 1 ? 0 : 1;
331     OI_UINT offset = context->common.filterBufferOffset;
332     OI_INT32 *s = context->common.subdata + 8 * nrof_channels * blkstart;
333     OI_UINT blkstop = blkstart + blkcount;
334 
335     for (blk = blkstart; blk < blkstop; blk++) {
336         if (offset == 0) {
337             COPY_BACKWARD_32BIT_ALIGNED_104_HALFWORDS(context->common.filterBuffer[0] + context->common.filterBufferLen - 104, context->common.filterBuffer[0]);
338             if (nrof_channels == 2) {
339                 COPY_BACKWARD_32BIT_ALIGNED_104_HALFWORDS(context->common.filterBuffer[1] + context->common.filterBufferLen - 104, context->common.filterBuffer[1]);
340             }
341             offset = context->common.filterBufferLen - 112;
342         } else {
343             offset -= 8;
344         }
345         for (ch = 0; ch < nrof_channels; ++ch) {
346             DCT2_8(context->common.filterBuffer[ch] + offset, s);
347             SYNTH112(pcm + ch, context->common.filterBuffer[ch] + offset, pcmStrideShift);
348             s += 8;
349         }
350         pcm += (8 << pcmStrideShift);
351     }
352     context->common.filterBufferOffset = offset;
353 }
354 
355 static const SYNTH_FRAME SynthFrameEnhanced[] = {
356     NULL,                       /* invalid */
357     OI_SBC_SynthFrame_Enhanced, /* mono */
358     OI_SBC_SynthFrame_Enhanced  /* stereo */
359 };
360 
361 #endif
362 
363 static const SYNTH_FRAME SynthFrame8SB[] = {
364     NULL,             /* invalid */
365     OI_SBC_SynthFrame_80, /* mono */
366     OI_SBC_SynthFrame_80  /* stereo */
367 };
368 
369 
370 static const SYNTH_FRAME SynthFrame4SB[] = {
371     NULL,                  /* invalid */
372     OI_SBC_SynthFrame_4SB, /* mono */
373     OI_SBC_SynthFrame_4SB  /* stereo */
374 };
375 
OI_SBC_SynthFrame(OI_CODEC_SBC_DECODER_CONTEXT * context,OI_INT16 * pcm,OI_UINT start_block,OI_UINT nrof_blocks)376 PRIVATE void OI_SBC_SynthFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT start_block, OI_UINT nrof_blocks)
377 {
378     OI_UINT nrof_subbands = context->common.frameInfo.nrof_subbands;
379     OI_UINT nrof_channels = context->common.frameInfo.nrof_channels;
380 
381     OI_ASSERT(nrof_subbands == 4 || nrof_subbands == 8);
382     if (nrof_subbands == 4) {
383         SynthFrame4SB[nrof_channels](context, pcm, start_block, nrof_blocks);
384 #ifdef SBC_ENHANCED
385     } else if (context->common.frameInfo.enhanced) {
386         SynthFrameEnhanced[nrof_channels](context, pcm, start_block, nrof_blocks);
387 #endif /* SBC_ENHANCED */
388     } else {
389         SynthFrame8SB[nrof_channels](context, pcm, start_block, nrof_blocks);
390     }
391 }
392 
393 
SynthWindow40_int32_int32_symmetry_with_sum(OI_INT16 * pcm,SBC_BUFFER_T buffer[80],OI_UINT strideShift)394 void SynthWindow40_int32_int32_symmetry_with_sum(OI_INT16 *pcm, SBC_BUFFER_T buffer[80], OI_UINT strideShift)
395 {
396     OI_INT32 pa;
397     OI_INT32 pb;
398 
399     /* These values should be zero, since out[2] of the 4-band cosine modulation
400      * is always zero. */
401     OI_ASSERT(buffer[ 2] == 0);
402     OI_ASSERT(buffer[10] == 0);
403     OI_ASSERT(buffer[18] == 0);
404     OI_ASSERT(buffer[26] == 0);
405     OI_ASSERT(buffer[34] == 0);
406     OI_ASSERT(buffer[42] == 0);
407     OI_ASSERT(buffer[50] == 0);
408     OI_ASSERT(buffer[58] == 0);
409     OI_ASSERT(buffer[66] == 0);
410     OI_ASSERT(buffer[74] == 0);
411 
412 
413     pa  = dec_window_4[ 4] * (buffer[12] + buffer[76]);
414     pa += dec_window_4[ 8] * (buffer[16] - buffer[64]);
415     pa += dec_window_4[12] * (buffer[28] + buffer[60]);
416     pa += dec_window_4[16] * (buffer[32] - buffer[48]);
417     pa += dec_window_4[20] *  buffer[44];
418     pa = SCALE(-pa, 15);
419     CLIP_INT16(pa);
420     pcm[0 << strideShift] = (OI_INT16)pa;
421 
422 
423     pa  = dec_window_4[ 1] * buffer[ 1]; pb  = dec_window_4[ 1] * buffer[79];
424     pb += dec_window_4[ 3] * buffer[ 3]; pa += dec_window_4[ 3] * buffer[77];
425     pa += dec_window_4[ 5] * buffer[13]; pb += dec_window_4[ 5] * buffer[67];
426     pb += dec_window_4[ 7] * buffer[15]; pa += dec_window_4[ 7] * buffer[65];
427     pa += dec_window_4[ 9] * buffer[17]; pb += dec_window_4[ 9] * buffer[63];
428     pb += dec_window_4[11] * buffer[19]; pa += dec_window_4[11] * buffer[61];
429     pa += dec_window_4[13] * buffer[29]; pb += dec_window_4[13] * buffer[51];
430     pb += dec_window_4[15] * buffer[31]; pa += dec_window_4[15] * buffer[49];
431     pa += dec_window_4[17] * buffer[33]; pb += dec_window_4[17] * buffer[47];
432     pb += dec_window_4[19] * buffer[35]; pa += dec_window_4[19] * buffer[45];
433     pa = SCALE(-pa, 15);
434     CLIP_INT16(pa);
435     pcm[1 << strideShift] = (OI_INT16)(pa);
436     pb = SCALE(-pb, 15);
437     CLIP_INT16(pb);
438     pcm[3 << strideShift] = (OI_INT16)(pb);
439 
440 
441     pa  = dec_window_4[2] * (/*buffer[ 2] + */ buffer[78]);  /* buffer[ 2] is always zero */
442     pa += dec_window_4[6] * (buffer[14] /* + buffer[66]*/);  /* buffer[66] is always zero */
443     pa += dec_window_4[10] * (/*buffer[18] + */ buffer[62]);  /* buffer[18] is always zero */
444     pa += dec_window_4[14] * (buffer[30] /* + buffer[50]*/);  /* buffer[50] is always zero */
445     pa += dec_window_4[18] * (/*buffer[34] + */ buffer[46]);  /* buffer[34] is always zero */
446     pa = SCALE(-pa, 15);
447     CLIP_INT16(pa);
448     pcm[2 << strideShift] = (OI_INT16)(pa);
449 }
450 
451 
452 /**
453   This routine implements the cosine modulation matrix for 4-subband
454   synthesis. This is called "matrixing" in the SBC specification. This
455   matrix, M4,  can be factored into an 8-point Type II Discrete Cosine
456   Transform, DCTII_4 and a matrix S4, given here:
457 
458   @code
459         __               __
460        |   0   0   1   0   |
461        |   0   0   0   1   |
462        |   0   0   0   0   |
463        |   0   0   0  -1   |
464   S4 = |   0   0  -1   0   |
465        |   0  -1   0   0   |
466        |  -1   0   0   0   |
467        |__ 0  -1   0   0 __|
468 
469   M4 * in = S4 * (DCTII_4 * in)
470   @endcode
471 
472   (DCTII_4 * in) is computed using a Fast Cosine Transform. The algorithm
473   here is based on an implementation computed by the SPIRAL computer
474   algebra system, manually converted to fixed-point arithmetic. S4 can be
475   implemented using only assignment and negation.
476   */
cosineModulateSynth4(SBC_BUFFER_T * RESTRICT out,OI_INT32 const * RESTRICT in)477 PRIVATE void cosineModulateSynth4(SBC_BUFFER_T *RESTRICT out, OI_INT32 const *RESTRICT in)
478 {
479     OI_INT32 f0, f1, f2, f3, f4, f7, f8, f9, f10;
480     OI_INT32 y0, y1, y2, y3;
481 
482     f0 = (in[0] - in[3]);
483     f1 = (in[0] + in[3]);
484     f2 = (in[1] - in[2]);
485     f3 = (in[1] + in[2]);
486 
487     f4 = f1 - f3;
488 
489     y0 = -SCALE(f1 + f3, DCT_SHIFT);
490     y2 = -SCALE(LONG_MULT_DCT(DCTII_4_K06_FIX, f4), DCT_SHIFT);
491     f7 = f0 + f2;
492     f8 = LONG_MULT_DCT(DCTII_4_K08_FIX, f0);
493     f9 = LONG_MULT_DCT(DCTII_4_K09_FIX, f7);
494     f10 = LONG_MULT_DCT(DCTII_4_K10_FIX, f2);
495     y3 = -SCALE(f8 + f9, DCT_SHIFT);
496     y1 = -SCALE(f10 - f9, DCT_SHIFT);
497 
498     out[0] = (OI_INT16) - y2;
499     out[1] = (OI_INT16) - y3;
500     out[2] = (OI_INT16)0;
501     out[3] = (OI_INT16)y3;
502     out[4] = (OI_INT16)y2;
503     out[5] = (OI_INT16)y1;
504     out[6] = (OI_INT16)y0;
505     out[7] = (OI_INT16)y1;
506 }
507 
508 /**
509 @}
510 */
511 #endif /* #if (defined(SBC_DEC_INCLUDED) && SBC_DEC_INCLUDED == TRUE) */
512