Loading lib_com/ivas_prot.h +15 −0 Original line number Diff line number Diff line Loading @@ -4153,6 +4153,21 @@ Word16 matrix_product_fx( const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication */ Word32 *Z_fx /* o : resulting matrix after the matrix multiplication */ ); void mat2svdMat_fx( const Word32 *mat, /* i : matrix as column ordered vector */ Word32 svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* o : matrix as two-dimensional arry */ const Word16 nRows, /* i : number of rows of the matrix */ const Word16 mCols, /* i : number of columns of the matrix */ const Word16 transpose /* i : flag indication transposition */ ); void svdMat2mat_fx( Word32 svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* i : matrix as two-dimensional arry */ Word32 *mat, /* o : matrix as column ordered vector */ const Word16 nRows, /* i : number of rows of the matrix */ const Word16 mCols /* i : number of columns of the matrix */ ); #endif void mat2svdMat( Loading lib_com/prot.h +5 −0 Original line number Diff line number Diff line Loading @@ -190,6 +190,11 @@ void set_f( const int16_t N /* i : Lenght of the vector */ ); void set_zero_fx( Word32 *vec, /* o : input vector */ const Word16 lvec /* i : length of the vector */ ); void set_zero( float *vec, /* o : input vector */ const int16_t lvec /* i : length of the vector */ Loading lib_com/tools.c +20 −1 Original line number Diff line number Diff line Loading @@ -270,8 +270,28 @@ void set_f( return; } #ifdef IVAS_FLOAT_FIXED /*---------------------------------------------------------------------* * set_zero() * * Set a vector vec[] of dimension lvec to zero *---------------------------------------------------------------------*/ void set_zero_fx( Word32 *vec, /* o : input vector */ const Word16 lvec /* i : length of the vector */ ) { Word16 i; FOR ( i = 0; i < lvec; i++ ) { *vec++ = 0; } return; } #endif /*---------------------------------------------------------------------* * set_zero() * Loading Loading @@ -1146,7 +1166,6 @@ void v_multc_fixed_16( return; } /*-------------------------------------------------------------------* * squant() * Loading lib_dec/ivas_dirac_output_synthesis_cov.c +255 −8 Original line number Diff line number Diff line Loading @@ -563,7 +563,21 @@ int16_t computeMixingMatrices( float mat_mult_buffer1[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; float mat_mult_buffer2[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; float mat_mult_buffer3[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; #ifdef IVAS_FLOAT_FIXED Word32 svd_in_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 mat_mult_buffer1_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 mat_mult_buffer2_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 Cx_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; Word32 Cy_fx[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; Word32 svd_u_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 svd_v_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word16 mat_mult_buffer1_fx_e; Word16 Cx_fx_e; Word16 Cy_fx_e; Word16 svd_u_buffer_fx_e[MAX_OUTPUT_CHANNELS]; Word16 svd_v_buffer_fx_e[MAX_OUTPUT_CHANNELS]; #endif push_wmops( "dirac_cov_mix_mat" ); set_zero( svd_s_buffer, MAX_OUTPUT_CHANNELS ); Loading @@ -579,8 +593,16 @@ int16_t computeMixingMatrices( *-----------------------------------------------------------------*/ /* Processing the SVD */ #ifdef IVAS_FLOAT_FIXED f2me_buf( Cy, Cy_fx, &Cy_fx_e, lengthCy * lengthCy ); mat2svdMat_fx( Cy_fx, svd_in_buffer_fx, lengthCy, lengthCy, 0 ); FOR ( Word32 g = 0; g < lengthCy; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), Cy_fx_e, ( svd_in_buffer[g] ), lengthCy ); } #else mat2svdMat( Cy, svd_in_buffer, lengthCy, lengthCy, 0 ); #endif svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCy, lengthCy ); /* Computing Ky */ Loading @@ -597,7 +619,17 @@ int16_t computeMixingMatrices( *-----------------------------------------------------------------*/ /* Processing the SVD */ #ifdef IVAS_FLOAT_FIXED f2me_buf( Cx, Cx_fx, &Cx_fx_e, lengthCx * lengthCx ); mat2svdMat_fx( Cx_fx, svd_in_buffer_fx, lengthCx, lengthCx, 0 ); FOR ( Word32 g = 0; g < lengthCx; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), Cx_fx_e, ( svd_in_buffer[g] ), lengthCx ); } #else mat2svdMat( Cx, svd_in_buffer, lengthCx, lengthCx, 0 ); #endif svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCx, lengthCx ); Loading Loading @@ -718,8 +750,6 @@ int16_t computeMixingMatrices( /* Computing the input matrix Kx'*Q'*G_hat'*Ky */ matrix_product( Kx, lengthCx, lengthCx, 1, Q, lengthCy, lengthCx, 1, mat_mult_buffer1 ); #ifdef IVAS_FLOAT_FIXED Word32 mat_mult_buffer1_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 mat_mult_buffer2_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 G_hat_fx[MAX_OUTPUT_CHANNELS]; Word16 mat_mult_buffer1_e, mat_mult_buffer2_e, G_hat_e; Loading @@ -736,7 +766,16 @@ int16_t computeMixingMatrices( if ( lengthCx < lengthCy ) { #ifdef IVAS_FLOAT_FIXED f2me_buf( mat_mult_buffer1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e, lengthCx * lengthCy ); mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, lengthCy, 1 ); FOR ( Word32 g = 0; g < lengthCy; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), mat_mult_buffer1_fx_e, ( svd_in_buffer[g] ), lengthCx ); } #else mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 1 ); #endif nL = lengthCy; nC = lengthCx; Loading @@ -745,7 +784,17 @@ int16_t computeMixingMatrices( } else { #ifdef IVAS_FLOAT_FIXED f2me_buf( mat_mult_buffer1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e, lengthCx * lengthCy ); mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, lengthCy, 0 ); FOR ( Word32 g = 0; g < lengthCx; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), mat_mult_buffer1_fx_e, ( svd_in_buffer[g] ), lengthCy ); } #else mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 0 ); #endif nL = lengthCx; nC = lengthCy; Loading @@ -758,8 +807,53 @@ int16_t computeMixingMatrices( /* can be skipped: lambda is always column-truncated identity matrix, so this operation just truncates V to num_input_channel columns */ #ifdef IVAS_FLOAT_FIXED Word16 min_q = -1; FOR ( Word32 g = 0; g < lengthCy; g++ ) { f2me_buf( svd_v_buffer[g], svd_v_buffer_fx[g], &svd_v_buffer_fx_e[g], lengthCx ); IF ( svd_v_buffer_fx_e[g] > min_q) { min_q = svd_v_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < lengthCy; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_v_buffer_fx[g][h] = L_shr( svd_v_buffer_fx[g][h], min_q - svd_v_buffer_fx_e[g] ); } } svd_v_buffer_fx_e[0] = min_q; min_q = -1; FOR ( Word32 g = 0; g < lengthCx; g++ ) { f2me_buf( svd_u_buffer[g], svd_u_buffer_fx[g], &svd_u_buffer_fx_e[g], lengthCx ); IF ( svd_u_buffer_fx_e[g] > min_q ) { min_q = svd_u_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < lengthCx; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_u_buffer_fx[g][h] = L_shr( svd_u_buffer_fx[g][h], min_q - svd_u_buffer_fx_e[g] ); } } svd_u_buffer_fx_e[0] = min_q; svdMat2mat_fx( svd_v_buffer_fx, mat_mult_buffer1_fx, lengthCy, lengthCx ); svdMat2mat_fx( svd_u_buffer_fx, mat_mult_buffer2_fx, lengthCx, lengthCx ); me2f_buf( mat_mult_buffer1_fx, svd_v_buffer_fx_e[0], mat_mult_buffer1, lengthCy * lengthCx ); me2f_buf( mat_mult_buffer2_fx, svd_u_buffer_fx_e[0], mat_mult_buffer2, lengthCx * lengthCx ); #else svdMat2mat( svd_v_buffer, mat_mult_buffer1, lengthCy, lengthCx ); svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx ); #endif matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0, mat_mult_buffer2, lengthCx, lengthCx, 1, Loading Loading @@ -881,7 +975,18 @@ int16_t computeMixingMatricesResidual( float mat_mult_buffer1[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; float mat_mult_buffer2[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; float mat_mult_buffer3[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; #ifdef IVAS_FLOAT_FIXED Word32 svd_in_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 mat_mult_buffer2_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 Cy_fx[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; Word32 svd_u_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 svd_v_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word16 mat_mult_buffer1_fx_e; Word16 Cy_fx_e; Word16 svd_u_buffer_fx_e[MAX_OUTPUT_CHANNELS]; Word16 svd_v_buffer_fx_e[MAX_OUTPUT_CHANNELS]; #endif push_wmops( "dirac_cov_mix_mat_r" ); #ifdef IVAS_FLOAT_FIXED Loading @@ -900,7 +1005,18 @@ int16_t computeMixingMatricesResidual( /* Processing the SVD */ /* linear array to svd buffer */ #ifdef IVAS_FLOAT_FIXED f2me_buf( Cy, Cy_fx, &Cy_fx_e, lengthCy * lengthCy ); mat2svdMat_fx( Cy_fx, svd_in_buffer_fx, lengthCy, lengthCy, 0 ); FOR ( Word32 g = 0; g < lengthCy; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), Cy_fx_e, ( svd_in_buffer[g] ), lengthCy ); } #else mat2svdMat( Cy, svd_in_buffer, lengthCy, lengthCy, 0 ); #endif svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCy, lengthCy ); Loading Loading @@ -993,14 +1109,71 @@ int16_t computeMixingMatricesResidual( } } #ifdef IVAS_FLOAT_FIXED f2me_buf( mat_mult_buffer1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e, lengthCx * lengthCy ); mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, lengthCy, 0 ); FOR ( Word32 g = 0; g < lengthCx; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), mat_mult_buffer1_fx_e, ( svd_in_buffer[g] ), lengthCy ); } #else mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 0 ); #endif svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCx, lengthCy ); /* Actually Processing P */ #ifdef IVAS_FLOAT_FIXED Word16 min_q = -1; FOR ( Word32 g = 0; g < lengthCy; g++ ) { f2me_buf( svd_v_buffer[g], svd_v_buffer_fx[g], &svd_v_buffer_fx_e[g], lengthCx ); IF ( svd_v_buffer_fx_e[g] > min_q ) { min_q = svd_v_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < lengthCy; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_v_buffer_fx[g][h] = L_shr( svd_v_buffer_fx[g][h], min_q - svd_v_buffer_fx_e[g] ); } } svd_v_buffer_fx_e[0] = min_q; min_q = -1; FOR ( Word32 g = 0; g < lengthCx; g++ ) { f2me_buf( svd_u_buffer[g], svd_u_buffer_fx[g], &svd_u_buffer_fx_e[g], lengthCx ); IF ( svd_u_buffer_fx_e[g] > min_q ) { min_q = svd_u_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < lengthCx; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_u_buffer_fx[g][h] = L_shr( svd_u_buffer_fx[g][h], min_q - svd_u_buffer_fx_e[g] ); } } svd_u_buffer_fx_e[0] = min_q; svdMat2mat_fx( svd_v_buffer_fx, mat_mult_buffer1_fx, lengthCy, lengthCx ); svdMat2mat_fx( svd_u_buffer_fx, mat_mult_buffer2_fx, lengthCx, lengthCx ); me2f_buf( mat_mult_buffer1_fx, svd_v_buffer_fx_e[0], mat_mult_buffer1, lengthCy * lengthCx ); me2f_buf( mat_mult_buffer2_fx, svd_u_buffer_fx_e[0], mat_mult_buffer2, lengthCx * lengthCx ); #else svdMat2mat( svd_v_buffer, mat_mult_buffer1, lengthCy, lengthCx ); svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx ); #endif matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0, mat_mult_buffer2, lengthCx, lengthCx, 1, mat_mult_buffer3 ); Loading Loading @@ -1156,8 +1329,15 @@ int16_t computeMixingMatricesISM( Word32 mat_mult_buffer3_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 Kx_fx[MAX_TRANSPORT_CHANNELS]; Word16 responses_e, ener_e, Ky_e, Q_e, Cx_diag_e, Q_Cx_e, mat_mult_buffer1_e, G_hat_e, mat_mult_buffer2_e, Kx_reg_inv_e, mixing_matrix_e, adj_e, mat_mult_buffer3_e, Kx_e; #endif Word32 svd_in_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 svd_u_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 svd_v_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word16 mat_mult_buffer1_fx_e; Word16 svd_u_buffer_fx_e[MAX_OUTPUT_CHANNELS]; Word16 svd_v_buffer_fx_e[MAX_OUTPUT_CHANNELS]; #endif push_wmops( "dirac_cov_mix_mat" ); out = EXIT_SUCCESS; Loading Loading @@ -1293,14 +1473,37 @@ int16_t computeMixingMatricesISM( if ( lengthCx < num_responses ) { #ifdef IVAS_FLOAT_FIXED f2me_buf( mat_mult_buffer1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e, lengthCx * num_responses ); mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, num_responses, 1 ); FOR ( Word32 g = 0; g < num_responses; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), mat_mult_buffer1_fx_e, ( svd_in_buffer[g] ), lengthCx ); } #else mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, num_responses, 1 ); #endif nL = num_responses; nC = lengthCx; svd( svd_in_buffer, svd_v_buffer, svd_s_buffer, svd_u_buffer, nL, nC ); } else { #ifdef IVAS_FLOAT_FIXED f2me_buf( mat_mult_buffer1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e, lengthCx * num_responses ); mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, num_responses, 0 ); FOR ( Word32 g = 0; g < lengthCx; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), mat_mult_buffer1_fx_e, ( svd_in_buffer[g] ), num_responses ); } #else mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, num_responses, 0 ); #endif nL = lengthCx; nC = num_responses; svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, nL, nC ); Loading @@ -1309,9 +1512,53 @@ int16_t computeMixingMatricesISM( /* Actually Processing P */ /* can be skipped: lambda is always column-truncated identity matrix, so this operation just truncates V to num_input_channel columns */ #ifdef IVAS_FLOAT_FIXED Word16 min_q = -1; FOR ( Word32 g = 0; g < num_responses; g++ ) { f2me_buf( svd_v_buffer[g], svd_v_buffer_fx[g], &svd_v_buffer_fx_e[g], lengthCx ); IF ( svd_v_buffer_fx_e[g] > min_q ) { min_q = svd_v_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < num_responses; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_v_buffer_fx[g][h] = L_shr( svd_v_buffer_fx[g][h], min_q - svd_v_buffer_fx_e[g] ); } } svd_v_buffer_fx_e[0] = min_q; min_q = -1; FOR ( Word32 g = 0; g < lengthCx; g++ ) { f2me_buf( svd_u_buffer[g], svd_u_buffer_fx[g], &svd_u_buffer_fx_e[g], lengthCx ); IF ( svd_u_buffer_fx_e[g] > min_q ) { min_q = svd_u_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < lengthCx; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_u_buffer_fx[g][h] = L_shr( svd_u_buffer_fx[g][h], min_q - svd_u_buffer_fx_e[g] ); } } svd_u_buffer_fx_e[0] = min_q; svdMat2mat_fx( svd_v_buffer_fx, mat_mult_buffer1_fx, num_responses, lengthCx ); svdMat2mat_fx( svd_u_buffer_fx, mat_mult_buffer2_fx, lengthCx, lengthCx ); me2f_buf( mat_mult_buffer1_fx, svd_v_buffer_fx_e[0], mat_mult_buffer1, num_responses * lengthCx ); me2f_buf( mat_mult_buffer2_fx, svd_u_buffer_fx_e[0], mat_mult_buffer2, lengthCx * lengthCx ); #else svdMat2mat( svd_v_buffer, mat_mult_buffer1, num_responses, lengthCx ); svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx ); #endif matrix_product( mat_mult_buffer1, num_responses, lengthCx, 0, mat_mult_buffer2, lengthCx, lengthCx, 1, mat_mult_buffer3 ); /************************ Formulate M **********************/ Loading lib_dec/ivas_svd_dec.c +82 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,88 @@ static void flushToZeroArray( float arr[MAX_OUTPUT_CHANNELS], const int16_t leng static void flushToZeroMat( float mat[][MAX_OUTPUT_CHANNELS], const int16_t m, const int16_t n ); #ifdef IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * mat2svdMat() * * external matrix format to internal *-------------------------------------------------------------------------*/ void mat2svdMat_fx( const Word32 *mat, /* i : matrix as column ordered vector */ Word32 svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* o : matrix as two-dimensional arry */ const Word16 nRows, /* i : number of rows of the matrix */ const Word16 mCols, /* i : number of columns of the matrix */ const Word16 transpose /* i : flag indication transposition */ ) { Word16 i, j; IF ( transpose ) { FOR ( i = 0; i < mCols; i++ ) { FOR ( j = 0; j < nRows; j++ ) { svdMat[i][j] = mat[j + nRows * i]; } set_zero_fx( &svdMat[i][mCols], MAX_OUTPUT_CHANNELS - nRows ); } FOR ( ; i < MAX_OUTPUT_CHANNELS; i++ ) { set_zero_fx( svdMat[i], MAX_OUTPUT_CHANNELS ); } } ELSE { FOR ( i = 0; i < nRows; i++ ) { FOR ( j = 0; j < mCols; j++ ) { svdMat[i][j] = mat[i + nRows * j]; } set_zero_fx( &svdMat[i][mCols], MAX_OUTPUT_CHANNELS - mCols ); } FOR ( ; i < MAX_OUTPUT_CHANNELS; i++ ) { set_zero_fx( svdMat[i], MAX_OUTPUT_CHANNELS ); } } return; } /*---------------------------------------------------------------------* * svdMat2mat() * * transfer a matrix from a two dimensional array to a column wise ordered vector *---------------------------------------------------------------------*/ void svdMat2mat_fx( Word32 svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* i : matrix as two-dimensional arry */ Word32 *mat, /* o : matrix as column ordered vector */ const Word16 nRows, /* i : number of rows of the matrix */ const Word16 mCols /* i : number of columns of the matrix */ ) { Word16 i, j; FOR ( i = 0; i < nRows; i++ ) { FOR ( j = 0; j < mCols; j++ ) { mat[i + nRows * j] = svdMat[i][j]; } } return; } #endif /*------------------------------------------------------------------------- * mat2svdMat() Loading Loading
lib_com/ivas_prot.h +15 −0 Original line number Diff line number Diff line Loading @@ -4153,6 +4153,21 @@ Word16 matrix_product_fx( const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication */ Word32 *Z_fx /* o : resulting matrix after the matrix multiplication */ ); void mat2svdMat_fx( const Word32 *mat, /* i : matrix as column ordered vector */ Word32 svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* o : matrix as two-dimensional arry */ const Word16 nRows, /* i : number of rows of the matrix */ const Word16 mCols, /* i : number of columns of the matrix */ const Word16 transpose /* i : flag indication transposition */ ); void svdMat2mat_fx( Word32 svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* i : matrix as two-dimensional arry */ Word32 *mat, /* o : matrix as column ordered vector */ const Word16 nRows, /* i : number of rows of the matrix */ const Word16 mCols /* i : number of columns of the matrix */ ); #endif void mat2svdMat( Loading
lib_com/prot.h +5 −0 Original line number Diff line number Diff line Loading @@ -190,6 +190,11 @@ void set_f( const int16_t N /* i : Lenght of the vector */ ); void set_zero_fx( Word32 *vec, /* o : input vector */ const Word16 lvec /* i : length of the vector */ ); void set_zero( float *vec, /* o : input vector */ const int16_t lvec /* i : length of the vector */ Loading
lib_com/tools.c +20 −1 Original line number Diff line number Diff line Loading @@ -270,8 +270,28 @@ void set_f( return; } #ifdef IVAS_FLOAT_FIXED /*---------------------------------------------------------------------* * set_zero() * * Set a vector vec[] of dimension lvec to zero *---------------------------------------------------------------------*/ void set_zero_fx( Word32 *vec, /* o : input vector */ const Word16 lvec /* i : length of the vector */ ) { Word16 i; FOR ( i = 0; i < lvec; i++ ) { *vec++ = 0; } return; } #endif /*---------------------------------------------------------------------* * set_zero() * Loading Loading @@ -1146,7 +1166,6 @@ void v_multc_fixed_16( return; } /*-------------------------------------------------------------------* * squant() * Loading
lib_dec/ivas_dirac_output_synthesis_cov.c +255 −8 Original line number Diff line number Diff line Loading @@ -563,7 +563,21 @@ int16_t computeMixingMatrices( float mat_mult_buffer1[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; float mat_mult_buffer2[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; float mat_mult_buffer3[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; #ifdef IVAS_FLOAT_FIXED Word32 svd_in_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 mat_mult_buffer1_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 mat_mult_buffer2_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 Cx_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; Word32 Cy_fx[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; Word32 svd_u_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 svd_v_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word16 mat_mult_buffer1_fx_e; Word16 Cx_fx_e; Word16 Cy_fx_e; Word16 svd_u_buffer_fx_e[MAX_OUTPUT_CHANNELS]; Word16 svd_v_buffer_fx_e[MAX_OUTPUT_CHANNELS]; #endif push_wmops( "dirac_cov_mix_mat" ); set_zero( svd_s_buffer, MAX_OUTPUT_CHANNELS ); Loading @@ -579,8 +593,16 @@ int16_t computeMixingMatrices( *-----------------------------------------------------------------*/ /* Processing the SVD */ #ifdef IVAS_FLOAT_FIXED f2me_buf( Cy, Cy_fx, &Cy_fx_e, lengthCy * lengthCy ); mat2svdMat_fx( Cy_fx, svd_in_buffer_fx, lengthCy, lengthCy, 0 ); FOR ( Word32 g = 0; g < lengthCy; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), Cy_fx_e, ( svd_in_buffer[g] ), lengthCy ); } #else mat2svdMat( Cy, svd_in_buffer, lengthCy, lengthCy, 0 ); #endif svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCy, lengthCy ); /* Computing Ky */ Loading @@ -597,7 +619,17 @@ int16_t computeMixingMatrices( *-----------------------------------------------------------------*/ /* Processing the SVD */ #ifdef IVAS_FLOAT_FIXED f2me_buf( Cx, Cx_fx, &Cx_fx_e, lengthCx * lengthCx ); mat2svdMat_fx( Cx_fx, svd_in_buffer_fx, lengthCx, lengthCx, 0 ); FOR ( Word32 g = 0; g < lengthCx; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), Cx_fx_e, ( svd_in_buffer[g] ), lengthCx ); } #else mat2svdMat( Cx, svd_in_buffer, lengthCx, lengthCx, 0 ); #endif svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCx, lengthCx ); Loading Loading @@ -718,8 +750,6 @@ int16_t computeMixingMatrices( /* Computing the input matrix Kx'*Q'*G_hat'*Ky */ matrix_product( Kx, lengthCx, lengthCx, 1, Q, lengthCy, lengthCx, 1, mat_mult_buffer1 ); #ifdef IVAS_FLOAT_FIXED Word32 mat_mult_buffer1_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 mat_mult_buffer2_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 G_hat_fx[MAX_OUTPUT_CHANNELS]; Word16 mat_mult_buffer1_e, mat_mult_buffer2_e, G_hat_e; Loading @@ -736,7 +766,16 @@ int16_t computeMixingMatrices( if ( lengthCx < lengthCy ) { #ifdef IVAS_FLOAT_FIXED f2me_buf( mat_mult_buffer1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e, lengthCx * lengthCy ); mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, lengthCy, 1 ); FOR ( Word32 g = 0; g < lengthCy; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), mat_mult_buffer1_fx_e, ( svd_in_buffer[g] ), lengthCx ); } #else mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 1 ); #endif nL = lengthCy; nC = lengthCx; Loading @@ -745,7 +784,17 @@ int16_t computeMixingMatrices( } else { #ifdef IVAS_FLOAT_FIXED f2me_buf( mat_mult_buffer1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e, lengthCx * lengthCy ); mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, lengthCy, 0 ); FOR ( Word32 g = 0; g < lengthCx; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), mat_mult_buffer1_fx_e, ( svd_in_buffer[g] ), lengthCy ); } #else mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 0 ); #endif nL = lengthCx; nC = lengthCy; Loading @@ -758,8 +807,53 @@ int16_t computeMixingMatrices( /* can be skipped: lambda is always column-truncated identity matrix, so this operation just truncates V to num_input_channel columns */ #ifdef IVAS_FLOAT_FIXED Word16 min_q = -1; FOR ( Word32 g = 0; g < lengthCy; g++ ) { f2me_buf( svd_v_buffer[g], svd_v_buffer_fx[g], &svd_v_buffer_fx_e[g], lengthCx ); IF ( svd_v_buffer_fx_e[g] > min_q) { min_q = svd_v_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < lengthCy; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_v_buffer_fx[g][h] = L_shr( svd_v_buffer_fx[g][h], min_q - svd_v_buffer_fx_e[g] ); } } svd_v_buffer_fx_e[0] = min_q; min_q = -1; FOR ( Word32 g = 0; g < lengthCx; g++ ) { f2me_buf( svd_u_buffer[g], svd_u_buffer_fx[g], &svd_u_buffer_fx_e[g], lengthCx ); IF ( svd_u_buffer_fx_e[g] > min_q ) { min_q = svd_u_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < lengthCx; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_u_buffer_fx[g][h] = L_shr( svd_u_buffer_fx[g][h], min_q - svd_u_buffer_fx_e[g] ); } } svd_u_buffer_fx_e[0] = min_q; svdMat2mat_fx( svd_v_buffer_fx, mat_mult_buffer1_fx, lengthCy, lengthCx ); svdMat2mat_fx( svd_u_buffer_fx, mat_mult_buffer2_fx, lengthCx, lengthCx ); me2f_buf( mat_mult_buffer1_fx, svd_v_buffer_fx_e[0], mat_mult_buffer1, lengthCy * lengthCx ); me2f_buf( mat_mult_buffer2_fx, svd_u_buffer_fx_e[0], mat_mult_buffer2, lengthCx * lengthCx ); #else svdMat2mat( svd_v_buffer, mat_mult_buffer1, lengthCy, lengthCx ); svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx ); #endif matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0, mat_mult_buffer2, lengthCx, lengthCx, 1, Loading Loading @@ -881,7 +975,18 @@ int16_t computeMixingMatricesResidual( float mat_mult_buffer1[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; float mat_mult_buffer2[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; float mat_mult_buffer3[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; #ifdef IVAS_FLOAT_FIXED Word32 svd_in_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 mat_mult_buffer2_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 Cy_fx[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; Word32 svd_u_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 svd_v_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word16 mat_mult_buffer1_fx_e; Word16 Cy_fx_e; Word16 svd_u_buffer_fx_e[MAX_OUTPUT_CHANNELS]; Word16 svd_v_buffer_fx_e[MAX_OUTPUT_CHANNELS]; #endif push_wmops( "dirac_cov_mix_mat_r" ); #ifdef IVAS_FLOAT_FIXED Loading @@ -900,7 +1005,18 @@ int16_t computeMixingMatricesResidual( /* Processing the SVD */ /* linear array to svd buffer */ #ifdef IVAS_FLOAT_FIXED f2me_buf( Cy, Cy_fx, &Cy_fx_e, lengthCy * lengthCy ); mat2svdMat_fx( Cy_fx, svd_in_buffer_fx, lengthCy, lengthCy, 0 ); FOR ( Word32 g = 0; g < lengthCy; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), Cy_fx_e, ( svd_in_buffer[g] ), lengthCy ); } #else mat2svdMat( Cy, svd_in_buffer, lengthCy, lengthCy, 0 ); #endif svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCy, lengthCy ); Loading Loading @@ -993,14 +1109,71 @@ int16_t computeMixingMatricesResidual( } } #ifdef IVAS_FLOAT_FIXED f2me_buf( mat_mult_buffer1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e, lengthCx * lengthCy ); mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, lengthCy, 0 ); FOR ( Word32 g = 0; g < lengthCx; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), mat_mult_buffer1_fx_e, ( svd_in_buffer[g] ), lengthCy ); } #else mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 0 ); #endif svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCx, lengthCy ); /* Actually Processing P */ #ifdef IVAS_FLOAT_FIXED Word16 min_q = -1; FOR ( Word32 g = 0; g < lengthCy; g++ ) { f2me_buf( svd_v_buffer[g], svd_v_buffer_fx[g], &svd_v_buffer_fx_e[g], lengthCx ); IF ( svd_v_buffer_fx_e[g] > min_q ) { min_q = svd_v_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < lengthCy; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_v_buffer_fx[g][h] = L_shr( svd_v_buffer_fx[g][h], min_q - svd_v_buffer_fx_e[g] ); } } svd_v_buffer_fx_e[0] = min_q; min_q = -1; FOR ( Word32 g = 0; g < lengthCx; g++ ) { f2me_buf( svd_u_buffer[g], svd_u_buffer_fx[g], &svd_u_buffer_fx_e[g], lengthCx ); IF ( svd_u_buffer_fx_e[g] > min_q ) { min_q = svd_u_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < lengthCx; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_u_buffer_fx[g][h] = L_shr( svd_u_buffer_fx[g][h], min_q - svd_u_buffer_fx_e[g] ); } } svd_u_buffer_fx_e[0] = min_q; svdMat2mat_fx( svd_v_buffer_fx, mat_mult_buffer1_fx, lengthCy, lengthCx ); svdMat2mat_fx( svd_u_buffer_fx, mat_mult_buffer2_fx, lengthCx, lengthCx ); me2f_buf( mat_mult_buffer1_fx, svd_v_buffer_fx_e[0], mat_mult_buffer1, lengthCy * lengthCx ); me2f_buf( mat_mult_buffer2_fx, svd_u_buffer_fx_e[0], mat_mult_buffer2, lengthCx * lengthCx ); #else svdMat2mat( svd_v_buffer, mat_mult_buffer1, lengthCy, lengthCx ); svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx ); #endif matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0, mat_mult_buffer2, lengthCx, lengthCx, 1, mat_mult_buffer3 ); Loading Loading @@ -1156,8 +1329,15 @@ int16_t computeMixingMatricesISM( Word32 mat_mult_buffer3_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; Word32 Kx_fx[MAX_TRANSPORT_CHANNELS]; Word16 responses_e, ener_e, Ky_e, Q_e, Cx_diag_e, Q_Cx_e, mat_mult_buffer1_e, G_hat_e, mat_mult_buffer2_e, Kx_reg_inv_e, mixing_matrix_e, adj_e, mat_mult_buffer3_e, Kx_e; #endif Word32 svd_in_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 svd_u_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word32 svd_v_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; Word16 mat_mult_buffer1_fx_e; Word16 svd_u_buffer_fx_e[MAX_OUTPUT_CHANNELS]; Word16 svd_v_buffer_fx_e[MAX_OUTPUT_CHANNELS]; #endif push_wmops( "dirac_cov_mix_mat" ); out = EXIT_SUCCESS; Loading Loading @@ -1293,14 +1473,37 @@ int16_t computeMixingMatricesISM( if ( lengthCx < num_responses ) { #ifdef IVAS_FLOAT_FIXED f2me_buf( mat_mult_buffer1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e, lengthCx * num_responses ); mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, num_responses, 1 ); FOR ( Word32 g = 0; g < num_responses; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), mat_mult_buffer1_fx_e, ( svd_in_buffer[g] ), lengthCx ); } #else mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, num_responses, 1 ); #endif nL = num_responses; nC = lengthCx; svd( svd_in_buffer, svd_v_buffer, svd_s_buffer, svd_u_buffer, nL, nC ); } else { #ifdef IVAS_FLOAT_FIXED f2me_buf( mat_mult_buffer1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e, lengthCx * num_responses ); mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, num_responses, 0 ); FOR ( Word32 g = 0; g < lengthCx; g++ ) { me2f_buf( ( svd_in_buffer_fx[g] ), mat_mult_buffer1_fx_e, ( svd_in_buffer[g] ), num_responses ); } #else mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, num_responses, 0 ); #endif nL = lengthCx; nC = num_responses; svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, nL, nC ); Loading @@ -1309,9 +1512,53 @@ int16_t computeMixingMatricesISM( /* Actually Processing P */ /* can be skipped: lambda is always column-truncated identity matrix, so this operation just truncates V to num_input_channel columns */ #ifdef IVAS_FLOAT_FIXED Word16 min_q = -1; FOR ( Word32 g = 0; g < num_responses; g++ ) { f2me_buf( svd_v_buffer[g], svd_v_buffer_fx[g], &svd_v_buffer_fx_e[g], lengthCx ); IF ( svd_v_buffer_fx_e[g] > min_q ) { min_q = svd_v_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < num_responses; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_v_buffer_fx[g][h] = L_shr( svd_v_buffer_fx[g][h], min_q - svd_v_buffer_fx_e[g] ); } } svd_v_buffer_fx_e[0] = min_q; min_q = -1; FOR ( Word32 g = 0; g < lengthCx; g++ ) { f2me_buf( svd_u_buffer[g], svd_u_buffer_fx[g], &svd_u_buffer_fx_e[g], lengthCx ); IF ( svd_u_buffer_fx_e[g] > min_q ) { min_q = svd_u_buffer_fx_e[g]; } } FOR ( Word32 g = 0; g < lengthCx; g++ ) { FOR ( Word32 h = 0; h < lengthCx; h++ ) { svd_u_buffer_fx[g][h] = L_shr( svd_u_buffer_fx[g][h], min_q - svd_u_buffer_fx_e[g] ); } } svd_u_buffer_fx_e[0] = min_q; svdMat2mat_fx( svd_v_buffer_fx, mat_mult_buffer1_fx, num_responses, lengthCx ); svdMat2mat_fx( svd_u_buffer_fx, mat_mult_buffer2_fx, lengthCx, lengthCx ); me2f_buf( mat_mult_buffer1_fx, svd_v_buffer_fx_e[0], mat_mult_buffer1, num_responses * lengthCx ); me2f_buf( mat_mult_buffer2_fx, svd_u_buffer_fx_e[0], mat_mult_buffer2, lengthCx * lengthCx ); #else svdMat2mat( svd_v_buffer, mat_mult_buffer1, num_responses, lengthCx ); svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx ); #endif matrix_product( mat_mult_buffer1, num_responses, lengthCx, 0, mat_mult_buffer2, lengthCx, lengthCx, 1, mat_mult_buffer3 ); /************************ Formulate M **********************/ Loading
lib_dec/ivas_svd_dec.c +82 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,88 @@ static void flushToZeroArray( float arr[MAX_OUTPUT_CHANNELS], const int16_t leng static void flushToZeroMat( float mat[][MAX_OUTPUT_CHANNELS], const int16_t m, const int16_t n ); #ifdef IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * mat2svdMat() * * external matrix format to internal *-------------------------------------------------------------------------*/ void mat2svdMat_fx( const Word32 *mat, /* i : matrix as column ordered vector */ Word32 svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* o : matrix as two-dimensional arry */ const Word16 nRows, /* i : number of rows of the matrix */ const Word16 mCols, /* i : number of columns of the matrix */ const Word16 transpose /* i : flag indication transposition */ ) { Word16 i, j; IF ( transpose ) { FOR ( i = 0; i < mCols; i++ ) { FOR ( j = 0; j < nRows; j++ ) { svdMat[i][j] = mat[j + nRows * i]; } set_zero_fx( &svdMat[i][mCols], MAX_OUTPUT_CHANNELS - nRows ); } FOR ( ; i < MAX_OUTPUT_CHANNELS; i++ ) { set_zero_fx( svdMat[i], MAX_OUTPUT_CHANNELS ); } } ELSE { FOR ( i = 0; i < nRows; i++ ) { FOR ( j = 0; j < mCols; j++ ) { svdMat[i][j] = mat[i + nRows * j]; } set_zero_fx( &svdMat[i][mCols], MAX_OUTPUT_CHANNELS - mCols ); } FOR ( ; i < MAX_OUTPUT_CHANNELS; i++ ) { set_zero_fx( svdMat[i], MAX_OUTPUT_CHANNELS ); } } return; } /*---------------------------------------------------------------------* * svdMat2mat() * * transfer a matrix from a two dimensional array to a column wise ordered vector *---------------------------------------------------------------------*/ void svdMat2mat_fx( Word32 svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* i : matrix as two-dimensional arry */ Word32 *mat, /* o : matrix as column ordered vector */ const Word16 nRows, /* i : number of rows of the matrix */ const Word16 mCols /* i : number of columns of the matrix */ ) { Word16 i, j; FOR ( i = 0; i < nRows; i++ ) { FOR ( j = 0; j < mCols; j++ ) { mat[i + nRows * j] = svdMat[i][j]; } } return; } #endif /*------------------------------------------------------------------------- * mat2svdMat() Loading