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