/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.restcomm.media.codec.ilbc;
/**
*
* @author oifa yulian
*/
public class CodingFunctions
{
private static final short[] emptyArray=new short[150];
private static final short bestIndexMin=(short)-21299;
private static final short bestIndexMax=(short)21299;
private static final int bestIndexMinI=-21299;
private static final int bestIndexMaxI=21299;
public static void hpInput(EncoderState encoderState,short[] data,int startIndex,int length)
{
short[] ba=Constants.HP_IN_COEFICIENTS;
short[] y=encoderState.getHpiMemY();
short[] x=encoderState.getHpiMemX();
int currIndex=startIndex+length;
int current;
int i;
for (i=startIndex; i<currIndex; i++)
{
current = y[1]*ba[3];
current += y[3]*ba[4];
current = current>>15;
current += y[0]*ba[3];
current += y[2]*ba[4];
current = current<<1;
current += data[i]*ba[0];
current += x[0]*ba[1];
current += x[1]*ba[2];
x[1] = x[0];
x[0] = data[i];
if(current>268431359)
data[i] = Short.MAX_VALUE;
else if(current< -268439552)
data[i] = Short.MIN_VALUE;
else
data[i] = (short)((current + 4096)>>13);
y[2] = y[0];
y[3] = y[1];
if (current>268435455)
current = Integer.MAX_VALUE;
else if (current<-268435456)
current = Integer.MIN_VALUE;
else
current = current<<3;
y[0] = (short)(current >> 16);
y[1] = (short)((current - (y[0]<<16))>>1);
}
}
public static void hpOutput(short[] signal,short[] ba,short[] y,short[] x,short len)
{
int i;
int temp,temp2,tempShift;
for (i=0; i<len; i++)
{
/*
y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2]
+ (-a[1])*y[i-1] + (-a[2])*y[i-2];
*/
temp = y[1]*ba[3]; /* (-a[1])*y[i-1] (low part) */
temp += y[3]*ba[4]; /* (-a[2])*y[i-2] (low part) */
temp = temp>>15;
temp += y[0]*ba[3]; /* (-a[1])*y[i-1] (high part) */
temp += y[2]*ba[4]; /* (-a[2])*y[i-2] (high part) */
temp = temp<<1;
temp += signal[i]*ba[0]; /* b[0]*x[0] */
temp += x[0]*ba[1]; /* b[1]*x[i-1] */
temp += x[1]*ba[2]; /* b[2]*x[i-2] */
/* Update state (input part) */
x[1] = x[0];
x[0] = signal[i];
/* Rounding in Q(12-1), i.e. add 2^10 */
temp2 = temp + 1024;
/* Saturate (to 2^26) so that the HP filtered signal does not overflow */
if(temp2>67108863)
temp2=67108863;
else if(temp2<-67108864)
temp2=-67108864;
/* Convert back to Q0 and multiply with 2 */
signal[i] = (short)(temp2>>11);
/* Update state (filtered part) */
y[2] = y[0];
y[3] = y[1];
/* upshift tmpW32 by 3 with saturation */
if (temp>268435455)
temp = Integer.MAX_VALUE;
else if (temp<-268435456)
temp = Integer.MIN_VALUE;
else
temp = temp<<3;
y[0] = (short)(temp>>16);
tempShift = y[0]<<16;
y[1] = (short)((temp - tempShift)>>1);
}
}
public static void lpcEncode(EncoderState encoderState,EncoderBits encoderBits,short[] synthDenum,int synthDenumIndex,short[] weightDenum,int weightDenumIndex,short[] data,int startIndex)
{
//GC items : lsf,lsfDeq
short[] lsf=new short[20];
short[] lsfDeq=new short[20];
simpleLpcAnalysis(encoderState,lsf,0,data,startIndex);
simpleLsfQ(encoderBits,lsfDeq, 0, lsf, 0);
lsfCheck(lsfDeq , 0, 10);
simpleInterpolateLsf(encoderState,synthDenum, synthDenumIndex, weightDenum, weightDenumIndex, lsf, 0, lsfDeq , 0, 10);
}
public static short[] simpleLpcAnalysis(EncoderState encoderState,short[] lsf,int lsfIndex,short[] data,int startIndex)
{
short[] A=new short[11];
short[] windowedData=new short[240];
short[] rc=new short[10];
int[] R=new int[11];
short[] lpcBuffer=encoderState.getLpcBuffer();
System.arraycopy(data, startIndex, lpcBuffer, 300-encoderState.SIZE, encoderState.SIZE);
int j=0;
BasicFunctions.multWithRightShift(windowedData,0, lpcBuffer,60, Constants.LPC_ASYM_WIN, 0, 240, 15);
autoCorrelation(windowedData,0, 240, 10, R, 0);
windowMultiply(R,0,R,0,Constants.LPC_LAG_WIN, 11);
if (!levinsonDurbin(R, 0, A, 0, rc, 0, 10))
{
A[0]=4096;
for(j=1;j<11;j++)
A[j]=0;
}
BasicFunctions.expand(A,0,A,0,Constants.LPC_CHIRP_SYNT_DENUM,11);
poly2Lsf(lsf,lsfIndex, A,0);
System.arraycopy(lpcBuffer, encoderState.SIZE, lpcBuffer, 0, 300-encoderState.SIZE);
return A;
}
public static void autoCorrelation(short[] input,int inputIndex,int inputLength, int order, int[] result,int resultIndex)
{
int i,j,nBits,scale,currIndex1,currIndex2;
short max=0,tempS;
if (order < 0)
order = inputLength;
for(i=0;i<inputLength;i++)
{
tempS=BasicFunctions.abs(input[inputIndex++]);
if(tempS>max)
max=tempS;
}
inputIndex-=inputLength;
if (max == 0)
scale = 0;
else
{
nBits = BasicFunctions.getSize(inputLength);
tempS = BasicFunctions.norm(max*max);
if (tempS > nBits)
scale = 0;
else
scale = (short)(nBits - tempS);
}
for (i = 0; i < order + 1; i++)
{
result[resultIndex] = 0;
currIndex1=inputIndex;
currIndex2=inputIndex+i;
for (j = inputLength - i; j > 0; j--)
result[resultIndex] += ((input[currIndex1++]*input[currIndex2++])>>scale);
resultIndex++;
}
}
public static void windowMultiply(int[] output,int outputIndex,int[] input,int inputIndex,int[] window,int length)
{
int i;
short xHi,xLow,yHi,yLow;
int nBits = BasicFunctions.norm(input[inputIndex]);
BasicFunctions.bitShiftLeft(input, inputIndex, input, inputIndex,length, nBits);
for (i = 0; i < length; i++)
{
xHi = (short)(input[inputIndex]>>16);
yHi = (short)(window[i]>>16);
xLow = (short)((input[inputIndex++] - (xHi<<16))>>1);
yLow = (short)((window[i] - (yHi<<16))>>1);
output[outputIndex]=(xHi*yHi)<<1;
output[outputIndex]+=(xHi*yLow)>>14;
output[outputIndex++]+=(xLow*yHi)>>14;
}
outputIndex-=length;
BasicFunctions.bitShiftRight(output, outputIndex, output, outputIndex,length, nBits);
}
public static boolean levinsonDurbin(int[] R,int rIndex,short[] A,int aIndex,short[] K,int kIndex,int order)
{
short[] rHi=new short[21];
short[] rLow=new short[21];
short[] aHi=new short[21];
short[] aLow=new short[21];
short[] aUpdHi=new short[21];
short[] aUpdLow=new short[21];
int nBits = BasicFunctions.norm(R[rIndex]);
int alphaExp;
int temp,temp2,temp3;
int i,j;
short tempS,tempS2;
short yHi,yLow,xHi,xLow;
int currIndex=rIndex+order;
for (i = order; i >= 0; i--)
{
temp = R[currIndex--]<<nBits;
rHi[i] = (short)(temp>>16);
rLow[i] = (short)((temp - (rHi[i]<<16))>>1);
}
temp2 = rHi[1]<<16;
temp3 = rLow[1]<<1;
temp2 += temp3;
if(temp2>0)
temp3=temp2;
else
temp3=-temp2;
temp = BasicFunctions.div(temp3, rHi[0], rLow[0]);
if (temp2 > 0)
temp = -temp;
xHi = (short)(temp>>16);
xLow = (short)((temp - (xHi<<16))>>1);
K[kIndex++] = xHi;
temp = temp>>4;
aHi[1] = (short)(temp>>16);
aLow[1] = (short)((temp - (aHi[1]<<16))>>1);
temp=(xHi*xLow) >> 14;
temp+=xHi*xHi;
temp<<=1;
if(temp<0)
temp=0-temp;
temp = Integer.MAX_VALUE - temp;
tempS = (short)(temp>>16);
tempS2 = (short)((temp - (tempS<<16))>>1);
temp=rHi[0]*tempS;
temp+=(rHi[0]*tempS2) >> 15;
temp+=(rLow[0]*tempS) >> 15;
temp <<= 1;
alphaExp = BasicFunctions.norm(temp);
temp = temp<<alphaExp;
yHi = (short)(temp>>16);
yLow = (short)((temp - (yHi<<16))>>1);
for (i = 2; i <= order; i++)
{
temp = 0;
currIndex=i-1;
for (j = 1; j < i; j++)
{
temp2=(rHi[j]*aLow[currIndex]) >> 15;
temp2+=(rLow[j]*aHi[currIndex]) >> 15;
temp+=temp2<<1;
temp+=(rHi[j]*aHi[currIndex]) << 1;
currIndex--;
}
temp = temp<<4;
temp+=rHi[i]<<16;
temp += rLow[i]<<1;
temp2 = Math.abs(temp);
temp3 = BasicFunctions.div(temp2, yHi, yLow);
if (temp > 0)
temp3 = -temp3;
nBits = BasicFunctions.norm(temp3);
if (alphaExp <= nBits || temp3 == 0)
temp3 = temp3<<alphaExp;
else
{
if (temp3 > 0)
temp3 = Integer.MAX_VALUE;
else
temp3 = Integer.MIN_VALUE;
}
xHi = (short)(temp3>>16);
xLow = (short)((temp3 - (xHi<<16))>>1);
K[kIndex++] = xHi;
if (BasicFunctions.abs(xHi) > 32750)
return false; // Unstable filter
currIndex=i-1;
currIndex=i-1;
for (j = 1; j < i; j++)
{
temp=aHi[j]<<16;
temp += aLow[j]<<1;
temp2=(xLow*aHi[currIndex]) >> 15;
temp2+=(xHi*aLow[currIndex]) >> 15;
temp2+=xHi*aHi[currIndex];
temp += temp2 << 1;
aUpdHi[j] = (short)(temp>>16);
aUpdLow[j] = (short)((temp - (aUpdHi[j]<<16))>>1);
currIndex--;
}
temp3 = temp3>>4;
aUpdHi[i] = (short)(temp3>>16);
aUpdLow[i] = (short)((temp3 - (aUpdHi[i]<<16))>>1);
temp = (((xHi*xLow) >> 14) + xHi*xHi) << 1;
if(temp<0)
temp = 0-temp;
temp = Integer.MAX_VALUE - temp;
tempS = (short)(temp>>16);
tempS2 = (short)((temp - (tempS<<16))>>1);
temp2=(yHi*tempS2) >> 15;
temp2+=(yLow*tempS) >> 15;
temp2+=yHi*tempS;
temp=temp2<<1;
nBits = BasicFunctions.norm(temp);
temp = temp<<nBits;
yHi = (short)(temp>>16);
yLow = (short)((temp - (yHi<<16))>>1);
alphaExp = (short)(alphaExp + nBits);
for (j = 1; j <= i; j++)
{
aHi[j] = aUpdHi[j];
aLow[j] = aUpdLow[j];
}
}
A[aIndex++] = 4096;
for (i = 1; i <= order; i++)
{
temp=aHi[i]<<16;
temp +=aLow[i]<<1;
temp<<=1;
temp+=32768;
A[aIndex++] = (short)(temp>>16);
}
return true;
}
public static void simpleInterpolateLsf(EncoderState encoderState,short[] synthdenum,int synthDenumIndex,short[] weightDenum,int weightDenumIndex,short[] lsf,int lsfIndex,short[] lsfDeq,int lsfDeqIndex,int length)
{
short[] lsfOld=encoderState.getLsfOld();
short[] lsfDeqOld=encoderState.getLsfDeqOld();
short[] lp=new short[11];
int step=length + 1;
int index = 0;
int i;
for (i = 0; i < encoderState.SUBFRAMES; i++)
{
lsfInterpolate2PolyEnc(lp, (short)0 ,lsfDeqOld, 0, lsfDeq, lsfDeqIndex , Constants.LSF_WEIGHT_20MS[i], length);
System.arraycopy(lp, 0, synthdenum, synthDenumIndex + index, step);
lsfInterpolate2PolyEnc(lp, (short)0 , lsfOld, 0, lsf, lsfIndex, Constants.LSF_WEIGHT_20MS[i], length);
BasicFunctions.expand(weightDenum,weightDenumIndex + index,lp,0,Constants.LPC_CHIRP_WEIGHT_DENUM,step);
index += step;
}
System.arraycopy(lsf, lsfIndex, lsfOld, 0, length);
System.arraycopy(lsfDeq, lsfDeqIndex, lsfDeqOld, 0, length);
}
public static void lsfInterpolate2PolyEnc(short[] a, short aIndex, short[] lsf1, int lsf1Index, short[] lsf2, int lsf2Index, short coef, int length)
{
//GC items : lsfTemp
short[] lsfTemp=new short[10];
interpolate(lsfTemp, 0, lsf1, lsf1Index, lsf2, lsf2Index, coef, length);
lsf2Poly(a, aIndex, lsfTemp, 0);
}
public static void interpolate(short[] out,int outIndex,short[] in1,int in1Index,short[] in2,int in2Index,short coef,int length)
{
int k;
short tempS = (short)(16384 - coef);
for (k = 0; k < length; k++)
out[outIndex++] = (short) ((coef*in1[in1Index++] + tempS*in2[in2Index++]+8192)>>14);
}
public static void lsf2Poly(short[] a,int aIndex,short[] lsf,int lsfIndex)
{
int k;
//GC items : f1,f2
int[] f1=new int[6];
int[] f2=new int[6];
short[] lsp=new short[10];
lsf2Lsp(lsf, lsfIndex, lsp, 0, 10);
getLspPoly(lsp, 0, f1, 0);
getLspPoly(lsp, 1, f2, 0);
for (k=5; k>0; k--)
{
f1[k]+=f1[k-1];
f2[k]-=f2[k-1];
}
a[aIndex]=4096;
int aStartIndex=aIndex+1;
int aEndIndex=aIndex+10;
int currIndex=1;
for (k=5; k>0; k--)
{
a[aStartIndex++] = (short)(((f1[currIndex] + f2[currIndex])+4096)>>13);
a[aEndIndex--] = (short)(((f1[currIndex] - f2[currIndex])+4096)>>13);
currIndex++;
}
}
public static void lsf2Lsp(short[] lsf,int lsfIndex,short[] lsp,int lspIndex,int count)
{
int j;
short tempS,tempS2;
for(j=0; j<count; j++)
{
tempS = (short)((lsf[lsfIndex++]*20861)>>15);
tempS2 = (short)(tempS>>8);
tempS = (short)(tempS & 0x00ff);
if (tempS2>63 || tempS2<0)
tempS2 = 63;
lsp[lspIndex++] = (short)(((Constants.COS_DERIVATIVE[tempS2]*tempS)>>12) + Constants.COS[tempS2]);
}
}
public static void getLspPoly(short[] lsp,int lspIndex,int[] f,int fIndex)
{
int j,k;
short xHi,xLow;
f[fIndex++]=16777216;
f[fIndex++] = lsp[lspIndex]*(-1024);
lspIndex+=2;
for(k=2; k<=5; k++)
{
f[fIndex]=f[fIndex-2];
for(j=k; j>1; j--)
{
xHi = (short)(f[fIndex-1]>>16);
xLow = (short)((f[fIndex-1]-(xHi<<16))>>1);
f[fIndex] += f[fIndex-2];
f[fIndex--] -= ((xHi*lsp[lspIndex])<<2) + (((xLow*lsp[lspIndex])>>15)<<2);
}
f[fIndex] -= lsp[lspIndex]<< 10;
fIndex+=k;
lspIndex+=2;
}
}
public static void poly2Lsf(short[] lsf,int lsfIndex,short[] A,int aIndex)
{
//GC : lsp
short[] lsp=new short[10];
poly2Lsp(A, aIndex, lsp, 0);
lspToLsf(lsp, 0,lsf, lsfIndex, 10);
}
public static void poly2Lsp(short[] A,int aIndex,short[] lsp,int lspIndex)
{
short[] f1=new short[6];
short[] f2=new short[6];
short xMid,xLow,xHi,yMid,yLow,yHi,x,y;
int temp;
int i,j;
int nBits;
int aLowIndex=aIndex + 1;
int aHighIndex=aIndex + 10;
f1[0]=1024;
f2[0]=1024;
for (i = 0; i < 5; i++)
{
f1[i+1] = (short)(((A[aLowIndex] + A[aHighIndex])>>2) - f1[i]);
f2[i+1] = (short)(((A[aLowIndex] - A[aHighIndex])>>2) + f2[i]);
aLowIndex++;
aHighIndex--;
}
short[] current=f1;
int currIndex = lspIndex;
int foundFreqs = 0;
xLow = Constants.COS_GRID[0];
yLow = chebushev(xLow, current, 0);
for (j = 1; j < Constants.COS_GRID.length && foundFreqs < 10; j++)
{
xHi = xLow;
yHi = yLow;
xLow = Constants.COS_GRID[j];
yLow = chebushev(xLow, current, 0);
if (yLow*yHi <= 0)
{
for (i = 0; i < 4; i++)
{
xMid = (short)((xLow>>1) + (xHi>>1));
yMid = chebushev(xMid, current, 0);
if (yLow*yMid <= 0)
{
yHi = yMid;
xHi = xMid;
}
else
{
yLow = yMid;
xLow = xMid;
}
}
x = (short)(xHi - xLow);
y = (short)(yHi - yLow);
if (y == 0)
lsp[currIndex++] = xLow;
else
{
temp = y;
y = BasicFunctions.abs(y);
nBits = (short)(BasicFunctions.norm(y)-16);
y = (short)(y<<nBits);
if (y != 0)
y=(short)(536838144 / y);
else
y=(short)Integer.MAX_VALUE;
y = (short)(((x*y)>>(19-nBits))&0xFFFF);
if (temp < 0)
y = (short)-y;
lsp[currIndex++] = (short)(xLow-(((yLow*y)>>10)&0xFFFF));
}
foundFreqs++;
if (foundFreqs<10)
{
xLow = lsp[currIndex-1];
if((foundFreqs%2)==0)
current=f1;
else
current=f2;
yLow = chebushev(xLow, current, 0);
}
}
}
if (foundFreqs < 10)
System.arraycopy(Constants.LSP_MEAN, 0, lsp, lspIndex, 10);
}
public static short chebushev(short value,short[] coefs,int coefsIndex)
{
int n,b2;
short b1Hi,b1Low;
int temp,temp2;
b2 = 0x1000000;
temp = value<<10;
coefsIndex++;
temp += coefs[coefsIndex++]<<14;
for (n = 2; n < 5; n++)
{
temp2 = temp;
b1Hi = (short)(temp>>16);
b1Low = (short)((temp-(b1Hi<<16))>>1);
temp=(((b1Low*value)>>15) + (b1Hi*value))<<2;
temp -= b2;
temp += coefs[coefsIndex++]<<14;
b2 = temp2;
}
b1Hi = (short)(temp>>16);
b1Low = (short)((temp-(b1Hi<<16))>>1);
temp=(((b1Low*value)>>15)<<1) + ((b1Hi*value)<<1);
temp -= b2;
temp += coefs[coefsIndex]<<13;
if (temp>33553408)
return Short.MAX_VALUE;
else if (temp<-33554432)
return Short.MIN_VALUE;
else
return (short)(temp>>10);
}
public static void lspToLsf(short[] lsp, int lspIndex,short[] lsf,int lsfIndex,int coefsNumber)
{
int i;
int j = 63;
int currValue;
int currLspIndex=lspIndex+coefsNumber-1;
int currLsfIndex=lsfIndex+coefsNumber-1;
for(i=coefsNumber-1; i>=0; i--)
{
while(Constants.COS[j]<lsp[currLspIndex] && j>0)
j--;
currValue = (j<<9)+((Constants.ACOS_DERIVATIVE[j]*(lsp[currLspIndex--]-Constants.COS[j]))>>11);
lsf[currLsfIndex--] = (short)((currValue*25736)>>15);
}
}
public static void simpleLsfQ(EncoderBits encoderBits,short[] lsfdeq,int lsfdeqIndex,short[] lsfArray,int lsfArrrayIndex)
{
splitVq(lsfdeq, lsfdeqIndex,encoderBits.getLSF(), 0, lsfArray, lsfArrrayIndex);
}
public static void splitVq(short[] qX,int qXIndex,short[] lsf,int lsfIndex,short[] X,int xIndex)
{
vq3(qX, qXIndex, lsf, lsfIndex, Constants.LSF_INDEX_CB[0], X, xIndex, Constants.LSF_SIZE_CB[0]);
vq3(qX, qXIndex + Constants.LSF_DIM_CB[0], lsf, lsfIndex+1, Constants.LSF_INDEX_CB[1], X, xIndex + Constants.LSF_DIM_CB[0], Constants.LSF_SIZE_CB[1]);
vq4(qX, qXIndex + Constants.LSF_DIM_CB[0] + Constants.LSF_DIM_CB[1], lsf, lsfIndex+2, Constants.LSF_INDEX_CB[2], X, xIndex + Constants.LSF_DIM_CB[0] + Constants.LSF_DIM_CB[1], Constants.LSF_SIZE_CB[2]);
}
public static void vq3(short[] qX,int qXIndex,short[] lsf,int lsfIndex,int cbIndex,short[] X,int xIndex,int cbSize)
{
int minValue = Integer.MAX_VALUE;
int i,j,temp;
short tempS;
int currIndex=0;
for (j = 0; j < cbSize; j++)
{
tempS = (short)(X[xIndex++] - Constants.LSF_CB[cbIndex++]);
temp = tempS*tempS;
tempS = (short)(X[xIndex++] - Constants.LSF_CB[cbIndex++]);
temp+=tempS*tempS;
tempS = (short)(X[xIndex++] - Constants.LSF_CB[cbIndex++]);
temp+=tempS*tempS;
xIndex-=3;
if (temp < minValue)
{
minValue = temp;
currIndex=j;
}
}
cbIndex-=3*cbSize;
lsf[lsfIndex] = (short)currIndex;
currIndex*=3;
currIndex+=cbIndex;
for (i = 0; i < 3; i++)
qX[qXIndex++] = Constants.LSF_CB[currIndex++];
}
public static void vq4(short[] qX,int qXIndex,short[] lsf,int lsfIndex,int cbIndex,short[] X,int xIndex,int cbSize)
{
int minValue = Integer.MAX_VALUE;
int i,j,temp;
short tempS;
int currIndex=0;
for (j = 0; j < cbSize; j++)
{
tempS = (short)(X[xIndex++] - Constants.LSF_CB[cbIndex++]);
temp = tempS*tempS;
for (i = 1; i < 4; i++)
{
tempS = (short)(X[xIndex++] - Constants.LSF_CB[cbIndex++]);
temp += tempS*tempS;
}
xIndex-=4;
if (temp < minValue)
{
minValue = temp;
currIndex=j;
}
}
cbIndex-=4*cbSize;
lsf[lsfIndex] = (short)currIndex;
currIndex*=4;
currIndex+=cbIndex;
for (i = 0; i < 4; i++)
qX[qXIndex++] = Constants.LSF_CB[currIndex++];
}
public static void lsfCheck(short[] lsf,int lsfIndex,int lsfSize)
{
int n,k;
int currIndex1,currIndex2;
for (n=0;n<2;n++)
{
for (k=0;k<lsfSize-1;k++)
{
currIndex1=lsfIndex + k;
currIndex2=currIndex1+1;
if ((lsf[currIndex2]-lsf[currIndex1])<Constants.EPS)
{
if (lsf[currIndex2]<lsf[currIndex1])
{
lsf[currIndex2]= (short)(lsf[currIndex1]+Constants.HALF_EPS);
lsf[currIndex1]= (short)(lsf[currIndex2]-Constants.HALF_EPS);
}
else
{
lsf[currIndex1]-=Constants.HALF_EPS;
lsf[currIndex2]+=Constants.HALF_EPS;
}
}
if (lsf[currIndex1]<Constants.MIN_LSF)
lsf[currIndex1]=Constants.MIN_LSF;
if (lsf[currIndex1]>Constants.MAX_LSF)
lsf[currIndex1]=Constants.MAX_LSF;
}
}
}
public static short gainDequant(short index, short maxIn, short stage)
{
if(maxIn<0)
maxIn=(short)(0-maxIn);
if(maxIn<1638)
maxIn=1638;
return (short)((maxIn*Constants.GAIN[stage][index] +8192)>>14);
}
public static short gainQuant(short gain,short maxIn,short stage,short[] index,int indexIndex)
{
int scale,cbIndex,n,temp,temp2,nBits;
short[] cb;
if(maxIn>1638)
scale = maxIn;
else
scale = 1638;
cb = Constants.GAIN[stage];
temp = gain<<14;
cbIndex=(32>>stage) >> 1;
nBits = (short)cbIndex;
for (n=4-stage;n>0;n--)
{
nBits>>=1;
if (temp > scale*cb[cbIndex])
cbIndex+=nBits;
else
cbIndex-=nBits;
}
temp2=scale*cb[cbIndex];
if (temp>temp2)
{
if ((scale*cb[cbIndex+1]-temp)<(temp-temp2))
cbIndex++;
}
else if ((temp-scale*cb[cbIndex-1])<=(temp2-temp))
cbIndex--;
temp=(32>>stage) - 1;
if(cbIndex>temp)
cbIndex=temp;
index[indexIndex]=(short)cbIndex;
return (short)((scale*cb[cbIndex]+8192)>>14);
}
public static void cbMemEnergyAugmentation(short[] interpSamples, int interpSamplesIndex, short[] cbMem, int cbMemIndex, short scale, short baseSize, short[] energy, int energyIndex, short[] energyShifts, int energyShiftsIndex)
{
energyIndex = energyIndex + baseSize-20;
energyShiftsIndex = energyShiftsIndex + baseSize-20;
cbMemIndex = cbMemIndex + 147;
int en1 = BasicFunctions.scaleRight(cbMem,cbMemIndex-19,cbMem,cbMemIndex-19,15,scale);
int currIndex=cbMemIndex - 20;
int currValue;
int n;
for (n=20; n<=39; n++)
{
en1 += (cbMem[currIndex]*cbMem[currIndex])>>scale;
currIndex--;
currValue = en1;
/* interpolation */
currValue += BasicFunctions.scaleRight(interpSamples,interpSamplesIndex,interpSamples,interpSamplesIndex,4,scale);
interpSamplesIndex += 4;
/* Compute energy for the remaining samples */
currValue += BasicFunctions.scaleRight(cbMem,cbMemIndex - n,cbMem,cbMemIndex - n,40-n,scale);
/* Normalize the energy and store the number of shifts */
energyShifts[energyShiftsIndex] = BasicFunctions.norm(currValue);
currValue = currValue<<energyShifts[energyShiftsIndex++];
energy[energyIndex++] = (short)(currValue>>16);
}
}
public static void cbMemEnergy(short range,short[] cb,int cbIndex,short[] filteredCB,int filteredCbIndex, short length, short targetLength, short[] energy, int energyIndex, short[] energyShifts, int energyShiftsIndex, short scale, short baseSize)
{
int currValue = BasicFunctions.scaleRight(cb, cbIndex + length - targetLength, cb, cbIndex + length - targetLength, targetLength, scale);
energyShifts[energyShiftsIndex] = (short)BasicFunctions.norm(currValue);
energy[energyIndex] = (short)((currValue<<energyShifts[energyShiftsIndex])>>16);
energyCalc(currValue, range, cb, cbIndex + length - targetLength - 1, cb, cbIndex + length - 1, energy, energyIndex, energyShifts, energyShiftsIndex, scale, (short)0);
currValue = BasicFunctions.scaleRight(filteredCB, filteredCbIndex + length - targetLength, filteredCB, filteredCbIndex + length - targetLength, targetLength, scale);
energyShifts[baseSize + energyShiftsIndex]=BasicFunctions.norm(currValue);
energy[baseSize + energyIndex] = (short)((currValue<<energyShifts[baseSize + energyShiftsIndex])>>16);
energyCalc(currValue, range, filteredCB, filteredCbIndex + length - targetLength - 1, filteredCB, filteredCbIndex + length - 1, energy, energyIndex, energyShifts, energyShiftsIndex, scale, baseSize);
}
public static void cbSearch(EncoderState encoderState,EncoderBits encoderBits,CbSearchData searchData,CbUpdateIndexData updateIndexData,short[] inTarget,int inTargetIndex,short[] decResidual,int decResidualIndex,int length,int vectorLength,short[] weightDenum,int weightDenumindex, int blockNumber,int cbIndexIndex,int gainIndexIndex)
{
//GC items : gains,cbBuf,energyShifts,targetVec,cbVectors,codedVec,interpSamples,interSamplesFilt,energy,augVec
short[] cbIndex=encoderBits.getCbIndex();
short[] gainIndex=encoderBits.getGainIndex();
/* Stack based */
short[] gains=new short[4];
short[] cbBuf=new short[161];
short[] energyShifts=new short[256];
short[] targetVec=new short[50];
short[] cbVectors=new short[147];
short[] codedVec=new short[40];
short[] interpSamples=new short[80];
short[] interSamplesFilt=new short[80];
short[] energy=new short[256];
short[] augVec=new short[256];
short[] inverseEnergy=energy;
short[] inverseEnergyShifts=energyShifts;
short[] buf=cbBuf;//+10 length 151
short[] target=targetVec;//+10 length 40
int[] cDot=new int[128];
int[] crit=new int[128];
short[] pp;
int ppIndex,sInd,eInd,targetEner,codedEner,gainResult;
int stage,i,j,nBits;
short scale,scale2;
short range,tempS,tempS2;
short baseSize=(short)(length-vectorLength+1);
if (vectorLength==40)
baseSize=(short)(length-19);
int numberOfZeroes=length-Constants.FILTER_RANGE[blockNumber];
BasicFunctions.filterAR(decResidual, decResidualIndex + numberOfZeroes, buf, 10+numberOfZeroes, weightDenum, weightDenumindex, 11, Constants.FILTER_RANGE[blockNumber]);
System.arraycopy(cbBuf, length, targetVec, 0, 10);
BasicFunctions.filterAR(inTarget, inTargetIndex, target, 10, weightDenum, weightDenumindex, 11, vectorLength);
System.arraycopy(target, 10, codedVec, 0, vectorLength);
int currIndex=10;
tempS=0;
for(i=0;i<length;i++)
{
if(buf[currIndex]>0 && buf[currIndex]>tempS)
tempS=buf[currIndex];
else if((0-buf[currIndex])>tempS)
tempS=(short)(0-buf[currIndex]);
currIndex++;
}
currIndex=10;
tempS2=0;
for(i=0;i<vectorLength;i++)
{
if(target[currIndex]>0 && target[currIndex]>tempS2)
tempS2=target[currIndex];
else if((0-target[currIndex])>tempS2)
tempS2=(short)(0-target[currIndex]);
currIndex++;
}
if ((tempS>0)&&(tempS2>0))
{
if(tempS2>tempS)
tempS = tempS2;
scale = BasicFunctions.getSize(tempS*tempS);
}
else
scale = 30;
scale = (short)(scale - 25);
if(scale<0)
scale=0;
scale2=scale;
targetEner = BasicFunctions.scaleRight(target,10,target,10,vectorLength, scale2);
filteredCBVecs(cbVectors, 0, buf, 10, length,Constants.FILTER_RANGE[blockNumber]);
range = Constants.SEARCH_RANGE[blockNumber][0];
if(vectorLength == 40)
{
interpolateSamples(interpSamples,0,buf,10,length);
interpolateSamples(interSamplesFilt,0,cbVectors,0,length);
cbMemEnergyAugmentation(interpSamples, 0, buf, 10, scale2, (short)20, energy, 0, energyShifts, 0);
cbMemEnergyAugmentation(interSamplesFilt, 0, cbVectors, 0, scale2, (short)(baseSize+20), energy, 0, energyShifts, 0);
cbMemEnergy(range, buf, 10, cbVectors, 0, (short)length, (short)vectorLength, energy, 20, energyShifts, 20, scale2, baseSize);
}
else
cbMemEnergy(range, buf, 10, cbVectors, 0, (short)length, (short)vectorLength, energy, 0, energyShifts, 0, scale2, baseSize);
energyInverse(energy,0,baseSize*2);
gains[0] = 16384;
for (stage=0; stage<3; stage++)
{
range = Constants.SEARCH_RANGE[blockNumber][stage];
/* initialize search measures */
updateIndexData.setCritMax(0);
updateIndexData.setShTotMax((short)-100);
updateIndexData.setBestIndex((short)0);
updateIndexData.setBestGain((short)0);
/* Calculate all the cross correlations (augmented part of CB) */
if (vectorLength==40)
{
augmentCbCorr(target, 10, buf, 10+length, interpSamples, 0, cDot, 0,20, 39, scale2);
currIndex=20;
}
else
currIndex=0;
crossCorrelation(cDot, currIndex, target, 10, buf, 10 + length - vectorLength, (short)vectorLength, range, scale2, (short)-1);
if (vectorLength==40)
range=(short)(Constants.SEARCH_RANGE[blockNumber][stage]+20);
else
range=Constants.SEARCH_RANGE[blockNumber][stage];
cbSearchCore(searchData,cDot, 0, range, (short)stage, inverseEnergy, 0, inverseEnergyShifts, 0, crit, 0);
updateBestIndex(updateIndexData,searchData.getCritNew(),searchData.getCritNewSh(),searchData.getIndexNew(),cDot[searchData.getIndexNew()],inverseEnergy[searchData.getIndexNew()],inverseEnergyShifts[searchData.getIndexNew()]);
sInd=(short)(updateIndexData.getBestIndex()-17);
eInd=(short)(sInd+34);
if (sInd<0)
{
eInd-=sInd;
sInd=0;
}
if (eInd>=range)
{
eInd=(short)(range-1);
sInd=(short)(eInd-34);
}
range = Constants.SEARCH_RANGE[blockNumber][stage];
if (vectorLength==40)
{
i=sInd;
if (sInd<20)
{
if(eInd+20>39)
augmentCbCorr(target, 10, cbVectors, length, interSamplesFilt, 0, cDot, 0, sInd+20, 39, scale2);
else
augmentCbCorr(target, 10, cbVectors, length, interSamplesFilt, 0, cDot, 0, sInd+20, eInd+20, scale2);
i=20;
}
if(20-sInd>0)
currIndex=20-sInd;
else
currIndex=0;
crossCorrelation(cDot, currIndex, target, 10, cbVectors, length - 20 - i, (short)vectorLength, (short)(eInd-i+1), scale2, (short)-1);
}
else
crossCorrelation(cDot, 0, target, 10, cbVectors, length - vectorLength - sInd, (short)vectorLength, (short)(eInd-sInd+1), scale2, (short)-1);
cbSearchCore(searchData,cDot, 0, (short)(eInd-sInd+1), (short)stage, inverseEnergy, baseSize+sInd, inverseEnergyShifts, baseSize+sInd, crit, 0);
updateBestIndex(updateIndexData,searchData.getCritNew(),searchData.getCritNewSh(),(short)(searchData.getIndexNew()+baseSize+sInd),cDot[searchData.getIndexNew()],inverseEnergy[searchData.getIndexNew()+baseSize+sInd],inverseEnergyShifts[searchData.getIndexNew()+baseSize+sInd]);
cbIndex[cbIndexIndex+stage] = updateIndexData.getBestIndex();
if(gains[stage]>0)
updateIndexData.setBestGain(gainQuant(updateIndexData.getBestGain(), gains[stage], (short)stage, gainIndex, gainIndexIndex+stage));
else
updateIndexData.setBestGain(gainQuant(updateIndexData.getBestGain(), (short)(0-gains[stage]), (short)stage, gainIndex, gainIndexIndex+stage));
if(vectorLength == 80-encoderState.STATE_SHORT_LEN)
{
if(cbIndex[cbIndexIndex+stage]<baseSize)
{
pp=buf;
ppIndex = 10+length-vectorLength-cbIndex[cbIndexIndex+stage];
}
else
{
pp=cbVectors;
ppIndex = length-vectorLength- cbIndex[cbIndexIndex+stage]+baseSize;
}
}
else
{
if (cbIndex[cbIndexIndex+stage]<baseSize)
{
if (cbIndex[cbIndexIndex+stage]>=20)
{
cbIndex[cbIndexIndex+stage]-=20;
pp=buf;
ppIndex = 10+length-vectorLength-cbIndex[cbIndexIndex+stage];
}
else
{
cbIndex[cbIndexIndex+stage]+=(baseSize-20);
createAugmentVector((short)(cbIndex[cbIndexIndex+stage]-baseSize+40),buf, 10+length, augVec, 0);
pp=augVec;
ppIndex = 0;
}
}
else
{
if ((cbIndex[cbIndexIndex+stage] - baseSize) >= 20)
{
cbIndex[cbIndexIndex+stage]-=20;
pp=cbVectors;
ppIndex = length-vectorLength- cbIndex[cbIndexIndex+stage]+baseSize;
}
else
{
cbIndex[cbIndexIndex+stage]+=(baseSize-20);
createAugmentVector((short)(cbIndex[cbIndexIndex+stage]-2*baseSize+40),cbVectors, length, augVec, 0);
pp=augVec;
ppIndex = 0;
}
}
}
BasicFunctions.addAffineVectorToVector(target, 10, pp, ppIndex, (short)(0-updateIndexData.getBestGain()), 8192, (short)14, vectorLength);
gains[stage+1] = updateIndexData.getBestGain();
}
currIndex=10;
for (i=0;i<vectorLength;i++)
codedVec[i]-=target[currIndex++];
codedEner = BasicFunctions.scaleRight(codedVec,0,codedVec,0,vectorLength, scale2);
j=gainIndex[gainIndexIndex];
tempS = BasicFunctions.norm(codedEner);
tempS2 = BasicFunctions.norm(targetEner);
if(tempS < tempS2)
nBits = (short)(16 - tempS);
else
nBits = (short)(16 - tempS2);
if(nBits<0)
targetEner = (targetEner<<(0-nBits))*((gains[1]*gains[1])>>14);
else
targetEner = (targetEner>>nBits)*((gains[1]*gains[1])>>14);
gainResult = ((gains[1]-1)<<1);
if(nBits<0)
tempS=(short)(codedEner<<(-nBits));
else
tempS=(short)(codedEner>>nBits);
for (i=gainIndex[gainIndexIndex];i<32;i++)
{
if ((tempS*Constants.GAIN_SQ5_SQ[i] - targetEner) < 0 && Constants.GAIN_SQ5[j] < gainResult)
j=i;
}
gainIndex[gainIndexIndex]=(short)j;
}
public static void cbSearchCore(CbSearchData searchData,int[] cDot, int cDotIndex, short range, short stage, short[] inverseEnergy, int inverseEnergyIndex, short[] inverseEnergyShift, int inverseEnergyShiftIndex, int[] crit, int critIndex)
{
int n,current,nBits,maxCrit;
short max,tempS;
if (stage==0)
{
for (n=0;n<range;n++)
{
if(cDot[cDotIndex]<0)
cDot[cDotIndex]=0;
cDotIndex++;
}
cDotIndex-=range;
}
current=0;
for(n=0;n<range;n++)
{
if(cDot[cDotIndex]>0 && cDot[cDotIndex]>current)
current=cDot[cDotIndex];
else if((0-cDot[cDotIndex])>current)
current=0-cDot[cDotIndex];
cDotIndex++;
}
cDotIndex-=range;
nBits=BasicFunctions.norm(current);
max=Short.MIN_VALUE;
for (n=0;n<range;n++)
{
tempS = (short)((cDot[cDotIndex++]<<nBits)>>16);
crit[critIndex]=((tempS*tempS)>>16)*inverseEnergy[inverseEnergyIndex++];
if (crit[critIndex]!=0 && inverseEnergyShift[inverseEnergyShiftIndex]>max)
max = inverseEnergyShift[inverseEnergyShiftIndex];
inverseEnergyShiftIndex++;
critIndex++;
}
if (max==Short.MIN_VALUE)
max = 0;
critIndex-=range;
inverseEnergyShiftIndex-=range;
for (n=0;n<range;n++)
{
if(max-inverseEnergyShift[inverseEnergyShiftIndex]>16)
crit[critIndex]=crit[critIndex]>>16;
else
{
tempS = (short)(max-inverseEnergyShift[inverseEnergyShiftIndex]);
if(tempS<0)
crit[critIndex]<<=-tempS;
else
crit[critIndex]>>=tempS;
}
inverseEnergyShiftIndex++;
critIndex++;
}
critIndex-=range;
maxCrit=crit[critIndex];
critIndex++;
searchData.setIndexNew((short)0);
for(n=1;n<range;n++)
{
if(crit[critIndex]>maxCrit)
{
maxCrit=crit[critIndex];
searchData.setIndexNew((short)n);
}
critIndex++;
}
searchData.setCritNew(maxCrit);
searchData.setCritNewSh((short)(32 - 2*nBits + max));
}
public static void cbConstruct(EncoderBits encoderBits,short[] decVector,int decVectorIndex,short[] mem,int memIndex,short length,short vectorLength,int cbIndexIndex,int gainIndexIndex)
{
//GC items : gain,cbVec0,cbVec1,cbVec2
short[] cbIndex=encoderBits.getCbIndex();
short[] gainIndex=encoderBits.getGainIndex();
short gain[]=new short[3];
short cbVec0[]=new short[40];
short cbVec1[]=new short[40];
short cbVec2[]=new short[40];
int i;
gain[0] = gainDequant(gainIndex[gainIndexIndex], (short)16384, (short)0);
gain[1] = gainDequant(gainIndex[gainIndexIndex+1], (short)gain[0], (short)1);
gain[2] = gainDequant(gainIndex[gainIndexIndex+2], (short)gain[1], (short)2);
System.arraycopy(emptyArray, 0, cbVec0, 0, 40);
System.arraycopy(emptyArray, 0, cbVec1, 0, 40);
System.arraycopy(emptyArray, 0, cbVec2, 0, 40);
getCbVec(cbVec0, 0, mem, memIndex, cbIndex[cbIndexIndex], length, vectorLength);
getCbVec(cbVec1, 0, mem, memIndex, cbIndex[cbIndexIndex+1], length, vectorLength);
getCbVec(cbVec2, 0, mem, memIndex, cbIndex[cbIndexIndex+2], length, vectorLength);
for(i=0;i<vectorLength;i++)
decVector[decVectorIndex++]=(short)((gain[0]*cbVec0[i] + gain[1]*cbVec1[i] + gain[2]*cbVec2[i] + 8192)>>14);
}
public static void stateSearch(EncoderState encoderState,EncoderBits encoderBits,short[] residual,int residualIndex,short[] syntDenum,int syntIndex,short[] weightDenum,int weightIndex)
{
//GC items : numerator,residualLongVec,sampleMa
short[] numerator=new short[11];
short[] residualLongVec=new short[126];
short[] sampleMa=new short[116];
short[] residualLong=residualLongVec; //+ 10 length 116
short[] sampleAr=residualLongVec; //+ 10 length 116
int nBits,n,currIndex,temp;
short max=0,tempS,tempS2;
for(n=0;n<encoderState.STATE_SHORT_LEN;n++)
{
tempS=residual[residualIndex++];
if(tempS<0)
tempS=(short)(0-tempS);
if(tempS>max)
max=tempS;
}
tempS = (short)(BasicFunctions.getSize(max)-12);
if(tempS<0)
tempS = 0;
currIndex=syntIndex+10;
for (n=0; n<11; n++)
numerator[n] = (short)(syntDenum[currIndex--]>>tempS);
residualIndex-=encoderState.STATE_SHORT_LEN;
System.arraycopy(residual, residualIndex, residualLong, 10, encoderState.STATE_SHORT_LEN);
System.arraycopy(emptyArray, 0, residualLong, 10+encoderState.STATE_SHORT_LEN, encoderState.STATE_SHORT_LEN);
System.arraycopy(emptyArray, 0, residualLongVec, 0, 10);
BasicFunctions.filterMA(residualLong,10,sampleMa,0,numerator,0,11,encoderState.STATE_SHORT_LEN+10);
System.arraycopy(emptyArray, 0, sampleMa, encoderState.STATE_SHORT_LEN + 10, encoderState.STATE_SHORT_LEN-10);
BasicFunctions.filterAR(sampleMa,0,sampleAr,10,syntDenum,syntIndex,11,2*encoderState.STATE_SHORT_LEN);
int arIndex=10;
int arIndex2=10+encoderState.STATE_SHORT_LEN;
for(n=0;n<encoderState.STATE_SHORT_LEN;n++)
sampleAr[arIndex++] += sampleAr[arIndex2++];
max=0;
arIndex=10;
for(n=0;n<encoderState.STATE_SHORT_LEN;n++)
{
tempS2=sampleAr[arIndex++];
if(tempS2<0)
tempS2=(short)(0-tempS2);
if(tempS2>max)
max=tempS2;
}
/* Find the best index */
if ((max<<tempS)<23170)
temp=(max*max)<<(2+2*tempS);
else
temp=Integer.MAX_VALUE;
currIndex=0;
for (n=0;n<63;n++)
{
if (temp>=Constants.CHOOSE_FRG_QUANT[n])
currIndex=n+1;
else
n=63;
}
encoderBits.setIdxForMax((short)currIndex);
if (currIndex<27)
nBits=4;
else
nBits=9;
BasicFunctions.scaleVector(sampleAr, 10, sampleAr, 10, Constants.SCALE[currIndex], encoderState.STATE_SHORT_LEN, nBits-tempS);
absQuant(encoderBits,sampleAr, 10, weightDenum, weightIndex);
}
public static void stateConstruct(EncoderBits encoderBits,short[] syntDenum,int syntDenumIndex,short[] outFix,int outFixIndex,int stateLen)
{
//GC items : numerator,sampleValVec,sampleMaVec
short[] numerator=new short[11];
short[] sampleValVec=new short[126];
short[] sampleMaVec=new short[126];
short[] sampleVal=sampleValVec; //+10 length 116
short[] sampleMa=sampleMaVec; //+10 length 116;
short[] sampleAr=sampleValVec; //+10 length 116;
short[] idxVec=encoderBits.getIdxVec();
int coef,bitShift,currIndex,currIndex2;
int k;
currIndex=syntDenumIndex+10;
for (k=0; k<11; k++)
numerator[k] = syntDenum[currIndex--];
int max = Constants.FRQ_QUANT_MOD[encoderBits.getIdxForMax()];
if (encoderBits.getIdxForMax()<37)
{
coef=2097152;
bitShift=22;
}
else if (encoderBits.getIdxForMax()<59)
{
coef=262144;
bitShift=19;
}
else
{
coef=65536;
bitShift=17;
}
currIndex=10;
currIndex2 = stateLen-1;
for(k=0; k<stateLen; k++)
sampleVal[currIndex++]=(short) ((max*Constants.STATE_SQ3[idxVec[currIndex2--]]+coef) >> bitShift);
System.arraycopy(emptyArray, 0, sampleVal, 10+stateLen, stateLen);
System.arraycopy(emptyArray, 0, sampleValVec, 0, 10);
BasicFunctions.filterMA(sampleVal, 10, sampleMa, 10, numerator, 0, 11, 11+stateLen);
System.arraycopy(emptyArray, 0, sampleMa, 20+stateLen, stateLen-10);
BasicFunctions.filterAR(sampleMa, 10, sampleAr, 10, syntDenum, syntDenumIndex, 11, 2*stateLen);
currIndex=10+stateLen-1;
currIndex2=10+2*stateLen-1;
for(k=0;k<stateLen;k++)
outFix[outFixIndex++]=(short)(sampleAr[currIndex--]+sampleAr[currIndex2--]);
}
public static void filteredCBVecs(short[] cbVectors, int cbVectorsIndex, short[] cbMem, int cbMemIndex, int length,int samples)
{
int n;
System.arraycopy(emptyArray, 0, cbMem, cbMemIndex+length, 4);
System.arraycopy(emptyArray, 0, cbMem, cbMemIndex-4, 4);
System.arraycopy(emptyArray, 0, cbVectors, cbVectorsIndex, length-samples);
BasicFunctions.filterMA(cbMem, cbMemIndex+4+length-samples, cbVectors, cbVectorsIndex+length-samples, Constants.CB_FILTERS_REV, 0, 8, samples);
}
public static void crossCorrelation(int[] crossCorrelation,int crossCorrelationIndex,short[] seq1, int seq1Index,short[] seq2, int seq2Index,short dimSeq,short dimCrossCorrelation,short rightShifts,short stepSeq2)
{
int i,j;
for (i = 0; i < dimCrossCorrelation; i++)
{
crossCorrelation[crossCorrelationIndex]=0;
for (j = 0; j < dimSeq; j++)
crossCorrelation[crossCorrelationIndex] += (seq1[seq1Index++]*seq2[seq2Index++])>>rightShifts;
seq1Index-=dimSeq;
seq2Index=seq2Index+stepSeq2-dimSeq;
crossCorrelationIndex++;
}
}
public static void updateBestIndex(CbUpdateIndexData updateIndexData,int critNew,short critNewSh,short indexNew,int cDotNew,short inverseEnergyNew,short energyShiftNew)
{
int shOld,shNew;
int gain;
short tempShort,tempScale;
int current=critNewSh-updateIndexData.getShTotMax();
if(current>31)
{
shOld=31;
shNew=0;
}
else if(current>0)
{
shOld=current;
shNew=0;
}
else if(current>-31)
{
shNew=0-current;
shOld=0;
}
else
{
shNew=31;
shOld=0;
}
if ((critNew>>shNew) > (updateIndexData.getCritMax()>>shOld))
{
tempShort = (short)(16 - BasicFunctions.norm(cDotNew));
tempScale=(short)(31-energyShiftNew-tempShort);
if(tempScale>31)
tempScale=31;
if(tempShort<0)
gain = ((cDotNew<<(-tempShort))*inverseEnergyNew)>>tempScale;
else
gain = ((cDotNew>>tempShort)*inverseEnergyNew)>>tempScale;
if (gain>bestIndexMaxI)
updateIndexData.setBestGain(bestIndexMax);
else if (gain<bestIndexMinI)
updateIndexData.setBestGain(bestIndexMin);
else
updateIndexData.setBestGain((short)gain);
updateIndexData.setCritMax(critNew);
updateIndexData.setShTotMax(critNewSh);
updateIndexData.setBestIndex(indexNew);
}
}
public static void getCbVec(short[] cbVec,int cbVecIndex,short[] mem,int memIndex,short index,int length,int vectorLength)
{
//GC items : tempBuffer
short tempBuffer[]=new short[45];
int baseSize=(short)(length-vectorLength+1);
int k;
if (vectorLength==40)
baseSize+=vectorLength>>1;
if (index<length-vectorLength+1)
{
k=index+vectorLength;
System.arraycopy(mem, memIndex+length-k, cbVec, cbVecIndex, vectorLength);
}
else if (index < baseSize)
{
k=2*(index-(length-vectorLength+1))+vectorLength;
createAugmentVector((short)(k>>1),mem,memIndex+length,cbVec,cbVecIndex);
}
else
{
if (index-baseSize<length-vectorLength+1)
{
System.arraycopy(emptyArray, 0, mem, memIndex-4, 4);
System.arraycopy(emptyArray, 0, mem, memIndex+length, 4);
BasicFunctions.filterMA(mem, memIndex+length-(index-baseSize+vectorLength)+4, cbVec, cbVecIndex, Constants.CB_FILTERS_REV, 0, 8, vectorLength);
}
else
{
System.arraycopy(emptyArray, 0, mem, memIndex+length, 4);
BasicFunctions.filterMA(mem, memIndex+length-vectorLength-1, tempBuffer, 0, Constants.CB_FILTERS_REV, 0, 8, vectorLength+5);
createAugmentVector((short)((vectorLength<<1)-20+index-baseSize-length-1),tempBuffer,45,cbVec,cbVecIndex);
}
}
}
public static void createAugmentVector(short index,short[] buf,int bufIndex,short[] cbVec,int cbVecIndex)
{
//GC items : cbVecTemp
short[] cbVecTmp=new short[4];
int currIndex=cbVecIndex+index-4;
System.arraycopy(buf, bufIndex-index, cbVec, cbVecIndex, index);
BasicFunctions.multWithRightShift(cbVec, currIndex, buf, bufIndex-index-4, Constants.ALPHA, 0, 4, 15);
BasicFunctions.reverseMultiplyRight(cbVecTmp, 0, buf, bufIndex-4, Constants.ALPHA, 3, 4, 15);
BasicFunctions.addWithRightShift(cbVec, currIndex, cbVec, currIndex, cbVecTmp, 0, 4, 0);
System.arraycopy(buf, bufIndex-index, cbVec, cbVecIndex + index, 40-index);
}
public static void energyInverse(short[] energy,int energyIndex,int length)
{
int n;
for (n=0; n<length; n++)
{
if(energy[energyIndex]<16384)
energy[energyIndex++]=Short.MAX_VALUE;
else
{
energy[energyIndex]=(short)(0x1FFFFFFF/energy[energyIndex]);
energyIndex++;
}
}
}
public static void energyCalc(int energy, short range, short[] ppi, int ppiIndex, short[] ppo, int ppoIndex, short[] energyArray, int energyArrayIndex, short[] energyShifts, int energyShiftsIndex, short scale, short baseSize)
{
int n;
energyShiftsIndex += 1 + baseSize;
energyArrayIndex += 1 + baseSize;
for(n=0;n<range-1;n++)
{
energy += ((ppi[ppiIndex] * ppi[ppiIndex])-(ppo[ppoIndex] * ppo[ppoIndex]))>>scale;
if(energy<0)
energy=0;
ppiIndex--;
ppoIndex--;
energyShifts[energyShiftsIndex] = BasicFunctions.norm(energy);
energyArray[energyArrayIndex++] = (short)((energy<<energyShifts[energyShiftsIndex])>>16);
energyShiftsIndex++;
}
}
public static void augmentCbCorr(short[] target, int targetIndex, short[] buf, int bufIndex, short[] interpSamples, int interpSamplesIndex, int[] cDot,int cDotIndex,int low,int high,int scale)
{
int n;
for (n=low; n<=high; n++)
{
cDot[cDotIndex] = BasicFunctions.scaleRight(target, targetIndex, buf, bufIndex-n, n-4, scale);
cDot[cDotIndex]+=BasicFunctions.scaleRight(target, targetIndex+n-4, interpSamples, interpSamplesIndex, 4, scale);
interpSamplesIndex += 4;
cDot[cDotIndex]+=BasicFunctions.scaleRight(target, targetIndex+n, buf, bufIndex-n, 40-n, scale);
cDotIndex++;
}
}
public static void absQuant(EncoderBits encoderBits,short[] in,int inIndex,short[] weightDenum, int weightDenumIndex)
{
short[] quantLen=new short[2];
short[] syntOutBuf=new short[68];
short[] inWeightedVec=new short[68];
short[] inWeighted=inWeightedVec; //+10 length 58
System.arraycopy(emptyArray, 0, syntOutBuf, 0, 68);
System.arraycopy(emptyArray, 0, inWeightedVec, 0, 10);
if (encoderBits.getStateFirst())
{
quantLen[0]=40;
quantLen[1]=(short)(EncoderState.STATE_SHORT_LEN-40);
}
else
{
quantLen[0]=(short)(EncoderState.STATE_SHORT_LEN-40);
quantLen[1]=40;
}
BasicFunctions.filterAR(in, inIndex, inWeighted, 10, weightDenum, weightDenumIndex, 11, quantLen[0]);
BasicFunctions.filterAR(in, inIndex+quantLen[0], inWeighted, 10+quantLen[0], weightDenum, weightDenumIndex+11, 11, quantLen[1]);
absQUantLoop(encoderBits,syntOutBuf, 10, inWeighted, 10,weightDenum, weightDenumIndex, quantLen, 0);
}
public static void absQUantLoop(EncoderBits encoderBits,short[] syntOut, int syntOutIndex, short[] inWeighted, int inWeightedIndex, short[] weightDenum, int weightDenumIndex, short[] quantLen, int quantLenIndex)
{
short[] idxVec=encoderBits.getIdxVec();
int startIndex=0,currIndex;
int i,j,k;
int temp,temp2;
for(i=0;i<2;i++)
{
currIndex=quantLenIndex+i;
for(j=0;j<quantLen[currIndex];j++)
{
BasicFunctions.filterAR(syntOut, syntOutIndex, syntOut, syntOutIndex, weightDenum, weightDenumIndex, 11, 1);
temp = inWeighted[inWeightedIndex] - syntOut[syntOutIndex];
temp2 = temp<<2;
if (temp2 > Short.MAX_VALUE)
temp2 = Short.MAX_VALUE;
else if (temp2 < Short.MIN_VALUE)
temp2 = Short.MIN_VALUE;
if (temp< -7577)
{
idxVec[startIndex + j] = (short)0;
syntOut[syntOutIndex++] = (short)(((Constants.STATE_SQ3[0] + 2) >> 2) + inWeighted[inWeightedIndex++] - temp);
}
else if (temp>8151)
{
idxVec[startIndex + j] = (short)7;
syntOut[syntOutIndex++] = (short)(((Constants.STATE_SQ3[7] + 2) >> 2) + inWeighted[inWeightedIndex++] - temp);
}
else
{
if (temp2 <= Constants.STATE_SQ3[0])
{
idxVec[startIndex + j] = (short)0;
syntOut[syntOutIndex++] = (short)(((Constants.STATE_SQ3[0] + 2) >> 2) + inWeighted[inWeightedIndex++] - temp);
}
else
{
k = 0;
while(temp2 > Constants.STATE_SQ3[k] && k<Constants.STATE_SQ3.length-1)
k++;
if (temp2 > ((Constants.STATE_SQ3[k] + Constants.STATE_SQ3[k - 1] + 1)>>1))
{
idxVec[startIndex + j] = (short)k;
syntOut[syntOutIndex++] = (short)(((Constants.STATE_SQ3[k] + 2) >> 2) + inWeighted[inWeightedIndex++] - temp);
}
else
{
idxVec[startIndex + j] = (short)(k-1);
syntOut[syntOutIndex++] = (short)(((Constants.STATE_SQ3[k-1] + 2) >> 2) + inWeighted[inWeightedIndex++] - temp);
}
}
}
}
startIndex+=quantLen[currIndex];
/* Update perceptual weighting filter at subframe border */
weightDenumIndex += 11;
}
}
public static void interpolateSamples(short[] interpSamples,int interpSamplesIndex,short[] cbMem,int cbMemIndex,int length)
{
int n,highIndex,lowIndex,temp;
for (n=0; n<20; n++)
{
highIndex = cbMemIndex+length-4;
lowIndex = cbMemIndex+length-n-24;
interpSamples[interpSamplesIndex++] = (short)(((Constants.ALPHA[3]*cbMem[highIndex++])>>15) + ((Constants.ALPHA[0]*cbMem[lowIndex++])>>15));
interpSamples[interpSamplesIndex++] = (short)(((Constants.ALPHA[2]*cbMem[highIndex++])>>15) + ((Constants.ALPHA[1]*cbMem[lowIndex++])>>15));
interpSamples[interpSamplesIndex++] = (short)(((Constants.ALPHA[1]*cbMem[highIndex++])>>15) + ((Constants.ALPHA[2]*cbMem[lowIndex++])>>15));
interpSamples[interpSamplesIndex++] = (short)(((Constants.ALPHA[0]*cbMem[highIndex++])>>15) + ((Constants.ALPHA[3]*cbMem[lowIndex++])>>15));
}
}
public static short frameClassify(short[] residual)
{
//GC items:ssqEn
int[] ssqEn=new int[5];
short max=0,tempS;
int n;
for(n=0;n<EncoderState.SIZE;n++)
{
tempS=residual[n];
if(tempS<0)
tempS=(short)(0-tempS);
if(tempS>max)
max=tempS;
}
short scale=(short)(BasicFunctions.getSize(max*max)-24);
if(scale<0)
scale=0;
int ssqIndex=2;
int currIndex=0;
for (n=EncoderState.SUBFRAMES-1; n>0; n--)
{
ssqEn[currIndex++] = BasicFunctions.scaleRight(residual,ssqIndex, residual,ssqIndex, 76, scale);
ssqIndex += 40;
}
/* Scale to maximum 20 bits in order to allow for the 11 bit window */
ssqIndex=0;
int maxSSq=ssqEn[0];
for(n=1;n<EncoderState.SUBFRAMES-1;n++)
{
if(ssqEn[n]>maxSSq)
maxSSq=ssqEn[n];
}
scale = (short)(BasicFunctions.getSize(maxSSq) - 20);
if(scale<0)
scale = 0;
ssqIndex=0;
currIndex=1;
for (n=EncoderState.SUBFRAMES-1; n>0; n--)
{
ssqEn[ssqIndex]=(ssqEn[ssqIndex]>>scale)*Constants.ENG_START_SEQUENCE[currIndex++];
ssqIndex++;
}
/* Extract the best choise of start state */
currIndex=0;
maxSSq=ssqEn[0];
for(n=1;n<EncoderState.SUBFRAMES-1;n++)
{
if(ssqEn[n]>maxSSq)
{
currIndex=n;
maxSSq=ssqEn[n];
}
}
return (short)(currIndex + 1);
}
public static void packBits(EncoderState encoderState,EncoderBits encoderBits,byte[] result)
{
int resIndex,idxVecIndex;
int i,k;
short[] lsf=encoderBits.getLSF();
short[] cbIndex=encoderBits.getCbIndex();
short[] gainIndex=encoderBits.getGainIndex();
short[] idxVec=encoderBits.getIdxVec();
result[0]=(byte)((lsf[0]<<2) | ((lsf[1]>>5) & 0x3));
result[1]=(byte)((lsf[1] & 0x1F)<<3 | ((lsf[2]>>4) & 0x7));
result[2]=(byte)((lsf[2] & 0xF)<<4);
if (encoderState.ENCODER_MODE==20)
{
if(encoderBits.getStateFirst())
result[2]|=(encoderBits.getStartIdx()&0x3)<<2 | 0x2;
else
result[2]|=(encoderBits.getStartIdx()&0x3)<<2;
result[2]|=(encoderBits.getIdxForMax()>>5) & 0x1;
result[3]=(byte)(((encoderBits.getIdxForMax() & 0x1F)<<3) | ((cbIndex[0]>>4) & 0x7));
result[4]=(byte)(((cbIndex[0] & 0xE)<<4) | (gainIndex[0] & 0x18) | ((gainIndex[1] & 0x8)>>1) | ((cbIndex[3]>>6) & 0x3));
result[5]=(byte)(((cbIndex[3] & 0x3E)<<2) | ((gainIndex[3]>>2) & 0x4) | ((gainIndex[4]>>2) & 0x2) | ((gainIndex[6]>>4) & 0x1));
resIndex=6;
}
else
{
result[2]|=(lsf[3]>>2) & 0xF;
result[3]=(byte)(((lsf[3] & 0x3)<<6) | ((lsf[4]>>1) & 0x3F));
result[4]=(byte)(((lsf[4] & 0x1)<<7) | (lsf[5] & 0x7F));
if(encoderBits.getStateFirst())
result[5]=(byte)((encoderBits.getStartIdx()<<5) | 0x10 | (encoderBits.getIdxForMax()>>2) & 0xF);
else
result[5]=(byte)((encoderBits.getStartIdx()<<5) | (encoderBits.getIdxForMax()>>2) & 0xF);
result[6]=(byte)(((encoderBits.getIdxForMax() & 0x3)<<6) | ((cbIndex[0]&0x78)>>1) | ((gainIndex[0]&0x10)>>3) | ((gainIndex[1]&0x80)>>3));
result[7]=(byte)(cbIndex[3]&0xFC | ((gainIndex[3] & 0x10)>>3) | ((gainIndex[4] & 0x80)>>3));
resIndex=8;
}
idxVecIndex=0;
for (k=0; k<7; k++)
{
result[resIndex]=0;
for (i=7; i>=0; i--)
result[resIndex] |= (((idxVec[idxVecIndex++] & 0x4)>>2)<<i);
resIndex++;
}
result[resIndex] = (byte)((idxVec[idxVecIndex++] & 0x4)<<5);
if (encoderState.ENCODER_MODE==20)
{
result[resIndex] |= (gainIndex[1] & 0x4)<<4;
result[resIndex] |= (gainIndex[3] & 0xC)<<2;
result[resIndex] |= (gainIndex[4] & 0x4)<<1;
result[resIndex] |= (gainIndex[6] & 0x8)>>1;
result[resIndex] |= (gainIndex[7] & 0xC)>>2;
}
else
{
result[resIndex] |= (idxVec[idxVecIndex++] & 0x4)<<4;
result[resIndex] |= (cbIndex[0] & 0x6)<<3;
result[resIndex] |= (gainIndex[0] & 0x8);
result[resIndex] |= (gainIndex[1] & 0x4);
result[resIndex] |= (cbIndex[3] & 0x2);
result[resIndex] |= (cbIndex[6] & 0x80)>>7;
resIndex++;
result[resIndex] = (byte)((cbIndex[6] & 0x7E)<<1 | (cbIndex[9] & 0xC0)>>6);
resIndex++;
result[resIndex] = (byte)((cbIndex[9] & 0x3E)<<2 | (cbIndex[12] & 0xE0)>>5);
resIndex++;
result[resIndex] = (byte)((cbIndex[12] & 0x1E)<<3 | (gainIndex[3] & 0xC) | (gainIndex[4] & 0x6)>>1);
resIndex++;
result[resIndex] = (byte)((gainIndex[6] & 0x18)<<3 | (gainIndex[7] & 0xC)<<2 | (gainIndex[9] & 0x10)>>1 | (gainIndex[10] & 0x8)>>1 | (gainIndex[12] & 0x10)>>3 | (gainIndex[13] & 0x8)>>3);
}
idxVecIndex=0;
resIndex++;
for (k=0; k<14; k++)
{
result[resIndex]=0;
for (i=6; i>=0; i-=2)
result[resIndex] |= ((idxVec[idxVecIndex++] & 0x3)<<i);
resIndex++;
}
if (encoderState.ENCODER_MODE==20)
{
result[resIndex++] =(byte)((idxVec[56]& 0x3)<<6 | (cbIndex[0] & 0x1)<<5 | (cbIndex[1] & 0x7C)>>2);
result[resIndex++] =(byte)(((cbIndex[1]& 0x3)<<6) | ((cbIndex[2]>>1) & 0x3F));
result[resIndex++] =(byte)((cbIndex[2] & 0x1)<<7 | (gainIndex[0] & 0x7)<<4 | (gainIndex[1] & 0x3)<<2 | (gainIndex[2] & 0x6)>>1);
result[resIndex++] =(byte)((gainIndex[2] & 0x1)<<7 | (cbIndex[3] & 0x1)<<6 | (cbIndex[4] & 0x7E)>>1);
result[resIndex++] = (byte)((cbIndex[4] & 0x1)<<7 | (cbIndex[5] & 0x7F));
result[resIndex++] = (byte)(cbIndex[6] & 0xFF);
result[resIndex++] = (byte)(cbIndex[7] & 0xFF);
result[resIndex++] = (byte)(cbIndex[8] & 0xFF);
result[resIndex++] = (byte)(((gainIndex[3] & 0x3)<<6) | ((gainIndex[4] & 0x3)<<4) | ((gainIndex[5] & 0x7)<<1) | ((gainIndex[6] & 0x4)>>2));
result[resIndex++] = (byte)(((gainIndex[6] & 0x3)<<6) | ((gainIndex[7] & 0x3)<<4) | ((gainIndex[8] & 0x7)<<1));
}
else
{
result[resIndex++] = (byte)((idxVec[56] & 0x3)<<6 | (idxVec[57] & 0x3)<<4 | (cbIndex[0] & 0x1)<<3 | (cbIndex[1] & 0x70)>>4);
result[resIndex++] = (byte)((cbIndex[1] & 0xF)<<4 | (cbIndex[2] & 0x78)>>3);
result[resIndex++] = (byte)((cbIndex[2] & 0x7)<<5 | (gainIndex[0] & 0x7)<<2 | (gainIndex[1] & 0x3));
result[resIndex++] = (byte)((gainIndex[2] & 0x7)<<7 | (cbIndex[3] & 0x1)<<4 | (cbIndex[4] & 0x78)>>3);
result[resIndex++] = (byte)((cbIndex[4] & 0x7)<<5 | (cbIndex[5] & 0x7C)>>2);
result[resIndex++] = (byte)((cbIndex[5] & 0x3)<<6 | (cbIndex[6] & 0x1)<<1 | (cbIndex[7] & 0xF8)>>3);
result[resIndex++] = (byte)((cbIndex[7] & 0x7)<<5 | (cbIndex[8] & 0xF8)>>3);
result[resIndex++] = (byte)((cbIndex[8] & 0x7)<<5 | (cbIndex[9] & 0x1)<<4 | (cbIndex[10] & 0xF0)>>4);
result[resIndex++] = (byte)((cbIndex[10] & 0xF)<<4 | (cbIndex[11] & 0xF0)>>4);
result[resIndex++] = (byte)((cbIndex[11] & 0xF)<<4 | (cbIndex[12] & 0x1)<<3 | (cbIndex[13] & 0xE0)>>5);
result[resIndex++] = (byte)((cbIndex[13] & 0x1F)<<3 | (cbIndex[14] & 0xE0)>>5);
result[resIndex++] = (byte)((cbIndex[14] & 0x1F)<<3 | (gainIndex[3] & 0x3)<<1 | (gainIndex[4] & 0x1));
result[resIndex++] = (byte)((gainIndex[5] & 0x7)<<5 | (gainIndex[6] & 0x7)<<2 | (gainIndex[7] & 0x3));
result[resIndex++] = (byte)((gainIndex[8] & 0x7)<<5 | (gainIndex[9] & 0xF)<<1 | (gainIndex[10] & 0x4)>>2);
result[resIndex++] = (byte)((gainIndex[10] & 0x3)<<6 | (gainIndex[11] & 0x7)<<3 | (gainIndex[12] & 0xE)>>1);
result[resIndex++] = (byte)((gainIndex[12] & 0x1)<<7 | (gainIndex[13] & 0x7)<<4 | (gainIndex[14] & 0x7)<<1);
}
}
public static void unpackBits(EncoderBits encoderBits,short[] data,int mode)
{
short[] lsf=encoderBits.getLSF();
short[] cbIndex=encoderBits.getCbIndex();
short[] gainIndex=encoderBits.getGainIndex();
short[] idxVec=encoderBits.getIdxVec();
short tempIndex1=0,tempIndex2=0;
short tempS;
int i,k;
/* First WebRtc_Word16 */
lsf[0] = (short)((data[tempIndex1]>>10) & 0x3F); /* Bit 0..5 */
lsf[1] = (short)((data[tempIndex1]>>3)&0x7F); /* Bit 6..12 */
lsf[2] = (short)((data[tempIndex1]&0x7)<<4); /* Bit 13..15 */
tempIndex1++;
/* Second WebRtc_Word16 */
lsf[2] |= (data[tempIndex1]>>12)&0xF; /* Bit 0..3 */
if (mode==20)
{
encoderBits.setStartIdx((short)((data[tempIndex1]>>10)&0x3)); /* Bit 4..5 */
encoderBits.setStateFirst(false);
if(((data[tempIndex1]>>9)&0x1)!=0)
encoderBits.setStateFirst(true); /* Bit 6 */
encoderBits.setIdxForMax((short)((data[tempIndex1]>>3)&0x3F)); /* Bit 7..12 */
cbIndex[0] = (short)((data[tempIndex1]&0x7)<<4); /* Bit 13..15 */
tempIndex1++;
/* Third WebRtc_Word16 */
cbIndex[0] |= (data[tempIndex1]>>12)&0xE; /* Bit 0..2 */
gainIndex[0] = (short)((data[tempIndex1]>>8)&0x18); /* Bit 3..4 */
gainIndex[1] = (short)((data[tempIndex1]>>7)&0x8); /* Bit 5 */
cbIndex[3] = (short)((data[tempIndex1]>>2)&0xFE); /* Bit 6..12 */
gainIndex[3] = (short)((data[tempIndex1]<<2)&0x10); /* Bit 13 */
gainIndex[4] = (short)((data[tempIndex1]<<2)&0x8); /* Bit 14 */
gainIndex[6] = (short)((data[tempIndex1]<<4)&0x10); /* Bit 15 */
}
else
{ /* mode==30 */
lsf[3] = (short)((data[tempIndex1]>>6)&0x3F); /* Bit 4..9 */
lsf[4] = (short)((data[tempIndex1]<<1)&0x7E); /* Bit 10..15 */
tempIndex1++;
/* Third WebRtc_Word16 */
lsf[4] |= (data[tempIndex1]>>15)&0x1; /* Bit 0 */
lsf[5] = (short)((data[tempIndex1]>>8)&0x7F); /* Bit 1..7 */
encoderBits.setStartIdx((short)((data[tempIndex1]>>5)&0x7)); /* Bit 8..10 */
encoderBits.setStateFirst(false);
if((short)((data[tempIndex1]>>4)&0x1)!=0)
encoderBits.setStateFirst(true);/* Bit 11 */
tempS=(short)((data[tempIndex1]<<2)&0x3C);/* Bit 12..15 */
tempIndex1++;
/* 4:th WebRtc_Word16 */
tempS |= (data[tempIndex1]>>14)&0x3; /* Bit 0..1 */
encoderBits.setIdxForMax(tempS);
cbIndex[0] = (short)((data[tempIndex1]>>7)&0x78); /* Bit 2..5 */
gainIndex[0] = (short)((data[tempIndex1]>>5)&0x10); /* Bit 6 */
gainIndex[1] = (short)((data[tempIndex1]>>5)&0x8); /* Bit 7 */
cbIndex[3] = (short)((data[tempIndex1])&0xFC); /* Bit 8..13 */
gainIndex[3] = (short)((data[tempIndex1]<<3)&0x10); /* Bit 14 */
gainIndex[4] = (short)((data[tempIndex1]<<3)&0x8); /* Bit 15 */
}
/* Class 2 bits of ULP */
/* 4:th to 6:th WebRtc_Word16 for 20 ms case
5:th to 7:th WebRtc_Word16 for 30 ms case */
tempIndex1++;
tempIndex2=0;
for (k=0; k<3; k++)
{
for (i=15; i>=0; i--)
idxVec[tempIndex2++] = (short)(((data[tempIndex1]>>i)<<2)&0x4);/* Bit 15-i */
tempIndex1++;
}
if (mode==20)
{
/* 7:th WebRtc_Word16 */
for (i=15; i>6; i--)
idxVec[tempIndex2++] = (short)(((data[tempIndex1]>>i)<<2)&0x4); /* Bit 15-i */
gainIndex[1] |= (data[tempIndex1]>>4)&0x4; /* Bit 9 */
gainIndex[3] |= (data[tempIndex1]>>2)&0xC; /* Bit 10..11 */
gainIndex[4] |= (data[tempIndex1]>>1)&0x4; /* Bit 12 */
gainIndex[6] |= (data[tempIndex1]<<1)&0x8; /* Bit 13 */
gainIndex[7] = (short)((data[tempIndex1]<<2)&0xC); /* Bit 14..15 */
}
else
{ /* mode==30 */
/* 8:th WebRtc_Word16 */
for (i=15; i>5; i--)
idxVec[tempIndex2++] = (short)(((data[tempIndex1]>>i)<<2)&0x4);/* Bit 15-i */
cbIndex[0] |= (data[tempIndex1]>>3)&0x6; /* Bit 10..11 */
gainIndex[0] |= (data[tempIndex1])&0x8; /* Bit 12 */
gainIndex[1] |= (data[tempIndex1])&0x4; /* Bit 13 */
cbIndex[3] |= (data[tempIndex1])&0x2; /* Bit 14 */
cbIndex[6] = (short)((data[tempIndex1]<<7)&0x80); /* Bit 15 */
tempIndex1++;
/* 9:th WebRtc_Word16 */
cbIndex[6] |= (data[tempIndex1]>>9)&0x7E; /* Bit 0..5 */
cbIndex[9] = (short)((data[tempIndex1]>>2)&0xFE); /* Bit 6..12 */
cbIndex[12] = (short)((data[tempIndex1]<<5)&0xE0); /* Bit 13..15 */
tempIndex1++;
/* 10:th WebRtc_Word16 */
cbIndex[12] |= (data[tempIndex1]>>11)&0x1E;/* Bit 0..3 */
gainIndex[3] |= (data[tempIndex1]>>8)&0xC; /* Bit 4..5 */
gainIndex[4] |= (data[tempIndex1]>>7)&0x6; /* Bit 6..7 */
gainIndex[6] = (short)((data[tempIndex1]>>3)&0x18); /* Bit 8..9 */
gainIndex[7] = (short)((data[tempIndex1]>>2)&0xC); /* Bit 10..11 */
gainIndex[9] = (short)((data[tempIndex1]<<1)&0x10); /* Bit 12 */
gainIndex[10] = (short)((data[tempIndex1]<<1)&0x8); /* Bit 13 */
gainIndex[12] = (short)((data[tempIndex1]<<3)&0x10); /* Bit 14 */
gainIndex[13] = (short)((data[tempIndex1]<<3)&0x8); /* Bit 15 */
}
tempIndex1++;
/* Class 3 bits of ULP */
/* 8:th to 14:th WebRtc_Word16 for 20 ms case
11:th to 17:th WebRtc_Word16 for 30 ms case */
tempIndex2=0;
for (k=0; k<7; k++)
{
for (i=14; i>=0; i-=2)
idxVec[tempIndex2++] |= (data[tempIndex1]>>i)&0x3; /* Bit 15-i..14-i*/
tempIndex1++;
}
if (mode==20)
{
/* 15:th WebRtc_Word16 */
idxVec[56] |= (data[tempIndex1]>>14)&0x3; /* Bit 0..1 */
cbIndex[0] |= (data[tempIndex1]>>13)&0x1; /* Bit 2 */
cbIndex[1] = (short)((data[tempIndex1]>>6)&0x7F); /* Bit 3..9 */
cbIndex[2] = (short)((data[tempIndex1]<<1)&0x7E); /* Bit 10..15 */
tempIndex1++;
/* 16:th WebRtc_Word16 */
cbIndex[2] |= (data[tempIndex1]>>15)&0x1; /* Bit 0 */
gainIndex[0] |= (data[tempIndex1]>>12)&0x7; /* Bit 1..3 */
gainIndex[1] |= (data[tempIndex1]>>10)&0x3; /* Bit 4..5 */
gainIndex[2] = (short)((data[tempIndex1]>>7)&0x7); /* Bit 6..8 */
cbIndex[3] |= (data[tempIndex1]>>6)&0x1; /* Bit 9 */
cbIndex[4] = (short)((data[tempIndex1]<<1)&0x7E); /* Bit 10..15 */
tempIndex1++;
/* 17:th WebRtc_Word16 */
cbIndex[4] |= (data[tempIndex1]>>15)&0x1; /* Bit 0 */
cbIndex[5] = (short)((data[tempIndex1]>>8)&0x7F); /* Bit 1..7 */
cbIndex[6] = (short)((data[tempIndex1])&0xFF); /* Bit 8..15 */
tempIndex1++;
/* 18:th WebRtc_Word16 */
cbIndex[7] = (short)((data[tempIndex1]>>8) & 0xFF); /* Bit 0..7 */
cbIndex[8] = (short)(data[tempIndex1]&0xFF); /* Bit 8..15 */
tempIndex1++;
/* 19:th WebRtc_Word16 */
gainIndex[3] |= (data[tempIndex1]>>14)&0x3; /* Bit 0..1 */
gainIndex[4] |= (data[tempIndex1]>>12)&0x3; /* Bit 2..3 */
gainIndex[5] = (short)((data[tempIndex1]>>9)&0x7); /* Bit 4..6 */
gainIndex[6] |= (data[tempIndex1]>>6)&0x7; /* Bit 7..9 */
gainIndex[7] |= (data[tempIndex1]>>4)&0x3; /* Bit 10..11 */
gainIndex[8] = (short)((data[tempIndex1]>>1)&0x7); /* Bit 12..14 */
}
else
{ /* mode==30 */
/* 18:th WebRtc_Word16 */
idxVec[56] |= (data[tempIndex1]>>14)&0x3; /* Bit 0..1 */
idxVec[57] |= (data[tempIndex1]>>12)&0x3; /* Bit 2..3 */
cbIndex[0] |= (data[tempIndex1]>>11)&1; /* Bit 4 */
cbIndex[1] = (short)((data[tempIndex1]>>4)&0x7F); /* Bit 5..11 */
cbIndex[2] = (short)((data[tempIndex1]<<3)&0x78); /* Bit 12..15 */
tempIndex1++;
/* 19:th WebRtc_Word16 */
cbIndex[2] |= (data[tempIndex1]>>13)&0x7; /* Bit 0..2 */
gainIndex[0] |= (data[tempIndex1]>>10)&0x7; /* Bit 3..5 */
gainIndex[1] |= (data[tempIndex1]>>8)&0x3; /* Bit 6..7 */
gainIndex[2] = (short)((data[tempIndex1]>>5)&0x7); /* Bit 8..10 */
cbIndex[3] |= (data[tempIndex1]>>4)&0x1; /* Bit 11 */
cbIndex[4] = (short)((data[tempIndex1]<<3)&0x78); /* Bit 12..15 */
tempIndex1++;
/* 20:th WebRtc_Word16 */
cbIndex[4] |= (data[tempIndex1]>>13)&0x7; /* Bit 0..2 */
cbIndex[5] = (short)((data[tempIndex1]>>6)&0x7F); /* Bit 3..9 */
cbIndex[6] |= (data[tempIndex1]>>5)&0x1; /* Bit 10 */
cbIndex[7] = (short)((data[tempIndex1]<<3)&0xF8); /* Bit 11..15 */
tempIndex1++;
/* 21:st WebRtc_Word16 */
cbIndex[7] |= (data[tempIndex1]>>13)&0x7; /* Bit 0..2 */
cbIndex[8] = (short)((data[tempIndex1]>>5)&0xFF); /* Bit 3..10 */
cbIndex[9] |= (data[tempIndex1]>>4)&0x1; /* Bit 11 */
cbIndex[10] = (short)((data[tempIndex1]<<4)&0xF0); /* Bit 12..15 */
tempIndex1++;
/* 22:nd WebRtc_Word16 */
cbIndex[10] |= (data[tempIndex1]>>12)&0xF; /* Bit 0..3 */
cbIndex[11] = (short)((data[tempIndex1]>>4)&0xFF); /* Bit 4..11 */
cbIndex[12] |= (data[tempIndex1]>>3)&0x1; /* Bit 12 */
cbIndex[13] = (short)((data[tempIndex1]<<5)&0xE0); /* Bit 13..15 */
tempIndex1++;
/* 23:rd WebRtc_Word16 */
cbIndex[13] |= (data[tempIndex1]>>11)&0x1F;/* Bit 0..4 */
cbIndex[14] = (short)((data[tempIndex1]>>3)&0xFF); /* Bit 5..12 */
gainIndex[3] |= (data[tempIndex1]>>1)&0x3; /* Bit 13..14 */
gainIndex[4] |= (data[tempIndex1]&0x1); /* Bit 15 */
tempIndex1++;
/* 24:rd WebRtc_Word16 */
gainIndex[5] = (short)((data[tempIndex1]>>13)&0x7); /* Bit 0..2 */
gainIndex[6] |= (data[tempIndex1]>>10)&0x7; /* Bit 3..5 */
gainIndex[7] |= (data[tempIndex1]>>8)&0x3; /* Bit 6..7 */
gainIndex[8] = (short)((data[tempIndex1]>>5)&0x7); /* Bit 8..10 */
gainIndex[9] |= (data[tempIndex1]>>1)&0xF; /* Bit 11..14 */
gainIndex[10] |= (data[tempIndex1]<<2)&0x4; /* Bit 15 */
tempIndex1++;
/* 25:rd WebRtc_Word16 */
gainIndex[10] |= (data[tempIndex1]>>14)&0x3; /* Bit 0..1 */
gainIndex[11] = (short)((data[tempIndex1]>>11)&0x7); /* Bit 2..4 */
gainIndex[12] |= (data[tempIndex1]>>7)&0xF; /* Bit 5..8 */
gainIndex[13] |= (data[tempIndex1]>>4)&0x7; /* Bit 9..11 */
gainIndex[14] = (short)((data[tempIndex1]>>1)&0x7); /* Bit 12..14 */
}
}
public static void updateDecIndex(EncoderBits encoderBits)
{
short[] index=encoderBits.getCbIndex();
int k;
for (k=4;k<6;k++)
{
if (index[k]>=44 && index[k]<108)
index[k]+=64;
else if (index[k]>=108 && index[k]<128)
index[k]+=128;
}
}
public static void simpleLsfDeq(short[] lsfDeq,int lsfDeqIndex,short[] index,int indexIndex,int lpcN)
{
int cbIndex=0;
int i,j;
for (i = 0; i < 3; i++)
{
cbIndex=Constants.LSF_INDEX_CB[i];
for (j = 0; j < Constants.LSF_DIM_CB[i]; j++)
lsfDeq[lsfDeqIndex++] = Constants.LSF_CB[cbIndex + index[indexIndex]*Constants.LSF_DIM_CB[i] + j];
indexIndex++;
}
if (lpcN>1)
{
/* decode last LSF */
for (i = 0; i < 3; i++)
{
cbIndex=Constants.LSF_INDEX_CB[i];
for (j = 0; j < Constants.LSF_DIM_CB[i]; j++)
lsfDeq[lsfDeqIndex++] = Constants.LSF_CB[cbIndex + index[indexIndex]*Constants.LSF_DIM_CB[i] + j];
indexIndex++;
}
}
}
public static void decoderInterpolateLsf(DecoderState decoderState,short[] syntDenum,int syntDenumIndex,short[] weightDenum,int weightDenumIndex,short[] lsfDeq,int lsfDeqIndex,short length)
{
//GC items:lp
short[] lp=new short[11];
int len = length + 1;
short s;
if (decoderState.DECODER_MODE==30)
{
lspInterpolate2PolyDec(lp, 0, decoderState.getLsfDeqOld(), 0, lsfDeq, lsfDeqIndex,Constants.LSF_WEIGHT_30MS[0], length);
System.arraycopy(lp, 0, syntDenum, syntDenumIndex, len);
BasicFunctions.expand(weightDenum, weightDenumIndex, lp, 0, Constants.LPC_CHIRP_SYNT_DENUM, len);
for (s = 1; s < decoderState.SUBFRAMES; s++)
{
syntDenumIndex += len;
weightDenumIndex+= len;
lspInterpolate2PolyDec(lp, 0, lsfDeq, lsfDeqIndex, lsfDeq, lsfDeqIndex + length,Constants.LSF_WEIGHT_30MS[s], length);
System.arraycopy(lp, 0, syntDenum, syntDenumIndex, len);
BasicFunctions.expand(weightDenum,weightDenumIndex, lp, 0, Constants.LPC_CHIRP_SYNT_DENUM, len);
}
}
else
{
for (s = 0; s < decoderState.SUBFRAMES; s++)
{
lspInterpolate2PolyDec(lp, 0, decoderState.getLsfDeqOld(), 0, lsfDeq, lsfDeqIndex,Constants.LSF_WEIGHT_20MS[s], length);
System.arraycopy(lp, 0, syntDenum, syntDenumIndex, len);
BasicFunctions.expand(weightDenum, weightDenumIndex, lp, 0, Constants.LPC_CHIRP_SYNT_DENUM, len);
syntDenumIndex += len;
weightDenumIndex+= len;
}
}
if (decoderState.DECODER_MODE==30)
System.arraycopy(lsfDeq, lsfDeqIndex + length, decoderState.getLsfDeqOld(), 0, length);
else
System.arraycopy(lsfDeq, lsfDeqIndex, decoderState.getLsfDeqOld(), 0, length);
}
public static void lspInterpolate2PolyDec(short[] a,int aIndex, short[] lsf1,int lsf1Index, short[] lsf2,int lsf2Index, short coef,int length)
{
//GC items:lsf temp
short[] lsfTemp=new short[10];
interpolate(lsfTemp, 0, lsf1, lsf1Index, lsf2, lsf2Index, coef, length);
lsf2Poly(a,aIndex,lsfTemp,0);
}
public static void decodeResidual(DecoderState decoderState,EncoderBits encoderBits,short[] decResidual,int decResidualIndex,short[] syntDenum,int syntDenumIndex)
{
short[] reverseDecresidual = decoderState.getEnhancementBuffer();
short[] memVec = decoderState.getPrevResidual();
int i,subCount,subFrame;
short startPos,nBack,nFor,memlGotten;
short diff = (short)(80 - decoderState.STATE_SHORT_LEN);
if (encoderBits.getStateFirst())
startPos = (short)((encoderBits.getStartIdx()-1)*40);
else
startPos = (short)((encoderBits.getStartIdx()-1)*40 + diff);
stateConstruct(encoderBits,syntDenum,syntDenumIndex + (encoderBits.getStartIdx()-1)*11,decResidual,decResidualIndex + startPos,decoderState.STATE_SHORT_LEN);
if(encoderBits.getStateFirst())
{
for(i=4;i<151-decoderState.STATE_SHORT_LEN;i++)
memVec[i]=0;
System.arraycopy(decResidual, startPos, memVec, 151-decoderState.STATE_SHORT_LEN, decoderState.STATE_SHORT_LEN);
cbConstruct(encoderBits,decResidual,decResidualIndex + startPos + decoderState.STATE_SHORT_LEN, memVec,66, (short)85, diff, 0, 0);
}
else
{
memlGotten = decoderState.STATE_SHORT_LEN;
BasicFunctions.reverseCopy(memVec, 150, decResidual, decResidualIndex + startPos, memlGotten);
for(i=4;i<151-memlGotten;i++)
memVec[i]=0;
cbConstruct(encoderBits,reverseDecresidual, 0, memVec, 66, (short)85, diff, 0, 0);
BasicFunctions.reverseCopy(decResidual, decResidualIndex + startPos-1, reverseDecresidual, 0, diff);
}
subCount=1;
nFor = (short)(decoderState.SUBFRAMES - encoderBits.getStartIdx() -1);
if(nFor > 0)
{
for(i=4;i<71;i++)
memVec[i]=0;
System.arraycopy(decResidual, decResidualIndex + 40 * (encoderBits.getStartIdx()-1), memVec, 71, 80);
for (subFrame=0; subFrame<nFor; subFrame++)
{
cbConstruct(encoderBits,decResidual, decResidualIndex + 40*(encoderBits.getStartIdx()+1+subFrame), memVec, 4, (short)147, (short)40, subCount*3, subCount*3);
for(i=4;i<111;i++)
memVec[i]=memVec[i+40];
System.arraycopy(decResidual, decResidualIndex + 40 * (encoderBits.getStartIdx()+1+subFrame) , memVec, 111, 40);
subCount++;
}
}
nBack = (short)(encoderBits.getStartIdx()-1);
if(nBack > 0)
{
memlGotten = (short)(40*(decoderState.SUBFRAMES + 1 - encoderBits.getStartIdx()));
if(memlGotten > 147)
memlGotten=147;
BasicFunctions.reverseCopy(memVec, 150, decResidual, decResidualIndex + 40 * (encoderBits.getStartIdx()-1), memlGotten);
for(i=4;i<151-memlGotten;i++)
memVec[i]=0;
for (subFrame=0; subFrame<nBack; subFrame++)
{
cbConstruct(encoderBits,reverseDecresidual, 40*subFrame, memVec, 4, (short)147, (short)40, subCount*3, subCount*3);
for(i=4;i<111;i++)
memVec[i]=memVec[i+40];
System.arraycopy(reverseDecresidual, 40 * subFrame, memVec, 111, 40);
subCount++;
}
BasicFunctions.reverseCopy(decResidual, decResidualIndex+40*nBack-1, reverseDecresidual, 0, 40*nBack);
}
}
public static int xCorrCoef(short[] target,int targetIndex,short[] regressor,int regressorIndex,short subl,short searchLen,short offset,short step)
{
/* Initializations, to make sure that the first one is selected */
short max,energyScale,totScale,scaleDiff,crossCorrSqMod,energyMod,crossCorrMod,crossCorrScale;
short energyModMax=Short.MAX_VALUE;
short totScaleMax=-500;
short crossCorrSqModMax=0;
short maxLag=0;
int pos=0;
int tempIndex1,tempIndex2,tempIndex3,tempIndex4,shifts,newCrit,maxCrit,k,energy,temp,crossCorr;
if (step==1)
{
max=BasicFunctions.getMaxAbsValue(regressor,regressorIndex,subl+searchLen-1);
tempIndex1=regressorIndex;
tempIndex2=regressorIndex + subl;
}
else
{
max=BasicFunctions.getMaxAbsValue(regressor,regressorIndex-searchLen,subl+searchLen-1);
tempIndex1=regressorIndex-1;
tempIndex2=regressorIndex + subl-1;
}
if (max>5000)
shifts=2;
else
shifts=0;
energy=BasicFunctions.scaleRight(regressor, regressorIndex, regressor, regressorIndex, subl, shifts);
for (k=0;k<searchLen;k++)
{
tempIndex3=targetIndex;
tempIndex4=regressorIndex + pos;
crossCorr=BasicFunctions.scaleRight(target, tempIndex3, regressor, tempIndex4, subl, shifts);
if ((energy>0)&&(crossCorr>0))
{
/* Put cross correlation and energy on 16 bit word */
crossCorrScale=(short)(BasicFunctions.norm(crossCorr)-16);
if(crossCorrScale>0)
crossCorrMod=(short)(crossCorr<<crossCorrScale);
else
crossCorrMod=(short)(crossCorr>>(0-crossCorrScale));
energyScale=(short)(BasicFunctions.norm(energy)-16);
if(energyScale>0)
energyMod=(short)(energy<<energyScale);
else
energyMod=(short)(energy>>(0-energyScale));
/* Square cross correlation and store upper WebRtc_Word16 */
crossCorrSqMod=(short)((crossCorrMod * crossCorrMod) >> 16);
/* Calculate the total number of (dynamic) right shifts that have
been performed on (crossCorr*crossCorr)/energy
*/
totScale=(short)(energyScale-(crossCorrScale<<1));
/* Calculate the shift difference in order to be able to compare the two
(crossCorr*crossCorr)/energy in the same domain
*/
scaleDiff=(short)(totScale-totScaleMax);
if(scaleDiff>31)
scaleDiff=31;
else if(scaleDiff<-31)
scaleDiff=-31;
//if(k<2)
// System.out.println("SQ MOD:" + crossCorrSqMod + ",SCALE DIFF:" + scaleDiff);
/* Compute the cross multiplication between the old best criteria
and the new one to be able to compare them without using a
division */
if (scaleDiff<0)
{
newCrit = ((crossCorrSqMod*energyModMax)>>(-scaleDiff));
maxCrit = crossCorrSqModMax*energyMod;
}
else
{
newCrit = crossCorrSqMod*energyModMax;
maxCrit = ((crossCorrSqModMax*energyMod)>>scaleDiff);
}
/* Store the new lag value if the new criteria is larger
than previous largest criteria */
if (newCrit > maxCrit)
{
crossCorrSqModMax = crossCorrSqMod;
energyModMax = energyMod;
totScaleMax = totScale;
maxLag = (short)k;
}
}
pos+=step;
/* Do a +/- to get the next energy */
temp=regressor[tempIndex2]*regressor[tempIndex2] - regressor[tempIndex1]*regressor[tempIndex1];
temp>>=shifts;
energy += step*temp;
tempIndex1+=step;
tempIndex2+=step;
}
return(maxLag+offset);
}
public static void doThePlc(DecoderState decoderState,short[] plcResidual,int plcResidualIndex,short[] plcLpc,int plcLpcIndex,short pli,short[] decResidual,int decResidualIndex,short[] lpc,int lpcIndex,short inLag)
{
short[] randVec=new short[240];
short scale,scale1,scale2,totScale;
short shift1,shift2,shift3,shiftMax;
short useGain,totGain,maxPerSquare,pitchFact,useLag,randLag,pick,crossSquareMax, crossSquare,tempS,tempS2,lag,max,denom,nom,corrLen;
int temp,temp2,tempShift,i,energy,j,ind,measure,maxMeasure;
CorrData tempCorrData=new CorrData(),corrData=new CorrData();
tempCorrData.setEnergy(0);
if (pli == 1)
{
decoderState.setConsPliCount(decoderState.getConsPliCount()+1);
if (decoderState.getPrevPli() != 1)
{
max=BasicFunctions.getMaxAbsValue(decoderState.getPrevResidual(),0,decoderState.SIZE);
scale = (short)((BasicFunctions.getSize(max)<<1) - 25);
if (scale < 0)
scale = 0;
decoderState.setPrevScale(scale);
lag = (short)(inLag - 3);
if(60 > decoderState.SIZE-inLag-3)
corrLen=60;
else
corrLen=(short)(decoderState.SIZE-inLag-3);
compCorr(corrData, decoderState.getPrevResidual(), 0, lag, decoderState.SIZE, corrLen, scale);
shiftMax = (short)(BasicFunctions.getSize(Math.abs(corrData.getCorrelation()))-15);
if(shiftMax>0)
{
tempShift=corrData.getCorrelation()>>shiftMax;
tempShift=tempShift*tempShift;
crossSquareMax=(short)(tempShift>>15);
}
else
{
tempShift=corrData.getCorrelation()<<(0-shiftMax);
tempShift=tempShift*tempShift;
crossSquareMax=(short)(tempShift>>15);
}
for (j=inLag-2;j<=inLag+3;j++)
{
compCorr(tempCorrData, decoderState.getPrevResidual(), 0, (short)j, decoderState.SIZE, corrLen, scale);
shift1 = (short)(BasicFunctions.getSize(Math.abs(tempCorrData.getCorrelation())-15));
if(shift1>0)
{
tempShift=tempCorrData.getCorrelation()>>shift1;
tempShift=tempShift*tempShift;
crossSquare=(short)(tempShift>>15);
}
else
{
tempShift=tempCorrData.getCorrelation()<<(0-shift1);
tempShift=tempShift*tempShift;
crossSquare=(short)(tempShift>>15);
}
shift2 = (short)(BasicFunctions.getSize(corrData.getEnergy())-15);
if(shift2>0)
measure=(corrData.getEnergy()>>shift2)*crossSquare;
else
measure=(corrData.getEnergy()<<(0-shift2))*crossSquare;
shift3 = (short)(BasicFunctions.getSize(tempCorrData.getEnergy())-15);
if(shift3>0)
maxMeasure=(tempCorrData.getEnergy()>>shift3)*crossSquareMax;
else
maxMeasure=(tempCorrData.getEnergy()<<(0-shift3))*crossSquareMax;
if(((shiftMax<<1)+shift3) > ((shift1<<1)+shift2))
{
tempShift=(shiftMax<<1);
tempShift-=(shift1<<1);
tempShift=tempShift+shift3-shift2;
if(tempShift>31)
tempS = 31;
else
tempS= (short)tempShift;
tempS2 = 0;
}
else
{
tempS = 0;
tempShift=(shift1<<1);
tempShift-=(shiftMax<<1);
tempShift=tempShift+shift2-shift3;
if(tempShift>31)
tempS2 = 31;
else
tempS2=(short)tempShift;
}
if ((measure>>tempS) > (maxMeasure>>tempS2))
{
lag = (short)j;
crossSquareMax = crossSquare;
corrData.setCorrelation(tempCorrData.getCorrelation());
shiftMax = shift1;
corrData.setEnergy(tempCorrData.getEnergy());
}
}
temp2=BasicFunctions.scaleRight(decoderState.getPrevResidual(),decoderState.SIZE-corrLen,decoderState.getPrevResidual(),decoderState.SIZE-corrLen,corrLen, scale);
if ((temp2>0)&&(tempCorrData.getEnergy()>0))
{
scale1=(short)(BasicFunctions.norm(temp2)-16);
if(scale1>0)
tempS=(short)(temp2<<scale1);
else
tempS=(short)(temp2>>(0-scale1));
scale2=(short)(BasicFunctions.norm(corrData.getEnergy())-16);
if(scale2>0)
tempS2=(short)(corrData.getEnergy()<<scale2);
else
tempS2=(short)(corrData.getEnergy()>>(0-scale2));
denom=(short)((tempS*tempS2)>>16);
totScale = (short)(scale1+scale2-1);
tempShift=(totScale>>1);
if(tempShift>0)
tempS = (short)(corrData.getCorrelation()<<tempShift);
else
tempS = (short)(corrData.getCorrelation()>>(0-tempShift));
tempShift=totScale-tempShift;
if(tempShift>0)
tempS2 = (short)(corrData.getCorrelation()<<tempShift);
else
tempS2 = (short)(corrData.getCorrelation()>>(0-tempShift));
nom = (short)(tempS*tempS2);
maxPerSquare = (short)(nom/denom);
}
else
maxPerSquare = 0;
}
else
{
lag = decoderState.getPrevLag();
maxPerSquare = decoderState.getPerSquare();
}
useGain = 32767;
if (decoderState.getConsPliCount()*decoderState.SIZE>320)
useGain = 29491;
else if (decoderState.getConsPliCount()*decoderState.SIZE>640)
useGain = 22938;
else if (decoderState.getConsPliCount()*decoderState.SIZE>960)
useGain = 16384;
else if (decoderState.getConsPliCount()*decoderState.SIZE>1280)
useGain = 0;
if (maxPerSquare>7868)
pitchFact = 32767;
else if (maxPerSquare>839)
{
ind = 5;
while ((maxPerSquare<Constants.PLC_PER_SQR[ind]) && (ind>0))
ind--;
temp = Constants.PLC_PITCH_FACT[ind];
temp += ((Constants.PLC_PF_SLOPE[ind]*(maxPerSquare-Constants.PLC_PER_SQR[ind])) >> 11);
if(temp>Short.MIN_VALUE)
pitchFact=Short.MIN_VALUE;
else
pitchFact=(short)temp;
}
else
pitchFact = 0;
useLag = lag;
if (lag<80)
useLag = (short)(2*lag);
energy = 0;
for (i=0; i<decoderState.SIZE; i++)
{
decoderState.setSeed((short)((decoderState.getSeed()*31821) + 13849));
randLag = (short)(53 + (decoderState.getSeed() & 63));
pick = (short)(i - randLag);
if (pick < 0)
randVec[i] = decoderState.getPrevResidual()[decoderState.SIZE+pick];
else
randVec[i] = decoderState.getPrevResidual()[pick];
pick = (short)(i - useLag);
if (pick < 0)
plcResidual[plcResidualIndex + i] = decoderState.getPrevResidual()[decoderState.SIZE+pick];
else
plcResidual[plcResidualIndex + i] = plcResidual[plcResidualIndex + pick];
if (i<80)
totGain=useGain;
else if (i<160)
totGain=(short)((31130 * useGain) >> 15);
else
totGain=(short)((29491 * useGain) >> 15);
tempShift=pitchFact * plcResidual[plcResidualIndex + i];
tempShift+=(32767-pitchFact)*randVec[i];
tempShift+=16384;
temp=(short)(tempShift>>15);
plcResidual[plcResidualIndex + i] = (short)((totGain*temp)>>15);
tempShift=plcResidual[plcResidualIndex + i] * plcResidual[plcResidualIndex + i];
energy += (short)(tempShift>>(decoderState.getPrevScale()+1));
}
tempShift=decoderState.SIZE*900;
if(decoderState.getPrevScale()+1>0)
tempShift=tempShift>>(decoderState.getPrevScale()+1);
else
tempShift=tempShift<<(0-decoderState.getPrevScale()-1);
if (energy < tempShift)
{
energy = 0;
for (i=0; i<decoderState.SIZE; i++)
plcResidual[plcResidualIndex + i] = randVec[i];
}
System.arraycopy(decoderState.getPrevLpc(), 0, plcLpc, plcLpcIndex, 10);
decoderState.setPrevLag(lag);
decoderState.setPerSquare(maxPerSquare);
}
else
{
System.arraycopy(decResidual, decResidualIndex, plcResidual, plcResidualIndex, decoderState.SIZE);
System.arraycopy(lpc, lpcIndex, plcLpc, plcLpcIndex, 11);
decoderState.setConsPliCount(0);
}
decoderState.setPrevPli(pli);
System.arraycopy(plcLpc, plcLpcIndex, decoderState.getPrevLpc(), 0, 11);
System.arraycopy(plcResidual, plcResidualIndex, decoderState.getPrevResidual(), 0, decoderState.SIZE);
}
public static void compCorr(CorrData currData,short[] buffer,int bufferIndex,short lag,short bLen,short sRange,short scale)
{
int currIndex=bLen-sRange-lag;
if(scale>0)
{
currData.setCorrelation(BasicFunctions.scaleRight(buffer, bufferIndex + bLen - sRange, buffer, currIndex, sRange, scale));
currData.setEnergy(BasicFunctions.scaleRight(buffer, currIndex, buffer, currIndex, sRange, scale));
}
else
{
currData.setCorrelation(BasicFunctions.scaleLeft(buffer, bufferIndex + bLen - sRange, buffer, currIndex, sRange, (0-scale)));
currData.setEnergy(BasicFunctions.scaleLeft(buffer, currIndex, buffer, currIndex, sRange, scale));
}
if (currData.getCorrelation() == 0)
{
currData.setCorrelation(0);
currData.setEnergy(1);
}
}
}