/*==================================================================================== EVS Codec 3GPP TS26.443 Jun 30, 2015. Version CR 26.443-0006 ====================================================================================*/ #include #include #include #include #include #include #include "options.h" #include "prot.h" /*------------------------------------------------------------------* * own_random() * * Random generator *------------------------------------------------------------------*/ short own_random( /* o : output random value */ short *seed /* i/o: random seed */ ) { *seed = (short) (*seed * 31821L + 13849L); return(*seed); } /*--------------------------------------------------------------------- * sign() * *---------------------------------------------------------------------*/ float sign( /* o : sign of x (+1/-1) */ const float x /* i : input value of x */ ) { if (x < 0.0f) { return -1.0f; } else { return 1.0f; } } /*--------------------------------------------------------------------- * log2_f() * *---------------------------------------------------------------------*/ float log2_f( /* o : logarithm2 of x */ const float x /* i : input value of x */ ) { return (float)(log(x)/log(2.0f)); } /*--------------------------------------------------------------------- * log2_i() * *---------------------------------------------------------------------*/ short log2_i( /* o : integer logarithm2 of x */ const unsigned int x /* i : input value of x */ ) { unsigned int v; unsigned int mask[] = {0x2, 0xc, 0xf0, 0xff00, 0xffff0000}; short shift[] = {1, 2, 4, 8, 16}; short i, r; v = x; r = 0; for (i = 4; i >= 0; i--) { if (v & mask[i]) { v >>= shift[i]; r |= shift[i]; } } return r; } /*--------------------------------------------------------------------- * sum_s() * sum_f() * *---------------------------------------------------------------------*/ short sum_s( /* o : sum of all vector elements */ const short *vec, /* i : input vector */ const short lvec /* i : length of input vector */ ) { short i; short tmp; tmp = 0; for( i=0; i= 0; i--) { y[i] = x[i]; } } return; } void mvs2s( const short x[], /* i : input vector */ short y[], /* o : output vector */ const short n /* i : vector size */ ) { short i; if ( n <= 0 ) { /* cannot transfer vectors with size 0 */ return; } if (y < x) { for (i = 0; i < n; i++) { y[i] = x[i]; } } else { for (i = n-1; i >= 0; i--) { y[i] = x[i]; } } return; } unsigned int mvr2s( const float x[], /* i : input vector */ short y[], /* o : output vector */ const short n /* i : vector size */ ) { short i; float temp; unsigned int noClipping = 0; if ( n <= 0 ) { /* cannot transfer vectors with size 0 */ return 0; } if ((void*)y < (const void*)x) { for (i = 0; i < n; i++) { temp = x[i]; temp = (float)floor(temp + 0.5f); if (temp > 32767.0f ) { temp = 32767.0f; noClipping++; } else if (temp < -32768.0f ) { temp = -32768.0f; noClipping++; } y[i] = (short)temp; } } else { for (i = n-1; i >= 0; i--) { temp = x[i]; temp = (float)floor(temp + 0.5f); if (temp > 32767.0f ) { temp = 32767.0f; noClipping++; } else if (temp < -32768.0f ) { temp = -32768.0f; noClipping++; } y[i] = (short)temp; } } return noClipping; } void mvs2r( const short x[], /* i : input vector */ float y[], /* o : output vector */ const short n /* i : vector size */ ) { short i; if ( n <= 0 ) { /* cannot transfer vectors with size 0 */ return; } if ((void*)y < (const void*)x) { for (i = 0; i < n; i++) { y[i] = (float)x[i]; } } else { for (i = n-1; i >= 0; i--) { y[i] = (float)x[i]; } } return; } void mvi2i( const int x[], /* i : input vector */ int y[], /* o : output vector */ const int n /* i : vector size */ ) { int i; if ( n <= 0 ) { /* no need to transfer vectors with size 0 */ return; } if (y < x) { for (i = 0; i < n; i++) { y[i] = x[i]; } } else { for (i = n-1; i >= 0; i--) { y[i] = x[i]; } } return; } /*---------------------------------------------------------------------* * maximum() * * Find index and value of the maximum in a vector *---------------------------------------------------------------------*/ short maximum( /* o : index of the maximum value in the input vector */ const float *vec, /* i : input vector */ const short lvec, /* i : length of input vector */ float *max /* o : maximum value in the input vector */ ) { short j, ind; float tmp; ind = 0; tmp = vec[0]; for ( j=1; j tmp ) { ind = j; tmp = vec[j]; } } if ( max != 0 ) { *max = tmp; } return ind; } /*---------------------------------------------------------------------* * minimum() * * Find index of a minimum in a vector *---------------------------------------------------------------------*/ short minimum( /* o : index of the minimum value in the input vector */ const float *vec, /* i : input vector */ const short lvec, /* i : length of input vector */ float *min /* o : minimum value in the input vector */ ) { short j, ind; float tmp; ind = 0; tmp = vec[0]; for ( j=1 ; j *ener_max ) { ind = j; *ener_max = temp; } } return ind; } /*---------------------------------------------------------------------* * mean() * * Find the mean of the vector *---------------------------------------------------------------------*/ float mean( /* o : mean of vector */ const float *vec, /* i : input vector */ const short lvec /* i : length of input vector */ ) { float tmp; tmp = sum_f( vec, lvec ) / (float)lvec; return tmp; } /*---------------------------------------------------------------------* * dotp() * * Dot product of vector x[] and vector y[] *---------------------------------------------------------------------*/ float dotp( /* o : dot product of x[] and y[] */ const float x[], /* i : vector x[] */ const float y[], /* i : vector y[] */ const short n /* i : vector length */ ) { short i; float suma; suma = x[0] * y[0]; for(i=1; i= 0; d--) { tmp = x[d] - cb[j++]; dist += weights[d]*(tmp*tmp); } if (dist < mindist) { mindist = dist; idx = c; } } if (xq == 0) { return idx; } j = idx*dim; for ( d = k; d >= 0; d--) { xq[d] = cb[j++]; } } else { for ( c = 0; c < cbsize; c++) { dist = 0.0f; for( d = 0; d < dim; d++) { tmp = x[d] - cb[j++]; dist += weights[d]*(tmp*tmp); } if (dist < mindist) { mindist = dist; idx = c; } } if (xq == 0) { return idx; } j = idx*dim; for ( d = 0; d < dim; d++) { xq[d] = cb[j++]; } } if (x_mean != 0) { for( d = 0; d < dim; d++) { xq[d] += x_mean[d]; } } return idx; } /*----------------------------------------------------------------------------------* * v_sort() * * Sorting of vectors. This is very fast with almost ordered vectors. *----------------------------------------------------------------------------------*/ void v_sort( float *r, /* i/o: Vector to be sorted in place */ const short lo, /* i : Low limit of sorting range */ const short up /* I : High limit of sorting range */ ) { short i, j; float tempr; for ( i=up-1; i>=lo; i-- ) { tempr = r[i]; for ( j=i+1; j<=up && (tempr>r[j]); j++ ) { r[j-1] = r[j]; } r[j-1] = tempr; } return; } /*---------------------------------------------------------------------* * var() * * Calculate the variance of a vector *---------------------------------------------------------------------*/ float var( /* o: variance of vector */ const float *x, /* i: input vector */ const int len /* i: length of inputvector */ ) { float m; float v; short i; m = mean(x, (const short)len); v = 0.0f; for (i = 0; i < len; i++) { v += (x[i] - m)*(x[i] - m); } v /= len; return v; } /*---------------------------------------------------------------------* * std_dev() * * Calculate the standard deviation of a vector *---------------------------------------------------------------------*/ float std_dev( /* o: standard deviation */ const float *x, /* i: input vector */ const int len /* i: length of the input vector */ ) { short i; float std; std = 1e-16f; for( i = 0; i < len; i++) { std += x[i] * x[i]; } std = (float)sqrt( std / len ); return std; } /*---------------------------------------------------------------------* * dot_product_mat() * * Calculates dot product of type x'*A*x, where x is column vector of size m, * and A is square matrix of size m*m *---------------------------------------------------------------------*/ float dot_product_mat( /* o : the dot product x'*A*x */ const float *x, /* i : vector x */ const float *A, /* i : matrix A */ const short m /* i : vector & matrix size */ ) { short i,j; float suma, tmp_sum; const float *pt_x, *pt_A; pt_A = A; suma = 0; for(i=0; i 1.0) { mod_a /= 2.0; shift_a--; } while (mod_a < 0.5) { mod_a *= 2.0; shift_a++; } shift_a &= 0xfffe; mod_a = fleft_shift(a, (int) shift_a); approx = 0.27f + 1.0127f * mod_a - 0.2864f * mod_a * mod_a; approx = fright_shift(approx, (int) (shift_a >> 1)); return (approx); } /*--------------------------------------------------------------------------------* * root_a_over_b() * * Implements an approximation to sqrt(a/b) * Firstly a & b are normalized to lie between 0.25 & 1.0 * by shifting the inputs left or right by an even number * of shifts. * Even shifts represent powers of 4 which, after the sqrt, * become powers of 2 and are easily dealt with. * At the heart of the algorithm is an approximation of the * curve sqrt(a/b) for 0.25 <= a <= 1.0 & 0.25 <= b <= 1.0. * Given the value of b, the 2nd order coefficients p0, p1 * & p2 can be determined so that... * Sqrt(a/b) approx = p0 + p1 * a + p2 * a^2 * where p0 approx = 0.7176 - 0.8815 * b + 0.4429 * b^2 * p1 approx = 2.6908 - 3.3056 * b + 1.6608 * b^2 * p2 approx = -0.7609 + 0.9346 * b - 0.4695 * b^2 * *---------------------------------------------------------------------------------*/ float root_a_over_b(float a, float b) { short int shift_a, shift_b, shift; float mod_a, mod_b; float p2 = -0.7609f; float p1 = 2.6908f; float p0 = 0.7176f; float b_sqr; float approx; if ((a <= 0.0f) || (b <= 0.0f)) { return 0.0; } a += 0x00000001; b += 0x00000001; /* This next piece of code implements a "norm" function */ /* and returns the shift needed to scale "a" to have a */ /* 1 in the (MSB-1) position. This is equivalent to */ /* giving a value between 0.5 & 1.0. */ mod_a = a; shift_a = 0; while (mod_a > 1.0) { mod_a /= 2.0; shift_a--; } while (mod_a < 0.5) { mod_a *= 2.0; shift_a++; } shift_a &= 0xfffe; mod_a = fleft_shift(a, (int) shift_a); /* This next piece of code implements a "norm" function */ /* and returns the shift needed to scale "b" to have a */ /* 1 in the (MSB-1) position. This is equivalent to */ /* giving a value between 0.5 & 1.0. */ mod_b = b; shift_b = 0; while (mod_b > 1.0) { mod_b /= 2.0; shift_b--; } while (mod_b < 0.5) { mod_b *= 2.0; shift_b++; } shift_b &= 0xfffe; mod_b = fleft_shift(b, (int) shift_b); shift = (shift_b - shift_a) >> 1; b_sqr = mod_b * mod_b; p2 += 0.9346f * mod_b + -0.4695f * b_sqr; p1 += -3.3056f * mod_b + 1.6608f * b_sqr; p0 += -0.8815f * mod_b + 0.4429f * b_sqr; approx = p0 + p1 * mod_a + p2 * mod_a * mod_a; approx = fleft_shift(approx, (int) shift); return (approx); } /*--------------------------------------------------------------------------------* * rint_new() * * Round to the nearest integer with mid-point exception *---------------------------------------------------------------------------------*/ double rint_new( double x ) { int a; /* middle value point test */ if (ceil (x + 0.5) == floor (x + 0.5)) { a = (int) ceil (x); if (a % 2 == 0) { return ceil (x); } else { return floor (x); } } else { return floor (x + 0.5); } } /*-------------------------------------------------------------------* * anint() * * Round to the nearest integer. *-------------------------------------------------------------------*/ double anint( double x ) { return (x)>=0?(int)((x)+0.5):(int)((x)-0.5); } /*-------------------------------------------------------------------* * is_numeric_float() * * Returns 0 for all NaN and Inf values defined according to IEEE 754 * floating point number's definition. Returns 1 for numeric values. *-------------------------------------------------------------------*/ short is_numeric_float( float x ) { return ( ((*((int *)&x)) & 0x7f800000) != 0x7f800000 ); }