static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread) { static const int SPREAD_FACTOR[3]= {15,10,5}; int i; opus_val16 c, s; opus_val16 gain, theta; int stride2=0; int factor; if (2*K>=len || spread==SPREAD_NONE) return; factor = SPREAD_FACTOR[spread-1]; gain = celt_div((opus_val32)MULT16_16(Q15_ONE,len),(opus_val32)(len+factor*K)); theta = HALF16(MULT16_16_Q15(gain,gain)); c = celt_cos_norm(EXTEND32(theta)); s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /* sin(theta) */ if (len>=8*stride) { stride2 = 1; /* This is just a simple (equivalent) way of computing sqrt(len/stride) with rounding. It's basically incrementing long as (stride2+0.5)^2 < len/stride. */ while ((stride2*stride2+stride2)*stride + (stride>>2) < len) stride2++; }
static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K) { int i, k, iter; celt_word16 c, s; celt_word16 gain, theta; celt_norm *Xptr; gain = celt_div((celt_word32)MULT16_16(Q15_ONE,len),(celt_word32)(3+len+6*K)); /* FIXME: Make that HALF16 instead of HALF32 */ theta = SUB16(Q15ONE, HALF32(MULT16_16_Q15(gain,gain))); /*if (len==30) { 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; x1 = Xptr[0]; x2 = Xptr[stride]; Xptr[stride] = MULT16_16_Q15(c,x2) + MULT16_16_Q15(s,x1); *Xptr++ = MULT16_16_Q15(c,x1) - MULT16_16_Q15(s,x2); } Xptr = &X[len-2*stride-1]; for (i=len-2*stride-1;i>=0;i--) { celt_norm x1, x2; x1 = Xptr[0]; x2 = Xptr[stride]; Xptr[stride] = MULT16_16_Q15(c,x2) + MULT16_16_Q15(s,x1); *Xptr-- = MULT16_16_Q15(c,x1) - MULT16_16_Q15(s,x2); } } /*if (len==30) { for (i=0;i<len;i++) printf ("%f ", X[i]); printf ("\n"); exit(0); }*/ }