synthesis-sbc.c 18 KB

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