Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

716 lines
16 KiB

//
// ITU-T G.723 Floating Point Speech Coder ANSI C Source Code. Version 1.00
// copyright (c) 1995, AudioCodes, DSP Group, France Telecom,
// Universite de Sherbrooke, Intel Corporation. All rights reserved.
//
#include <stdio.h>
#include <math.h>
#include "opt.h"
#include "typedef.h"
#include "cst_lbc.h"
#include "tab_lbc.h"
#include "util_lbc.h"
#include "lsp.h"
#include "timer.h"
#include "mmxutil.h"
#if COMPILE_MMX
// This file includes all the Lsp related functions
//--------------------------------------------------------------
int mult(short x, short y)
{
return ( ((int)x)*((int)y) >> 16 );
}
//--------------------------------------------------------------
int LspSearchInt(short *Lspw, short *LspTab)
{
#if ASM_SVQ
int mem8000[2] = {0x80008000,0x80008000}, zero[2] = {0,0};
short maxes[4],mx;
int retu;
int *ptr,tmp,t,i,k;
#define lsp esi
#define tab edi
#define idx edx
#define pidx eax // packed index: n+3 n+2 n+1 n
#define maxi ecx
#define r0 mm0
#define r1 mm1
#define r2 mm2
#define r3 mm3
#define r4 mm4
#define max mm5
// Expand Lspw table so it's 0000 1111 2222 3333 4444 5555 6666 7777
ptr = (int *)Lspw;
k = 14;
for (i=7; i>=0; i--)
{
t = Lspw[i]; t = t & 0xffff;
tmp = t;
tmp = (tmp << 16) | t;
ptr[k] = ptr[k+1] = tmp;
k -= 2;
}
// Need LspTab to be ordered 0 4 8 12 1 5 9 13 etc.
// so that lo word of each qword sees 0123, next sees 4567, etc.
//
// 'idx' counts iterations, so it goes 0 to 256 in steps of 4.
// The 4 LspTab sets at any given time are 8*idx, 8*idx+8, +16, +24
// Lspw[n] is lsp+8*n, as defined below
#define a(n) [tab+8*idx+8*n]
#define b(n) [lsp+8*n]
ASM
{
push lsp;
push tab;
push idx;
push pidx;
push maxi;
mov lsp,Lspw;
mov tab,LspTab;
xor idx,idx;
xor maxi,maxi;
mov pidx,003020100h;
movq max,mem8000;
/*
The code below is interleaved with k=1.
The structure is: four levels of indentation, one for each of the
4 terms of the sum. The instructions completely left-justified
are the part of the loop that's wrapped around on itself.
Note that the code reads 8 bytes past the end of the LspTab that's
passed to it. This is made o.k. by making the table that's passed
to it have 8 dummy bytes at the end.
*/
// Start up the pipeline
movq r0,a(0);
movq r1,r0;
pmulhw r0,b(4);
psubsw r1,b(0);
movq r2,a(1);
movq r3,r2;
psllw r0,2;
pmulhw r0,r1;
pmulhw r2,b(5);
psubsw r3,b(1);
movq r1,a(2);
psllw r2,2;
pmulhw r2,r3;
movq r3,r1;
pmulhw r1,b(6);
psubsw r3,b(2);
paddw r0,r2;
movq r2,a(3);
psllw r1,2;
pmulhw r1,r3;
movq r3,r2;
pmulhw r2,b(7);
psubsw r3,b(3);
paddw r1,r0;
loop1:
movq r0,a(4);
movq r4,r1; // save accum so not wiped out by first half of loop
psllw r2,2;
movq r1,r0;
pmulhw r2,r3;
pmulhw r0,b(4);
psubsw r1,b(0);
paddw r4,r2; // now final answer is in r4
movq r2,a(5);
paddw r4,mem8000 // make final sum unsigned
movq r3,r2; // 0123
psllw r0,2;
psubusw max,r4 // start to compute max
pmulhw r0,r1; // 0.23
pmulhw r2,b(5);
paddw max,r4 // max now done
psubsw r3,b(1);
pcmpeqw r4,max // now 1111's means a new max was found
movq r1,a(6); // 0123
packsswb r4,r4; // put all fields in low 32 bits
psllw r2,2;
movd ebx,r4;
pmulhw r2,r3; // 012.
xor ebx,0ffffffffh; // invert mask
and maxi,ebx; // get old index to keep
movq r3,r1; // 0123
pmulhw r1,b(6);
psubsw r3,b(2);
xor ebx,0ffffffffh; // invert mask
paddw r0,r2; // 01.3
and ebx,pidx; // get new index
psllw r1,2;
movq r2,a(7);// 0123
pmulhw r1,r3; // 012.
movq r3,r2; // 0123
or maxi,ebx; // now maxi is done
pmulhw r2,b(7);
psubsw r3,b(3);
paddw r1,r0; // .123
add idx,4;
add pidx,004040404h;
cmp idx,256;
jl loop1;
psubw max,mem8000;
mov retu,maxi;
movq maxes,max;
pop maxi;
pop pidx;
pop idx;
pop tab;
pop lsp;
}
// find which of the 4 maxes is the max, and return the appropriate
// one of the 4 maxindices.
mx = maxes[0]; t = 0;
if (maxes[1] >= mx) { mx = maxes[1]; t = 8; }
if (maxes[2] >= mx) { mx = maxes[2]; t = 16; }
if (maxes[3] >= mx) { mx = maxes[3]; t = 24; }
ASM emms;
retu = (retu >> t) & 0xff;
return(retu);
#undef a
#undef b
#undef idx
#undef lsp
#undef tab
#undef max
#undef maxi
#else // if assembly code not selected, use C code
int Indx[4],i,s,ret;
short Max[4],Err,mx;
short m0,m1,m2,m3,m4,m5,m6,m7,t;
for (i=0; i<4; i++)
{
Max[i] = Indx[i] = 0;
}
for (i=0; i < LspCbSize; i++)
{
s = (i&3);
m0 = mult(Lspw[4],LspTab[s+0]);
t = LspTab[s+0]-Lspw[0]; m1 = mult(t,m0<<2);
m2 = mult(Lspw[5],LspTab[s+4]);
t = LspTab[s+4]-Lspw[1]; m3 = mult(t,m2<<2);
m4 = mult(Lspw[6],LspTab[s+8]);
t = LspTab[s+8]-Lspw[2]; m5 = mult(t,m4<<2);
m6 = mult(Lspw[7],LspTab[s+12]);
t = LspTab[s+12]-Lspw[3]; m7 = mult(t,m6<<2);
Err = m1+m3+m5+m7;
if (Err >= Max[s])
{
Max[s] = Err;
Indx[s] = i;
}
if (s==3)
LspTab += 16;
}
mx = Max[0]; ret = Indx[0];
if (Max[1] >= mx) { mx = Max[1]; ret = Indx[1]; }
if (Max[2] >= mx) { mx = Max[2]; ret = Indx[2]; }
if (Max[3] >= mx) { mx = Max[3]; ret = Indx[3]; }
return(ret);
#endif
}
//--------------------------------------------------------------
Word32 Svq_Int(float *Lsp, float *Wvect)
{
#define LSP_SCALE 256
int i;
Word32 Rez;
int z;
short Wint[LpcOrder],LspTemp[LpcOrder];
DECLARE_SHORT(Lspw,32);
ALIGN_ARRAY(Lspw);
for (i=0; i<LpcOrder; i++)
{
z = (int)(LSP_SCALE*2*Lsp[i]);
if (z > 32767) LspTemp[i] = 32767;
else if (z < -32768) LspTemp[i] = -32768;
else LspTemp[i] = z;
}
FloatToShortScaled(Wvect,Wint,10,0);
Rez = (Word32) 0;
// For each of the 3 bands
Lspw[0] = LspTemp[0]; Lspw[1] = LspTemp[1]; Lspw[2] = LspTemp[2];
Lspw[3] = 0;
Lspw[4] = -Wint[0]; Lspw[5] = -Wint[1]; Lspw[6] = -Wint[2];
Lspw[7] = 0;
Rez = LspSearchInt(Lspw,LspTableInt);
Lspw[0] = LspTemp[3]; Lspw[1] = LspTemp[4]; Lspw[2] = LspTemp[5];
Lspw[3] = 0;
Lspw[4] = -Wint[3]; Lspw[5] = -Wint[4]; Lspw[6] = -Wint[5];
Lspw[7] = 0;
Rez = (Rez<<8) + LspSearchInt(Lspw,&LspTableInt[1024]);
Lspw[0] = LspTemp[6]; Lspw[1] = LspTemp[7]; Lspw[2] = LspTemp[8];
Lspw[3] = LspTemp[9];
Lspw[4] = -Wint[6]; Lspw[5] = -Wint[7]; Lspw[6] = -Wint[8];
Lspw[7] = -Wint[9];
Rez = (Rez<<8) + LspSearchInt(Lspw,&LspTableInt[2048]);
return Rez;
}
#endif
//---------------------------------------------------------------
float Polynomial(float *Lpq, int CosPtr)
{
return(Lpq[LpcOrder]*CosineTable[0] +
Lpq[LpcOrder-2]*CosineTable[CosPtr] +
Lpq[LpcOrder-4]*CosineTable[(CosPtr*2)&(CosineTableSize-1)] +
Lpq[LpcOrder-6]*CosineTable[(CosPtr*3)&(CosineTableSize-1)] +
Lpq[LpcOrder-8]*CosineTable[(CosPtr*4)&(CosineTableSize-1)] +
Lpq[LpcOrder-10]*CosineTable[(CosPtr*5)&(CosineTableSize-1)]);
}
//--------------------------------------------------------------
void AtoLsp(float *LspVect, float *Lpc, float *PrevLsp)
{
int i,j,k;
int LspCnt;
float Lpq[LpcOrder+2];
float PrevVal,CurrVal,AbsPrev,AbsCurr;
// Small additional bandwidth expansion
for (i=0; i < LpcOrder; i++)
LspVect[i] = Lpc[i]*BandExpTable[i];
// Compute Lp and Lq
Lpq[0] = Lpq[1] = 1.0f;
for (i=0; i < LpcOrder/2; i++)
{
Lpq[2*i+2] = -Lpq[2*i+0] - LspVect[i] - LspVect[LpcOrder-1-i];
Lpq[2*i+3] = Lpq[2*i+1] - LspVect[i] + LspVect[LpcOrder-1-i];
}
Lpq[LpcOrder+0] *= 0.5f;
Lpq[LpcOrder+1] *= 0.5f;
// Do first evaluation
k = 0;
LspCnt = 0;
PrevVal = Polynomial(Lpq,0);
for (i=1; i < CosineTableSize/2; i++)
{
// Evaluate the polynomial
CurrVal = Polynomial(&Lpq[k],i);
// Test for sign change
if ((asint(CurrVal) ^ asint(PrevVal)) < 0)
{
AbsPrev = (float)fabs(PrevVal);
AbsCurr = (float)fabs(CurrVal);
LspVect[LspCnt++] = (i-1 + AbsPrev/(AbsPrev+AbsCurr));
// Check if all found
if (LspCnt == LpcOrder)
break;
// Switch the pointer, evaluate again
k ^= 1;
CurrVal = Polynomial(&Lpq[k],i);
}
PrevVal = CurrVal;
}
// Check if all Lsp found
if (LspCnt != LpcOrder)
{
for (j=0; j < LpcOrder; j++)
LspVect[j] = PrevLsp[j];
}
return;
}
//--------------------------------------------------------------
Word32 Lsp_Qnt(float *CurrLsp, float *PrevLsp, int UseMMX)
{
int i;
float Wvect[LpcOrder];
float Min,Tmp;
// Compute the weighting vector
Wvect[0] = 1.0f/(CurrLsp[1] - CurrLsp[0]);
Wvect[LpcOrder-1] = 1.0f/(CurrLsp[LpcOrder-1] - CurrLsp[LpcOrder-2]);
for (i=1; i < LpcOrder-1; i++)
{
Min = CurrLsp[i+1] - CurrLsp[i];
Tmp = CurrLsp[i] - CurrLsp[i-1];
if (Tmp < Min)
Min = Tmp;
if (Min > 0.0f)
Wvect[i] = 1.0f/Min;
else
Wvect[i] = 1.0f;
}
// Generate predicted vector as (DC-removed-Curr) - b*(DC-removed-Prev)
CurrLsp[0] = (CurrLsp[0] - LspDcTable[0]) -
LspPred0*(PrevLsp[0] - LspDcTable[0]);
CurrLsp[1] = (CurrLsp[1] - LspDcTable[1]) -
LspPred0*(PrevLsp[1] - LspDcTable[1]);
CurrLsp[2] = (CurrLsp[2] - LspDcTable[2]) -
LspPred0*(PrevLsp[2] - LspDcTable[2]);
CurrLsp[3] = (CurrLsp[3] - LspDcTable[3]) -
LspPred0*(PrevLsp[3] - LspDcTable[3]);
CurrLsp[4] = (CurrLsp[4] - LspDcTable[4]) -
LspPred0*(PrevLsp[4] - LspDcTable[4]);
CurrLsp[5] = (CurrLsp[5] - LspDcTable[5]) -
LspPred0*(PrevLsp[5] - LspDcTable[5]);
CurrLsp[6] = (CurrLsp[6] - LspDcTable[6]) -
LspPred0*(PrevLsp[6] - LspDcTable[6]);
CurrLsp[7] = (CurrLsp[7] - LspDcTable[7]) -
LspPred0*(PrevLsp[7] - LspDcTable[7]);
CurrLsp[8] = (CurrLsp[8] - LspDcTable[8]) -
LspPred0*(PrevLsp[8] - LspDcTable[8]);
CurrLsp[9] = (CurrLsp[9] - LspDcTable[9]) -
LspPred0*(PrevLsp[9] - LspDcTable[9]);
// Do the SVQ
#if COMPILE_MMX
if (UseMMX)
return Svq_Int(CurrLsp, Wvect);
else
#endif
return Lsp_Svq(CurrLsp, Wvect);
}
//--------------------------------------------------------------
Word32 Lsp_Svq(float *Lsp, float *Wvect)
{
int i,k;
Word32 Rez;
int Indx,Start,Dim;
float *LspQntPnt;
float Max,Err,lsp0,lsp1,lsp2,lsp3,w0,w1,w2,w3;
float LspTemp[LpcOrder];
for (i=0; i<LpcOrder; i++)
LspTemp[i] = 2.0f*Lsp[i];
Rez = (Word32) 0;
// For each of the 3 bands
for (k=0; k < LspQntBands; k++)
{
// Initialize the search
Max = 0.0f; //-1.0f;
Indx = 0;
LspQntPnt = BandQntTable[k];
Start = BandInfoTable[k][0];
Dim = BandInfoTable[k][1];
lsp0 = LspTemp[Start+0];
lsp1 = LspTemp[Start+1];
lsp2 = LspTemp[Start+2];
w0 = Wvect[Start+0];
w1 = Wvect[Start+1];
w2 = Wvect[Start+2];
if (k < 2)
{
for (i=0; i < LspCbSize; i++)
{
Err = (lsp0 - LspQntPnt[0])*w0*LspQntPnt[0] +
(lsp1 - LspQntPnt[1])*w1*LspQntPnt[1] +
(lsp2 - LspQntPnt[2])*w2*LspQntPnt[2];
LspQntPnt += 3;
if (asint(Err) > asint(Max))
{
Max = Err;
Indx = i;
}
}
}
else
{
lsp3 = LspTemp[Start+3];
w3 = Wvect[Start+3];
for (i=0; i < LspCbSize; i++)
{
Err = (lsp0 - LspQntPnt[0])*w0*LspQntPnt[0] +
(lsp1 - LspQntPnt[1])*w1*LspQntPnt[1] +
(lsp2 - LspQntPnt[2])*w2*LspQntPnt[2] +
(lsp3 - LspQntPnt[3])*w3*LspQntPnt[3];
LspQntPnt += 4;
if (asint(Err) > asint(Max))
{
Max = Err;
Indx = i;
}
}
}
Rez = (Rez << 8) | Indx;
}
return Rez;
}
//--------------------------------------------------------------
Flag Lsp_Inq(float *Lsp, float *PrevLsp, Word32 LspId, int Crc)
{
int i,j;
float *LspQntPnt;
float Lprd,Scon,Tmpf,Scon2;
int Tmp;
Flag Test;
if (Crc == 0)
{
Scon = 2.0f;
Lprd = LspPred0;
}
else
{
LspId = (Word32) 0;
Scon = 4.0f;
Lprd = LspPred1;
}
Scon2 = Scon - 0.03125f;
// Reconstruct the LSP vector
for (i=LspQntBands-1; i >= 0; i--)
{
Tmp = LspId & (Word32) 0x000000ff;
LspId >>= 8;
LspQntPnt = BandQntTable[i];
for (j=0; j < BandInfoTable[i][1]; j++)
Lsp[BandInfoTable[i][0] + j] = LspQntPnt[Tmp*BandInfoTable[i][1] + j];
}
// Add predicted vector and DC to decoded vector
for (j=0; j < LpcOrder; j++)
Lsp[j] = Lsp[j] + (PrevLsp[j] - LspDcTable[j])*Lprd + LspDcTable[j];
// Perform the stability check
for (i=0; i < LpcOrder; i++)
{
// Test the first and last one
if (Lsp[0] < 3.0)
Lsp[0] = 3.0f;
if (Lsp[LpcOrder-1] > 252.0f)
Lsp[LpcOrder-1] = 252.0f;
// Test the others
for (j=1; j < LpcOrder; j++)
{
Tmpf = Scon + Lsp[j-1] - Lsp[j];
if (Tmpf > 0)
{
Tmpf *= 0.5f;
Lsp[j-1] -= Tmpf;
Lsp[j] += Tmpf;
}
}
// Test if stable
Test = False;
for (j=1; j < LpcOrder; j++)
if ((Lsp[j] - Lsp[j-1]) < Scon2)
Test = True;
if (Test == False)
break;
}
if (Test == True)
for (j=0; j < LpcOrder; j++)
Lsp[j] = PrevLsp[j];
return Test;
}
//--------------------------------------------------------------
void Lsp_Int(float *QntLpc, float *CurrLsp, float *PrevLsp)
{
int i,j;
float *Dpnt;
float Fac[4] = {0.25f, 0.5f, 0.75f, 1.0f};
Dpnt = QntLpc;
for (i=0; i < SubFrames; i++)
{
// Interpolate
for (j=0; j < LpcOrder; j++)
Dpnt[j] = (1.0f - Fac[i])*PrevLsp[j] + Fac[i]*CurrLsp[j];
// Convert to Lpc
LsptoA(Dpnt);
Dpnt += LpcOrder;
}
// Copy the Lsp vector
for (i=0; i < LpcOrder; i++)
PrevLsp[i] = CurrLsp[i];
}
//--------------------------------------------------------------
void LsptoA(float *Lsp)
{
int i,j;
float P[LpcOrder/2+1];
float Q[LpcOrder/2+1];
float Fac[(LpcOrder/2)-2] = {1.0f,0.5f,0.25f};
// Convert Lsp's to cosines
for (i=0; i < LpcOrder; i++)
{
j = MyFloor(Lsp[i]);
Lsp[i] = -(CosineTable[j] +
(CosineTable[j+1]-CosineTable[j])*(Lsp[i]-j));
}
// Init P and Q. Note that P,Q * 2^26 correspond to fixed-point code
P[0] = 0.5f;
P[1] = Lsp[0] + Lsp[2];
P[2] = 1.0f + 2.0f*Lsp[0]*Lsp[2];
Q[0] = 0.5f;
Q[1] = Lsp[1] + Lsp[3];
Q[2] = 1.0f + 2.0f*Lsp[1]*Lsp[3];
// Compute all the others
for (i=2; i < LpcOrder/2; i++)
{
P[i+1] = P[i-1] + P[i]*Lsp[2*i+0];
Q[i+1] = Q[i-1] + Q[i]*Lsp[2*i+1];
// All update
for (j=i; j >= 2; j--)
{
P[j] = P[j-1]*Lsp[2*i+0] + 0.5f*(P[j]+P[j-2]);
Q[j] = Q[j-1]*Lsp[2*i+1] + 0.5f*(Q[j]+Q[j-2]);
}
// Update PQ[01]
P[0] = P[0]*0.5f;
Q[0] = Q[0]*0.5f;
P[1] = (P[1] + Lsp[2*i+0]*Fac[i-2])*0.5f;
Q[1] = (Q[1] + Lsp[2*i+1]*Fac[i-2])*0.5f;
}
// Convert to Lpc
for (i=0; i < LpcOrder/2; i++)
{
Lsp[i] = (-P[i] - P[i+1] + Q[i] - Q[i+1])*8.0f;
Lsp[LpcOrder-1-i] = (-P[i] - P[i+1] - Q[i] + Q[i+1])*8.0f;
}
}