Doing the spreading with a "pseudo-fractional-Hadamard" transform
This commit is contained in:
parent
8974f00d53
commit
354bf60b04
1 changed files with 66 additions and 46 deletions
108
libcelt/vq.c
108
libcelt/vq.c
|
@ -45,58 +45,78 @@
|
||||||
#define M_PI 3.141592653
|
#define M_PI 3.141592653
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K)
|
static void frac_hadamard1(celt_norm *X, int len, int stride, celt_word16 c, celt_word16 s)
|
||||||
{
|
{
|
||||||
int i, k, iter;
|
int j;
|
||||||
celt_word16 c, s;
|
celt_norm *x, *y;
|
||||||
celt_word16 gain, theta;
|
celt_norm * end;
|
||||||
celt_norm *Xptr;
|
|
||||||
gain = celt_div((celt_word32)MULT16_16(Q15_ONE,len),(celt_word32)(3+len+6*K));
|
j = 0;
|
||||||
/* FIXME: Make that HALF16 instead of HALF32 */
|
x = X;
|
||||||
theta = SUB16(Q15ONE, HALF32(MULT16_16_Q15(gain,gain)));
|
y = X+stride;
|
||||||
/*if (len==30)
|
end = X+len;
|
||||||
{
|
do
|
||||||
for (i=0;i<len;i++)
|
|
||||||
X[i] = 0;
|
|
||||||
X[14] = 1;
|
|
||||||
}*/
|
|
||||||
c = celt_cos_norm(EXTEND32(theta));
|
|
||||||
s = dir*celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /* sin(theta) */
|
|
||||||
if (len > 8*stride)
|
|
||||||
stride *= len/(8*stride);
|
|
||||||
iter = 1;
|
|
||||||
for (k=0;k<iter;k++)
|
|
||||||
{
|
|
||||||
/* We could use MULT16_16_P15 instead of MULT16_16_Q15 for more accuracy,
|
|
||||||
but at this point, I really don't think it's necessary */
|
|
||||||
Xptr = X;
|
|
||||||
for (i=0;i<len-stride;i++)
|
|
||||||
{
|
{
|
||||||
celt_norm x1, x2;
|
celt_norm x1, x2;
|
||||||
x1 = Xptr[0];
|
x1 = *x;
|
||||||
x2 = Xptr[stride];
|
x2 = *y;
|
||||||
Xptr[stride] = EXTRACT16(SHR32(MULT16_16(c,x2) + MULT16_16(s,x1),15));
|
*x++ = EXTRACT16(SHR32(MULT16_16(c,x1) + MULT16_16(s,x2),15));
|
||||||
*Xptr++ = EXTRACT16(SHR32(MULT16_16(c,x1) - MULT16_16(s,x2),15));
|
*y++ = EXTRACT16(SHR32(MULT16_16(s,x1) - MULT16_16(c,x2),15));
|
||||||
}
|
j++;
|
||||||
Xptr = &X[len-2*stride-1];
|
if (j>=stride)
|
||||||
for (i=len-2*stride-1;i>=0;i--)
|
|
||||||
{
|
{
|
||||||
celt_norm x1, x2;
|
j=0;
|
||||||
x1 = Xptr[0];
|
x+=stride;
|
||||||
x2 = Xptr[stride];
|
y+=stride;
|
||||||
Xptr[stride] = EXTRACT16(SHR32(MULT16_16(c,x2) + MULT16_16(s,x1),15));
|
|
||||||
*Xptr-- = EXTRACT16(SHR32(MULT16_16(c,x1) - MULT16_16(s,x2),15));
|
|
||||||
}
|
}
|
||||||
}
|
} while (y<end);
|
||||||
/*if (len==30)
|
|
||||||
|
/* Reverse samples so that the next level starts from the other end */
|
||||||
|
for (j=0;j<len>>1;j++)
|
||||||
{
|
{
|
||||||
for (i=0;i<len;i++)
|
celt_norm tmp = X[j];
|
||||||
printf ("%f ", X[i]);
|
X[j] = X[len-j-1];
|
||||||
printf ("\n");
|
X[len-j-1] = tmp;
|
||||||
exit(0);
|
}
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_LEVELS 8
|
||||||
|
static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K)
|
||||||
|
{
|
||||||
|
int i, N=0;
|
||||||
|
celt_word16 gain, theta;
|
||||||
|
int istride[MAX_LEVELS];
|
||||||
|
celt_word16 c, s;
|
||||||
|
|
||||||
|
do {
|
||||||
|
istride[N] = stride;
|
||||||
|
stride *= 2;
|
||||||
|
N++;
|
||||||
|
} while (N<MAX_LEVELS && stride < len);
|
||||||
|
|
||||||
|
gain = celt_div((celt_word32)MULT16_16(Q15_ONE,len),(celt_word32)(3+len+4*K));
|
||||||
|
/* FIXME: Make that HALF16 instead of HALF32 */
|
||||||
|
theta = HALF32(MULT16_16_Q15(gain,gain));
|
||||||
|
c = celt_cos_norm(EXTEND32(theta));
|
||||||
|
s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /* sin(theta) */
|
||||||
|
|
||||||
|
if (dir > 0)
|
||||||
|
{
|
||||||
|
for (i=0;i<N;i++)
|
||||||
|
frac_hadamard1(X, len, istride[i], c, s);
|
||||||
|
} else {
|
||||||
|
for (i=N-1;i>=0;i--)
|
||||||
|
frac_hadamard1(X, len, istride[i], c, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Undo last reversal */
|
||||||
|
for (i=0;i<len>>1;i++)
|
||||||
|
{
|
||||||
|
celt_norm tmp = X[i];
|
||||||
|
X[i] = X[len-i-1];
|
||||||
|
X[len-i-1] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Takes the pitch vector and the decoded residual vector, computes the gain
|
/** Takes the pitch vector and the decoded residual vector, computes the gain
|
||||||
that will give ||p+g*y||=1 and mixes the residual with the pitch. */
|
that will give ||p+g*y||=1 and mixes the residual with the pitch. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue