1ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta/******************************************************************************
2ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *
3ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *  Copyright (C) 2014 The Android Open Source Project
49ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *  Copyright 2003 - 2004 Open Interface North America, Inc. All rights
59ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                        reserved.
6ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *
7ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *  Licensed under the Apache License, Version 2.0 (the "License");
8ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *  you may not use this file except in compliance with the License.
9ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *  You may obtain a copy of the License at:
10ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *
11ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *  http://www.apache.org/licenses/LICENSE-2.0
12ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *
13ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *  Unless required by applicable law or agreed to in writing, software
14ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *  distributed under the License is distributed on an "AS IS" BASIS,
15ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *  See the License for the specific language governing permissions and
17ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *  limitations under the License.
18ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *
19ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta ******************************************************************************/
20ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
21ee96a3c60fca590d38025925c072d264e06493c4Myles Watson/*******************************************************************************
22ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  $Revision: #1 $
23ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
24ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
25ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta/** @file
26ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
27ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaThis file, along with synthesis-generated.c, contains the synthesis
28ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptafilterbank routines. The operations performed correspond to the
29ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptaoperations described in A2DP Appendix B, Figure 12.3. Several
30ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptamathematical optimizations are performed, particularly for the
31ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta8-subband case.
32ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
33ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaOne important optimization is to note that the "matrixing" operation
34ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptacan be decomposed into the product of a type II discrete cosine kernel
35ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptaand another, sparse matrix.
36ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
37ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaAccording to Fig 12.3, in the 8-subband case,
38ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@code
39ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    N[k][i] = cos((i+0.5)*(k+4)*pi/8), k = 0..15 and i = 0..7
40ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@endcode
41ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
42ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaN can be factored as R * C2, where C2 is an 8-point type II discrete
43ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptacosine kernel given by
44ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@code
45ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    C2[k][i] = cos((i+0.5)*k*pi/8)), k = 0..7 and i = 0..7
46ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@endcode
47ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
48ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaR turns out to be a sparse 16x8 matrix with the following non-zero
49ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptaentries:
50ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@code
51ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    R[k][k+4]        =  1,   k = 0..3
52ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    R[k][abs(12-k)]  = -1,   k = 5..15
53ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@endcode
54ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
55ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaThe spec describes computing V[0..15] as N * R.
56ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@code
57ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[0..15] = N * R = (R * C2) * R = R * (C2 * R)
58ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@endcode
59ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
60ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaC2 * R corresponds to computing the discrete cosine transform of R, so
61ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaV[0..15] can be computed by taking the DCT of R followed by assignment
62ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptaand selective negation of the DCT result into V.
63ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
64ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta        Although this was derived empirically using GNU Octave, it is
65ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta        formally demonstrated in, e.g., Liu, Chi-Min and Lee,
66ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta        Wen-Chieh. "A Unified Fast Algorithm for Cosine Modulated
67ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta        Filter Banks in Current Audio Coding Standards." Journal of
68ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta        the AES 47 (December 1999): 1061.
69ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
70ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaGiven the shift operation performed prior to computing V[0..15], it is
71ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptaclear that V[0..159] represents a rolling history of the 10 most
72ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptarecent groups of blocks input to the synthesis operation. Interpreting
73ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptathe matrix N in light of its factorization into C2 and R, R's
74ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptasparseness has implications for interpreting the values in V. In
75ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptaparticular, there is considerable redundancy in the values stored in
76ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaV. Furthermore, since R[4][0..7] are all zeros, one out of every 16
77ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptavalues in V will be zero regardless of the input data. Within each
78ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptablock of 16 values in V, fully half of them are redundant or
79ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptairrelevant:
80ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
81ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@code
82ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[ 0] =  DCT[4]
83ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[ 1] =  DCT[5]
84ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[ 2] =  DCT[6]
85ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[ 3] =  DCT[7]
86ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[ 4] = 0
87ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[ 5] = -DCT[7] = -V[3] (redundant)
88ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[ 6] = -DCT[6] = -V[2] (redundant)
89ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[ 7] = -DCT[5] = -V[1] (redundant)
90ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[ 8] = -DCT[4] = -V[0] (redundant)
91ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[ 9] = -DCT[3]
92ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[10] = -DCT[2]
93ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[11] = -DCT[1]
94ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[12] = -DCT[0]
95ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[13] = -DCT[1] = V[11] (redundant)
96ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[14] = -DCT[2] = V[10] (redundant)
97ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    V[15] = -DCT[3] = V[ 9] (redundant)
98ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@endcode
99ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
100ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaSince the elements of V beyond 15 were originally computed the same
101ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptaway during a previous run, what holds true for V[x] also holds true
102ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptafor V[x+16]. Thus, so long as care is taken to maintain the mapping,
103ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptawe need only actually store the unique values, which correspond to the
104ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptaoutput of the DCT, in some cases inverted. In fact, instead of storing
105ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaV[0..159], we could store DCT[0..79] which would contain a history of
106ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaDCT results. More on this in a bit.
107ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
108ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaGoing back to figure 12.3 in the spec, it should be clear that the
109ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptavector U need not actually be explicitly constructed, but that with
110ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptasuitable indexing into V during the window operation, the same end can
111ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptabe accomplished. In the same spirit of the pseudocode shown in the
112ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptafigure, the following is the construction of W without using U:
113ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
114ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@code
115ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    for i=0 to 79 do
116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        W[i] = D[i]*VSIGN(i)*V[remap_V(i)] where remap_V(i) = 32*(int(i/16)) +
117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson(i % 16) + (i % 16 >= 8 ? 16 : 0)
118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                             and VSIGN(i) maps i%16 into {1, 1,
119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson1, 1, 0, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1 }
120ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta                                             These values correspond to the
121ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta                                             signs of the redundant values as
122ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta                                             shown in the explanation three
123ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta                                             paragraphs above.
124ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@endcode
125ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
126ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaWe saw above how V[4..8,13..15] (and by extension
127ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaV[(4..8,13..15)+16*n]) can be defined in terms of other elements
128ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptawithin the subblock of V. V[0..3,9..12] correspond to DCT elements.
129ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
130ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@code
131ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    for i=0 to 79 do
132ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta        W[i] = D[i]*DSIGN(i)*DCT[remap_DCT(i)]
133ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@endcode
134ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
135ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaThe DCT is calculated using the Arai-Agui-Nakajima factorization,
136ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptawhich saves some computation by producing output that needs to be
137ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptamultiplied by scaling factors before being used.
138ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
139ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@code
140ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    for i=0 to 79 do
141ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta        W[i] = D[i]*SCALE[i%8]*AAN_DCT[remap_DCT(i)]
142ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@endcode
143ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
144ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaD can be premultiplied with the DCT scaling factors to yield
145ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
146ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@code
147ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    for i=0 to 79 do
148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        W[i] = DSCALED[i]*AAN_DCT[remap_DCT(i)] where DSCALED[i] =
149911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonD[i]*SCALE[i%8]
150ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@endcode
151ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
152ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant GuptaThe output samples X[0..7] are defined as sums of W:
153ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
154ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@code
155ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta        X[j] = sum{i=0..9}(W[j+8*i])
156ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@endcode
157ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
158ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@ingroup codec_internal
159ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta*/
160ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
161ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta/**
162ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@addtogroup codec_internal
163ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@{
164ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta*/
165ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
166ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include "oi_codec_sbc_private.h"
167ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
168a239d20e95238c37d02121abb49b14d433c5afc2Jakub Pawlowskiconst int32_t dec_window_4[21] = {
169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    0,      /* +0.00000000E+00 */
170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    97,     /* +5.36548976E-04 */
171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    270,    /* +1.49188357E-03 */
172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    495,    /* +2.73370904E-03 */
173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    694,    /* +3.83720193E-03 */
174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    704,    /* +3.89205149E-03 */
175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    338,    /* +1.86581691E-03 */
176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    -554,   /* -3.06012286E-03 */
177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    1974,   /* +1.09137620E-02 */
178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    3697,   /* +2.04385087E-02 */
179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    5224,   /* +2.88757392E-02 */
180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    5824,   /* +3.21939290E-02 */
181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    4681,   /* +2.58767811E-02 */
182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    1109,   /* +6.13245186E-03 */
183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    -5214,  /* -2.88217274E-02 */
184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    -14047, /* -7.76463494E-02 */
185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    24529,  /* +1.35593274E-01 */
186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    35274,  /* +1.94987841E-01 */
187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    44618,  /* +2.46636662E-01 */
188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    50984,  /* +2.81828203E-01 */
189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    53243,  /* +2.94315332E-01 */
190ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta};
191ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define DCTII_4_K06_FIX (11585) /* S1.14      11585   0.707107*/
193ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define DCTII_4_K08_FIX (21407) /* S1.14      21407   1.306563*/
195ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define DCTII_4_K09_FIX (-15137) /* S1.14     -15137  -0.923880*/
197ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define DCTII_4_K10_FIX (-8867) /* S1.14      -8867  -0.541196*/
199ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
200ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta/** Scales x by y bits to the right, adding a rounding factor.
201ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta */
202ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#ifndef SCALE
203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define SCALE(x, y) (((x) + (1 << ((y)-1))) >> (y))
204ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#endif
205ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
206ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#ifndef CLIP_INT16
207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define CLIP_INT16(x)                \
208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  do {                               \
209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((x) > OI_INT16_MAX) {        \
210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (x) = OI_INT16_MAX;            \
211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if ((x) < OI_INT16_MIN) { \
212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (x) = OI_INT16_MIN;            \
213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }                                \
214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } while (0)
215ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#endif
216ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
217ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta/**
218ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta * Default C language implementation of a 16x32->32 multiply. This function may
219ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta * be replaced by a platform-specific version for speed.
220ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta *
221ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta * @param u A signed 16-bit multiplicand
222ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta * @param v A signed 32-bit multiplier
223ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
224ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta * @return  A signed 32-bit value corresponding to the 32 most significant bits
225ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta * of the 48-bit product of u and v.
226ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta */
227911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonINLINE int32_t default_mul_16s_32s_hi(int16_t u, int32_t v) {
228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t v0;
229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int16_t v1;
230ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int32_t w, x;
232ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  v0 = (uint16_t)(v & 0xffff);
234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  v1 = (int16_t)(v >> 16);
235ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  w = v1 * u;
237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  x = u * v0;
238ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return w + (x >> 16);
240ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta}
241ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
242ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#define MUL_16S_32S_HI(_x, _y) default_mul_16s_32s_hi(_x, _y)
243ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define LONG_MULT_DCT(K, sample) (MUL_16S_32S_HI(K, sample) << 2)
245ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
246911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonPRIVATE void SynthWindow80_generated(int16_t* pcm,
247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                     SBC_BUFFER_T const* RESTRICT buffer,
248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                     OI_UINT strideShift);
249911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonPRIVATE void SynthWindow112_generated(int16_t* pcm,
250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                      SBC_BUFFER_T const* RESTRICT buffer,
251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                      OI_UINT strideShift);
252911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonPRIVATE void dct2_8(SBC_BUFFER_T* RESTRICT out, int32_t const* RESTRICT x);
253ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsontypedef void (*SYNTH_FRAME)(OI_CODEC_SBC_DECODER_CONTEXT* context, int16_t* pcm,
255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            OI_UINT blkstart, OI_UINT blkcount);
256ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
257ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#ifndef COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS
258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(dest, src) \
259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  do {                                                      \
260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    shift_buffer(dest, src, 72);                            \
261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } while (0)
262ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#endif
263ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
264ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#ifndef DCT2_8
265ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#define DCT2_8(dst, src) dct2_8(dst, src)
266ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#endif
267ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
268ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#ifndef SYNTH80
269ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#define SYNTH80 SynthWindow80_generated
270ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#endif
271ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
272ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#ifndef SYNTH112
273ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#define SYNTH112 SynthWindow112_generated
274ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#endif
275ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
276911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonPRIVATE void OI_SBC_SynthFrame_80(OI_CODEC_SBC_DECODER_CONTEXT* context,
277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                  int16_t* pcm, OI_UINT blkstart,
278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                  OI_UINT blkcount) {
279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT blk;
280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT ch;
281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT nrof_channels = context->common.frameInfo.nrof_channels;
282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT pcmStrideShift = context->common.pcmStride == 1 ? 0 : 1;
283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT offset = context->common.filterBufferOffset;
284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int32_t* s = context->common.subdata + 8 * nrof_channels * blkstart;
285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT blkstop = blkstart + blkcount;
286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (blk = blkstart; blk < blkstop; blk++) {
288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (offset == 0) {
289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(
290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          context->common.filterBuffer[0] + context->common.filterBufferLen -
291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              72,
292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          context->common.filterBuffer[0]);
293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (nrof_channels == 2) {
294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(
295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            context->common.filterBuffer[1] + context->common.filterBufferLen -
296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                72,
297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            context->common.filterBuffer[1]);
298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      offset = context->common.filterBufferLen - 80;
300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      offset -= 1 * 8;
302ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    }
303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (ch = 0; ch < nrof_channels; ch++) {
305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      DCT2_8(context->common.filterBuffer[ch] + offset, s);
306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      SYNTH80(pcm + ch, context->common.filterBuffer[ch] + offset,
307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              pcmStrideShift);
308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      s += 8;
309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    pcm += (8 << pcmStrideShift);
311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  context->common.filterBufferOffset = offset;
313ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta}
314ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
315911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonPRIVATE void OI_SBC_SynthFrame_4SB(OI_CODEC_SBC_DECODER_CONTEXT* context,
316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                   int16_t* pcm, OI_UINT blkstart,
317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                   OI_UINT blkcount) {
318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT blk;
319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT ch;
320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT nrof_channels = context->common.frameInfo.nrof_channels;
321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT pcmStrideShift = context->common.pcmStride == 1 ? 0 : 1;
322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT offset = context->common.filterBufferOffset;
323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int32_t* s = context->common.subdata + 8 * nrof_channels * blkstart;
324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT blkstop = blkstart + blkcount;
325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (blk = blkstart; blk < blkstop; blk++) {
327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (offset == 0) {
328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(
329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          context->common.filterBuffer[0] + context->common.filterBufferLen -
330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              72,
331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          context->common.filterBuffer[0]);
332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (nrof_channels == 2) {
333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(
334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            context->common.filterBuffer[1] + context->common.filterBufferLen -
335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                72,
336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            context->common.filterBuffer[1]);
337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      offset = context->common.filterBufferLen - 80;
339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      offset -= 8;
341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (ch = 0; ch < nrof_channels; ch++) {
343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      cosineModulateSynth4(context->common.filterBuffer[ch] + offset, s);
344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      SynthWindow40_int32_int32_symmetry_with_sum(
345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          pcm + ch, context->common.filterBuffer[ch] + offset, pcmStrideShift);
346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      s += 4;
347ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    }
348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    pcm += (4 << pcmStrideShift);
349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  context->common.filterBufferOffset = offset;
351ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta}
352ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
353ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#ifdef SBC_ENHANCED
354ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
355911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonPRIVATE void OI_SBC_SynthFrame_Enhanced(OI_CODEC_SBC_DECODER_CONTEXT* context,
356911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                        int16_t* pcm, OI_UINT blkstart,
357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                        OI_UINT blkcount) {
358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT blk;
359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT ch;
360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT nrof_channels = context->common.frameInfo.nrof_channels;
361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT pcmStrideShift = context->common.pcmStride == 1 ? 0 : 1;
362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT offset = context->common.filterBufferOffset;
363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int32_t* s = context->common.subdata + 8 * nrof_channels * blkstart;
364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT blkstop = blkstart + blkcount;
365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (blk = blkstart; blk < blkstop; blk++) {
367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (offset == 0) {
368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      COPY_BACKWARD_32BIT_ALIGNED_104_HALFWORDS(
369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          context->common.filterBuffer[0] + context->common.filterBufferLen -
370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              104,
371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          context->common.filterBuffer[0]);
372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (nrof_channels == 2) {
373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        COPY_BACKWARD_32BIT_ALIGNED_104_HALFWORDS(
374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            context->common.filterBuffer[1] + context->common.filterBufferLen -
375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                104,
376911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            context->common.filterBuffer[1]);
377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      offset = context->common.filterBufferLen - 112;
379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      offset -= 8;
381ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    }
382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (ch = 0; ch < nrof_channels; ++ch) {
383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      DCT2_8(context->common.filterBuffer[ch] + offset, s);
384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      SYNTH112(pcm + ch, context->common.filterBuffer[ch] + offset,
385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               pcmStrideShift);
386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      s += 8;
387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    pcm += (8 << pcmStrideShift);
389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  context->common.filterBufferOffset = offset;
391ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta}
392ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
393ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptastatic const SYNTH_FRAME SynthFrameEnhanced[] = {
394ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    NULL,                       /* invalid */
395ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    OI_SBC_SynthFrame_Enhanced, /* mono */
396ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    OI_SBC_SynthFrame_Enhanced  /* stereo */
397ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta};
398ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
399ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#endif
400ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
401ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptastatic const SYNTH_FRAME SynthFrame8SB[] = {
402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    NULL,                 /* invalid */
403ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    OI_SBC_SynthFrame_80, /* mono */
404ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    OI_SBC_SynthFrame_80  /* stereo */
405ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta};
406ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
407ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptastatic const SYNTH_FRAME SynthFrame4SB[] = {
408ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    NULL,                  /* invalid */
409ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    OI_SBC_SynthFrame_4SB, /* mono */
410ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta    OI_SBC_SynthFrame_4SB  /* stereo */
411ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta};
412ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
413911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonPRIVATE void OI_SBC_SynthFrame(OI_CODEC_SBC_DECODER_CONTEXT* context,
414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               int16_t* pcm, OI_UINT start_block,
415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               OI_UINT nrof_blocks) {
416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT nrof_subbands = context->common.frameInfo.nrof_subbands;
417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_UINT nrof_channels = context->common.frameInfo.nrof_channels;
418ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(nrof_subbands == 4 || nrof_subbands == 8);
420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (nrof_subbands == 4) {
421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    SynthFrame4SB[nrof_channels](context, pcm, start_block, nrof_blocks);
422ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#ifdef SBC_ENHANCED
423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (context->common.frameInfo.enhanced) {
424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    SynthFrameEnhanced[nrof_channels](context, pcm, start_block, nrof_blocks);
425ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#endif /* SBC_ENHANCED */
426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    SynthFrame8SB[nrof_channels](context, pcm, start_block, nrof_blocks);
428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
429ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta}
430ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid SynthWindow40_int32_int32_symmetry_with_sum(int16_t* pcm,
432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 SBC_BUFFER_T buffer[80],
433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 OI_UINT strideShift) {
434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int32_t pa;
435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int32_t pb;
436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* These values should be zero, since out[2] of the 4-band cosine modulation
438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * is always zero. */
439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(buffer[2] == 0);
440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(buffer[10] == 0);
441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(buffer[18] == 0);
442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(buffer[26] == 0);
443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(buffer[34] == 0);
444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(buffer[42] == 0);
445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(buffer[50] == 0);
446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(buffer[58] == 0);
447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(buffer[66] == 0);
448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OI_ASSERT(buffer[74] == 0);
449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa = dec_window_4[4] * (buffer[12] + buffer[76]);
451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[8] * (buffer[16] - buffer[64]);
452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[12] * (buffer[28] + buffer[60]);
453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[16] * (buffer[32] - buffer[48]);
454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[20] * buffer[44];
455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa = SCALE(-pa, 15);
456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  CLIP_INT16(pa);
457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pcm[0 << strideShift] = (int16_t)pa;
458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa = dec_window_4[1] * buffer[1];
460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb = dec_window_4[1] * buffer[79];
461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb += dec_window_4[3] * buffer[3];
462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[3] * buffer[77];
463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[5] * buffer[13];
464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb += dec_window_4[5] * buffer[67];
465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb += dec_window_4[7] * buffer[15];
466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[7] * buffer[65];
467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[9] * buffer[17];
468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb += dec_window_4[9] * buffer[63];
469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb += dec_window_4[11] * buffer[19];
470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[11] * buffer[61];
471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[13] * buffer[29];
472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb += dec_window_4[13] * buffer[51];
473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb += dec_window_4[15] * buffer[31];
474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[15] * buffer[49];
475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[17] * buffer[33];
476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb += dec_window_4[17] * buffer[47];
477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb += dec_window_4[19] * buffer[35];
478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[19] * buffer[45];
479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa = SCALE(-pa, 15);
480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  CLIP_INT16(pa);
481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pcm[1 << strideShift] = (int16_t)(pa);
482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pb = SCALE(-pb, 15);
483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  CLIP_INT16(pb);
484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pcm[3 << strideShift] = (int16_t)(pb);
485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa = dec_window_4[2] *
487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (/*buffer[ 2] + */ buffer[78]); /* buffer[ 2] is always zero */
488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[6] *
489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (buffer[14] /* + buffer[66]*/); /* buffer[66] is always zero */
490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[10] *
491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (/*buffer[18] + */ buffer[62]); /* buffer[18] is always zero */
492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[14] *
493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (buffer[30] /* + buffer[50]*/); /* buffer[50] is always zero */
494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa += dec_window_4[18] *
495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (/*buffer[34] + */ buffer[46]); /* buffer[34] is always zero */
496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pa = SCALE(-pa, 15);
497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  CLIP_INT16(pa);
498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pcm[2 << strideShift] = (int16_t)(pa);
499ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta}
500ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
501ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta/**
502ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  This routine implements the cosine modulation matrix for 4-subband
503ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  synthesis. This is called "matrixing" in the SBC specification. This
504ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  matrix, M4,  can be factored into an 8-point Type II Discrete Cosine
505ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  Transform, DCTII_4 and a matrix S4, given here:
506ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
507ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  @code
508ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta        __               __
509ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta       |   0   0   1   0   |
510ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta       |   0   0   0   1   |
511ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta       |   0   0   0   0   |
512ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta       |   0   0   0  -1   |
513ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  S4 = |   0   0  -1   0   |
514ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta       |   0  -1   0   0   |
515ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta       |  -1   0   0   0   |
516ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta       |__ 0  -1   0   0 __|
517ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
518ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  M4 * in = S4 * (DCTII_4 * in)
519ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  @endcode
520ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
521ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  (DCTII_4 * in) is computed using a Fast Cosine Transform. The algorithm
522ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  here is based on an implementation computed by the SPIRAL computer
523ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  algebra system, manually converted to fixed-point arithmetic. S4 can be
524ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  implemented using only assignment and negation.
525ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta  */
526911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonPRIVATE void cosineModulateSynth4(SBC_BUFFER_T* RESTRICT out,
527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                  int32_t const* RESTRICT in) {
528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int32_t f0, f1, f2, f3, f4, f7, f8, f9, f10;
529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int32_t y0, y1, y2, y3;
530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
531911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  f0 = (in[0] - in[3]);
532911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  f1 = (in[0] + in[3]);
533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  f2 = (in[1] - in[2]);
534911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  f3 = (in[1] + in[2]);
535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  f4 = f1 - f3;
537911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  y0 = -SCALE(f1 + f3, DCT_SHIFT);
539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  y2 = -SCALE(LONG_MULT_DCT(DCTII_4_K06_FIX, f4), DCT_SHIFT);
540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  f7 = f0 + f2;
541911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  f8 = LONG_MULT_DCT(DCTII_4_K08_FIX, f0);
542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  f9 = LONG_MULT_DCT(DCTII_4_K09_FIX, f7);
543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  f10 = LONG_MULT_DCT(DCTII_4_K10_FIX, f2);
544911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  y3 = -SCALE(f8 + f9, DCT_SHIFT);
545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  y1 = -SCALE(f10 - f9, DCT_SHIFT);
546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  out[0] = (int16_t)-y2;
548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  out[1] = (int16_t)-y3;
549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  out[2] = (int16_t)0;
550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  out[3] = (int16_t)y3;
551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  out[4] = (int16_t)y2;
552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  out[5] = (int16_t)y1;
553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  out[6] = (int16_t)y0;
554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  out[7] = (int16_t)y1;
555ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta}
556ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta
557ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta/**
558ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta@}
559ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta*/
560