mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-27 10:57:34 +09:00
parent
b188579bb6
commit
a8b1099a1e
228 changed files with 10990 additions and 5670 deletions
|
|
@ -40,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
/* Number of binary divisions, when not in low complexity mode */
|
||||
#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
|
||||
#define MAX_ITERATIONS_A2NLSF_FIX 30
|
||||
#define MAX_ITERATIONS_A2NLSF_FIX 16
|
||||
|
||||
/* Helper function for A2NLSF(..) */
|
||||
/* Transforms polynomials from cos(n*f) to cos(f)^n */
|
||||
|
|
@ -130,7 +130,7 @@ void silk_A2NLSF(
|
|||
const opus_int d /* I Filter order (must be even) */
|
||||
)
|
||||
{
|
||||
opus_int i, k, m, dd, root_ix, ffrac;
|
||||
opus_int i, k, m, dd, root_ix, ffrac;
|
||||
opus_int32 xlo, xhi, xmid;
|
||||
opus_int32 ylo, yhi, ymid, thr;
|
||||
opus_int32 nom, den;
|
||||
|
|
@ -239,13 +239,13 @@ void silk_A2NLSF(
|
|||
/* Set NLSFs to white spectrum and exit */
|
||||
NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
|
||||
for( k = 1; k < d; k++ ) {
|
||||
NLSF[ k ] = (opus_int16)silk_SMULBB( k + 1, NLSF[ 0 ] );
|
||||
NLSF[ k ] = (opus_int16)silk_ADD16( NLSF[ k-1 ], NLSF[ 0 ] );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Error: Apply progressively more bandwidth expansion and run again */
|
||||
silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/
|
||||
silk_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) );
|
||||
|
||||
silk_A2NLSF_init( a_Q16, P, Q, dd );
|
||||
p = P; /* Pointer to polynomial */
|
||||
|
|
|
|||
|
|
@ -80,7 +80,8 @@ opus_int silk_Encode( /* O Returns error co
|
|||
opus_int nSamplesIn, /* I Number of samples in input vector */
|
||||
ec_enc *psRangeEnc, /* I/O Compressor data structure */
|
||||
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
|
||||
const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */
|
||||
const opus_int prefillFlag, /* I Flag to indicate prefilling buffers no coding */
|
||||
int activity /* I Decision of Opus voice activity detector */
|
||||
);
|
||||
|
||||
/****************************************/
|
||||
|
|
|
|||
|
|
@ -118,6 +118,10 @@ void silk_CNG(
|
|||
/* Smooth gains */
|
||||
for( i = 0; i < psDec->nb_subfr; i++ ) {
|
||||
psCNG->CNG_smth_Gain_Q16 += silk_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 );
|
||||
/* If the smoothed gain is 3 dB greater than this subframe's gain, use this subframe's gain to adapt faster. */
|
||||
if( silk_SMULWW( psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_THRESHOLD_Q16 ) > psDecCtrl->Gains_Q16[ i ] ) {
|
||||
psCNG->CNG_smth_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -138,16 +142,16 @@ void silk_CNG(
|
|||
gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
|
||||
}
|
||||
gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
|
||||
|
||||
|
||||
silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
|
||||
|
||||
/* Convert CNG NLSF to filter representation */
|
||||
silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
|
||||
silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch );
|
||||
|
||||
/* Generate CNG signal, by synthesis filtering */
|
||||
silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
|
||||
for( i = 0; i < length; i++ ) {
|
||||
silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
|
||||
|
|
@ -170,11 +174,11 @@ void silk_CNG(
|
|||
}
|
||||
|
||||
/* Update states */
|
||||
CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q14[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
|
||||
|
||||
CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
|
||||
|
||||
/* Scale with Gain and add to input signal */
|
||||
frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) );
|
||||
|
||||
|
||||
}
|
||||
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
/* first d output samples are set to zero */
|
||||
/*******************************************/
|
||||
|
||||
/* OPT: Using celt_fir() for this function should be faster, but it may cause
|
||||
integer overflows in intermediate values (not final results), which the
|
||||
current implementation silences by casting to unsigned. Enabling
|
||||
this should be safe in pretty much all cases, even though it is not technically
|
||||
C89-compliant. */
|
||||
#define USE_CELT_FIR 0
|
||||
|
||||
void silk_LPC_analysis_filter(
|
||||
opus_int16 *out, /* O Output signal */
|
||||
const opus_int16 *in, /* I Input signal */
|
||||
|
|
@ -49,8 +56,7 @@ void silk_LPC_analysis_filter(
|
|||
)
|
||||
{
|
||||
opus_int j;
|
||||
#ifdef FIXED_POINT
|
||||
opus_int16 mem[SILK_MAX_ORDER_LPC];
|
||||
#if defined(FIXED_POINT) && USE_CELT_FIR
|
||||
opus_int16 num[SILK_MAX_ORDER_LPC];
|
||||
#else
|
||||
int ix;
|
||||
|
|
@ -58,19 +64,16 @@ void silk_LPC_analysis_filter(
|
|||
const opus_int16 *in_ptr;
|
||||
#endif
|
||||
|
||||
silk_assert( d >= 6 );
|
||||
silk_assert( (d & 1) == 0 );
|
||||
silk_assert( d <= len );
|
||||
celt_assert( d >= 6 );
|
||||
celt_assert( (d & 1) == 0 );
|
||||
celt_assert( d <= len );
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
silk_assert( d <= SILK_MAX_ORDER_LPC );
|
||||
#if defined(FIXED_POINT) && USE_CELT_FIR
|
||||
celt_assert( d <= SILK_MAX_ORDER_LPC );
|
||||
for ( j = 0; j < d; j++ ) {
|
||||
num[ j ] = -B[ j ];
|
||||
}
|
||||
for (j=0;j<d;j++) {
|
||||
mem[ j ] = in[ d - j - 1 ];
|
||||
}
|
||||
celt_fir( in + d, num, out + d, len - d, d, mem, arch );
|
||||
celt_fir( in + d, num, out + d, len - d, d, arch );
|
||||
for ( j = 0; j < d; j++ ) {
|
||||
out[ j ] = 0;
|
||||
}
|
||||
|
|
|
|||
82
media/libopus/silk/LPC_fit.c
Normal file
82
media/libopus/silk/LPC_fit.c
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2013, Koen Vos. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around.
|
||||
This logic is reused in _celt_lpc(). Any bug fixes should also be applied there. */
|
||||
void silk_LPC_fit(
|
||||
opus_int16 *a_QOUT, /* O Output signal */
|
||||
opus_int32 *a_QIN, /* I/O Input signal */
|
||||
const opus_int QOUT, /* I Input Q domain */
|
||||
const opus_int QIN, /* I Input Q domain */
|
||||
const opus_int d /* I Filter order */
|
||||
)
|
||||
{
|
||||
opus_int i, k, idx = 0;
|
||||
opus_int32 maxabs, absval, chirp_Q16;
|
||||
|
||||
/* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
|
||||
for( i = 0; i < 10; i++ ) {
|
||||
/* Find maximum absolute value and its index */
|
||||
maxabs = 0;
|
||||
for( k = 0; k < d; k++ ) {
|
||||
absval = silk_abs( a_QIN[k] );
|
||||
if( absval > maxabs ) {
|
||||
maxabs = absval;
|
||||
idx = k;
|
||||
}
|
||||
}
|
||||
maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT );
|
||||
|
||||
if( maxabs > silk_int16_MAX ) {
|
||||
/* Reduce magnitude of prediction coefficients */
|
||||
maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
|
||||
chirp_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
|
||||
silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
|
||||
silk_bwexpander_32( a_QIN, d, chirp_Q16 );
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( i == 10 ) {
|
||||
/* Reached the last iteration, clip the coefficients */
|
||||
for( k = 0; k < d; k++ ) {
|
||||
a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) );
|
||||
a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT );
|
||||
}
|
||||
} else {
|
||||
for( k = 0; k < d; k++ ) {
|
||||
a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#endif
|
||||
|
||||
#include "SigProc_FIX.h"
|
||||
#include "define.h"
|
||||
|
||||
#define QA 24
|
||||
#define A_LIMIT SILK_FIX_CONST( 0.99975, QA )
|
||||
|
|
@ -38,117 +39,103 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
/* Compute inverse of LPC prediction gain, and */
|
||||
/* test if LPC coefficients are stable (all poles within unit circle) */
|
||||
static opus_int32 LPC_inverse_pred_gain_QA( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
|
||||
static opus_int32 LPC_inverse_pred_gain_QA_c( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
opus_int32 A_QA[ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
|
||||
const opus_int order /* I Prediction order */
|
||||
)
|
||||
{
|
||||
opus_int k, n, mult2Q;
|
||||
opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA;
|
||||
opus_int32 *Aold_QA, *Anew_QA;
|
||||
opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
|
||||
|
||||
Anew_QA = A_QA[ order & 1 ];
|
||||
|
||||
invGain_Q30 = (opus_int32)1 << 30;
|
||||
invGain_Q30 = SILK_FIX_CONST( 1, 30 );
|
||||
for( k = order - 1; k > 0; k-- ) {
|
||||
/* Check for stability */
|
||||
if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) {
|
||||
if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set RC equal to negated AR coef */
|
||||
rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA );
|
||||
rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
|
||||
|
||||
/* rc_mult1_Q30 range: [ 1 : 2^30 ] */
|
||||
rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
|
||||
rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
|
||||
silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
|
||||
silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
|
||||
|
||||
/* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
|
||||
mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
|
||||
rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
|
||||
|
||||
/* Update inverse gain */
|
||||
/* invGain_Q30 range: [ 0 : 2^30 ] */
|
||||
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
|
||||
silk_assert( invGain_Q30 >= 0 );
|
||||
silk_assert( invGain_Q30 <= ( 1 << 30 ) );
|
||||
if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Swap pointers */
|
||||
Aold_QA = Anew_QA;
|
||||
Anew_QA = A_QA[ k & 1 ];
|
||||
/* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
|
||||
mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
|
||||
rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
|
||||
|
||||
/* Update AR coefficient */
|
||||
for( n = 0; n < k; n++ ) {
|
||||
tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 );
|
||||
Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q );
|
||||
for( n = 0; n < (k + 1) >> 1; n++ ) {
|
||||
opus_int64 tmp64;
|
||||
tmp1 = A_QA[ n ];
|
||||
tmp2 = A_QA[ k - n - 1 ];
|
||||
tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
|
||||
MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
|
||||
if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
|
||||
return 0;
|
||||
}
|
||||
A_QA[ n ] = ( opus_int32 )tmp64;
|
||||
tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
|
||||
MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
|
||||
if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
|
||||
return 0;
|
||||
}
|
||||
A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for stability */
|
||||
if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
|
||||
if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set RC equal to negated AR coef */
|
||||
rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA );
|
||||
rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
|
||||
|
||||
/* Range: [ 1 : 2^30 ] */
|
||||
rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
|
||||
rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
|
||||
|
||||
/* Update inverse gain */
|
||||
/* Range: [ 0 : 2^30 ] */
|
||||
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
|
||||
silk_assert( invGain_Q30 >= 0 );
|
||||
silk_assert( invGain_Q30 <= 1<<30 );
|
||||
silk_assert( invGain_Q30 >= 0 );
|
||||
silk_assert( invGain_Q30 <= ( 1 << 30 ) );
|
||||
if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return invGain_Q30;
|
||||
}
|
||||
|
||||
/* For input in Q12 domain */
|
||||
opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
)
|
||||
{
|
||||
opus_int k;
|
||||
opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 *Anew_QA;
|
||||
opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 DC_resp = 0;
|
||||
|
||||
Anew_QA = Atmp_QA[ order & 1 ];
|
||||
|
||||
/* Increase Q domain of the AR coefficients */
|
||||
for( k = 0; k < order; k++ ) {
|
||||
DC_resp += (opus_int32)A_Q12[ k ];
|
||||
Anew_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
|
||||
Atmp_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
|
||||
}
|
||||
/* If the DC is unstable, we don't even need to do the full calculations */
|
||||
if( DC_resp >= 4096 ) {
|
||||
return 0;
|
||||
}
|
||||
return LPC_inverse_pred_gain_QA( Atmp_QA, order );
|
||||
return LPC_inverse_pred_gain_QA_c( Atmp_QA, order );
|
||||
}
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
/* For input in Q24 domain */
|
||||
opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
)
|
||||
{
|
||||
opus_int k;
|
||||
opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 *Anew_QA;
|
||||
|
||||
Anew_QA = Atmp_QA[ order & 1 ];
|
||||
|
||||
/* Increase Q domain of the AR coefficients */
|
||||
for( k = 0; k < order; k++ ) {
|
||||
Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA );
|
||||
}
|
||||
|
||||
return LPC_inverse_pred_gain_QA( Atmp_QA, order );
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -130,6 +130,6 @@ void silk_LP_variable_cutoff(
|
|||
|
||||
/* ARMA low-pass filtering */
|
||||
silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
|
||||
silk_biquad_alt( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1);
|
||||
silk_biquad_alt_stride1( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifndef SIGPROCFIX_API_MACROCOUNT_H
|
||||
#define SIGPROCFIX_API_MACROCOUNT_H
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef silk_MACRO_COUNT
|
||||
#include <stdio.h>
|
||||
#define varDefine opus_int64 ops_count = 0;
|
||||
|
||||
extern opus_int64 ops_count;
|
||||
|
|
@ -319,14 +319,6 @@ static OPUS_INLINE opus_int32 silk_ADD_POS_SAT32(opus_int64 a, opus_int64 b){
|
|||
return(tmp);
|
||||
}
|
||||
|
||||
#undef silk_ADD_POS_SAT64
|
||||
static OPUS_INLINE opus_int64 silk_ADD_POS_SAT64(opus_int64 a, opus_int64 b){
|
||||
opus_int64 tmp;
|
||||
ops_count += 1;
|
||||
tmp = ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)));
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
#undef silk_LSHIFT8
|
||||
static OPUS_INLINE opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){
|
||||
opus_int8 ret;
|
||||
|
|
@ -699,7 +691,7 @@ return(ret);
|
|||
|
||||
|
||||
#undef silk_LIMIT_32
|
||||
static OPUS_INLINE opus_int silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
|
||||
static OPUS_INLINE opus_int32 silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
|
||||
{
|
||||
opus_int32 ret;
|
||||
ops_count += 6;
|
||||
|
|
|
|||
|
|
@ -539,8 +539,7 @@ static OPUS_INLINE opus_int32 silk_DIV32_16_(opus_int32 a32, opus_int32 b32, cha
|
|||
no checking needed for silk_POS_SAT32
|
||||
no checking needed for silk_ADD_POS_SAT8
|
||||
no checking needed for silk_ADD_POS_SAT16
|
||||
no checking needed for silk_ADD_POS_SAT32
|
||||
no checking needed for silk_ADD_POS_SAT64 */
|
||||
no checking needed for silk_ADD_POS_SAT32 */
|
||||
|
||||
#undef silk_LSHIFT8
|
||||
#define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__)
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ static OPUS_INLINE void silk_NLSF2A_find_poly(
|
|||
void silk_NLSF2A(
|
||||
opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
|
||||
const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
|
||||
const opus_int d /* I filter order (should be even) */
|
||||
const opus_int d, /* I filter order (should be even) */
|
||||
int arch /* I Run-time architecture */
|
||||
)
|
||||
{
|
||||
/* This ordering was found to maximize quality. It improves numerical accuracy of
|
||||
|
|
@ -83,15 +84,14 @@ void silk_NLSF2A(
|
|||
opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
|
||||
opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
|
||||
opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 maxabs, absval, idx=0, sc_Q16;
|
||||
|
||||
silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
|
||||
silk_assert( d==10||d==16 );
|
||||
celt_assert( d==10 || d==16 );
|
||||
|
||||
/* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
|
||||
ordering = d == 16 ? ordering16 : ordering10;
|
||||
for( k = 0; k < d; k++ ) {
|
||||
silk_assert(NLSF[k] >= 0 );
|
||||
silk_assert( NLSF[k] >= 0 );
|
||||
|
||||
/* f_int on a scale 0-127 (rounded down) */
|
||||
f_int = silk_RSHIFT( NLSF[k], 15 - 7 );
|
||||
|
|
@ -126,52 +126,15 @@ void silk_NLSF2A(
|
|||
a32_QA1[ d-k-1 ] = Qtmp - Ptmp; /* QA+1 */
|
||||
}
|
||||
|
||||
/* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
|
||||
for( i = 0; i < 10; i++ ) {
|
||||
/* Find maximum absolute value and its index */
|
||||
maxabs = 0;
|
||||
for( k = 0; k < d; k++ ) {
|
||||
absval = silk_abs( a32_QA1[k] );
|
||||
if( absval > maxabs ) {
|
||||
maxabs = absval;
|
||||
idx = k;
|
||||
}
|
||||
}
|
||||
maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */
|
||||
/* Convert int32 coefficients to Q12 int16 coefs */
|
||||
silk_LPC_fit( a_Q12, a32_QA1, 12, QA + 1, d );
|
||||
|
||||
if( maxabs > silk_int16_MAX ) {
|
||||
/* Reduce magnitude of prediction coefficients */
|
||||
maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
|
||||
sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
|
||||
silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
|
||||
silk_bwexpander_32( a32_QA1, d, sc_Q16 );
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( i == 10 ) {
|
||||
/* Reached the last iteration, clip the coefficients */
|
||||
for( i = 0; silk_LPC_inverse_pred_gain( a_Q12, d, arch ) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
|
||||
/* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
|
||||
/* on the unscaled coefficients, convert to Q12 and measure again */
|
||||
silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
|
||||
for( k = 0; k < d; k++ ) {
|
||||
a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */
|
||||
a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 );
|
||||
}
|
||||
} else {
|
||||
for( k = 0; k < d; k++ ) {
|
||||
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
|
||||
if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
|
||||
/* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
|
||||
/* on the unscaled coefficients, convert to Q12 and measure again */
|
||||
silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
|
||||
for( k = 0; k < d; k++ ) {
|
||||
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,36 +33,44 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */
|
||||
void silk_NLSF_VQ(
|
||||
opus_int32 err_Q26[], /* O Quantization errors [K] */
|
||||
opus_int32 err_Q24[], /* O Quantization errors [K] */
|
||||
const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */
|
||||
const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */
|
||||
const opus_int16 pWght_Q9[], /* I Codebook weights [K*LPC_order] */
|
||||
const opus_int K, /* I Number of codebook vectors */
|
||||
const opus_int LPC_order /* I Number of LPCs */
|
||||
)
|
||||
{
|
||||
opus_int i, m;
|
||||
opus_int32 diff_Q15, sum_error_Q30, sum_error_Q26;
|
||||
opus_int i, m;
|
||||
opus_int32 diff_Q15, diffw_Q24, sum_error_Q24, pred_Q24;
|
||||
const opus_int16 *w_Q9_ptr;
|
||||
const opus_uint8 *cb_Q8_ptr;
|
||||
|
||||
silk_assert( LPC_order <= 16 );
|
||||
silk_assert( ( LPC_order & 1 ) == 0 );
|
||||
celt_assert( ( LPC_order & 1 ) == 0 );
|
||||
|
||||
/* Loop over codebook */
|
||||
cb_Q8_ptr = pCB_Q8;
|
||||
w_Q9_ptr = pWght_Q9;
|
||||
for( i = 0; i < K; i++ ) {
|
||||
sum_error_Q26 = 0;
|
||||
for( m = 0; m < LPC_order; m += 2 ) {
|
||||
/* Compute weighted squared quantization error for index m */
|
||||
diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
|
||||
sum_error_Q30 = silk_SMULBB( diff_Q15, diff_Q15 );
|
||||
sum_error_Q24 = 0;
|
||||
pred_Q24 = 0;
|
||||
for( m = LPC_order-2; m >= 0; m -= 2 ) {
|
||||
/* Compute weighted absolute predictive quantization error for index m + 1 */
|
||||
diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m + 1 ], (opus_int32)cb_Q8_ptr[ m + 1 ], 7 ); /* range: [ -32767 : 32767 ]*/
|
||||
diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m + 1 ] );
|
||||
sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) );
|
||||
pred_Q24 = diffw_Q24;
|
||||
|
||||
/* Compute weighted squared quantization error for index m + 1 */
|
||||
diff_Q15 = silk_SUB_LSHIFT32( in_Q15[m + 1], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
|
||||
sum_error_Q30 = silk_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 );
|
||||
/* Compute weighted absolute predictive quantization error for index m */
|
||||
diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)cb_Q8_ptr[ m ], 7 ); /* range: [ -32767 : 32767 ]*/
|
||||
diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m ] );
|
||||
sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) );
|
||||
pred_Q24 = diffw_Q24;
|
||||
|
||||
sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 );
|
||||
|
||||
silk_assert( sum_error_Q26 >= 0 );
|
||||
silk_assert( sum_error_Q30 >= 0 );
|
||||
silk_assert( sum_error_Q24 >= 0 );
|
||||
}
|
||||
err_Q26[ i ] = sum_error_Q26;
|
||||
err_Q24[ i ] = sum_error_Q24;
|
||||
cb_Q8_ptr += LPC_order;
|
||||
w_Q9_ptr += LPC_order;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ void silk_NLSF_VQ_weights_laroia(
|
|||
opus_int k;
|
||||
opus_int32 tmp1_int, tmp2_int;
|
||||
|
||||
silk_assert( D > 0 );
|
||||
silk_assert( ( D & 1 ) == 0 );
|
||||
celt_assert( D > 0 );
|
||||
celt_assert( ( D & 1 ) == 0 );
|
||||
|
||||
/* First value */
|
||||
tmp1_int = silk_max_int( pNLSF_Q15[ 0 ], 1 );
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "main.h"
|
||||
|
||||
/* Predictive dequantizer for NLSF residuals */
|
||||
static OPUS_INLINE void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */
|
||||
static OPUS_INLINE void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */
|
||||
opus_int16 x_Q10[], /* O Output [ order ] */
|
||||
const opus_int8 indices[], /* I Quantization indices [ order ] */
|
||||
const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */
|
||||
|
|
@ -70,15 +70,9 @@ void silk_NLSF_decode(
|
|||
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
|
||||
opus_int16 ec_ix[ MAX_LPC_ORDER ];
|
||||
opus_int16 res_Q10[ MAX_LPC_ORDER ];
|
||||
opus_int16 W_tmp_QW[ MAX_LPC_ORDER ];
|
||||
opus_int32 W_tmp_Q9, NLSF_Q15_tmp;
|
||||
opus_int32 NLSF_Q15_tmp;
|
||||
const opus_uint8 *pCB_element;
|
||||
|
||||
/* Decode first stage */
|
||||
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
|
||||
for( i = 0; i < psNLSF_CB->order; i++ ) {
|
||||
pNLSF_Q15[ i ] = silk_LSHIFT( (opus_int16)pCB_element[ i ], 7 );
|
||||
}
|
||||
const opus_int16 *pCB_Wght_Q9;
|
||||
|
||||
/* Unpack entropy table indices and predictor for current CB1 index */
|
||||
silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] );
|
||||
|
|
@ -86,13 +80,11 @@ void silk_NLSF_decode(
|
|||
/* Predictive residual dequantizer */
|
||||
silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order );
|
||||
|
||||
/* Weights from codebook vector */
|
||||
silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order );
|
||||
|
||||
/* Apply inverse square-rooted weights and add to output */
|
||||
/* Apply inverse square-rooted weights to first stage and add to output */
|
||||
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
|
||||
pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
|
||||
for( i = 0; i < psNLSF_CB->order; i++ ) {
|
||||
W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
|
||||
NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), W_tmp_Q9 ) );
|
||||
NLSF_Q15_tmp = silk_ADD_LSHIFT32( silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), pCB_Wght_Q9[ i ] ), (opus_int16)pCB_element[ i ], 7 );
|
||||
pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
|
|||
nStates = 1;
|
||||
RD_Q25[ 0 ] = 0;
|
||||
prev_out_Q10[ 0 ] = 0;
|
||||
for( i = order - 1; ; i-- ) {
|
||||
for( i = order - 1; i >= 0; i-- ) {
|
||||
rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ];
|
||||
in_Q10 = x_Q10[ i ];
|
||||
for( j = 0; j < nStates; j++ ) {
|
||||
|
|
@ -131,7 +131,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
|
|||
RD_Q25[ j + nStates ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 );
|
||||
}
|
||||
|
||||
if( nStates <= ( NLSF_QUANT_DEL_DEC_STATES >> 1 ) ) {
|
||||
if( nStates <= NLSF_QUANT_DEL_DEC_STATES/2 ) {
|
||||
/* double number of states and copy */
|
||||
for( j = 0; j < nStates; j++ ) {
|
||||
ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1;
|
||||
|
|
@ -140,7 +140,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
|
|||
for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
|
||||
ind[ j ][ i ] = ind[ j - nStates ][ i ];
|
||||
}
|
||||
} else if( i > 0 ) {
|
||||
} else {
|
||||
/* sort lower and upper half of RD_Q25, pairwise */
|
||||
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
|
||||
if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) {
|
||||
|
|
@ -191,8 +191,6 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
|
|||
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
|
||||
ind[ j ][ i ] += silk_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 );
|
||||
}
|
||||
} else { /* i == 0 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
/***********************/
|
||||
opus_int32 silk_NLSF_encode( /* O Returns RD value in Q25 */
|
||||
opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
|
||||
opus_int16 *pNLSF_Q15, /* I/O Quantized NLSF vector [ LPC_ORDER ] */
|
||||
opus_int16 *pNLSF_Q15, /* I/O (Un)quantized NLSF vector [ LPC_ORDER ] */
|
||||
const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
|
||||
const opus_int16 *pW_QW, /* I NLSF weight vector [ LPC_ORDER ] */
|
||||
const opus_int16 *pW_Q2, /* I NLSF weight vector [ LPC_ORDER ] */
|
||||
const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */
|
||||
const opus_int nSurvivors, /* I Max survivors after first stage */
|
||||
const opus_int signalType /* I Signal type: 0/1/2 */
|
||||
|
|
@ -47,34 +47,32 @@ opus_int32 silk_NLSF_encode( /* O Returns
|
|||
{
|
||||
opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7;
|
||||
opus_int32 W_tmp_Q9, ret;
|
||||
VARDECL( opus_int32, err_Q26 );
|
||||
VARDECL( opus_int32, err_Q24 );
|
||||
VARDECL( opus_int32, RD_Q25 );
|
||||
VARDECL( opus_int, tempIndices1 );
|
||||
VARDECL( opus_int8, tempIndices2 );
|
||||
opus_int16 res_Q15[ MAX_LPC_ORDER ];
|
||||
opus_int16 res_Q10[ MAX_LPC_ORDER ];
|
||||
opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ];
|
||||
opus_int16 W_tmp_QW[ MAX_LPC_ORDER ];
|
||||
opus_int16 W_adj_Q5[ MAX_LPC_ORDER ];
|
||||
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
|
||||
opus_int16 ec_ix[ MAX_LPC_ORDER ];
|
||||
const opus_uint8 *pCB_element, *iCDF_ptr;
|
||||
const opus_int16 *pCB_Wght_Q9;
|
||||
SAVE_STACK;
|
||||
|
||||
silk_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS );
|
||||
silk_assert( signalType >= 0 && signalType <= 2 );
|
||||
celt_assert( signalType >= 0 && signalType <= 2 );
|
||||
silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 );
|
||||
|
||||
/* NLSF stabilization */
|
||||
silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
|
||||
|
||||
/* First stage: VQ */
|
||||
ALLOC( err_Q26, psNLSF_CB->nVectors, opus_int32 );
|
||||
silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order );
|
||||
ALLOC( err_Q24, psNLSF_CB->nVectors, opus_int32 );
|
||||
silk_NLSF_VQ( err_Q24, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->CB1_Wght_Q9, psNLSF_CB->nVectors, psNLSF_CB->order );
|
||||
|
||||
/* Sort the quantization errors */
|
||||
ALLOC( tempIndices1, nSurvivors, opus_int );
|
||||
silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
|
||||
silk_insertion_sort_increasing( err_Q24, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
|
||||
|
||||
ALLOC( RD_Q25, nSurvivors, opus_int32 );
|
||||
ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 );
|
||||
|
|
@ -85,23 +83,12 @@ opus_int32 silk_NLSF_encode( /* O Returns
|
|||
|
||||
/* Residual after first stage */
|
||||
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ];
|
||||
pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ ind1 * psNLSF_CB->order ];
|
||||
for( i = 0; i < psNLSF_CB->order; i++ ) {
|
||||
NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 );
|
||||
res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ];
|
||||
}
|
||||
|
||||
/* Weights from codebook vector */
|
||||
silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order );
|
||||
|
||||
/* Apply square-rooted weights */
|
||||
for( i = 0; i < psNLSF_CB->order; i++ ) {
|
||||
W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
|
||||
res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 );
|
||||
}
|
||||
|
||||
/* Modify input weights accordingly */
|
||||
for( i = 0; i < psNLSF_CB->order; i++ ) {
|
||||
W_adj_Q5[ i ] = silk_DIV32_16( silk_LSHIFT( (opus_int32)pW_QW[ i ], 5 ), W_tmp_QW[ i ] );
|
||||
W_tmp_Q9 = pCB_Wght_Q9[ i ];
|
||||
res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ], W_tmp_Q9 ), 14 );
|
||||
W_adj_Q5[ i ] = silk_DIV32_varQ( (opus_int32)pW_Q2[ i ], silk_SMULBB( W_tmp_Q9, W_tmp_Q9 ), 21 );
|
||||
}
|
||||
|
||||
/* Unpack entropy table indices and predictor for current CB1 index */
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
static OPUS_INLINE void silk_nsq_scale_states(
|
||||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
const opus_int32 x_Q3[], /* I input in Q3 */
|
||||
const opus_int16 x16[], /* I input */
|
||||
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
|
||||
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
|
||||
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
|
||||
|
|
@ -75,21 +75,21 @@ static OPUS_INLINE void silk_noise_shape_quantizer(
|
|||
|
||||
void silk_NSQ_c
|
||||
(
|
||||
const silk_encoder_state *psEncC, /* I/O Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
SideInfoIndices *psIndices, /* I/O Quantization Indices */
|
||||
const opus_int32 x_Q3[], /* I Prefiltered input signal */
|
||||
opus_int8 pulses[], /* O Quantized pulse signal */
|
||||
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
|
||||
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
|
||||
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
|
||||
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
|
||||
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
|
||||
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
|
||||
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
|
||||
const opus_int LTP_scale_Q14 /* I LTP state scaling */
|
||||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
SideInfoIndices *psIndices, /* I/O Quantization Indices */
|
||||
const opus_int16 x16[], /* I Input */
|
||||
opus_int8 pulses[], /* O Quantized pulse signal */
|
||||
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
|
||||
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
|
||||
const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
|
||||
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
|
||||
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
|
||||
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
|
||||
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
|
||||
const opus_int LTP_scale_Q14 /* I LTP state scaling */
|
||||
)
|
||||
{
|
||||
opus_int k, lag, start_idx, LSF_interpolation_flag;
|
||||
|
|
@ -117,8 +117,7 @@ void silk_NSQ_c
|
|||
LSF_interpolation_flag = 1;
|
||||
}
|
||||
|
||||
ALLOC( sLTP_Q15,
|
||||
psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
|
||||
ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
|
||||
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
|
||||
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
|
||||
/* Set up pointers to start of sub frame */
|
||||
|
|
@ -128,7 +127,7 @@ void silk_NSQ_c
|
|||
for( k = 0; k < psEncC->nb_subfr; k++ ) {
|
||||
A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
|
||||
B_Q14 = <PCoef_Q14[ k * LTP_ORDER ];
|
||||
AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
|
||||
AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
|
||||
|
||||
/* Noise shape parameters */
|
||||
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
|
||||
|
|
@ -144,7 +143,7 @@ void silk_NSQ_c
|
|||
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
|
||||
/* Rewhiten with new A coefs */
|
||||
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
|
||||
silk_assert( start_idx > 0 );
|
||||
celt_assert( start_idx > 0 );
|
||||
|
||||
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
|
||||
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
|
||||
|
|
@ -154,13 +153,13 @@ void silk_NSQ_c
|
|||
}
|
||||
}
|
||||
|
||||
silk_nsq_scale_states( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
|
||||
silk_nsq_scale_states( psEncC, NSQ, x16, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
|
||||
|
||||
silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
|
||||
AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
|
||||
offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder, psEncC->arch );
|
||||
|
||||
x_Q3 += psEncC->subfr_length;
|
||||
x16 += psEncC->subfr_length;
|
||||
pulses += psEncC->subfr_length;
|
||||
pxq += psEncC->subfr_length;
|
||||
}
|
||||
|
|
@ -169,15 +168,14 @@ void silk_NSQ_c
|
|||
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
|
||||
|
||||
/* Save quantized speech and noise shaping signals */
|
||||
/* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */
|
||||
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
|
||||
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
/***********************************/
|
||||
/* silk_noise_shape_quantizer */
|
||||
/***********************************/
|
||||
/******************************/
|
||||
/* silk_noise_shape_quantizer */
|
||||
/******************************/
|
||||
|
||||
#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
|
||||
static OPUS_INLINE
|
||||
|
|
@ -249,22 +247,22 @@ void silk_noise_shape_quantizer(
|
|||
}
|
||||
|
||||
/* Noise shape feedback */
|
||||
silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(psLPC_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
|
||||
celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(&NSQ->sDiff_shp_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
|
||||
|
||||
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 );
|
||||
|
||||
n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
|
||||
n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 );
|
||||
|
||||
silk_assert( lag > 0 || signalType != TYPE_VOICED );
|
||||
celt_assert( lag > 0 || signalType != TYPE_VOICED );
|
||||
|
||||
/* Combine prediction and noise shaping signals */
|
||||
tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */
|
||||
tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */
|
||||
if( lag > 0 ) {
|
||||
/* Symmetric, packed FIR coefficients */
|
||||
n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q13 = silk_SMULWB( silk_ADD_SAT32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 );
|
||||
shp_lag_ptr++;
|
||||
|
|
@ -279,14 +277,27 @@ void silk_noise_shape_quantizer(
|
|||
r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */
|
||||
|
||||
/* Flip sign depending on dither */
|
||||
if ( NSQ->rand_seed < 0 ) {
|
||||
r_Q10 = -r_Q10;
|
||||
if( NSQ->rand_seed < 0 ) {
|
||||
r_Q10 = -r_Q10;
|
||||
}
|
||||
r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
|
||||
|
||||
/* Find two quantization level candidates and measure their rate-distortion */
|
||||
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
|
||||
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
|
||||
if (Lambda_Q10 > 2048) {
|
||||
/* For aggressive RDO, the bias becomes more than one pulse. */
|
||||
int rdo_offset = Lambda_Q10/2 - 512;
|
||||
if (q1_Q10 > rdo_offset) {
|
||||
q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
|
||||
} else if (q1_Q10 < -rdo_offset) {
|
||||
q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
|
||||
} else if (q1_Q10 < 0) {
|
||||
q1_Q0 = -1;
|
||||
} else {
|
||||
q1_Q0 = 0;
|
||||
}
|
||||
}
|
||||
if( q1_Q0 > 0 ) {
|
||||
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
|
||||
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
|
||||
|
|
@ -337,7 +348,8 @@ void silk_noise_shape_quantizer(
|
|||
/* Update states */
|
||||
psLPC_Q14++;
|
||||
*psLPC_Q14 = xq_Q14;
|
||||
sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 );
|
||||
NSQ->sDiff_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_sc_Q10[ i ], 4 );
|
||||
sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( NSQ->sDiff_shp_Q14, n_AR_Q12, 2 );
|
||||
NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14;
|
||||
|
||||
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 );
|
||||
|
|
@ -356,7 +368,7 @@ void silk_noise_shape_quantizer(
|
|||
static OPUS_INLINE void silk_nsq_scale_states(
|
||||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
const opus_int32 x_Q3[], /* I input in Q3 */
|
||||
const opus_int16 x16[], /* I input */
|
||||
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
|
||||
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
|
||||
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
|
||||
|
|
@ -368,28 +380,18 @@ static OPUS_INLINE void silk_nsq_scale_states(
|
|||
)
|
||||
{
|
||||
opus_int i, lag;
|
||||
opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
|
||||
opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
|
||||
|
||||
lag = pitchL[ subfr ];
|
||||
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
|
||||
silk_assert( inv_gain_Q31 != 0 );
|
||||
|
||||
/* Calculate gain adjustment factor */
|
||||
if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
|
||||
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
|
||||
} else {
|
||||
gain_adj_Q16 = (opus_int32)1 << 16;
|
||||
}
|
||||
|
||||
/* Scale input */
|
||||
inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
|
||||
inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
|
||||
for( i = 0; i < psEncC->subfr_length; i++ ) {
|
||||
x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
|
||||
x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
|
||||
}
|
||||
|
||||
/* Save inverse gain */
|
||||
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
|
||||
|
||||
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
|
||||
if( NSQ->rewhite_flag ) {
|
||||
if( subfr == 0 ) {
|
||||
|
|
@ -403,7 +405,9 @@ static OPUS_INLINE void silk_nsq_scale_states(
|
|||
}
|
||||
|
||||
/* Adjust for changing gain */
|
||||
if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
|
||||
if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
|
||||
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
|
||||
|
||||
/* Scale long-term shaping state */
|
||||
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
|
||||
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
|
||||
|
|
@ -417,6 +421,7 @@ static OPUS_INLINE void silk_nsq_scale_states(
|
|||
}
|
||||
|
||||
NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 );
|
||||
NSQ->sDiff_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sDiff_shp_Q14 );
|
||||
|
||||
/* Scale short-term prediction and shaping states */
|
||||
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
|
||||
|
|
@ -425,5 +430,8 @@ static OPUS_INLINE void silk_nsq_scale_states(
|
|||
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
|
||||
NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
|
||||
}
|
||||
|
||||
/* Save inverse gain */
|
||||
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ typedef struct {
|
|||
opus_int32 Shape_Q14[ DECISION_DELAY ];
|
||||
opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
|
||||
opus_int32 LF_AR_Q14;
|
||||
opus_int32 Diff_Q14;
|
||||
opus_int32 Seed;
|
||||
opus_int32 SeedInit;
|
||||
opus_int32 RD_Q10;
|
||||
|
|
@ -53,6 +54,7 @@ typedef struct {
|
|||
opus_int32 RD_Q10;
|
||||
opus_int32 xq_Q14;
|
||||
opus_int32 LF_AR_Q14;
|
||||
opus_int32 Diff_Q14;
|
||||
opus_int32 sLTP_shp_Q14;
|
||||
opus_int32 LPC_exc_Q14;
|
||||
} NSQ_sample_struct;
|
||||
|
|
@ -66,7 +68,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
|
|||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
|
||||
const opus_int32 x_Q3[], /* I Input in Q3 */
|
||||
const opus_int16 x16[], /* I Input */
|
||||
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
|
||||
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
|
||||
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
|
||||
|
|
@ -107,27 +109,27 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
|
|||
opus_int predictLPCOrder, /* I Prediction filter order */
|
||||
opus_int warping_Q16, /* I */
|
||||
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
|
||||
opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
|
||||
opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
|
||||
opus_int decisionDelay, /* I */
|
||||
int arch /* I */
|
||||
);
|
||||
|
||||
void silk_NSQ_del_dec_c(
|
||||
const silk_encoder_state *psEncC, /* I/O Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
SideInfoIndices *psIndices, /* I/O Quantization Indices */
|
||||
const opus_int32 x_Q3[], /* I Prefiltered input signal */
|
||||
opus_int8 pulses[], /* O Quantized pulse signal */
|
||||
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
|
||||
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
|
||||
const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
|
||||
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
|
||||
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
|
||||
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
|
||||
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
|
||||
const opus_int LTP_scale_Q14 /* I LTP state scaling */
|
||||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
SideInfoIndices *psIndices, /* I/O Quantization Indices */
|
||||
const opus_int16 x16[], /* I Input */
|
||||
opus_int8 pulses[], /* O Quantized pulse signal */
|
||||
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
|
||||
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
|
||||
const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
|
||||
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
|
||||
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
|
||||
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
|
||||
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
|
||||
const opus_int LTP_scale_Q14 /* I LTP state scaling */
|
||||
)
|
||||
{
|
||||
opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
|
||||
|
|
@ -159,6 +161,7 @@ void silk_NSQ_del_dec_c(
|
|||
psDD->SeedInit = psDD->Seed;
|
||||
psDD->RD_Q10 = 0;
|
||||
psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14;
|
||||
psDD->Diff_Q14 = NSQ->sDiff_shp_Q14;
|
||||
psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ];
|
||||
silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
|
||||
silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) );
|
||||
|
|
@ -186,8 +189,7 @@ void silk_NSQ_del_dec_c(
|
|||
LSF_interpolation_flag = 1;
|
||||
}
|
||||
|
||||
ALLOC( sLTP_Q15,
|
||||
psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
|
||||
ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
|
||||
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
|
||||
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
|
||||
ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
|
||||
|
|
@ -199,7 +201,7 @@ void silk_NSQ_del_dec_c(
|
|||
for( k = 0; k < psEncC->nb_subfr; k++ ) {
|
||||
A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
|
||||
B_Q14 = <PCoef_Q14[ k * LTP_ORDER ];
|
||||
AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
|
||||
AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
|
||||
|
||||
/* Noise shape parameters */
|
||||
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
|
||||
|
|
@ -235,7 +237,8 @@ void silk_NSQ_del_dec_c(
|
|||
psDD = &psDelDec[ Winner_ind ];
|
||||
last_smple_idx = smpl_buf_idx + decisionDelay;
|
||||
for( i = 0; i < decisionDelay; i++ ) {
|
||||
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
|
||||
last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
|
||||
if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
|
||||
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
|
||||
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) );
|
||||
|
|
@ -247,7 +250,7 @@ void silk_NSQ_del_dec_c(
|
|||
|
||||
/* Rewhiten with new A coefs */
|
||||
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
|
||||
silk_assert( start_idx > 0 );
|
||||
celt_assert( start_idx > 0 );
|
||||
|
||||
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
|
||||
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
|
||||
|
|
@ -257,7 +260,7 @@ void silk_NSQ_del_dec_c(
|
|||
}
|
||||
}
|
||||
|
||||
silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k,
|
||||
silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x16, x_sc_Q10, sLTP, sLTP_Q15, k,
|
||||
psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
|
||||
|
||||
silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
|
||||
|
|
@ -265,7 +268,7 @@ void silk_NSQ_del_dec_c(
|
|||
Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
|
||||
psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay, psEncC->arch );
|
||||
|
||||
x_Q3 += psEncC->subfr_length;
|
||||
x16 += psEncC->subfr_length;
|
||||
pulses += psEncC->subfr_length;
|
||||
pxq += psEncC->subfr_length;
|
||||
}
|
||||
|
|
@ -286,7 +289,9 @@ void silk_NSQ_del_dec_c(
|
|||
last_smple_idx = smpl_buf_idx + decisionDelay;
|
||||
Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
|
||||
for( i = 0; i < decisionDelay; i++ ) {
|
||||
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
|
||||
last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
|
||||
if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
|
||||
|
||||
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
|
||||
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) );
|
||||
|
|
@ -297,10 +302,10 @@ void silk_NSQ_del_dec_c(
|
|||
|
||||
/* Update states */
|
||||
NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14;
|
||||
NSQ->sDiff_shp_Q14 = psDD->Diff_Q14;
|
||||
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
|
||||
|
||||
/* Save quantized speech signal */
|
||||
/* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
|
||||
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
|
||||
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
|
||||
RESTORE_STACK;
|
||||
|
|
@ -335,7 +340,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
|
|||
opus_int predictLPCOrder, /* I Prediction filter order */
|
||||
opus_int warping_Q16, /* I */
|
||||
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
|
||||
opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
|
||||
opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
|
||||
opus_int decisionDelay, /* I */
|
||||
int arch /* I */
|
||||
)
|
||||
|
|
@ -356,7 +361,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
|
|||
NSQ_sample_struct *psSS;
|
||||
SAVE_STACK;
|
||||
|
||||
silk_assert( nStatesDelayedDecision > 0 );
|
||||
celt_assert( nStatesDelayedDecision > 0 );
|
||||
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
|
||||
|
||||
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
|
||||
|
|
@ -389,8 +394,8 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
|
|||
/* Long-term shaping */
|
||||
if( lag > 0 ) {
|
||||
/* Symmetric, packed FIR coefficients */
|
||||
n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q14 = silk_SMULWB( silk_ADD_SAT32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */
|
||||
shp_lag_ptr++;
|
||||
} else {
|
||||
|
|
@ -414,9 +419,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
|
|||
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */
|
||||
|
||||
/* Noise shape feedback */
|
||||
silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
/* Output of lowpass section */
|
||||
tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 );
|
||||
tmp2 = silk_SMLAWB( psDD->Diff_Q14, psDD->sAR2_Q14[ 0 ], warping_Q16 );
|
||||
/* Output of allpass section */
|
||||
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
|
||||
psDD->sAR2_Q14[ 0 ] = tmp2;
|
||||
|
|
@ -446,9 +451,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
|
|||
|
||||
/* Input minus prediction plus noise feedback */
|
||||
/* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
|
||||
tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */
|
||||
tmp1 = silk_ADD_SAT32( n_AR_Q14, n_LF_Q14 ); /* Q14 */
|
||||
tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */
|
||||
tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */
|
||||
tmp1 = silk_SUB_SAT32( tmp2, tmp1 ); /* Q13 */
|
||||
tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */
|
||||
|
||||
r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */
|
||||
|
|
@ -462,6 +467,19 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
|
|||
/* Find two quantization level candidates and measure their rate-distortion */
|
||||
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
|
||||
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
|
||||
if (Lambda_Q10 > 2048) {
|
||||
/* For aggressive RDO, the bias becomes more than one pulse. */
|
||||
int rdo_offset = Lambda_Q10/2 - 512;
|
||||
if (q1_Q10 > rdo_offset) {
|
||||
q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
|
||||
} else if (q1_Q10 < -rdo_offset) {
|
||||
q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
|
||||
} else if (q1_Q10 < 0) {
|
||||
q1_Q0 = -1;
|
||||
} else {
|
||||
q1_Q0 = 0;
|
||||
}
|
||||
}
|
||||
if( q1_Q0 > 0 ) {
|
||||
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
|
||||
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
|
||||
|
|
@ -515,8 +533,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
|
|||
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
|
||||
|
||||
/* Update states */
|
||||
sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
|
||||
psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
|
||||
psSS[ 0 ].Diff_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
|
||||
sLF_AR_shp_Q14 = silk_SUB32( psSS[ 0 ].Diff_Q14, n_AR_Q14 );
|
||||
psSS[ 0 ].sLTP_shp_Q14 = silk_SUB_SAT32( sLF_AR_shp_Q14, n_LF_Q14 );
|
||||
psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14;
|
||||
psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14;
|
||||
psSS[ 0 ].xq_Q14 = xq_Q14;
|
||||
|
|
@ -529,21 +548,22 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
|
|||
exc_Q14 = -exc_Q14;
|
||||
}
|
||||
|
||||
|
||||
/* Add predictions */
|
||||
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
|
||||
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
|
||||
|
||||
/* Update states */
|
||||
sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
|
||||
psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
|
||||
psSS[ 1 ].Diff_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
|
||||
sLF_AR_shp_Q14 = silk_SUB32( psSS[ 1 ].Diff_Q14, n_AR_Q14 );
|
||||
psSS[ 1 ].sLTP_shp_Q14 = silk_SUB_SAT32( sLF_AR_shp_Q14, n_LF_Q14 );
|
||||
psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14;
|
||||
psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14;
|
||||
psSS[ 1 ].xq_Q14 = xq_Q14;
|
||||
}
|
||||
|
||||
*smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
|
||||
last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
|
||||
*smpl_buf_idx = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
|
||||
if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
|
||||
last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
|
||||
|
||||
/* Find winner */
|
||||
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
|
||||
|
|
@ -607,6 +627,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
|
|||
psDD = &psDelDec[ k ];
|
||||
psSS = &psSampleState[ k ][ 0 ];
|
||||
psDD->LF_AR_Q14 = psSS->LF_AR_Q14;
|
||||
psDD->Diff_Q14 = psSS->Diff_Q14;
|
||||
psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
|
||||
psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14;
|
||||
psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10;
|
||||
|
|
@ -631,7 +652,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
|
|||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
|
||||
const opus_int32 x_Q3[], /* I Input in Q3 */
|
||||
const opus_int16 x16[], /* I Input */
|
||||
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
|
||||
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
|
||||
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
|
||||
|
|
@ -645,29 +666,19 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
|
|||
)
|
||||
{
|
||||
opus_int i, k, lag;
|
||||
opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
|
||||
opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
|
||||
NSQ_del_dec_struct *psDD;
|
||||
|
||||
lag = pitchL[ subfr ];
|
||||
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
|
||||
silk_assert( inv_gain_Q31 != 0 );
|
||||
|
||||
/* Calculate gain adjustment factor */
|
||||
if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
|
||||
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
|
||||
} else {
|
||||
gain_adj_Q16 = (opus_int32)1 << 16;
|
||||
}
|
||||
|
||||
/* Scale input */
|
||||
inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
|
||||
inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
|
||||
for( i = 0; i < psEncC->subfr_length; i++ ) {
|
||||
x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
|
||||
x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
|
||||
}
|
||||
|
||||
/* Save inverse gain */
|
||||
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
|
||||
|
||||
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
|
||||
if( NSQ->rewhite_flag ) {
|
||||
if( subfr == 0 ) {
|
||||
|
|
@ -681,7 +692,9 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
|
|||
}
|
||||
|
||||
/* Adjust for changing gain */
|
||||
if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
|
||||
if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
|
||||
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
|
||||
|
||||
/* Scale long-term shaping state */
|
||||
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
|
||||
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
|
||||
|
|
@ -699,6 +712,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
|
|||
|
||||
/* Scale scalar states */
|
||||
psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 );
|
||||
psDD->Diff_Q14 = silk_SMULWW( gain_adj_Q16, psDD->Diff_Q14 );
|
||||
|
||||
/* Scale short-term prediction and shaping states */
|
||||
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
|
||||
|
|
@ -712,5 +726,8 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
|
|||
psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
/* Save inverse gain */
|
||||
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ static OPUS_INLINE void silk_PLC_conceal(
|
|||
/* Reduce random noise for unvoiced frames with high LPC gain */
|
||||
opus_int32 invGain_Q30, down_scale_Q30;
|
||||
|
||||
invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order );
|
||||
invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch );
|
||||
|
||||
down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
|
||||
down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
|
||||
|
|
@ -291,7 +291,7 @@ static OPUS_INLINE void silk_PLC_conceal(
|
|||
|
||||
/* Rewhiten LTP state */
|
||||
idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
|
||||
silk_assert( idx > 0 );
|
||||
celt_assert( idx > 0 );
|
||||
silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch );
|
||||
/* Scale LTP state */
|
||||
inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
|
||||
|
|
@ -345,7 +345,7 @@ static OPUS_INLINE void silk_PLC_conceal(
|
|||
/* Copy LPC state */
|
||||
silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
|
||||
silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
|
||||
celt_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
|
||||
for( i = 0; i < psDec->frame_length; i++ ) {
|
||||
/* partly unrolled */
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ extern "C"
|
|||
|
||||
/*#define silk_MACRO_COUNT */ /* Used to enable WMOPS counting */
|
||||
|
||||
#define SILK_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */
|
||||
#define SILK_MAX_ORDER_LPC 24 /* max order of the LPC analysis in schur() and k2a() */
|
||||
|
||||
#include <string.h> /* for memset(), memcpy(), memmove() */
|
||||
#include "typedef.h"
|
||||
|
|
@ -47,6 +47,11 @@ extern "C"
|
|||
#include "x86/SigProc_FIX_sse.h"
|
||||
#endif
|
||||
|
||||
#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
|
||||
#include "arm/biquad_alt_arm.h"
|
||||
#include "arm/LPC_inv_pred_gain_arm.h"
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
/* SIGNAL PROCESSING FUNCTIONS */
|
||||
/********************************************************************/
|
||||
|
|
@ -96,14 +101,22 @@ void silk_resampler_down2_3(
|
|||
* slower than biquad() but uses more precise coefficients
|
||||
* can handle (slowly) varying coefficients
|
||||
*/
|
||||
void silk_biquad_alt(
|
||||
void silk_biquad_alt_stride1(
|
||||
const opus_int16 *in, /* I input signal */
|
||||
const opus_int32 *B_Q28, /* I MA coefficients [3] */
|
||||
const opus_int32 *A_Q28, /* I AR coefficients [2] */
|
||||
opus_int32 *S, /* I/O State vector [2] */
|
||||
opus_int16 *out, /* O output signal */
|
||||
const opus_int32 len, /* I signal length (must be even) */
|
||||
opus_int stride /* I Operate on interleaved signal if > 1 */
|
||||
const opus_int32 len /* I signal length (must be even) */
|
||||
);
|
||||
|
||||
void silk_biquad_alt_stride2_c(
|
||||
const opus_int16 *in, /* I input signal */
|
||||
const opus_int32 *B_Q28, /* I MA coefficients [3] */
|
||||
const opus_int32 *A_Q28, /* I AR coefficients [2] */
|
||||
opus_int32 *S, /* I/O State vector [4] */
|
||||
opus_int16 *out, /* O output signal */
|
||||
const opus_int32 len /* I signal length (must be even) */
|
||||
);
|
||||
|
||||
/* Variable order MA prediction error filter. */
|
||||
|
|
@ -132,17 +145,11 @@ void silk_bwexpander_32(
|
|||
|
||||
/* Compute inverse of LPC prediction gain, and */
|
||||
/* test if LPC coefficients are stable (all poles within unit circle) */
|
||||
opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
);
|
||||
|
||||
/* For input in Q24 domain */
|
||||
opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
);
|
||||
|
||||
/* Split signal in two decimated bands using first-order allpass filters */
|
||||
void silk_ana_filt_bank_1(
|
||||
const opus_int16 *in, /* I Input signal [N] */
|
||||
|
|
@ -152,6 +159,14 @@ void silk_ana_filt_bank_1(
|
|||
const opus_int32 N /* I Number of input samples */
|
||||
);
|
||||
|
||||
#if !defined(OVERRIDE_silk_biquad_alt_stride2)
|
||||
#define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_c(in, B_Q28, A_Q28, S, out, len))
|
||||
#endif
|
||||
|
||||
#if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
|
||||
#define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_c(A_Q12, order))
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
/* SCALAR FUNCTIONS */
|
||||
/********************************************************************/
|
||||
|
|
@ -271,7 +286,17 @@ void silk_A2NLSF(
|
|||
void silk_NLSF2A(
|
||||
opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
|
||||
const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
|
||||
const opus_int d /* I filter order (should be even) */
|
||||
const opus_int d, /* I filter order (should be even) */
|
||||
int arch /* I Run-time architecture */
|
||||
);
|
||||
|
||||
/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
|
||||
void silk_LPC_fit(
|
||||
opus_int16 *a_QOUT, /* O Output signal */
|
||||
opus_int32 *a_QIN, /* I/O Input signal */
|
||||
const opus_int QOUT, /* I Input Q domain */
|
||||
const opus_int QIN, /* I Input Q domain */
|
||||
const opus_int d /* I Filter order */
|
||||
);
|
||||
|
||||
void silk_insertion_sort_increasing(
|
||||
|
|
@ -356,7 +381,7 @@ opus_int32 silk_inner_prod_aligned_scale(
|
|||
const opus_int len /* I vector lengths */
|
||||
);
|
||||
|
||||
opus_int64 silk_inner_prod16_aligned_64_c(
|
||||
opus_int64 silk_inner_prod16_c(
|
||||
const opus_int16 *inVec1, /* I input vector 1 */
|
||||
const opus_int16 *inVec2, /* I input vector 2 */
|
||||
const opus_int len /* I vector lengths */
|
||||
|
|
@ -471,8 +496,7 @@ static OPUS_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
|
|||
/* Add with saturation for positive input values */
|
||||
#define silk_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b)))
|
||||
#define silk_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)))
|
||||
#define silk_ADD_POS_SAT32(a, b) ((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
|
||||
#define silk_ADD_POS_SAT64(a, b) ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)))
|
||||
#define silk_ADD_POS_SAT32(a, b) ((((opus_uint32)(a)+(opus_uint32)(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
|
||||
|
||||
#define silk_LSHIFT8(a, shift) ((opus_int8)((opus_uint8)(a)<<(shift))) /* shift >= 0, shift < 8 */
|
||||
#define silk_LSHIFT16(a, shift) ((opus_int16)((opus_uint16)(a)<<(shift))) /* shift >= 0, shift < 16 */
|
||||
|
|
@ -572,7 +596,9 @@ static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
|
|||
/* Make sure to store the result as the seed for the next call (also in between */
|
||||
/* frames), otherwise result won't be random at all. When only using some of the */
|
||||
/* bits, take the most significant bits by right-shifting. */
|
||||
#define silk_RAND(seed) (silk_MLA_ovflw(907633515, (seed), 196314165))
|
||||
#define RAND_MULTIPLIER 196314165
|
||||
#define RAND_INCREMENT 907633515
|
||||
#define silk_RAND(seed) (silk_MLA_ovflw((RAND_INCREMENT), (seed), (RAND_MULTIPLIER)))
|
||||
|
||||
/* Add some multiplication functions that can be easily mapped to ARM. */
|
||||
|
||||
|
|
@ -587,8 +613,8 @@ static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
|
|||
#define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
|
||||
((void)(arch), silk_burg_modified_c(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
|
||||
|
||||
#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \
|
||||
((void)(arch),silk_inner_prod16_aligned_64_c(inVec1, inVec2, len))
|
||||
#define silk_inner_prod16(inVec1, inVec2, len, arch) \
|
||||
((void)(arch),silk_inner_prod16_c(inVec1, inVec2, len))
|
||||
#endif
|
||||
|
||||
#include "Inlines.h"
|
||||
|
|
|
|||
|
|
@ -101,9 +101,9 @@ opus_int silk_VAD_GetSA_Q8_c( /* O Return v
|
|||
|
||||
/* Safety checks */
|
||||
silk_assert( VAD_N_BANDS == 4 );
|
||||
silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
|
||||
silk_assert( psEncC->frame_length <= 512 );
|
||||
silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
|
||||
celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
|
||||
celt_assert( psEncC->frame_length <= 512 );
|
||||
celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
|
||||
|
||||
/***********************/
|
||||
/* Filter and Decimate */
|
||||
|
|
@ -252,15 +252,14 @@ opus_int silk_VAD_GetSA_Q8_c( /* O Return v
|
|||
speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
|
||||
}
|
||||
|
||||
if( psEncC->frame_length == 20 * psEncC->fs_kHz ) {
|
||||
speech_nrg = silk_RSHIFT32( speech_nrg, 1 );
|
||||
}
|
||||
/* Power scaling */
|
||||
if( speech_nrg <= 0 ) {
|
||||
SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
|
||||
} else if( speech_nrg < 32768 ) {
|
||||
if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
|
||||
speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 );
|
||||
} else {
|
||||
speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 );
|
||||
}
|
||||
} else if( speech_nrg < 16384 ) {
|
||||
speech_nrg = silk_LSHIFT32( speech_nrg, 16 );
|
||||
|
||||
/* square-root */
|
||||
speech_nrg = silk_SQRT_APPROX( speech_nrg );
|
||||
|
|
@ -313,6 +312,8 @@ void silk_VAD_GetNoiseLevels(
|
|||
/* Initially faster smoothing */
|
||||
if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */
|
||||
min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 );
|
||||
/* Increment frame counter */
|
||||
psSilk_VAD->counter++;
|
||||
} else {
|
||||
min_coef = 0;
|
||||
}
|
||||
|
|
@ -356,7 +357,4 @@ void silk_VAD_GetNoiseLevels(
|
|||
/* Store as part of state */
|
||||
psSilk_VAD->NL[ k ] = nl;
|
||||
}
|
||||
|
||||
/* Increment frame counter */
|
||||
psSilk_VAD->counter++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,84 +34,95 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
|
||||
void silk_VQ_WMat_EC_c(
|
||||
opus_int8 *ind, /* O index of best codebook vector */
|
||||
opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
|
||||
opus_int32 *res_nrg_Q15, /* O best residual energy */
|
||||
opus_int32 *rate_dist_Q8, /* O best total bitrate */
|
||||
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
|
||||
const opus_int16 *in_Q14, /* I input vector to be quantized */
|
||||
const opus_int32 *W_Q18, /* I weighting matrix */
|
||||
const opus_int32 *XX_Q17, /* I correlation matrix */
|
||||
const opus_int32 *xX_Q17, /* I correlation vector */
|
||||
const opus_int8 *cb_Q7, /* I codebook */
|
||||
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
|
||||
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
|
||||
const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
|
||||
const opus_int subfr_len, /* I number of samples per subframe */
|
||||
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
|
||||
opus_int L /* I number of vectors in codebook */
|
||||
const opus_int L /* I number of vectors in codebook */
|
||||
)
|
||||
{
|
||||
opus_int k, gain_tmp_Q7;
|
||||
const opus_int8 *cb_row_Q7;
|
||||
opus_int16 diff_Q14[ 5 ];
|
||||
opus_int32 sum1_Q14, sum2_Q16;
|
||||
opus_int32 neg_xX_Q24[ 5 ];
|
||||
opus_int32 sum1_Q15, sum2_Q24;
|
||||
opus_int32 bits_res_Q8, bits_tot_Q8;
|
||||
|
||||
/* Negate and convert to new Q domain */
|
||||
neg_xX_Q24[ 0 ] = -silk_LSHIFT32( xX_Q17[ 0 ], 7 );
|
||||
neg_xX_Q24[ 1 ] = -silk_LSHIFT32( xX_Q17[ 1 ], 7 );
|
||||
neg_xX_Q24[ 2 ] = -silk_LSHIFT32( xX_Q17[ 2 ], 7 );
|
||||
neg_xX_Q24[ 3 ] = -silk_LSHIFT32( xX_Q17[ 3 ], 7 );
|
||||
neg_xX_Q24[ 4 ] = -silk_LSHIFT32( xX_Q17[ 4 ], 7 );
|
||||
|
||||
/* Loop over codebook */
|
||||
*rate_dist_Q14 = silk_int32_MAX;
|
||||
*rate_dist_Q8 = silk_int32_MAX;
|
||||
*res_nrg_Q15 = silk_int32_MAX;
|
||||
cb_row_Q7 = cb_Q7;
|
||||
/* If things go really bad, at least *ind is set to something safe. */
|
||||
*ind = 0;
|
||||
for( k = 0; k < L; k++ ) {
|
||||
opus_int32 penalty;
|
||||
gain_tmp_Q7 = cb_gain_Q7[k];
|
||||
|
||||
diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 );
|
||||
diff_Q14[ 1 ] = in_Q14[ 1 ] - silk_LSHIFT( cb_row_Q7[ 1 ], 7 );
|
||||
diff_Q14[ 2 ] = in_Q14[ 2 ] - silk_LSHIFT( cb_row_Q7[ 2 ], 7 );
|
||||
diff_Q14[ 3 ] = in_Q14[ 3 ] - silk_LSHIFT( cb_row_Q7[ 3 ], 7 );
|
||||
diff_Q14[ 4 ] = in_Q14[ 4 ] - silk_LSHIFT( cb_row_Q7[ 4 ], 7 );
|
||||
|
||||
/* Weighted rate */
|
||||
sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] );
|
||||
/* Quantization error: 1 - 2 * xX * cb + cb' * XX * cb */
|
||||
sum1_Q15 = SILK_FIX_CONST( 1.001, 15 );
|
||||
|
||||
/* Penalty for too large gain */
|
||||
sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 );
|
||||
penalty = silk_LSHIFT32( silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 11 );
|
||||
|
||||
silk_assert( sum1_Q14 >= 0 );
|
||||
/* first row of XX_Q17 */
|
||||
sum2_Q24 = silk_MLA( neg_xX_Q24[ 0 ], XX_Q17[ 1 ], cb_row_Q7[ 1 ] );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 2 ], cb_row_Q7[ 2 ] );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 3 ], cb_row_Q7[ 3 ] );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 4 ], cb_row_Q7[ 4 ] );
|
||||
sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 0 ], cb_row_Q7[ 0 ] );
|
||||
sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 0 ] );
|
||||
|
||||
/* first row of W_Q18 */
|
||||
sum2_Q16 = silk_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] );
|
||||
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] );
|
||||
/* second row of XX_Q17 */
|
||||
sum2_Q24 = silk_MLA( neg_xX_Q24[ 1 ], XX_Q17[ 7 ], cb_row_Q7[ 2 ] );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 8 ], cb_row_Q7[ 3 ] );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 9 ], cb_row_Q7[ 4 ] );
|
||||
sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 6 ], cb_row_Q7[ 1 ] );
|
||||
sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 1 ] );
|
||||
|
||||
/* second row of W_Q18 */
|
||||
sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] );
|
||||
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] );
|
||||
/* third row of XX_Q17 */
|
||||
sum2_Q24 = silk_MLA( neg_xX_Q24[ 2 ], XX_Q17[ 13 ], cb_row_Q7[ 3 ] );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 14 ], cb_row_Q7[ 4 ] );
|
||||
sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 12 ], cb_row_Q7[ 2 ] );
|
||||
sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 2 ] );
|
||||
|
||||
/* third row of W_Q18 */
|
||||
sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] );
|
||||
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] );
|
||||
/* fourth row of XX_Q17 */
|
||||
sum2_Q24 = silk_MLA( neg_xX_Q24[ 3 ], XX_Q17[ 19 ], cb_row_Q7[ 4 ] );
|
||||
sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 18 ], cb_row_Q7[ 3 ] );
|
||||
sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 3 ] );
|
||||
|
||||
/* fourth row of W_Q18 */
|
||||
sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] );
|
||||
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] );
|
||||
|
||||
/* last row of W_Q18 */
|
||||
sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] );
|
||||
sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] );
|
||||
|
||||
silk_assert( sum1_Q14 >= 0 );
|
||||
/* last row of XX_Q17 */
|
||||
sum2_Q24 = silk_LSHIFT32( neg_xX_Q24[ 4 ], 1 );
|
||||
sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 24 ], cb_row_Q7[ 4 ] );
|
||||
sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 4 ] );
|
||||
|
||||
/* find best */
|
||||
if( sum1_Q14 < *rate_dist_Q14 ) {
|
||||
*rate_dist_Q14 = sum1_Q14;
|
||||
*ind = (opus_int8)k;
|
||||
*gain_Q7 = gain_tmp_Q7;
|
||||
if( sum1_Q15 >= 0 ) {
|
||||
/* Translate residual energy to bits using high-rate assumption (6 dB ==> 1 bit/sample) */
|
||||
bits_res_Q8 = silk_SMULBB( subfr_len, silk_lin2log( sum1_Q15 + penalty) - (15 << 7) );
|
||||
/* In the following line we reduce the codelength component by half ("-1"); seems to slightly improve quality */
|
||||
bits_tot_Q8 = silk_ADD_LSHIFT32( bits_res_Q8, cl_Q5[ k ], 3-1 );
|
||||
if( bits_tot_Q8 <= *rate_dist_Q8 ) {
|
||||
*rate_dist_Q8 = bits_tot_Q8;
|
||||
*res_nrg_Q15 = sum1_Q15 + penalty;
|
||||
*ind = (opus_int8)k;
|
||||
*gain_Q7 = gain_tmp_Q7;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go to next cbk vector */
|
||||
|
|
|
|||
57
media/libopus/silk/arm/LPC_inv_pred_gain_arm.h
Normal file
57
media/libopus/silk/arm/LPC_inv_pred_gain_arm.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2017 Google Inc.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_LPC_INV_PRED_GAIN_ARM_H
|
||||
# define SILK_LPC_INV_PRED_GAIN_ARM_H
|
||||
|
||||
# include "celt/arm/armcpu.h"
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
opus_int32 silk_LPC_inverse_pred_gain_neon( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
);
|
||||
|
||||
# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
|
||||
# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
|
||||
# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), PRESUME_NEON(silk_LPC_inverse_pred_gain)(A_Q12, order))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
|
||||
/*Is run-time CPU detection enabled on this platform?*/
|
||||
# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
extern opus_int32 (*const SILK_LPC_INVERSE_PRED_GAIN_IMPL[OPUS_ARCHMASK+1])(const opus_int16 *A_Q12, const opus_int order);
|
||||
# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
|
||||
# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((*SILK_LPC_INVERSE_PRED_GAIN_IMPL[(arch)&OPUS_ARCHMASK])(A_Q12, order))
|
||||
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
|
||||
# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_neon(A_Q12, order))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* end SILK_LPC_INV_PRED_GAIN_ARM_H */
|
||||
288
media/libopus/silk/arm/LPC_inv_pred_gain_neon_intr.c
Normal file
288
media/libopus/silk/arm/LPC_inv_pred_gain_neon_intr.c
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2017 Google Inc.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include "SigProc_FIX.h"
|
||||
#include "define.h"
|
||||
|
||||
#define QA 24
|
||||
#define A_LIMIT SILK_FIX_CONST( 0.99975, QA )
|
||||
|
||||
#define MUL32_FRAC_Q(a32, b32, Q) ((opus_int32)(silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q)))
|
||||
|
||||
/* The difficulty is how to judge a 64-bit signed integer tmp64 is 32-bit overflowed,
|
||||
* since NEON has no 64-bit min, max or comparison instructions.
|
||||
* A failed idea is to compare the results of vmovn(tmp64) and vqmovn(tmp64) whether they are equal or not.
|
||||
* However, this idea fails when the tmp64 is something like 0xFFFFFFF980000000.
|
||||
* Here we know that mult2Q >= 1, so the highest bit (bit 63, sign bit) of tmp64 must equal to bit 62.
|
||||
* tmp64 was shifted left by 1 and we got tmp64'. If high_half(tmp64') != 0 and high_half(tmp64') != -1,
|
||||
* then we know that bit 31 to bit 63 of tmp64 can not all be the sign bit, and therefore tmp64 is 32-bit overflowed.
|
||||
* That is, we judge if tmp64' > 0x00000000FFFFFFFF, or tmp64' <= 0xFFFFFFFF00000000.
|
||||
* We use narrowing shift right 31 bits to tmp32' to save data bandwidth and instructions.
|
||||
* That is, we judge if tmp32' > 0x00000000, or tmp32' <= 0xFFFFFFFF.
|
||||
*/
|
||||
|
||||
/* Compute inverse of LPC prediction gain, and */
|
||||
/* test if LPC coefficients are stable (all poles within unit circle) */
|
||||
static OPUS_INLINE opus_int32 LPC_inverse_pred_gain_QA_neon( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
opus_int32 A_QA[ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
|
||||
const opus_int order /* I Prediction order */
|
||||
)
|
||||
{
|
||||
opus_int k, n, mult2Q;
|
||||
opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
|
||||
opus_int32 max, min;
|
||||
int32x4_t max_s32x4, min_s32x4;
|
||||
int32x2_t max_s32x2, min_s32x2;
|
||||
|
||||
max_s32x4 = vdupq_n_s32( silk_int32_MIN );
|
||||
min_s32x4 = vdupq_n_s32( silk_int32_MAX );
|
||||
invGain_Q30 = SILK_FIX_CONST( 1, 30 );
|
||||
for( k = order - 1; k > 0; k-- ) {
|
||||
int32x2_t rc_Q31_s32x2, rc_mult2_s32x2;
|
||||
int64x2_t mult2Q_s64x2;
|
||||
|
||||
/* Check for stability */
|
||||
if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set RC equal to negated AR coef */
|
||||
rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
|
||||
|
||||
/* rc_mult1_Q30 range: [ 1 : 2^30 ] */
|
||||
rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
|
||||
silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
|
||||
silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
|
||||
|
||||
/* Update inverse gain */
|
||||
/* invGain_Q30 range: [ 0 : 2^30 ] */
|
||||
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
|
||||
silk_assert( invGain_Q30 >= 0 );
|
||||
silk_assert( invGain_Q30 <= ( 1 << 30 ) );
|
||||
if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
|
||||
mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
|
||||
rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
|
||||
|
||||
/* Update AR coefficient */
|
||||
rc_Q31_s32x2 = vdup_n_s32( rc_Q31 );
|
||||
mult2Q_s64x2 = vdupq_n_s64( -mult2Q );
|
||||
rc_mult2_s32x2 = vdup_n_s32( rc_mult2 );
|
||||
|
||||
for( n = 0; n < ( ( k + 1 ) >> 1 ) - 3; n += 4 ) {
|
||||
/* We always calculate extra elements of A_QA buffer when ( k % 4 ) != 0, to take the advantage of SIMD parallelization. */
|
||||
int32x4_t tmp1_s32x4, tmp2_s32x4, t0_s32x4, t1_s32x4, s0_s32x4, s1_s32x4, t_QA0_s32x4, t_QA1_s32x4;
|
||||
int64x2_t t0_s64x2, t1_s64x2, t2_s64x2, t3_s64x2;
|
||||
tmp1_s32x4 = vld1q_s32( A_QA + n );
|
||||
tmp2_s32x4 = vld1q_s32( A_QA + k - n - 4 );
|
||||
tmp2_s32x4 = vrev64q_s32( tmp2_s32x4 );
|
||||
tmp2_s32x4 = vcombine_s32( vget_high_s32( tmp2_s32x4 ), vget_low_s32( tmp2_s32x4 ) );
|
||||
t0_s32x4 = vqrdmulhq_lane_s32( tmp2_s32x4, rc_Q31_s32x2, 0 );
|
||||
t1_s32x4 = vqrdmulhq_lane_s32( tmp1_s32x4, rc_Q31_s32x2, 0 );
|
||||
t_QA0_s32x4 = vqsubq_s32( tmp1_s32x4, t0_s32x4 );
|
||||
t_QA1_s32x4 = vqsubq_s32( tmp2_s32x4, t1_s32x4 );
|
||||
t0_s64x2 = vmull_s32( vget_low_s32 ( t_QA0_s32x4 ), rc_mult2_s32x2 );
|
||||
t1_s64x2 = vmull_s32( vget_high_s32( t_QA0_s32x4 ), rc_mult2_s32x2 );
|
||||
t2_s64x2 = vmull_s32( vget_low_s32 ( t_QA1_s32x4 ), rc_mult2_s32x2 );
|
||||
t3_s64x2 = vmull_s32( vget_high_s32( t_QA1_s32x4 ), rc_mult2_s32x2 );
|
||||
t0_s64x2 = vrshlq_s64( t0_s64x2, mult2Q_s64x2 );
|
||||
t1_s64x2 = vrshlq_s64( t1_s64x2, mult2Q_s64x2 );
|
||||
t2_s64x2 = vrshlq_s64( t2_s64x2, mult2Q_s64x2 );
|
||||
t3_s64x2 = vrshlq_s64( t3_s64x2, mult2Q_s64x2 );
|
||||
t0_s32x4 = vcombine_s32( vmovn_s64( t0_s64x2 ), vmovn_s64( t1_s64x2 ) );
|
||||
t1_s32x4 = vcombine_s32( vmovn_s64( t2_s64x2 ), vmovn_s64( t3_s64x2 ) );
|
||||
s0_s32x4 = vcombine_s32( vshrn_n_s64( t0_s64x2, 31 ), vshrn_n_s64( t1_s64x2, 31 ) );
|
||||
s1_s32x4 = vcombine_s32( vshrn_n_s64( t2_s64x2, 31 ), vshrn_n_s64( t3_s64x2, 31 ) );
|
||||
max_s32x4 = vmaxq_s32( max_s32x4, s0_s32x4 );
|
||||
min_s32x4 = vminq_s32( min_s32x4, s0_s32x4 );
|
||||
max_s32x4 = vmaxq_s32( max_s32x4, s1_s32x4 );
|
||||
min_s32x4 = vminq_s32( min_s32x4, s1_s32x4 );
|
||||
t1_s32x4 = vrev64q_s32( t1_s32x4 );
|
||||
t1_s32x4 = vcombine_s32( vget_high_s32( t1_s32x4 ), vget_low_s32( t1_s32x4 ) );
|
||||
vst1q_s32( A_QA + n, t0_s32x4 );
|
||||
vst1q_s32( A_QA + k - n - 4, t1_s32x4 );
|
||||
}
|
||||
for( ; n < (k + 1) >> 1; n++ ) {
|
||||
opus_int64 tmp64;
|
||||
tmp1 = A_QA[ n ];
|
||||
tmp2 = A_QA[ k - n - 1 ];
|
||||
tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
|
||||
MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
|
||||
if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
|
||||
return 0;
|
||||
}
|
||||
A_QA[ n ] = ( opus_int32 )tmp64;
|
||||
tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
|
||||
MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
|
||||
if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
|
||||
return 0;
|
||||
}
|
||||
A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for stability */
|
||||
if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
max_s32x2 = vmax_s32( vget_low_s32( max_s32x4 ), vget_high_s32( max_s32x4 ) );
|
||||
min_s32x2 = vmin_s32( vget_low_s32( min_s32x4 ), vget_high_s32( min_s32x4 ) );
|
||||
max_s32x2 = vmax_s32( max_s32x2, vreinterpret_s32_s64( vshr_n_s64( vreinterpret_s64_s32( max_s32x2 ), 32 ) ) );
|
||||
min_s32x2 = vmin_s32( min_s32x2, vreinterpret_s32_s64( vshr_n_s64( vreinterpret_s64_s32( min_s32x2 ), 32 ) ) );
|
||||
max = vget_lane_s32( max_s32x2, 0 );
|
||||
min = vget_lane_s32( min_s32x2, 0 );
|
||||
if( ( max > 0 ) || ( min < -1 ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set RC equal to negated AR coef */
|
||||
rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
|
||||
|
||||
/* Range: [ 1 : 2^30 ] */
|
||||
rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
|
||||
|
||||
/* Update inverse gain */
|
||||
/* Range: [ 0 : 2^30 ] */
|
||||
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
|
||||
silk_assert( invGain_Q30 >= 0 );
|
||||
silk_assert( invGain_Q30 <= ( 1 << 30 ) );
|
||||
if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return invGain_Q30;
|
||||
}
|
||||
|
||||
/* For input in Q12 domain */
|
||||
opus_int32 silk_LPC_inverse_pred_gain_neon( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
)
|
||||
{
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
const opus_int32 invGain_Q30_c = silk_LPC_inverse_pred_gain_c( A_Q12, order );
|
||||
#endif
|
||||
|
||||
opus_int32 invGain_Q30;
|
||||
if( ( SILK_MAX_ORDER_LPC != 24 ) || ( order & 1 )) {
|
||||
invGain_Q30 = silk_LPC_inverse_pred_gain_c( A_Q12, order );
|
||||
}
|
||||
else {
|
||||
opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 DC_resp;
|
||||
int16x8_t t0_s16x8, t1_s16x8, t2_s16x8;
|
||||
int32x4_t t0_s32x4;
|
||||
const opus_int leftover = order & 7;
|
||||
|
||||
/* Increase Q domain of the AR coefficients */
|
||||
t0_s16x8 = vld1q_s16( A_Q12 + 0 );
|
||||
t1_s16x8 = vld1q_s16( A_Q12 + 8 );
|
||||
if ( order > 16 ) {
|
||||
t2_s16x8 = vld1q_s16( A_Q12 + 16 );
|
||||
}
|
||||
t0_s32x4 = vpaddlq_s16( t0_s16x8 );
|
||||
|
||||
switch( order - leftover )
|
||||
{
|
||||
case 24:
|
||||
t0_s32x4 = vpadalq_s16( t0_s32x4, t2_s16x8 );
|
||||
vst1q_s32( Atmp_QA + 16, vshll_n_s16( vget_low_s16 ( t2_s16x8 ), QA - 12 ) );
|
||||
vst1q_s32( Atmp_QA + 20, vshll_n_s16( vget_high_s16( t2_s16x8 ), QA - 12 ) );
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 16:
|
||||
t0_s32x4 = vpadalq_s16( t0_s32x4, t1_s16x8 );
|
||||
vst1q_s32( Atmp_QA + 8, vshll_n_s16( vget_low_s16 ( t1_s16x8 ), QA - 12 ) );
|
||||
vst1q_s32( Atmp_QA + 12, vshll_n_s16( vget_high_s16( t1_s16x8 ), QA - 12 ) );
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 8:
|
||||
{
|
||||
const int32x2_t t_s32x2 = vpadd_s32( vget_low_s32( t0_s32x4 ), vget_high_s32( t0_s32x4 ) );
|
||||
const int64x1_t t_s64x1 = vpaddl_s32( t_s32x2 );
|
||||
DC_resp = vget_lane_s32( vreinterpret_s32_s64( t_s64x1 ), 0 );
|
||||
vst1q_s32( Atmp_QA + 0, vshll_n_s16( vget_low_s16 ( t0_s16x8 ), QA - 12 ) );
|
||||
vst1q_s32( Atmp_QA + 4, vshll_n_s16( vget_high_s16( t0_s16x8 ), QA - 12 ) );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DC_resp = 0;
|
||||
break;
|
||||
}
|
||||
A_Q12 += order - leftover;
|
||||
|
||||
switch( leftover )
|
||||
{
|
||||
case 6:
|
||||
DC_resp += (opus_int32)A_Q12[ 5 ];
|
||||
DC_resp += (opus_int32)A_Q12[ 4 ];
|
||||
Atmp_QA[ order - leftover + 5 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 5 ], QA - 12 );
|
||||
Atmp_QA[ order - leftover + 4 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 4 ], QA - 12 );
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 4:
|
||||
DC_resp += (opus_int32)A_Q12[ 3 ];
|
||||
DC_resp += (opus_int32)A_Q12[ 2 ];
|
||||
Atmp_QA[ order - leftover + 3 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 3 ], QA - 12 );
|
||||
Atmp_QA[ order - leftover + 2 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 2 ], QA - 12 );
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 2:
|
||||
DC_resp += (opus_int32)A_Q12[ 1 ];
|
||||
DC_resp += (opus_int32)A_Q12[ 0 ];
|
||||
Atmp_QA[ order - leftover + 1 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 1 ], QA - 12 );
|
||||
Atmp_QA[ order - leftover + 0 ] = silk_LSHIFT32( (opus_int32)A_Q12[ 0 ], QA - 12 );
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the DC is unstable, we don't even need to do the full calculations */
|
||||
if( DC_resp >= 4096 ) {
|
||||
invGain_Q30 = 0;
|
||||
} else {
|
||||
invGain_Q30 = LPC_inverse_pred_gain_QA_neon( Atmp_QA, order );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
silk_assert( invGain_Q30_c == invGain_Q30 );
|
||||
#endif
|
||||
|
||||
return invGain_Q30;
|
||||
}
|
||||
100
media/libopus/silk/arm/NSQ_del_dec_arm.h
Normal file
100
media/libopus/silk/arm/NSQ_del_dec_arm.h
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2017 Google Inc.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_NSQ_DEL_DEC_ARM_H
|
||||
#define SILK_NSQ_DEL_DEC_ARM_H
|
||||
|
||||
#include "celt/arm/armcpu.h"
|
||||
|
||||
#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
void silk_NSQ_del_dec_neon(
|
||||
const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
|
||||
SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
|
||||
const opus_int16 PredCoef_Q12[2 * MAX_LPC_ORDER],
|
||||
const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
|
||||
const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
|
||||
const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
|
||||
const opus_int Tilt_Q14[MAX_NB_SUBFR],
|
||||
const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
|
||||
const opus_int32 Gains_Q16[MAX_NB_SUBFR],
|
||||
const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
|
||||
const opus_int LTP_scale_Q14);
|
||||
|
||||
#if !defined(OPUS_HAVE_RTCD)
|
||||
#define OVERRIDE_silk_NSQ_del_dec (1)
|
||||
#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
|
||||
LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
|
||||
LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
|
||||
LTP_scale_Q14, arch) \
|
||||
((void)(arch), \
|
||||
PRESUME_NEON(silk_NSQ_del_dec)( \
|
||||
psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, \
|
||||
AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
|
||||
Lambda_Q10, LTP_scale_Q14))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(OVERRIDE_silk_NSQ_del_dec)
|
||||
/*Is run-time CPU detection enabled on this platform?*/
|
||||
#if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
|
||||
!defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
|
||||
const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
|
||||
SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
|
||||
const opus_int16 PredCoef_Q12[2 * MAX_LPC_ORDER],
|
||||
const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
|
||||
const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
|
||||
const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
|
||||
const opus_int Tilt_Q14[MAX_NB_SUBFR],
|
||||
const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
|
||||
const opus_int32 Gains_Q16[MAX_NB_SUBFR],
|
||||
const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
|
||||
const opus_int LTP_scale_Q14);
|
||||
#define OVERRIDE_silk_NSQ_del_dec (1)
|
||||
#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
|
||||
LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
|
||||
LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
|
||||
LTP_scale_Q14, arch) \
|
||||
((*SILK_NSQ_DEL_DEC_IMPL[(arch)&OPUS_ARCHMASK])( \
|
||||
psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, \
|
||||
AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
|
||||
Lambda_Q10, LTP_scale_Q14))
|
||||
#elif defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
#define OVERRIDE_silk_NSQ_del_dec (1)
|
||||
#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
|
||||
LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
|
||||
LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
|
||||
LTP_scale_Q14, arch) \
|
||||
((void)(arch), \
|
||||
silk_NSQ_del_dec_neon(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
|
||||
LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
|
||||
LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
|
||||
LTP_scale_Q14))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* end SILK_NSQ_DEL_DEC_ARM_H */
|
||||
1124
media/libopus/silk/arm/NSQ_del_dec_neon_intr.c
Normal file
1124
media/libopus/silk/arm/NSQ_del_dec_neon_intr.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -28,30 +28,31 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define SILK_NSQ_NEON_H
|
||||
|
||||
#include "cpu_support.h"
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
#undef silk_short_prediction_create_arch_coef
|
||||
/* For vectorized calc, reverse a_Q12 coefs, convert to 32-bit, and shift for vqdmulhq_s32. */
|
||||
static OPUS_INLINE void silk_short_prediction_create_arch_coef_neon(opus_int32 *out, const opus_int16 *in, opus_int order)
|
||||
{
|
||||
out[15] = in[0] << 15;
|
||||
out[14] = in[1] << 15;
|
||||
out[13] = in[2] << 15;
|
||||
out[12] = in[3] << 15;
|
||||
out[11] = in[4] << 15;
|
||||
out[10] = in[5] << 15;
|
||||
out[9] = in[6] << 15;
|
||||
out[8] = in[7] << 15;
|
||||
out[7] = in[8] << 15;
|
||||
out[6] = in[9] << 15;
|
||||
out[15] = silk_LSHIFT32(in[0], 15);
|
||||
out[14] = silk_LSHIFT32(in[1], 15);
|
||||
out[13] = silk_LSHIFT32(in[2], 15);
|
||||
out[12] = silk_LSHIFT32(in[3], 15);
|
||||
out[11] = silk_LSHIFT32(in[4], 15);
|
||||
out[10] = silk_LSHIFT32(in[5], 15);
|
||||
out[9] = silk_LSHIFT32(in[6], 15);
|
||||
out[8] = silk_LSHIFT32(in[7], 15);
|
||||
out[7] = silk_LSHIFT32(in[8], 15);
|
||||
out[6] = silk_LSHIFT32(in[9], 15);
|
||||
|
||||
if (order == 16)
|
||||
{
|
||||
out[5] = in[10] << 15;
|
||||
out[4] = in[11] << 15;
|
||||
out[3] = in[12] << 15;
|
||||
out[2] = in[13] << 15;
|
||||
out[1] = in[14] << 15;
|
||||
out[0] = in[15] << 15;
|
||||
out[5] = silk_LSHIFT32(in[10], 15);
|
||||
out[4] = silk_LSHIFT32(in[11], 15);
|
||||
out[3] = silk_LSHIFT32(in[12], 15);
|
||||
out[2] = silk_LSHIFT32(in[13], 15);
|
||||
out[1] = silk_LSHIFT32(in[14], 15);
|
||||
out[0] = silk_LSHIFT32(in[15], 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,13 +28,62 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main_FIX.h"
|
||||
#include "NSQ.h"
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
#if defined(OPUS_HAVE_RTCD)
|
||||
|
||||
# if (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
|
||||
!defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
|
||||
void (*const SILK_BIQUAD_ALT_STRIDE2_IMPL[OPUS_ARCHMASK + 1])(
|
||||
const opus_int16 *in, /* I input signal */
|
||||
const opus_int32 *B_Q28, /* I MA coefficients [3] */
|
||||
const opus_int32 *A_Q28, /* I AR coefficients [2] */
|
||||
opus_int32 *S, /* I/O State vector [4] */
|
||||
opus_int16 *out, /* O output signal */
|
||||
const opus_int32 len /* I signal length (must be even) */
|
||||
) = {
|
||||
silk_biquad_alt_stride2_c, /* ARMv4 */
|
||||
silk_biquad_alt_stride2_c, /* EDSP */
|
||||
silk_biquad_alt_stride2_c, /* Media */
|
||||
silk_biquad_alt_stride2_neon, /* Neon */
|
||||
};
|
||||
|
||||
opus_int32 (*const SILK_LPC_INVERSE_PRED_GAIN_IMPL[OPUS_ARCHMASK + 1])( /* O Returns inverse prediction gain in energy domain, Q30 */
|
||||
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
|
||||
const opus_int order /* I Prediction order */
|
||||
) = {
|
||||
silk_LPC_inverse_pred_gain_c, /* ARMv4 */
|
||||
silk_LPC_inverse_pred_gain_c, /* EDSP */
|
||||
silk_LPC_inverse_pred_gain_c, /* Media */
|
||||
silk_LPC_inverse_pred_gain_neon, /* Neon */
|
||||
};
|
||||
|
||||
void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
|
||||
const silk_encoder_state *psEncC, /* I Encoder State */
|
||||
silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
SideInfoIndices *psIndices, /* I/O Quantization Indices */
|
||||
const opus_int16 x16[], /* I Input */
|
||||
opus_int8 pulses[], /* O Quantized pulse signal */
|
||||
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
|
||||
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
|
||||
const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
|
||||
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
|
||||
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
|
||||
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
|
||||
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
|
||||
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
|
||||
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
|
||||
const opus_int LTP_scale_Q14 /* I LTP state scaling */
|
||||
) = {
|
||||
silk_NSQ_del_dec_c, /* ARMv4 */
|
||||
silk_NSQ_del_dec_c, /* EDSP */
|
||||
silk_NSQ_del_dec_c, /* Media */
|
||||
silk_NSQ_del_dec_neon, /* Neon */
|
||||
};
|
||||
|
||||
/*There is no table for silk_noise_shape_quantizer_short_prediction because the
|
||||
NEON version takes different parameters than the C version.
|
||||
Instead RTCD is done via if statements at the call sites.
|
||||
|
|
@ -52,4 +101,23 @@ opus_int32
|
|||
|
||||
# endif
|
||||
|
||||
# if defined(FIXED_POINT) && \
|
||||
defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
|
||||
void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK + 1])(
|
||||
opus_int32 *corr, /* O Result [order + 1] */
|
||||
opus_int *scale, /* O Scaling of the correlation vector */
|
||||
const opus_int16 *input, /* I Input data to correlate */
|
||||
const opus_int warping_Q16, /* I Warping coefficient */
|
||||
const opus_int length, /* I Length of input */
|
||||
const opus_int order /* I Correlation order (even) */
|
||||
) = {
|
||||
silk_warped_autocorrelation_FIX_c, /* ARMv4 */
|
||||
silk_warped_autocorrelation_FIX_c, /* EDSP */
|
||||
silk_warped_autocorrelation_FIX_c, /* Media */
|
||||
silk_warped_autocorrelation_FIX_neon, /* Neon */
|
||||
};
|
||||
|
||||
# endif
|
||||
|
||||
#endif /* OPUS_HAVE_RTCD */
|
||||
|
|
|
|||
68
media/libopus/silk/arm/biquad_alt_arm.h
Normal file
68
media/libopus/silk/arm/biquad_alt_arm.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2017 Google Inc.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_BIQUAD_ALT_ARM_H
|
||||
# define SILK_BIQUAD_ALT_ARM_H
|
||||
|
||||
# include "celt/arm/armcpu.h"
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
void silk_biquad_alt_stride2_neon(
|
||||
const opus_int16 *in, /* I input signal */
|
||||
const opus_int32 *B_Q28, /* I MA coefficients [3] */
|
||||
const opus_int32 *A_Q28, /* I AR coefficients [2] */
|
||||
opus_int32 *S, /* I/O State vector [4] */
|
||||
opus_int16 *out, /* O output signal */
|
||||
const opus_int32 len /* I signal length (must be even) */
|
||||
);
|
||||
|
||||
# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
|
||||
# define OVERRIDE_silk_biquad_alt_stride2 (1)
|
||||
# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), PRESUME_NEON(silk_biquad_alt_stride2)(in, B_Q28, A_Q28, S, out, len))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined(OVERRIDE_silk_biquad_alt_stride2)
|
||||
/*Is run-time CPU detection enabled on this platform?*/
|
||||
# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
extern void (*const SILK_BIQUAD_ALT_STRIDE2_IMPL[OPUS_ARCHMASK+1])(
|
||||
const opus_int16 *in, /* I input signal */
|
||||
const opus_int32 *B_Q28, /* I MA coefficients [3] */
|
||||
const opus_int32 *A_Q28, /* I AR coefficients [2] */
|
||||
opus_int32 *S, /* I/O State vector [4] */
|
||||
opus_int16 *out, /* O output signal */
|
||||
const opus_int32 len /* I signal length (must be even) */
|
||||
);
|
||||
# define OVERRIDE_silk_biquad_alt_stride2 (1)
|
||||
# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((*SILK_BIQUAD_ALT_STRIDE2_IMPL[(arch)&OPUS_ARCHMASK])(in, B_Q28, A_Q28, S, out, len))
|
||||
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
# define OVERRIDE_silk_biquad_alt_stride2 (1)
|
||||
# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_neon(in, B_Q28, A_Q28, S, out, len))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* end SILK_BIQUAD_ALT_ARM_H */
|
||||
156
media/libopus/silk/arm/biquad_alt_neon_intr.c
Normal file
156
media/libopus/silk/arm/biquad_alt_neon_intr.c
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2017 Google Inc.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <arm_neon.h>
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
# include <string.h>
|
||||
# include "stack_alloc.h"
|
||||
#endif
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
static inline void silk_biquad_alt_stride2_kernel( const int32x4_t A_L_s32x4, const int32x4_t A_U_s32x4, const int32x4_t B_Q28_s32x4, const int32x2_t t_s32x2, const int32x4_t in_s32x4, int32x4_t *S_s32x4, int32x2_t *out32_Q14_s32x2 )
|
||||
{
|
||||
int32x4_t t_s32x4, out32_Q14_s32x4;
|
||||
|
||||
*out32_Q14_s32x2 = vadd_s32( vget_low_s32( *S_s32x4 ), t_s32x2 ); /* silk_SMLAWB( S{0,1}, B_Q28[ 0 ], in{0,1} ) */
|
||||
*S_s32x4 = vcombine_s32( vget_high_s32( *S_s32x4 ), vdup_n_s32( 0 ) ); /* S{0,1} = S{2,3}; S{2,3} = 0; */
|
||||
*out32_Q14_s32x2 = vshl_n_s32( *out32_Q14_s32x2, 2 ); /* out32_Q14_{0,1} = silk_LSHIFT( silk_SMLAWB( S{0,1}, B_Q28[ 0 ], in{0,1} ), 2 ); */
|
||||
out32_Q14_s32x4 = vcombine_s32( *out32_Q14_s32x2, *out32_Q14_s32x2 ); /* out32_Q14_{0,1,0,1} */
|
||||
t_s32x4 = vqdmulhq_s32( out32_Q14_s32x4, A_L_s32x4 ); /* silk_SMULWB( out32_Q14_{0,1,0,1}, A{0,0,1,1}_L_Q28 ) */
|
||||
*S_s32x4 = vrsraq_n_s32( *S_s32x4, t_s32x4, 14 ); /* S{0,1} = S{2,3} + silk_RSHIFT_ROUND(); S{2,3} = silk_RSHIFT_ROUND(); */
|
||||
t_s32x4 = vqdmulhq_s32( out32_Q14_s32x4, A_U_s32x4 ); /* silk_SMULWB( out32_Q14_{0,1,0,1}, A{0,0,1,1}_U_Q28 ) */
|
||||
*S_s32x4 = vaddq_s32( *S_s32x4, t_s32x4 ); /* S0 = silk_SMLAWB( S{0,1,2,3}, out32_Q14_{0,1,0,1}, A{0,0,1,1}_U_Q28 ); */
|
||||
t_s32x4 = vqdmulhq_s32( in_s32x4, B_Q28_s32x4 ); /* silk_SMULWB( B_Q28[ {1,1,2,2} ], in{0,1,0,1} ) */
|
||||
*S_s32x4 = vaddq_s32( *S_s32x4, t_s32x4 ); /* S0 = silk_SMLAWB( S0, B_Q28[ {1,1,2,2} ], in{0,1,0,1} ); */
|
||||
}
|
||||
|
||||
void silk_biquad_alt_stride2_neon(
|
||||
const opus_int16 *in, /* I input signal */
|
||||
const opus_int32 *B_Q28, /* I MA coefficients [3] */
|
||||
const opus_int32 *A_Q28, /* I AR coefficients [2] */
|
||||
opus_int32 *S, /* I/O State vector [4] */
|
||||
opus_int16 *out, /* O output signal */
|
||||
const opus_int32 len /* I signal length (must be even) */
|
||||
)
|
||||
{
|
||||
/* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
|
||||
opus_int k = 0;
|
||||
const int32x2_t offset_s32x2 = vdup_n_s32( (1<<14) - 1 );
|
||||
const int32x4_t offset_s32x4 = vcombine_s32( offset_s32x2, offset_s32x2 );
|
||||
int16x4_t in_s16x4 = vdup_n_s16( 0 );
|
||||
int16x4_t out_s16x4;
|
||||
int32x2_t A_Q28_s32x2, A_L_s32x2, A_U_s32x2, B_Q28_s32x2, t_s32x2;
|
||||
int32x4_t A_L_s32x4, A_U_s32x4, B_Q28_s32x4, S_s32x4, out32_Q14_s32x4;
|
||||
int32x2x2_t t0_s32x2x2, t1_s32x2x2, t2_s32x2x2, S_s32x2x2;
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
opus_int32 S_c[ 4 ];
|
||||
VARDECL( opus_int16, out_c );
|
||||
SAVE_STACK;
|
||||
ALLOC( out_c, 2 * len, opus_int16 );
|
||||
|
||||
silk_memcpy( &S_c, S, sizeof( S_c ) );
|
||||
silk_biquad_alt_stride2_c( in, B_Q28, A_Q28, S_c, out_c, len );
|
||||
#endif
|
||||
|
||||
/* Negate A_Q28 values and split in two parts */
|
||||
A_Q28_s32x2 = vld1_s32( A_Q28 );
|
||||
A_Q28_s32x2 = vneg_s32( A_Q28_s32x2 );
|
||||
A_L_s32x2 = vshl_n_s32( A_Q28_s32x2, 18 ); /* ( -A_Q28[] & 0x00003FFF ) << 18 */
|
||||
A_L_s32x2 = vreinterpret_s32_u32( vshr_n_u32( vreinterpret_u32_s32( A_L_s32x2 ), 3 ) ); /* ( -A_Q28[] & 0x00003FFF ) << 15 */
|
||||
A_U_s32x2 = vshr_n_s32( A_Q28_s32x2, 14 ); /* silk_RSHIFT( -A_Q28[], 14 ) */
|
||||
A_U_s32x2 = vshl_n_s32( A_U_s32x2, 16 ); /* silk_RSHIFT( -A_Q28[], 14 ) << 16 (Clip two leading bits to conform to C function.) */
|
||||
A_U_s32x2 = vshr_n_s32( A_U_s32x2, 1 ); /* silk_RSHIFT( -A_Q28[], 14 ) << 15 */
|
||||
|
||||
B_Q28_s32x2 = vld1_s32( B_Q28 );
|
||||
t_s32x2 = vld1_s32( B_Q28 + 1 );
|
||||
t0_s32x2x2 = vzip_s32( A_L_s32x2, A_L_s32x2 );
|
||||
t1_s32x2x2 = vzip_s32( A_U_s32x2, A_U_s32x2 );
|
||||
t2_s32x2x2 = vzip_s32( t_s32x2, t_s32x2 );
|
||||
A_L_s32x4 = vcombine_s32( t0_s32x2x2.val[ 0 ], t0_s32x2x2.val[ 1 ] ); /* A{0,0,1,1}_L_Q28 */
|
||||
A_U_s32x4 = vcombine_s32( t1_s32x2x2.val[ 0 ], t1_s32x2x2.val[ 1 ] ); /* A{0,0,1,1}_U_Q28 */
|
||||
B_Q28_s32x4 = vcombine_s32( t2_s32x2x2.val[ 0 ], t2_s32x2x2.val[ 1 ] ); /* B_Q28[ {1,1,2,2} ] */
|
||||
S_s32x4 = vld1q_s32( S ); /* S0 = S[ 0 ]; S3 = S[ 3 ]; */
|
||||
S_s32x2x2 = vtrn_s32( vget_low_s32( S_s32x4 ), vget_high_s32( S_s32x4 ) ); /* S2 = S[ 1 ]; S1 = S[ 2 ]; */
|
||||
S_s32x4 = vcombine_s32( S_s32x2x2.val[ 0 ], S_s32x2x2.val[ 1 ] );
|
||||
|
||||
for( ; k < len - 1; k += 2 ) {
|
||||
int32x4_t in_s32x4[ 2 ], t_s32x4;
|
||||
int32x2_t out32_Q14_s32x2[ 2 ];
|
||||
|
||||
/* S[ 2 * i + 0 ], S[ 2 * i + 1 ], S[ 2 * i + 2 ], S[ 2 * i + 3 ]: Q12 */
|
||||
in_s16x4 = vld1_s16( &in[ 2 * k ] ); /* in{0,1,2,3} = in[ 2 * k + {0,1,2,3} ]; */
|
||||
in_s32x4[ 0 ] = vshll_n_s16( in_s16x4, 15 ); /* in{0,1,2,3} << 15 */
|
||||
t_s32x4 = vqdmulhq_lane_s32( in_s32x4[ 0 ], B_Q28_s32x2, 0 ); /* silk_SMULWB( B_Q28[ 0 ], in{0,1,2,3} ) */
|
||||
in_s32x4[ 1 ] = vcombine_s32( vget_high_s32( in_s32x4[ 0 ] ), vget_high_s32( in_s32x4[ 0 ] ) ); /* in{2,3,2,3} << 15 */
|
||||
in_s32x4[ 0 ] = vcombine_s32( vget_low_s32 ( in_s32x4[ 0 ] ), vget_low_s32 ( in_s32x4[ 0 ] ) ); /* in{0,1,0,1} << 15 */
|
||||
silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, vget_low_s32 ( t_s32x4 ), in_s32x4[ 0 ], &S_s32x4, &out32_Q14_s32x2[ 0 ] );
|
||||
silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, vget_high_s32( t_s32x4 ), in_s32x4[ 1 ], &S_s32x4, &out32_Q14_s32x2[ 1 ] );
|
||||
|
||||
/* Scale back to Q0 and saturate */
|
||||
out32_Q14_s32x4 = vcombine_s32( out32_Q14_s32x2[ 0 ], out32_Q14_s32x2[ 1 ] ); /* out32_Q14_{0,1,2,3} */
|
||||
out32_Q14_s32x4 = vaddq_s32( out32_Q14_s32x4, offset_s32x4 ); /* out32_Q14_{0,1,2,3} + (1<<14) - 1 */
|
||||
out_s16x4 = vqshrn_n_s32( out32_Q14_s32x4, 14 ); /* (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,2,3} + (1<<14) - 1, 14 ) ) */
|
||||
vst1_s16( &out[ 2 * k ], out_s16x4 ); /* out[ 2 * k + {0,1,2,3} ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,2,3} + (1<<14) - 1, 14 ) ); */
|
||||
}
|
||||
|
||||
/* Process leftover. */
|
||||
if( k < len ) {
|
||||
int32x4_t in_s32x4;
|
||||
int32x2_t out32_Q14_s32x2;
|
||||
|
||||
/* S[ 2 * i + 0 ], S[ 2 * i + 1 ]: Q12 */
|
||||
in_s16x4 = vld1_lane_s16( &in[ 2 * k + 0 ], in_s16x4, 0 ); /* in{0,1} = in[ 2 * k + {0,1} ]; */
|
||||
in_s16x4 = vld1_lane_s16( &in[ 2 * k + 1 ], in_s16x4, 1 ); /* in{0,1} = in[ 2 * k + {0,1} ]; */
|
||||
in_s32x4 = vshll_n_s16( in_s16x4, 15 ); /* in{0,1} << 15 */
|
||||
t_s32x2 = vqdmulh_lane_s32( vget_low_s32( in_s32x4 ), B_Q28_s32x2, 0 ); /* silk_SMULWB( B_Q28[ 0 ], in{0,1} ) */
|
||||
in_s32x4 = vcombine_s32( vget_low_s32( in_s32x4 ), vget_low_s32( in_s32x4 ) ); /* in{0,1,0,1} << 15 */
|
||||
silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, t_s32x2, in_s32x4, &S_s32x4, &out32_Q14_s32x2 );
|
||||
|
||||
/* Scale back to Q0 and saturate */
|
||||
out32_Q14_s32x2 = vadd_s32( out32_Q14_s32x2, offset_s32x2 ); /* out32_Q14_{0,1} + (1<<14) - 1 */
|
||||
out32_Q14_s32x4 = vcombine_s32( out32_Q14_s32x2, out32_Q14_s32x2 ); /* out32_Q14_{0,1,0,1} + (1<<14) - 1 */
|
||||
out_s16x4 = vqshrn_n_s32( out32_Q14_s32x4, 14 ); /* (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,0,1} + (1<<14) - 1, 14 ) ) */
|
||||
vst1_lane_s16( &out[ 2 * k + 0 ], out_s16x4, 0 ); /* out[ 2 * k + 0 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_0 + (1<<14) - 1, 14 ) ); */
|
||||
vst1_lane_s16( &out[ 2 * k + 1 ], out_s16x4, 1 ); /* out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_1 + (1<<14) - 1, 14 ) ); */
|
||||
}
|
||||
|
||||
vst1q_lane_s32( &S[ 0 ], S_s32x4, 0 ); /* S[ 0 ] = S0; */
|
||||
vst1q_lane_s32( &S[ 1 ], S_s32x4, 2 ); /* S[ 1 ] = S2; */
|
||||
vst1q_lane_s32( &S[ 2 ], S_s32x4, 1 ); /* S[ 2 ] = S1; */
|
||||
vst1q_lane_s32( &S[ 3 ], S_s32x4, 3 ); /* S[ 3 ] = S3; */
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
silk_assert( !memcmp( S_c, S, sizeof( S_c ) ) );
|
||||
silk_assert( !memcmp( out_c, out, 2 * len * sizeof( opus_int16 ) ) );
|
||||
RESTORE_STACK;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -28,6 +28,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef SILK_MACROS_ARMv4_H
|
||||
#define SILK_MACROS_ARMv4_H
|
||||
|
||||
/* This macro only avoids the undefined behaviour from a left shift of
|
||||
a negative value. It should only be used in macros that can't include
|
||||
SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
|
||||
#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
|
||||
|
||||
/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
|
||||
#undef silk_SMULWB
|
||||
static OPUS_INLINE opus_int32 silk_SMULWB_armv4(opus_int32 a, opus_int16 b)
|
||||
|
|
@ -38,7 +43,7 @@ static OPUS_INLINE opus_int32 silk_SMULWB_armv4(opus_int32 a, opus_int16 b)
|
|||
"#silk_SMULWB\n\t"
|
||||
"smull %0, %1, %2, %3\n\t"
|
||||
: "=&r"(rd_lo), "=&r"(rd_hi)
|
||||
: "%r"(a), "r"(b<<16)
|
||||
: "%r"(a), "r"(SAFE_SHL(b,16))
|
||||
);
|
||||
return rd_hi;
|
||||
}
|
||||
|
|
@ -80,7 +85,7 @@ static OPUS_INLINE opus_int32 silk_SMULWW_armv4(opus_int32 a, opus_int32 b)
|
|||
: "=&r"(rd_lo), "=&r"(rd_hi)
|
||||
: "%r"(a), "r"(b)
|
||||
);
|
||||
return (rd_hi<<16)+(rd_lo>>16);
|
||||
return SAFE_SHL(rd_hi,16)+(rd_lo>>16);
|
||||
}
|
||||
#define silk_SMULWW(a, b) (silk_SMULWW_armv4(a, b))
|
||||
|
||||
|
|
@ -96,8 +101,10 @@ static OPUS_INLINE opus_int32 silk_SMLAWW_armv4(opus_int32 a, opus_int32 b,
|
|||
: "=&r"(rd_lo), "=&r"(rd_hi)
|
||||
: "%r"(b), "r"(c)
|
||||
);
|
||||
return a+(rd_hi<<16)+(rd_lo>>16);
|
||||
return a+SAFE_SHL(rd_hi,16)+(rd_lo>>16);
|
||||
}
|
||||
#define silk_SMLAWW(a, b, c) (silk_SMLAWW_armv4(a, b, c))
|
||||
|
||||
#undef SAFE_SHL
|
||||
|
||||
#endif /* SILK_MACROS_ARMv4_H */
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef SILK_MACROS_ARMv5E_H
|
||||
#define SILK_MACROS_ARMv5E_H
|
||||
|
||||
/* This macro only avoids the undefined behaviour from a left shift of
|
||||
a negative value. It should only be used in macros that can't include
|
||||
SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
|
||||
#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
|
||||
|
||||
/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
|
||||
#undef silk_SMULWB
|
||||
static OPUS_INLINE opus_int32 silk_SMULWB_armv5e(opus_int32 a, opus_int16 b)
|
||||
|
|
@ -190,7 +195,7 @@ static OPUS_INLINE opus_int32 silk_CLZ16_armv5(opus_int16 in16)
|
|||
"#silk_CLZ16\n\t"
|
||||
"clz %0, %1;\n"
|
||||
: "=r"(res)
|
||||
: "r"(in16<<16|0x8000)
|
||||
: "r"(SAFE_SHL(in16,16)|0x8000)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -210,4 +215,6 @@ static OPUS_INLINE opus_int32 silk_CLZ32_armv5(opus_int32 in32)
|
|||
}
|
||||
#define silk_CLZ32(in32) (silk_CLZ32_armv5(in32))
|
||||
|
||||
#undef SAFE_SHL
|
||||
|
||||
#endif /* SILK_MACROS_ARMv5E_H */
|
||||
|
|
|
|||
|
|
@ -39,14 +39,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "SigProc_FIX.h"
|
||||
|
||||
/* Second order ARMA filter, alternative implementation */
|
||||
void silk_biquad_alt(
|
||||
void silk_biquad_alt_stride1(
|
||||
const opus_int16 *in, /* I input signal */
|
||||
const opus_int32 *B_Q28, /* I MA coefficients [3] */
|
||||
const opus_int32 *A_Q28, /* I AR coefficients [2] */
|
||||
opus_int32 *S, /* I/O State vector [2] */
|
||||
opus_int16 *out, /* O output signal */
|
||||
const opus_int32 len, /* I signal length (must be even) */
|
||||
opus_int stride /* I Operate on interleaved signal if > 1 */
|
||||
const opus_int32 len /* I signal length (must be even) */
|
||||
)
|
||||
{
|
||||
/* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
|
||||
|
|
@ -61,7 +60,7 @@ void silk_biquad_alt(
|
|||
|
||||
for( k = 0; k < len; k++ ) {
|
||||
/* S[ 0 ], S[ 1 ]: Q12 */
|
||||
inval = in[ k * stride ];
|
||||
inval = in[ k ];
|
||||
out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
|
||||
|
||||
S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
|
||||
|
|
@ -73,6 +72,50 @@ void silk_biquad_alt(
|
|||
S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
|
||||
|
||||
/* Scale back to Q0 and saturate */
|
||||
out[ k * stride ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
|
||||
out[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
|
||||
}
|
||||
}
|
||||
|
||||
void silk_biquad_alt_stride2_c(
|
||||
const opus_int16 *in, /* I input signal */
|
||||
const opus_int32 *B_Q28, /* I MA coefficients [3] */
|
||||
const opus_int32 *A_Q28, /* I AR coefficients [2] */
|
||||
opus_int32 *S, /* I/O State vector [4] */
|
||||
opus_int16 *out, /* O output signal */
|
||||
const opus_int32 len /* I signal length (must be even) */
|
||||
)
|
||||
{
|
||||
/* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
|
||||
opus_int k;
|
||||
opus_int32 A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14[ 2 ];
|
||||
|
||||
/* Negate A_Q28 values and split in two parts */
|
||||
A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */
|
||||
A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */
|
||||
A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */
|
||||
A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */
|
||||
|
||||
for( k = 0; k < len; k++ ) {
|
||||
/* S[ 0 ], S[ 1 ], S[ 2 ], S[ 3 ]: Q12 */
|
||||
out32_Q14[ 0 ] = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], in[ 2 * k + 0 ] ), 2 );
|
||||
out32_Q14[ 1 ] = silk_LSHIFT( silk_SMLAWB( S[ 2 ], B_Q28[ 0 ], in[ 2 * k + 1 ] ), 2 );
|
||||
|
||||
S[ 0 ] = S[ 1 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A0_L_Q28 ), 14 );
|
||||
S[ 2 ] = S[ 3 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A0_L_Q28 ), 14 );
|
||||
S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14[ 0 ], A0_U_Q28 );
|
||||
S[ 2 ] = silk_SMLAWB( S[ 2 ], out32_Q14[ 1 ], A0_U_Q28 );
|
||||
S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], in[ 2 * k + 0 ] );
|
||||
S[ 2 ] = silk_SMLAWB( S[ 2 ], B_Q28[ 1 ], in[ 2 * k + 1 ] );
|
||||
|
||||
S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A1_L_Q28 ), 14 );
|
||||
S[ 3 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A1_L_Q28 ), 14 );
|
||||
S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14[ 0 ], A1_U_Q28 );
|
||||
S[ 3 ] = silk_SMLAWB( S[ 3 ], out32_Q14[ 1 ], A1_U_Q28 );
|
||||
S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], in[ 2 * k + 0 ] );
|
||||
S[ 3 ] = silk_SMLAWB( S[ 3 ], B_Q28[ 2 ], in[ 2 * k + 1 ] );
|
||||
|
||||
/* Scale back to Q0 and saturate */
|
||||
out[ 2 * k + 0 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 0 ] + (1<<14) - 1, 14 ) );
|
||||
out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 1 ] + (1<<14) - 1, 14 ) );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ void silk_bwexpander(
|
|||
/* Bias in silk_SMULWB can lead to unstable filters */
|
||||
for( i = 0; i < d - 1; i++ ) {
|
||||
ar[ i ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ i ] ), 16 );
|
||||
chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
|
||||
chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
|
||||
}
|
||||
ar[ d - 1 ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ d - 1 ] ), 16 );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "SigProc_FIX.h"
|
||||
|
||||
/* Chirp (bandwidth expand) LP AR filter */
|
||||
/* Chirp (bandwidth expand) LP AR filter.
|
||||
This logic is reused in _celt_lpc(). Any bug fixes should also be applied there. */
|
||||
void silk_bwexpander_32(
|
||||
opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */
|
||||
const opus_int d, /* I Length of ar */
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ opus_int check_control_input(
|
|||
silk_EncControlStruct *encControl /* I Control structure */
|
||||
)
|
||||
{
|
||||
silk_assert( encControl != NULL );
|
||||
celt_assert( encControl != NULL );
|
||||
|
||||
if( ( ( encControl->API_sampleRate != 8000 ) &&
|
||||
( encControl->API_sampleRate != 12000 ) &&
|
||||
|
|
@ -59,46 +59,46 @@ opus_int check_control_input(
|
|||
( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) ||
|
||||
( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) ||
|
||||
( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
return SILK_ENC_FS_NOT_SUPPORTED;
|
||||
}
|
||||
if( encControl->payloadSize_ms != 10 &&
|
||||
encControl->payloadSize_ms != 20 &&
|
||||
encControl->payloadSize_ms != 40 &&
|
||||
encControl->payloadSize_ms != 60 ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;
|
||||
}
|
||||
if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
return SILK_ENC_INVALID_LOSS_RATE;
|
||||
}
|
||||
if( encControl->useDTX < 0 || encControl->useDTX > 1 ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
return SILK_ENC_INVALID_DTX_SETTING;
|
||||
}
|
||||
if( encControl->useCBR < 0 || encControl->useCBR > 1 ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
return SILK_ENC_INVALID_CBR_SETTING;
|
||||
}
|
||||
if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
return SILK_ENC_INVALID_INBAND_FEC_SETTING;
|
||||
}
|
||||
if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
|
||||
}
|
||||
if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
|
||||
}
|
||||
if( encControl->nChannelsInternal > encControl->nChannelsAPI ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
|
||||
}
|
||||
if( encControl->complexity < 0 || encControl->complexity > 10 ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
return SILK_ENC_INVALID_COMPLEXITY_SETTING;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ typedef struct {
|
|||
/* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */
|
||||
opus_int useInBandFEC;
|
||||
|
||||
/* I: Flag to actually code in-band Forward Error Correction (FEC) in the current packet; 0/1 */
|
||||
opus_int LBRR_coded;
|
||||
|
||||
/* I: Flag to enable discontinuous transmission (DTX); 0/1 */
|
||||
opus_int useDTX;
|
||||
|
||||
|
|
@ -110,6 +113,11 @@ typedef struct {
|
|||
/* O: Tells the Opus encoder we're ready to switch */
|
||||
opus_int switchReady;
|
||||
|
||||
/* O: SILK Signal type */
|
||||
opus_int signalType;
|
||||
|
||||
/* O: SILK offset (dithering) */
|
||||
opus_int offset;
|
||||
} silk_EncControlStruct;
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
|
|||
|
|
@ -32,45 +32,82 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "main.h"
|
||||
#include "tuning_parameters.h"
|
||||
|
||||
/* These tables hold SNR values divided by 21 (so they fit in 8 bits)
|
||||
for different target bitrates spaced at 400 bps interval. The first
|
||||
10 values are omitted (0-4 kb/s) because they're all zeros.
|
||||
These tables were obtained by running different SNRs through the
|
||||
encoder and measuring the active bitrate. */
|
||||
static const unsigned char silk_TargetRate_NB_21[117 - 10] = {
|
||||
0, 15, 39, 52, 61, 68,
|
||||
74, 79, 84, 88, 92, 95, 99,102,105,108,111,114,117,119,122,124,
|
||||
126,129,131,133,135,137,139,142,143,145,147,149,151,153,155,157,
|
||||
158,160,162,163,165,167,168,170,171,173,174,176,177,179,180,182,
|
||||
183,185,186,187,189,190,192,193,194,196,197,199,200,201,203,204,
|
||||
205,207,208,209,211,212,213,215,216,217,219,220,221,223,224,225,
|
||||
227,228,230,231,232,234,235,236,238,239,241,242,243,245,246,248,
|
||||
249,250,252,253,255
|
||||
};
|
||||
|
||||
static const unsigned char silk_TargetRate_MB_21[165 - 10] = {
|
||||
0, 0, 28, 43, 52, 59,
|
||||
65, 70, 74, 78, 81, 85, 87, 90, 93, 95, 98,100,102,105,107,109,
|
||||
111,113,115,116,118,120,122,123,125,127,128,130,131,133,134,136,
|
||||
137,138,140,141,143,144,145,147,148,149,151,152,153,154,156,157,
|
||||
158,159,160,162,163,164,165,166,167,168,169,171,172,173,174,175,
|
||||
176,177,178,179,180,181,182,183,184,185,186,187,188,188,189,190,
|
||||
191,192,193,194,195,196,197,198,199,200,201,202,203,203,204,205,
|
||||
206,207,208,209,210,211,212,213,214,214,215,216,217,218,219,220,
|
||||
221,222,223,224,224,225,226,227,228,229,230,231,232,233,234,235,
|
||||
236,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,
|
||||
251,252,253,254,255
|
||||
};
|
||||
|
||||
static const unsigned char silk_TargetRate_WB_21[201 - 10] = {
|
||||
0, 0, 0, 8, 29, 41,
|
||||
49, 56, 62, 66, 70, 74, 77, 80, 83, 86, 88, 91, 93, 95, 97, 99,
|
||||
101,103,105,107,108,110,112,113,115,116,118,119,121,122,123,125,
|
||||
126,127,129,130,131,132,134,135,136,137,138,140,141,142,143,144,
|
||||
145,146,147,148,149,150,151,152,153,154,156,157,158,159,159,160,
|
||||
161,162,163,164,165,166,167,168,169,170,171,171,172,173,174,175,
|
||||
176,177,177,178,179,180,181,181,182,183,184,185,185,186,187,188,
|
||||
189,189,190,191,192,192,193,194,195,195,196,197,198,198,199,200,
|
||||
200,201,202,203,203,204,205,206,206,207,208,209,209,210,211,211,
|
||||
212,213,214,214,215,216,216,217,218,219,219,220,221,221,222,223,
|
||||
224,224,225,226,226,227,228,229,229,230,231,232,232,233,234,234,
|
||||
235,236,237,237,238,239,240,240,241,242,243,243,244,245,246,246,
|
||||
247,248,249,249,250,251,252,253,255
|
||||
};
|
||||
|
||||
/* Control SNR of redidual quantizer */
|
||||
opus_int silk_control_SNR(
|
||||
silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */
|
||||
opus_int32 TargetRate_bps /* I Target max bitrate (bps) */
|
||||
)
|
||||
{
|
||||
opus_int k, ret = SILK_NO_ERROR;
|
||||
opus_int32 frac_Q6;
|
||||
const opus_int32 *rateTable;
|
||||
int id;
|
||||
int bound;
|
||||
const unsigned char *snr_table;
|
||||
|
||||
/* Set bitrate/coding quality */
|
||||
TargetRate_bps = silk_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS );
|
||||
if( TargetRate_bps != psEncC->TargetRate_bps ) {
|
||||
psEncC->TargetRate_bps = TargetRate_bps;
|
||||
|
||||
/* If new TargetRate_bps, translate to SNR_dB value */
|
||||
if( psEncC->fs_kHz == 8 ) {
|
||||
rateTable = silk_TargetRate_table_NB;
|
||||
} else if( psEncC->fs_kHz == 12 ) {
|
||||
rateTable = silk_TargetRate_table_MB;
|
||||
} else {
|
||||
rateTable = silk_TargetRate_table_WB;
|
||||
}
|
||||
|
||||
/* Reduce bitrate for 10 ms modes in these calculations */
|
||||
if( psEncC->nb_subfr == 2 ) {
|
||||
TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS;
|
||||
}
|
||||
|
||||
/* Find bitrate interval in table and interpolate */
|
||||
for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) {
|
||||
if( TargetRate_bps <= rateTable[ k ] ) {
|
||||
frac_Q6 = silk_DIV32( silk_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ),
|
||||
rateTable[ k ] - rateTable[ k - 1 ] );
|
||||
psEncC->SNR_dB_Q7 = silk_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + silk_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
psEncC->TargetRate_bps = TargetRate_bps;
|
||||
if( psEncC->nb_subfr == 2 ) {
|
||||
TargetRate_bps -= 2000 + psEncC->fs_kHz/16;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if( psEncC->fs_kHz == 8 ) {
|
||||
bound = sizeof(silk_TargetRate_NB_21);
|
||||
snr_table = silk_TargetRate_NB_21;
|
||||
} else if( psEncC->fs_kHz == 12 ) {
|
||||
bound = sizeof(silk_TargetRate_MB_21);
|
||||
snr_table = silk_TargetRate_MB_21;
|
||||
} else {
|
||||
bound = sizeof(silk_TargetRate_WB_21);
|
||||
snr_table = silk_TargetRate_WB_21;
|
||||
}
|
||||
id = (TargetRate_bps+200)/400;
|
||||
id = silk_min(id - 10, bound-1);
|
||||
if( id <= 0 ) {
|
||||
psEncC->SNR_dB_Q7 = 0;
|
||||
} else {
|
||||
psEncC->SNR_dB_Q7 = snr_table[id]*21;
|
||||
}
|
||||
return SILK_NO_ERROR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,9 +39,15 @@ opus_int silk_control_audio_bandwidth(
|
|||
)
|
||||
{
|
||||
opus_int fs_kHz;
|
||||
opus_int orig_kHz;
|
||||
opus_int32 fs_Hz;
|
||||
|
||||
fs_kHz = psEncC->fs_kHz;
|
||||
orig_kHz = psEncC->fs_kHz;
|
||||
/* Handle a bandwidth-switching reset where we need to be aware what the last sampling rate was. */
|
||||
if( orig_kHz == 0 ) {
|
||||
orig_kHz = psEncC->sLP.saved_fs_kHz;
|
||||
}
|
||||
fs_kHz = orig_kHz;
|
||||
fs_Hz = silk_SMULBB( fs_kHz, 1000 );
|
||||
if( fs_Hz == 0 ) {
|
||||
/* Encoder has just been initialized */
|
||||
|
|
@ -61,7 +67,7 @@ opus_int silk_control_audio_bandwidth(
|
|||
}
|
||||
if( psEncC->allow_bandwidth_switch || encControl->opusCanSwitch ) {
|
||||
/* Check if we should switch down */
|
||||
if( silk_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz )
|
||||
if( silk_SMULBB( orig_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz )
|
||||
{
|
||||
/* Switch down */
|
||||
if( psEncC->sLP.mode == 0 ) {
|
||||
|
|
@ -76,7 +82,7 @@ opus_int silk_control_audio_bandwidth(
|
|||
psEncC->sLP.mode = 0;
|
||||
|
||||
/* Switch to a lower sample frequency */
|
||||
fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8;
|
||||
fs_kHz = orig_kHz == 16 ? 12 : 8;
|
||||
} else {
|
||||
if( psEncC->sLP.transition_frame_no <= 0 ) {
|
||||
encControl->switchReady = 1;
|
||||
|
|
@ -90,12 +96,12 @@ opus_int silk_control_audio_bandwidth(
|
|||
}
|
||||
else
|
||||
/* Check if we should switch up */
|
||||
if( silk_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz )
|
||||
if( silk_SMULBB( orig_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz )
|
||||
{
|
||||
/* Switch up */
|
||||
if( encControl->opusCanSwitch ) {
|
||||
/* Switch to a higher sample frequency */
|
||||
fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16;
|
||||
fs_kHz = orig_kHz == 8 ? 12 : 16;
|
||||
|
||||
/* New transition */
|
||||
psEncC->sLP.transition_frame_no = 0;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ static opus_int silk_setup_complexity(
|
|||
|
||||
static OPUS_INLINE opus_int silk_setup_LBRR(
|
||||
silk_encoder_state *psEncC, /* I/O */
|
||||
const opus_int32 TargetRate_bps /* I */
|
||||
const silk_EncControlStruct *encControl /* I */
|
||||
);
|
||||
|
||||
|
||||
|
|
@ -65,7 +65,6 @@ static OPUS_INLINE opus_int silk_setup_LBRR(
|
|||
opus_int silk_control_encoder(
|
||||
silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */
|
||||
silk_EncControlStruct *encControl, /* I Control structure */
|
||||
const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
|
||||
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
|
||||
const opus_int channelNb, /* I Channel number */
|
||||
const opus_int force_fs_kHz
|
||||
|
|
@ -125,7 +124,7 @@ opus_int silk_control_encoder(
|
|||
/********************************************/
|
||||
/* Set LBRR usage */
|
||||
/********************************************/
|
||||
ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps );
|
||||
ret += silk_setup_LBRR( &psEnc->sCmn, encControl );
|
||||
|
||||
psEnc->sCmn.controlled_since_last_payload = 1;
|
||||
|
||||
|
|
@ -239,12 +238,11 @@ static opus_int silk_setup_fs(
|
|||
}
|
||||
|
||||
/* Set internal sampling frequency */
|
||||
silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
|
||||
silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
|
||||
celt_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
|
||||
celt_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
|
||||
if( psEnc->sCmn.fs_kHz != fs_kHz ) {
|
||||
/* reset part of the state */
|
||||
silk_memset( &psEnc->sShape, 0, sizeof( psEnc->sShape ) );
|
||||
silk_memset( &psEnc->sPrefilt, 0, sizeof( psEnc->sPrefilt ) );
|
||||
silk_memset( &psEnc->sCmn.sNSQ, 0, sizeof( psEnc->sCmn.sNSQ ) );
|
||||
silk_memset( psEnc->sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
|
||||
silk_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) );
|
||||
|
|
@ -255,7 +253,6 @@ static opus_int silk_setup_fs(
|
|||
/* Initialize non-zero parameters */
|
||||
psEnc->sCmn.prevLag = 100;
|
||||
psEnc->sCmn.first_frame_after_reset = 1;
|
||||
psEnc->sPrefilt.lagPrev = 100;
|
||||
psEnc->sShape.LastGainIndex = 10;
|
||||
psEnc->sCmn.sNSQ.lagPrev = 100;
|
||||
psEnc->sCmn.sNSQ.prev_gain_Q16 = 65536;
|
||||
|
|
@ -293,19 +290,16 @@ static opus_int silk_setup_fs(
|
|||
psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );
|
||||
}
|
||||
if( psEnc->sCmn.fs_kHz == 16 ) {
|
||||
psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 );
|
||||
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
|
||||
} else if( psEnc->sCmn.fs_kHz == 12 ) {
|
||||
psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 );
|
||||
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
|
||||
} else {
|
||||
psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 );
|
||||
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that settings are valid */
|
||||
silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
|
||||
celt_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -318,61 +312,76 @@ static opus_int silk_setup_complexity(
|
|||
opus_int ret = 0;
|
||||
|
||||
/* Set encoding complexity */
|
||||
silk_assert( Complexity >= 0 && Complexity <= 10 );
|
||||
if( Complexity < 2 ) {
|
||||
celt_assert( Complexity >= 0 && Complexity <= 10 );
|
||||
if( Complexity < 1 ) {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 6;
|
||||
psEncC->shapingLPCOrder = 8;
|
||||
psEncC->shapingLPCOrder = 12;
|
||||
psEncC->la_shape = 3 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = 1;
|
||||
psEncC->useInterpolatedNLSFs = 0;
|
||||
psEncC->LTPQuantLowComplexity = 1;
|
||||
psEncC->NLSF_MSVQ_Survivors = 2;
|
||||
psEncC->warping_Q16 = 0;
|
||||
} else if( Complexity < 2 ) {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 8;
|
||||
psEncC->shapingLPCOrder = 14;
|
||||
psEncC->la_shape = 5 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = 1;
|
||||
psEncC->useInterpolatedNLSFs = 0;
|
||||
psEncC->NLSF_MSVQ_Survivors = 3;
|
||||
psEncC->warping_Q16 = 0;
|
||||
} else if( Complexity < 3 ) {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 6;
|
||||
psEncC->shapingLPCOrder = 12;
|
||||
psEncC->la_shape = 3 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = 2;
|
||||
psEncC->useInterpolatedNLSFs = 0;
|
||||
psEncC->NLSF_MSVQ_Survivors = 2;
|
||||
psEncC->warping_Q16 = 0;
|
||||
} else if( Complexity < 4 ) {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 8;
|
||||
psEncC->shapingLPCOrder = 10;
|
||||
psEncC->shapingLPCOrder = 14;
|
||||
psEncC->la_shape = 5 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = 1;
|
||||
psEncC->nStatesDelayedDecision = 2;
|
||||
psEncC->useInterpolatedNLSFs = 0;
|
||||
psEncC->LTPQuantLowComplexity = 0;
|
||||
psEncC->NLSF_MSVQ_Survivors = 4;
|
||||
psEncC->warping_Q16 = 0;
|
||||
} else if( Complexity < 6 ) {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.74, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 10;
|
||||
psEncC->shapingLPCOrder = 12;
|
||||
psEncC->shapingLPCOrder = 16;
|
||||
psEncC->la_shape = 5 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = 2;
|
||||
psEncC->useInterpolatedNLSFs = 1;
|
||||
psEncC->LTPQuantLowComplexity = 0;
|
||||
psEncC->NLSF_MSVQ_Survivors = 8;
|
||||
psEncC->NLSF_MSVQ_Survivors = 6;
|
||||
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
|
||||
} else if( Complexity < 8 ) {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.72, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 12;
|
||||
psEncC->shapingLPCOrder = 14;
|
||||
psEncC->shapingLPCOrder = 20;
|
||||
psEncC->la_shape = 5 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = 3;
|
||||
psEncC->useInterpolatedNLSFs = 1;
|
||||
psEncC->LTPQuantLowComplexity = 0;
|
||||
psEncC->NLSF_MSVQ_Survivors = 16;
|
||||
psEncC->NLSF_MSVQ_Survivors = 8;
|
||||
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
|
||||
} else {
|
||||
psEncC->pitchEstimationComplexity = SILK_PE_MAX_COMPLEX;
|
||||
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.7, 16 );
|
||||
psEncC->pitchEstimationLPCOrder = 16;
|
||||
psEncC->shapingLPCOrder = 16;
|
||||
psEncC->shapingLPCOrder = 24;
|
||||
psEncC->la_shape = 5 * psEncC->fs_kHz;
|
||||
psEncC->nStatesDelayedDecision = MAX_DEL_DEC_STATES;
|
||||
psEncC->useInterpolatedNLSFs = 1;
|
||||
psEncC->LTPQuantLowComplexity = 0;
|
||||
psEncC->NLSF_MSVQ_Survivors = 32;
|
||||
psEncC->NLSF_MSVQ_Survivors = 16;
|
||||
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
|
||||
}
|
||||
|
||||
|
|
@ -381,46 +390,32 @@ static opus_int silk_setup_complexity(
|
|||
psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape;
|
||||
psEncC->Complexity = Complexity;
|
||||
|
||||
silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
|
||||
silk_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER );
|
||||
silk_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES );
|
||||
silk_assert( psEncC->warping_Q16 <= 32767 );
|
||||
silk_assert( psEncC->la_shape <= LA_SHAPE_MAX );
|
||||
silk_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX );
|
||||
silk_assert( psEncC->NLSF_MSVQ_Survivors <= NLSF_VQ_MAX_SURVIVORS );
|
||||
celt_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
|
||||
celt_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER );
|
||||
celt_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES );
|
||||
celt_assert( psEncC->warping_Q16 <= 32767 );
|
||||
celt_assert( psEncC->la_shape <= LA_SHAPE_MAX );
|
||||
celt_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static OPUS_INLINE opus_int silk_setup_LBRR(
|
||||
silk_encoder_state *psEncC, /* I/O */
|
||||
const opus_int32 TargetRate_bps /* I */
|
||||
const silk_EncControlStruct *encControl /* I */
|
||||
)
|
||||
{
|
||||
opus_int LBRR_in_previous_packet, ret = SILK_NO_ERROR;
|
||||
opus_int32 LBRR_rate_thres_bps;
|
||||
|
||||
LBRR_in_previous_packet = psEncC->LBRR_enabled;
|
||||
psEncC->LBRR_enabled = 0;
|
||||
if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) {
|
||||
if( psEncC->fs_kHz == 8 ) {
|
||||
LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS;
|
||||
} else if( psEncC->fs_kHz == 12 ) {
|
||||
LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS;
|
||||
psEncC->LBRR_enabled = encControl->LBRR_coded;
|
||||
if( psEncC->LBRR_enabled ) {
|
||||
/* Set gain increase for coding LBRR excitation */
|
||||
if( LBRR_in_previous_packet == 0 ) {
|
||||
/* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */
|
||||
psEncC->LBRR_GainIncreases = 7;
|
||||
} else {
|
||||
LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS;
|
||||
}
|
||||
LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
|
||||
|
||||
if( TargetRate_bps > LBRR_rate_thres_bps ) {
|
||||
/* Set gain increase for coding LBRR excitation */
|
||||
if( LBRR_in_previous_packet == 0 ) {
|
||||
/* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */
|
||||
psEncC->LBRR_GainIncreases = 7;
|
||||
} else {
|
||||
psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
|
||||
}
|
||||
psEncC->LBRR_enabled = 1;
|
||||
psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,18 +30,20 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#if SILK_DEBUG || SILK_TIC_TOC
|
||||
#include "SigProc_FIX.h"
|
||||
#endif
|
||||
|
||||
#if SILK_TIC_TOC
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#if (defined(_WIN32) || defined(_WINCE))
|
||||
#include <windows.h> /* timer */
|
||||
#else /* Linux or Mac*/
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
unsigned long silk_GetHighResolutionTime(void) /* O time in usec*/
|
||||
{
|
||||
/* Returns a time counter in microsec */
|
||||
|
|
@ -65,7 +67,7 @@ unsigned long GetHighResolutionTime(void) /* O time in usec*/
|
|||
int silk_Timer_nTimers = 0;
|
||||
int silk_Timer_depth_ctr = 0;
|
||||
char silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN];
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX];
|
||||
#else
|
||||
unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX];
|
||||
|
|
@ -76,7 +78,7 @@ opus_int64 silk_Timer_sum[silk_NUM_TIMERS_MAX];
|
|||
opus_int64 silk_Timer_max[silk_NUM_TIMERS_MAX];
|
||||
opus_int64 silk_Timer_depth[silk_NUM_TIMERS_MAX];
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
void silk_TimerSave(char *file_name)
|
||||
{
|
||||
if( silk_Timer_nTimers > 0 )
|
||||
|
|
|
|||
|
|
@ -28,41 +28,29 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef SILK_DEBUG_H
|
||||
#define SILK_DEBUG_H
|
||||
|
||||
/* Set to 1 to enable DEBUG_STORE_DATA() macros for dumping
|
||||
* intermediate signals from the codec.
|
||||
*/
|
||||
#define SILK_DEBUG 0
|
||||
|
||||
/* Flag for using timers */
|
||||
#define SILK_TIC_TOC 0
|
||||
|
||||
#if SILK_DEBUG || SILK_TIC_TOC
|
||||
#include "typedef.h"
|
||||
#include <stdio.h> /* file writing */
|
||||
#include <string.h> /* strcpy, strcmp */
|
||||
#include <stdio.h> /* file writing */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
unsigned long GetHighResolutionTime(void); /* O time in usec*/
|
||||
|
||||
/* make SILK_DEBUG dependent on compiler's _DEBUG */
|
||||
#if defined _WIN32
|
||||
#ifdef _DEBUG
|
||||
#define SILK_DEBUG 1
|
||||
#else
|
||||
#define SILK_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* overrule the above */
|
||||
#if 0
|
||||
/* #define NO_ASSERTS*/
|
||||
#undef SILK_DEBUG
|
||||
#define SILK_DEBUG 1
|
||||
#endif
|
||||
#else
|
||||
#define SILK_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* Flag for using timers */
|
||||
#define SILK_TIC_TOC 0
|
||||
|
||||
|
||||
#if SILK_TIC_TOC
|
||||
|
||||
unsigned long GetHighResolutionTime(void); /* O time in usec*/
|
||||
|
||||
#if (defined(_WIN32) || defined(_WINCE))
|
||||
#include <windows.h> /* timer */
|
||||
#else /* Linux or Mac*/
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ opus_int silk_Decode( /* O Returns error co
|
|||
int delay_stack_alloc;
|
||||
SAVE_STACK;
|
||||
|
||||
silk_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
|
||||
celt_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
|
||||
|
||||
/**********************************/
|
||||
/* Test if first frame in payload */
|
||||
|
|
@ -143,13 +143,13 @@ opus_int silk_Decode( /* O Returns error co
|
|||
channel_state[ n ].nFramesPerPacket = 3;
|
||||
channel_state[ n ].nb_subfr = 4;
|
||||
} else {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
RESTORE_STACK;
|
||||
return SILK_DEC_INVALID_FRAME_SIZE;
|
||||
}
|
||||
fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1;
|
||||
if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
RESTORE_STACK;
|
||||
return SILK_DEC_INVALID_SAMPLING_FREQUENCY;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ void silk_decode_core(
|
|||
if( k == 0 || ( k == 2 && NLSF_interpolation_flag ) ) {
|
||||
/* Rewhiten with new A coefs */
|
||||
start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
|
||||
silk_assert( start_idx > 0 );
|
||||
celt_assert( start_idx > 0 );
|
||||
|
||||
if( k == 2 ) {
|
||||
silk_memcpy( &psDec->outBuf[ psDec->ltp_mem_length ], xq, 2 * psDec->subfr_length * sizeof( opus_int16 ) );
|
||||
|
|
@ -196,7 +196,7 @@ void silk_decode_core(
|
|||
|
||||
for( i = 0; i < psDec->subfr_length; i++ ) {
|
||||
/* Short-term prediction */
|
||||
silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
|
||||
celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
|
||||
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
|
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] );
|
||||
|
|
@ -225,8 +225,6 @@ void silk_decode_core(
|
|||
pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
|
||||
}
|
||||
|
||||
/* DEBUG_STORE_DATA( dec.pcm, pxq, psDec->subfr_length * sizeof( opus_int16 ) ) */
|
||||
|
||||
/* Update LPC filter state */
|
||||
silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
|
||||
pexc_Q14 += psDec->subfr_length;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ opus_int silk_decode_frame(
|
|||
psDecCtrl->LTP_scale_Q14 = 0;
|
||||
|
||||
/* Safety checks */
|
||||
silk_assert( L > 0 && L <= MAX_FRAME_LENGTH );
|
||||
celt_assert( L > 0 && L <= MAX_FRAME_LENGTH );
|
||||
|
||||
if( lostFlag == FLAG_DECODE_NORMAL ||
|
||||
( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) )
|
||||
|
|
@ -91,7 +91,7 @@ opus_int silk_decode_frame(
|
|||
|
||||
psDec->lossCnt = 0;
|
||||
psDec->prevSignalType = psDec->indices.signalType;
|
||||
silk_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
|
||||
celt_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
|
||||
|
||||
/* A frame has been decoded without errors */
|
||||
psDec->first_frame_after_reset = 0;
|
||||
|
|
@ -103,7 +103,7 @@ opus_int silk_decode_frame(
|
|||
/*************************/
|
||||
/* Update output buffer. */
|
||||
/*************************/
|
||||
silk_assert( psDec->ltp_mem_length >= psDec->frame_length );
|
||||
celt_assert( psDec->ltp_mem_length >= psDec->frame_length );
|
||||
mv_len = psDec->ltp_mem_length - psDec->frame_length;
|
||||
silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
|
||||
silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ void silk_decode_indices(
|
|||
/**********************/
|
||||
psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 );
|
||||
silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] );
|
||||
silk_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
|
||||
celt_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
|
||||
for( i = 0; i < psDec->psNLSF_CB->order; i++ ) {
|
||||
Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
|
||||
if( Ix == 0 ) {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ void silk_decode_parameters(
|
|||
silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB );
|
||||
|
||||
/* Convert NLSF parameters to AR prediction filter coefficients */
|
||||
silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order );
|
||||
silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order, psDec->arch );
|
||||
|
||||
/* If just reset, e.g., because internal Fs changed, do not allow interpolation */
|
||||
/* improves the case of packet loss in the first frame after a switch */
|
||||
|
|
@ -69,7 +69,7 @@ void silk_decode_parameters(
|
|||
}
|
||||
|
||||
/* Convert NLSF parameters to AR prediction filter coefficients */
|
||||
silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order );
|
||||
silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order, psDec->arch );
|
||||
} else {
|
||||
/* Copy LPC coefficients for first half from second half */
|
||||
silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ void silk_decode_pitch(
|
|||
Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
|
||||
cbk_size = PE_NB_CBKS_STAGE2_EXT;
|
||||
} else {
|
||||
silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
|
||||
celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
|
||||
Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
|
||||
cbk_size = PE_NB_CBKS_STAGE2_10MS;
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ void silk_decode_pitch(
|
|||
Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
|
||||
cbk_size = PE_NB_CBKS_STAGE3_MAX;
|
||||
} else {
|
||||
silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
|
||||
celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
|
||||
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
|
||||
cbk_size = PE_NB_CBKS_STAGE3_10MS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ void silk_decode_pulses(
|
|||
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
|
||||
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
|
||||
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
|
||||
silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
|
||||
celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
|
||||
iter++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ opus_int silk_decoder_set_fs(
|
|||
{
|
||||
opus_int frame_length, ret = 0;
|
||||
|
||||
silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
|
||||
silk_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
|
||||
celt_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
|
||||
celt_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
|
||||
|
||||
/* New (sub)frame length */
|
||||
psDec->subfr_length = silk_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz );
|
||||
|
|
@ -86,7 +86,7 @@ opus_int silk_decoder_set_fs(
|
|||
psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
|
||||
} else {
|
||||
/* unsupported sampling rate */
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
}
|
||||
psDec->first_frame_after_reset = 1;
|
||||
psDec->lagPrev = 100;
|
||||
|
|
@ -101,7 +101,7 @@ opus_int silk_decoder_set_fs(
|
|||
}
|
||||
|
||||
/* Check that settings are valid */
|
||||
silk_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
|
||||
celt_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ extern "C"
|
|||
/* Limits on bitrate */
|
||||
#define MIN_TARGET_RATE_BPS 5000
|
||||
#define MAX_TARGET_RATE_BPS 80000
|
||||
#define TARGET_RATE_TAB_SZ 8
|
||||
|
||||
/* LBRR thresholds */
|
||||
#define LBRR_NB_MIN_RATE_BPS 12000
|
||||
|
|
@ -56,6 +55,12 @@ extern "C"
|
|||
/* DTX settings */
|
||||
#define NB_SPEECH_FRAMES_BEFORE_DTX 10 /* eq 200 ms */
|
||||
#define MAX_CONSECUTIVE_DTX 20 /* eq 400 ms */
|
||||
#define DTX_ACTIVITY_THRESHOLD 0.1f
|
||||
|
||||
/* VAD decision */
|
||||
#define VAD_NO_DECISION -1
|
||||
#define VAD_NO_ACTIVITY 0
|
||||
#define VAD_ACTIVITY 1
|
||||
|
||||
/* Maximum sampling frequency */
|
||||
#define MAX_FS_KHZ 16
|
||||
|
|
@ -147,7 +152,7 @@ extern "C"
|
|||
#define USE_HARM_SHAPING 1
|
||||
|
||||
/* Max LPC order of noise shaping filters */
|
||||
#define MAX_SHAPE_LPC_ORDER 16
|
||||
#define MAX_SHAPE_LPC_ORDER 24
|
||||
|
||||
#define HARM_SHAPE_FIR_TAPS 3
|
||||
|
||||
|
|
@ -157,8 +162,7 @@ extern "C"
|
|||
#define LTP_BUF_LENGTH 512
|
||||
#define LTP_MASK ( LTP_BUF_LENGTH - 1 )
|
||||
|
||||
#define DECISION_DELAY 32
|
||||
#define DECISION_DELAY_MASK ( DECISION_DELAY - 1 )
|
||||
#define DECISION_DELAY 40
|
||||
|
||||
/* Number of subframes for excitation entropy coding */
|
||||
#define SHELL_CODEC_FRAME_LENGTH 16
|
||||
|
|
@ -173,11 +177,7 @@ extern "C"
|
|||
|
||||
#define MAX_MATRIX_SIZE MAX_LPC_ORDER /* Max of LPC Order and LTP order */
|
||||
|
||||
#if( MAX_LPC_ORDER > DECISION_DELAY )
|
||||
# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER
|
||||
#else
|
||||
# define NSQ_LPC_BUF_LENGTH DECISION_DELAY
|
||||
#endif
|
||||
|
||||
/***************************/
|
||||
/* Voice activity detector */
|
||||
|
|
@ -205,7 +205,6 @@ extern "C"
|
|||
/******************/
|
||||
#define NLSF_W_Q 2
|
||||
#define NLSF_VQ_MAX_VECTORS 32
|
||||
#define NLSF_VQ_MAX_SURVIVORS 32
|
||||
#define NLSF_QUANT_MAX_AMPLITUDE 4
|
||||
#define NLSF_QUANT_MAX_AMPLITUDE_EXT 10
|
||||
#define NLSF_QUANT_LEVEL_ADJ 0.1
|
||||
|
|
@ -226,6 +225,7 @@ extern "C"
|
|||
/* Defines for CN generation */
|
||||
#define CNG_BUF_MASK_MAX 255 /* 2^floor(log2(MAX_FRAME_LENGTH))-1 */
|
||||
#define CNG_GAIN_SMTH_Q16 4634 /* 0.25^(1/4) */
|
||||
#define CNG_GAIN_SMTH_THRESHOLD_Q16 46396 /* -3 dB */
|
||||
#define CNG_NLSF_SMTH_Q16 16348 /* 0.25 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ opus_int silk_InitEncoder( /* O Returns error co
|
|||
silk_memset( psEnc, 0, sizeof( silk_encoder ) );
|
||||
for( n = 0; n < ENCODER_NUM_CHANNELS; n++ ) {
|
||||
if( ret += silk_init_encoder( &psEnc->state_Fxx[ n ], arch ) ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ opus_int silk_InitEncoder( /* O Returns error co
|
|||
|
||||
/* Read control structure */
|
||||
if( ret += silk_QueryEncoder( encState, encStatus ) ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -144,7 +144,8 @@ opus_int silk_Encode( /* O Returns error co
|
|||
opus_int nSamplesIn, /* I Number of samples in input vector */
|
||||
ec_enc *psRangeEnc, /* I/O Compressor data structure */
|
||||
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
|
||||
const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */
|
||||
const opus_int prefillFlag, /* I Flag to indicate prefilling buffers no coding */
|
||||
opus_int activity /* I Decision of Opus voice activity detector */
|
||||
)
|
||||
{
|
||||
opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0;
|
||||
|
|
@ -166,7 +167,7 @@ opus_int silk_Encode( /* O Returns error co
|
|||
|
||||
/* Check values in encoder control structure */
|
||||
if( ( ret = check_control_input( encControl ) ) != 0 ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
RESTORE_STACK;
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -199,16 +200,26 @@ opus_int silk_Encode( /* O Returns error co
|
|||
tot_blocks = ( nBlocksOf10ms > 1 ) ? nBlocksOf10ms >> 1 : 1;
|
||||
curr_block = 0;
|
||||
if( prefillFlag ) {
|
||||
silk_LP_state save_LP;
|
||||
/* Only accept input length of 10 ms */
|
||||
if( nBlocksOf10ms != 1 ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
RESTORE_STACK;
|
||||
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
|
||||
}
|
||||
if ( prefillFlag == 2 ) {
|
||||
save_LP = psEnc->state_Fxx[ 0 ].sCmn.sLP;
|
||||
/* Save the sampling rate so the bandwidth switching code can keep handling transitions. */
|
||||
save_LP.saved_fs_kHz = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz;
|
||||
}
|
||||
/* Reset Encoder */
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
ret = silk_init_encoder( &psEnc->state_Fxx[ n ], psEnc->state_Fxx[ n ].sCmn.arch );
|
||||
silk_assert( !ret );
|
||||
/* Restore the variable LP state. */
|
||||
if ( prefillFlag == 2 ) {
|
||||
psEnc->state_Fxx[ n ].sCmn.sLP = save_LP;
|
||||
}
|
||||
celt_assert( !ret );
|
||||
}
|
||||
tmp_payloadSize_ms = encControl->payloadSize_ms;
|
||||
encControl->payloadSize_ms = 10;
|
||||
|
|
@ -221,23 +232,22 @@ opus_int silk_Encode( /* O Returns error co
|
|||
} else {
|
||||
/* Only accept input lengths that are a multiple of 10 ms */
|
||||
if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
RESTORE_STACK;
|
||||
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
|
||||
}
|
||||
/* Make sure no more than one packet can be produced */
|
||||
if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) {
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
RESTORE_STACK;
|
||||
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
|
||||
}
|
||||
}
|
||||
|
||||
TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 );
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
/* Force the side channel to the same rate as the mid */
|
||||
opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0;
|
||||
if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
|
||||
if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
|
||||
silk_assert( 0 );
|
||||
RESTORE_STACK;
|
||||
return ret;
|
||||
|
|
@ -249,7 +259,7 @@ opus_int silk_Encode( /* O Returns error co
|
|||
}
|
||||
psEnc->state_Fxx[ n ].sCmn.inDTX = psEnc->state_Fxx[ n ].sCmn.useDTX;
|
||||
}
|
||||
silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
|
||||
celt_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
|
||||
|
||||
/* Input buffering/resampling and encoding */
|
||||
nSamplesToBufferMax =
|
||||
|
|
@ -307,7 +317,7 @@ opus_int silk_Encode( /* O Returns error co
|
|||
}
|
||||
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
|
||||
} else {
|
||||
silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
|
||||
celt_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
|
||||
silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16));
|
||||
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
|
||||
&psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
|
||||
|
|
@ -323,8 +333,8 @@ opus_int silk_Encode( /* O Returns error co
|
|||
/* Silk encoder */
|
||||
if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) {
|
||||
/* Enough data in input buffer, so encode */
|
||||
silk_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length );
|
||||
silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length );
|
||||
celt_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length );
|
||||
celt_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length );
|
||||
|
||||
/* Deal with LBRR data */
|
||||
if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) {
|
||||
|
|
@ -416,7 +426,6 @@ opus_int silk_Encode( /* O Returns error co
|
|||
/* Reset side channel encoder memory for first frame with side coding */
|
||||
if( psEnc->prev_decode_only_middle == 1 ) {
|
||||
silk_memset( &psEnc->state_Fxx[ 1 ].sShape, 0, sizeof( psEnc->state_Fxx[ 1 ].sShape ) );
|
||||
silk_memset( &psEnc->state_Fxx[ 1 ].sPrefilt, 0, sizeof( psEnc->state_Fxx[ 1 ].sPrefilt ) );
|
||||
silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sNSQ, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sNSQ ) );
|
||||
silk_memset( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15 ) );
|
||||
silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State ) );
|
||||
|
|
@ -427,7 +436,7 @@ opus_int silk_Encode( /* O Returns error co
|
|||
psEnc->state_Fxx[ 1 ].sCmn.sNSQ.prev_gain_Q16 = 65536;
|
||||
psEnc->state_Fxx[ 1 ].sCmn.first_frame_after_reset = 1;
|
||||
}
|
||||
silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ] );
|
||||
silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ], activity );
|
||||
} else {
|
||||
psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] = 0;
|
||||
}
|
||||
|
|
@ -442,7 +451,7 @@ opus_int silk_Encode( /* O Returns error co
|
|||
silk_memcpy( psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) );
|
||||
silk_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length ], 2 * sizeof( opus_int16 ) );
|
||||
}
|
||||
silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ] );
|
||||
silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ], activity );
|
||||
|
||||
/* Encode */
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
|
|
@ -557,6 +566,10 @@ opus_int silk_Encode( /* O Returns error co
|
|||
}
|
||||
}
|
||||
|
||||
encControl->signalType = psEnc->state_Fxx[0].sCmn.indices.signalType;
|
||||
encControl->offset = silk_Quantization_Offsets_Q10
|
||||
[ psEnc->state_Fxx[0].sCmn.indices.signalType >> 1 ]
|
||||
[ psEnc->state_Fxx[0].sCmn.indices.quantOffsetType ];
|
||||
RESTORE_STACK;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ void silk_encode_indices(
|
|||
/* Encode signal type and quantizer offset */
|
||||
/*******************************************/
|
||||
typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType;
|
||||
silk_assert( typeOffset >= 0 && typeOffset < 6 );
|
||||
silk_assert( encode_LBRR == 0 || typeOffset >= 2 );
|
||||
celt_assert( typeOffset >= 0 && typeOffset < 6 );
|
||||
celt_assert( encode_LBRR == 0 || typeOffset >= 2 );
|
||||
if( encode_LBRR || typeOffset >= 2 ) {
|
||||
ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 );
|
||||
} else {
|
||||
|
|
@ -90,7 +90,7 @@ void silk_encode_indices(
|
|||
/****************/
|
||||
ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 );
|
||||
silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] );
|
||||
silk_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder );
|
||||
celt_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder );
|
||||
for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) {
|
||||
if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) {
|
||||
ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ void silk_encode_pulses(
|
|||
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
|
||||
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
|
||||
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
|
||||
silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
|
||||
celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
|
||||
iter++;
|
||||
silk_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,15 +57,15 @@ void silk_apply_sine_window(
|
|||
opus_int k, f_Q16, c_Q16;
|
||||
opus_int32 S0_Q16, S1_Q16;
|
||||
|
||||
silk_assert( win_type == 1 || win_type == 2 );
|
||||
celt_assert( win_type == 1 || win_type == 2 );
|
||||
|
||||
/* Length must be in a range from 16 to 120 and a multiple of 4 */
|
||||
silk_assert( length >= 16 && length <= 120 );
|
||||
silk_assert( ( length & 3 ) == 0 );
|
||||
celt_assert( length >= 16 && length <= 120 );
|
||||
celt_assert( ( length & 3 ) == 0 );
|
||||
|
||||
/* Frequency */
|
||||
k = ( length >> 2 ) - 4;
|
||||
silk_assert( k >= 0 && k <= 26 );
|
||||
celt_assert( k >= 0 && k <= 26 );
|
||||
f_Q16 = (opus_int)freq_table_Q16[ k ];
|
||||
|
||||
/* Factor used for cosine approximation */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2017 Google Inc.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
|
||||
# define SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
|
||||
|
||||
# include "celt/arm/armcpu.h"
|
||||
|
||||
# if defined(FIXED_POINT)
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
void silk_warped_autocorrelation_FIX_neon(
|
||||
opus_int32 *corr, /* O Result [order + 1] */
|
||||
opus_int *scale, /* O Scaling of the correlation vector */
|
||||
const opus_int16 *input, /* I Input data to correlate */
|
||||
const opus_int warping_Q16, /* I Warping coefficient */
|
||||
const opus_int length, /* I Length of input */
|
||||
const opus_int order /* I Correlation order (even) */
|
||||
);
|
||||
|
||||
# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
|
||||
# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
|
||||
# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
|
||||
((void)(arch), PRESUME_NEON(silk_warped_autocorrelation_FIX)(corr, scale, input, warping_Q16, length, order))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
|
||||
/*Is run-time CPU detection enabled on this platform?*/
|
||||
# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
extern void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK+1])(opus_int32*, opus_int*, const opus_int16*, const opus_int, const opus_int, const opus_int);
|
||||
# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
|
||||
# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
|
||||
((*SILK_WARPED_AUTOCORRELATION_FIX_IMPL[(arch)&OPUS_ARCHMASK])(corr, scale, input, warping_Q16, length, order))
|
||||
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
|
||||
# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
|
||||
((void)(arch), silk_warped_autocorrelation_FIX_neon(corr, scale, input, warping_Q16, length, order))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# endif /* end FIXED_POINT */
|
||||
|
||||
#endif /* end SILK_WARPED_AUTOCORRELATION_FIX_ARM_H */
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2017 Google Inc., Jean-Marc Valin
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <arm_neon.h>
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
# include <string.h>
|
||||
#endif
|
||||
#include "stack_alloc.h"
|
||||
#include "main_FIX.h"
|
||||
|
||||
static OPUS_INLINE void calc_corr( const opus_int32 *const input_QS, opus_int64 *const corr_QC, const opus_int offset, const int32x4_t state_QS_s32x4 )
|
||||
{
|
||||
int64x2_t corr_QC_s64x2[ 2 ], t_s64x2[ 2 ];
|
||||
const int32x4_t input_QS_s32x4 = vld1q_s32( input_QS + offset );
|
||||
corr_QC_s64x2[ 0 ] = vld1q_s64( corr_QC + offset + 0 );
|
||||
corr_QC_s64x2[ 1 ] = vld1q_s64( corr_QC + offset + 2 );
|
||||
t_s64x2[ 0 ] = vmull_s32( vget_low_s32( state_QS_s32x4 ), vget_low_s32( input_QS_s32x4 ) );
|
||||
t_s64x2[ 1 ] = vmull_s32( vget_high_s32( state_QS_s32x4 ), vget_high_s32( input_QS_s32x4 ) );
|
||||
corr_QC_s64x2[ 0 ] = vsraq_n_s64( corr_QC_s64x2[ 0 ], t_s64x2[ 0 ], 2 * QS - QC );
|
||||
corr_QC_s64x2[ 1 ] = vsraq_n_s64( corr_QC_s64x2[ 1 ], t_s64x2[ 1 ], 2 * QS - QC );
|
||||
vst1q_s64( corr_QC + offset + 0, corr_QC_s64x2[ 0 ] );
|
||||
vst1q_s64( corr_QC + offset + 2, corr_QC_s64x2[ 1 ] );
|
||||
}
|
||||
|
||||
static OPUS_INLINE int32x4_t calc_state( const int32x4_t state_QS0_s32x4, const int32x4_t state_QS0_1_s32x4, const int32x4_t state_QS1_1_s32x4, const int32x4_t warping_Q16_s32x4 )
|
||||
{
|
||||
int32x4_t t_s32x4 = vsubq_s32( state_QS0_s32x4, state_QS0_1_s32x4 );
|
||||
t_s32x4 = vqdmulhq_s32( t_s32x4, warping_Q16_s32x4 );
|
||||
return vaddq_s32( state_QS1_1_s32x4, t_s32x4 );
|
||||
}
|
||||
|
||||
void silk_warped_autocorrelation_FIX_neon(
|
||||
opus_int32 *corr, /* O Result [order + 1] */
|
||||
opus_int *scale, /* O Scaling of the correlation vector */
|
||||
const opus_int16 *input, /* I Input data to correlate */
|
||||
const opus_int warping_Q16, /* I Warping coefficient */
|
||||
const opus_int length, /* I Length of input */
|
||||
const opus_int order /* I Correlation order (even) */
|
||||
)
|
||||
{
|
||||
if( ( MAX_SHAPE_LPC_ORDER > 24 ) || ( order < 6 ) ) {
|
||||
silk_warped_autocorrelation_FIX_c( corr, scale, input, warping_Q16, length, order );
|
||||
} else {
|
||||
opus_int n, i, lsh;
|
||||
opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; /* In reverse order */
|
||||
opus_int64 corr_QC_orderT;
|
||||
int64x2_t lsh_s64x2;
|
||||
const opus_int orderT = ( order + 3 ) & ~3;
|
||||
opus_int64 *corr_QCT;
|
||||
opus_int32 *input_QS;
|
||||
VARDECL( opus_int32, input_QST );
|
||||
VARDECL( opus_int32, state );
|
||||
SAVE_STACK;
|
||||
|
||||
/* Order must be even */
|
||||
silk_assert( ( order & 1 ) == 0 );
|
||||
silk_assert( 2 * QS - QC >= 0 );
|
||||
|
||||
/* The additional +4 is to ensure a later vld1q_s32 call does not overflow. */
|
||||
/* Strictly, only +3 is needed but +4 simplifies initialization using the 4x32 neon load. */
|
||||
ALLOC( input_QST, length + 2 * MAX_SHAPE_LPC_ORDER + 4, opus_int32 );
|
||||
|
||||
input_QS = input_QST;
|
||||
/* input_QS has zero paddings in the beginning and end. */
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
|
||||
/* Loop over samples */
|
||||
for( n = 0; n < length - 7; n += 8, input_QS += 8 ) {
|
||||
const int16x8_t t0_s16x4 = vld1q_s16( input + n );
|
||||
vst1q_s32( input_QS + 0, vshll_n_s16( vget_low_s16( t0_s16x4 ), QS ) );
|
||||
vst1q_s32( input_QS + 4, vshll_n_s16( vget_high_s16( t0_s16x4 ), QS ) );
|
||||
}
|
||||
for( ; n < length; n++, input_QS++ ) {
|
||||
input_QS[ 0 ] = silk_LSHIFT32( (opus_int32)input[ n ], QS );
|
||||
}
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS += 4;
|
||||
vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
|
||||
input_QS = input_QST + MAX_SHAPE_LPC_ORDER - orderT;
|
||||
|
||||
/* The following loop runs ( length + order ) times, with ( order ) extra epilogues. */
|
||||
/* The zero paddings in input_QS guarantee corr_QC's correctness even with the extra epilogues. */
|
||||
/* The values of state_QS will be polluted by the extra epilogues, however they are temporary values. */
|
||||
|
||||
/* Keep the C code here to help understand the intrinsics optimization. */
|
||||
/*
|
||||
{
|
||||
opus_int32 state_QS[ 2 ][ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
|
||||
opus_int32 *state_QST[ 3 ];
|
||||
state_QST[ 0 ] = state_QS[ 0 ];
|
||||
state_QST[ 1 ] = state_QS[ 1 ];
|
||||
for( n = 0; n < length + order; n++, input_QS++ ) {
|
||||
state_QST[ 0 ][ orderT ] = input_QS[ orderT ];
|
||||
for( i = 0; i < orderT; i++ ) {
|
||||
corr_QC[ i ] += silk_RSHIFT64( silk_SMULL( state_QST[ 0 ][ i ], input_QS[ i ] ), 2 * QS - QC );
|
||||
state_QST[ 1 ][ i ] = silk_SMLAWB( state_QST[ 1 ][ i + 1 ], state_QST[ 0 ][ i ] - state_QST[ 0 ][ i + 1 ], warping_Q16 );
|
||||
}
|
||||
state_QST[ 2 ] = state_QST[ 0 ];
|
||||
state_QST[ 0 ] = state_QST[ 1 ];
|
||||
state_QST[ 1 ] = state_QST[ 2 ];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
{
|
||||
const int32x4_t warping_Q16_s32x4 = vdupq_n_s32( warping_Q16 << 15 );
|
||||
const opus_int32 *in = input_QS + orderT;
|
||||
opus_int o = orderT;
|
||||
int32x4_t state_QS_s32x4[ 3 ][ 2 ];
|
||||
|
||||
/* The additional +4 is to ensure a later vld1q_s32 call does not overflow. */
|
||||
ALLOC( state, length + order + 4, opus_int32 );
|
||||
state_QS_s32x4[ 2 ][ 1 ] = vdupq_n_s32( 0 );
|
||||
|
||||
/* Calculate 8 taps of all inputs in each loop. */
|
||||
do {
|
||||
state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 0 ][ 1 ] =
|
||||
state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 1 ][ 1 ] = vdupq_n_s32( 0 );
|
||||
n = 0;
|
||||
do {
|
||||
calc_corr( input_QS + n, corr_QC, o - 8, state_QS_s32x4[ 0 ][ 0 ] );
|
||||
calc_corr( input_QS + n, corr_QC, o - 4, state_QS_s32x4[ 0 ][ 1 ] );
|
||||
state_QS_s32x4[ 2 ][ 1 ] = vld1q_s32( in + n );
|
||||
vst1q_lane_s32( state + n, state_QS_s32x4[ 0 ][ 0 ], 0 );
|
||||
state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 0 ][ 1 ], 1 );
|
||||
state_QS_s32x4[ 2 ][ 1 ] = vextq_s32( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], 1 );
|
||||
state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 );
|
||||
state_QS_s32x4[ 0 ][ 1 ] = calc_state( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], state_QS_s32x4[ 1 ][ 1 ], warping_Q16_s32x4 );
|
||||
state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ];
|
||||
state_QS_s32x4[ 1 ][ 1 ] = state_QS_s32x4[ 2 ][ 1 ];
|
||||
} while( ++n < ( length + order ) );
|
||||
in = state;
|
||||
o -= 8;
|
||||
} while( o > 4 );
|
||||
|
||||
if( o ) {
|
||||
/* Calculate the last 4 taps of all inputs. */
|
||||
opus_int32 *stateT = state;
|
||||
silk_assert( o == 4 );
|
||||
state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 1 ][ 0 ] = vdupq_n_s32( 0 );
|
||||
n = length + order;
|
||||
do {
|
||||
calc_corr( input_QS, corr_QC, 0, state_QS_s32x4[ 0 ][ 0 ] );
|
||||
state_QS_s32x4[ 2 ][ 0 ] = vld1q_s32( stateT );
|
||||
vst1q_lane_s32( stateT, state_QS_s32x4[ 0 ][ 0 ], 0 );
|
||||
state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], 1 );
|
||||
state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 );
|
||||
state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ];
|
||||
input_QS++;
|
||||
stateT++;
|
||||
} while( --n );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const opus_int16 *inputT = input;
|
||||
int32x4_t t_s32x4;
|
||||
int64x1_t t_s64x1;
|
||||
int64x2_t t_s64x2 = vdupq_n_s64( 0 );
|
||||
for( n = 0; n <= length - 8; n += 8 ) {
|
||||
int16x8_t input_s16x8 = vld1q_s16( inputT );
|
||||
t_s32x4 = vmull_s16( vget_low_s16( input_s16x8 ), vget_low_s16( input_s16x8 ) );
|
||||
t_s32x4 = vmlal_s16( t_s32x4, vget_high_s16( input_s16x8 ), vget_high_s16( input_s16x8 ) );
|
||||
t_s64x2 = vaddw_s32( t_s64x2, vget_low_s32( t_s32x4 ) );
|
||||
t_s64x2 = vaddw_s32( t_s64x2, vget_high_s32( t_s32x4 ) );
|
||||
inputT += 8;
|
||||
}
|
||||
t_s64x1 = vadd_s64( vget_low_s64( t_s64x2 ), vget_high_s64( t_s64x2 ) );
|
||||
corr_QC_orderT = vget_lane_s64( t_s64x1, 0 );
|
||||
for( ; n < length; n++ ) {
|
||||
corr_QC_orderT += silk_SMULL( input[ n ], input[ n ] );
|
||||
}
|
||||
corr_QC_orderT = silk_LSHIFT64( corr_QC_orderT, QC );
|
||||
corr_QC[ orderT ] = corr_QC_orderT;
|
||||
}
|
||||
|
||||
corr_QCT = corr_QC + orderT - order;
|
||||
lsh = silk_CLZ64( corr_QC_orderT ) - 35;
|
||||
lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC );
|
||||
*scale = -( QC + lsh );
|
||||
silk_assert( *scale >= -30 && *scale <= 12 );
|
||||
lsh_s64x2 = vdupq_n_s64( lsh );
|
||||
for( i = 0; i <= order - 3; i += 4 ) {
|
||||
int32x4_t corr_s32x4;
|
||||
int64x2_t corr_QC0_s64x2, corr_QC1_s64x2;
|
||||
corr_QC0_s64x2 = vld1q_s64( corr_QCT + i );
|
||||
corr_QC1_s64x2 = vld1q_s64( corr_QCT + i + 2 );
|
||||
corr_QC0_s64x2 = vshlq_s64( corr_QC0_s64x2, lsh_s64x2 );
|
||||
corr_QC1_s64x2 = vshlq_s64( corr_QC1_s64x2, lsh_s64x2 );
|
||||
corr_s32x4 = vcombine_s32( vmovn_s64( corr_QC1_s64x2 ), vmovn_s64( corr_QC0_s64x2 ) );
|
||||
corr_s32x4 = vrev64q_s32( corr_s32x4 );
|
||||
vst1q_s32( corr + order - i - 3, corr_s32x4 );
|
||||
}
|
||||
if( lsh >= 0 ) {
|
||||
for( ; i < order + 1; i++ ) {
|
||||
corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QCT[ i ], lsh ) );
|
||||
}
|
||||
} else {
|
||||
for( ; i < order + 1; i++ ) {
|
||||
corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QCT[ i ], -lsh ) );
|
||||
}
|
||||
}
|
||||
silk_assert( corr_QCT[ order ] >= 0 ); /* If breaking, decrease QC*/
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
{
|
||||
opus_int32 corr_c[ MAX_SHAPE_LPC_ORDER + 1 ];
|
||||
opus_int scale_c;
|
||||
silk_warped_autocorrelation_FIX_c( corr_c, &scale_c, input, warping_Q16, length, order );
|
||||
silk_assert( !memcmp( corr_c, corr, sizeof( corr_c[ 0 ] ) * ( order + 1 ) ) );
|
||||
silk_assert( scale_c == *scale );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */
|
||||
|
||||
#define QA 25
|
||||
#define N_BITS_HEAD_ROOM 2
|
||||
#define N_BITS_HEAD_ROOM 3
|
||||
#define MIN_RSHIFTS -16
|
||||
#define MAX_RSHIFTS (32 - QA)
|
||||
|
||||
|
|
@ -65,10 +65,10 @@ void silk_burg_modified_c(
|
|||
opus_int32 xcorr[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int64 C0_64;
|
||||
|
||||
silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
|
||||
celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
|
||||
|
||||
/* Compute autocorrelations, added over subframes */
|
||||
C0_64 = silk_inner_prod16_aligned_64( x, x, subfr_length*nb_subfr, arch );
|
||||
C0_64 = silk_inner_prod16( x, x, subfr_length*nb_subfr, arch );
|
||||
lz = silk_CLZ64(C0_64);
|
||||
rshifts = 32 + 1 + N_BITS_HEAD_ROOM - lz;
|
||||
if (rshifts > MAX_RSHIFTS) rshifts = MAX_RSHIFTS;
|
||||
|
|
@ -87,7 +87,7 @@ void silk_burg_modified_c(
|
|||
x_ptr = x + s * subfr_length;
|
||||
for( n = 1; n < D + 1; n++ ) {
|
||||
C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64(
|
||||
silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts );
|
||||
silk_inner_prod16( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -150,7 +150,7 @@ void silk_burg_modified_c(
|
|||
C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */
|
||||
C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */
|
||||
Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */
|
||||
/* We sometimes have get overflows in the multiplications (even beyond +/- 2^32),
|
||||
/* We sometimes get overflows in the multiplications (even beyond +/- 2^32),
|
||||
but they cancel each other and the real result seems to always fit in a 32-bit
|
||||
signed integer. This was determined experimentally, not theoretically (unfortunately). */
|
||||
tmp1 = silk_MLA_ovflw( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */
|
||||
|
|
@ -253,7 +253,7 @@ void silk_burg_modified_c(
|
|||
if( rshifts > 0 ) {
|
||||
for( s = 0; s < nb_subfr; s++ ) {
|
||||
x_ptr = x + s * subfr_length;
|
||||
C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D, arch ), rshifts );
|
||||
C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16( x_ptr, x_ptr, D, arch ), rshifts );
|
||||
}
|
||||
} else {
|
||||
for( s = 0; s < nb_subfr; s++ ) {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ void silk_corrVector_FIX(
|
|||
for( lag = 0; lag < order; lag++ ) {
|
||||
inner_prod = 0;
|
||||
for( i = 0; i < L; i++ ) {
|
||||
inner_prod += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts );
|
||||
inner_prod = silk_ADD_RSHIFT32( inner_prod, silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts );
|
||||
}
|
||||
Xt[ lag ] = inner_prod; /* X[:,lag]'*t */
|
||||
ptr1--; /* Go to next column of X */
|
||||
|
|
@ -77,61 +77,54 @@ void silk_corrMatrix_FIX(
|
|||
const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */
|
||||
const opus_int L, /* I Length of vectors */
|
||||
const opus_int order, /* I Max lag for correlation */
|
||||
const opus_int head_room, /* I Desired headroom */
|
||||
opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */
|
||||
opus_int *rshifts, /* I/O Right shifts of correlations */
|
||||
opus_int32 *nrg, /* O Energy of x vector */
|
||||
opus_int *rshifts, /* O Right shifts of correlations and energy */
|
||||
int arch /* I Run-time architecture */
|
||||
)
|
||||
{
|
||||
opus_int i, j, lag, rshifts_local, head_room_rshifts;
|
||||
opus_int i, j, lag;
|
||||
opus_int32 energy;
|
||||
const opus_int16 *ptr1, *ptr2;
|
||||
|
||||
/* Calculate energy to find shift used to fit in 32 bits */
|
||||
silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 );
|
||||
/* Add shifts to get the desired head room */
|
||||
head_room_rshifts = silk_max( head_room - silk_CLZ32( energy ), 0 );
|
||||
|
||||
energy = silk_RSHIFT32( energy, head_room_rshifts );
|
||||
rshifts_local += head_room_rshifts;
|
||||
silk_sum_sqr_shift( nrg, rshifts, x, L + order - 1 );
|
||||
energy = *nrg;
|
||||
|
||||
/* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */
|
||||
/* Remove contribution of first order - 1 samples */
|
||||
for( i = 0; i < order - 1; i++ ) {
|
||||
energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), rshifts_local );
|
||||
}
|
||||
if( rshifts_local < *rshifts ) {
|
||||
/* Adjust energy */
|
||||
energy = silk_RSHIFT32( energy, *rshifts - rshifts_local );
|
||||
rshifts_local = *rshifts;
|
||||
energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), *rshifts );
|
||||
}
|
||||
|
||||
/* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */
|
||||
/* Fill out the diagonal of the correlation matrix */
|
||||
matrix_ptr( XX, 0, 0, order ) = energy;
|
||||
silk_assert( energy >= 0 );
|
||||
ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */
|
||||
for( j = 1; j < order; j++ ) {
|
||||
energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) );
|
||||
energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) );
|
||||
energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), *rshifts ) );
|
||||
energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), *rshifts ) );
|
||||
matrix_ptr( XX, j, j, order ) = energy;
|
||||
silk_assert( energy >= 0 );
|
||||
}
|
||||
|
||||
ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */
|
||||
/* Calculate the remaining elements of the correlation matrix */
|
||||
if( rshifts_local > 0 ) {
|
||||
if( *rshifts > 0 ) {
|
||||
/* Right shifting used */
|
||||
for( lag = 1; lag < order; lag++ ) {
|
||||
/* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */
|
||||
energy = 0;
|
||||
for( i = 0; i < L; i++ ) {
|
||||
energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local );
|
||||
energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), *rshifts );
|
||||
}
|
||||
/* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */
|
||||
matrix_ptr( XX, lag, 0, order ) = energy;
|
||||
matrix_ptr( XX, 0, lag, order ) = energy;
|
||||
for( j = 1; j < ( order - lag ); j++ ) {
|
||||
energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) );
|
||||
energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) );
|
||||
energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), *rshifts ) );
|
||||
energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), *rshifts ) );
|
||||
matrix_ptr( XX, lag + j, j, order ) = energy;
|
||||
matrix_ptr( XX, j, lag + j, order ) = energy;
|
||||
}
|
||||
|
|
@ -153,6 +146,5 @@ void silk_corrMatrix_FIX(
|
|||
ptr2--;/* Update pointer to first sample of next column (lag) in X */
|
||||
}
|
||||
}
|
||||
*rshifts = rshifts_local;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "main_FIX.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "tuning_parameters.h"
|
||||
|
|
@ -37,26 +38,33 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
static OPUS_INLINE void silk_LBRR_encode_FIX(
|
||||
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
|
||||
silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */
|
||||
const opus_int32 xfw_Q3[], /* I Input signal */
|
||||
const opus_int16 x16[], /* I Input signal */
|
||||
opus_int condCoding /* I The type of conditional coding used so far for this frame */
|
||||
);
|
||||
|
||||
void silk_encode_do_VAD_FIX(
|
||||
silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */
|
||||
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
|
||||
opus_int activity /* I Decision of Opus voice activity detector */
|
||||
)
|
||||
{
|
||||
const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
|
||||
|
||||
/****************************/
|
||||
/* Voice Activity Detection */
|
||||
/****************************/
|
||||
silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
|
||||
/* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
|
||||
if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
|
||||
psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* Convert speech activity into VAD and DTX flags */
|
||||
/**************************************************/
|
||||
if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) {
|
||||
if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
|
||||
psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
|
||||
psEnc->sCmn.noSpeechCounter++;
|
||||
if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) {
|
||||
if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
|
||||
psEnc->sCmn.inDTX = 0;
|
||||
} else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
|
||||
psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
|
||||
|
|
@ -94,6 +102,9 @@ opus_int silk_encode_frame_FIX(
|
|||
opus_int16 ec_prevLagIndex_copy;
|
||||
opus_int ec_prevSignalType_copy;
|
||||
opus_int8 LastGainIndex_copy2;
|
||||
opus_int gain_lock[ MAX_NB_SUBFR ] = {0};
|
||||
opus_int16 best_gain_mult[ MAX_NB_SUBFR ];
|
||||
opus_int best_sum[ MAX_NB_SUBFR ];
|
||||
SAVE_STACK;
|
||||
|
||||
/* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
|
||||
|
|
@ -118,7 +129,6 @@ opus_int silk_encode_frame_FIX(
|
|||
silk_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) );
|
||||
|
||||
if( !psEnc->sCmn.prefillFlag ) {
|
||||
VARDECL( opus_int32, xfw_Q3 );
|
||||
VARDECL( opus_int16, res_pitch );
|
||||
VARDECL( opus_uint8, ec_buf_copy );
|
||||
opus_int16 *res_pitch_frame;
|
||||
|
|
@ -132,7 +142,7 @@ opus_int silk_encode_frame_FIX(
|
|||
/*****************************************/
|
||||
/* Find pitch lags, initial LPC analysis */
|
||||
/*****************************************/
|
||||
silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch );
|
||||
silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame - psEnc->sCmn.ltp_mem_length, psEnc->sCmn.arch );
|
||||
|
||||
/************************/
|
||||
/* Noise shape analysis */
|
||||
|
|
@ -142,23 +152,17 @@ opus_int silk_encode_frame_FIX(
|
|||
/***************************************************/
|
||||
/* Find linear prediction coefficients (LPC + LTP) */
|
||||
/***************************************************/
|
||||
silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding );
|
||||
silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
|
||||
|
||||
/****************************************/
|
||||
/* Process gains */
|
||||
/****************************************/
|
||||
silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding );
|
||||
|
||||
/*****************************************/
|
||||
/* Prefiltering for noise shaper */
|
||||
/*****************************************/
|
||||
ALLOC( xfw_Q3, psEnc->sCmn.frame_length, opus_int32 );
|
||||
silk_prefilter_FIX( psEnc, &sEncCtrl, xfw_Q3, x_frame );
|
||||
|
||||
/****************************************/
|
||||
/* Low Bitrate Redundant Encoding */
|
||||
/****************************************/
|
||||
silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw_Q3, condCoding );
|
||||
silk_LBRR_encode_FIX( psEnc, &sEncCtrl, x_frame, condCoding );
|
||||
|
||||
/* Loop over quantizer and entropy coding to control bitrate */
|
||||
maxIter = 6;
|
||||
|
|
@ -194,17 +198,21 @@ opus_int silk_encode_frame_FIX(
|
|||
/* Noise shaping quantization */
|
||||
/*****************************************/
|
||||
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses,
|
||||
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
|
||||
silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
|
||||
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
|
||||
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
|
||||
psEnc->sCmn.arch );
|
||||
} else {
|
||||
silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses,
|
||||
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
|
||||
silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
|
||||
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
|
||||
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
|
||||
psEnc->sCmn.arch);
|
||||
}
|
||||
|
||||
if ( iter == maxIter && !found_lower ) {
|
||||
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
/* Encode Parameters */
|
||||
/****************************************/
|
||||
|
|
@ -218,6 +226,33 @@ opus_int silk_encode_frame_FIX(
|
|||
|
||||
nBits = ec_tell( psRangeEnc );
|
||||
|
||||
/* If we still bust after the last iteration, do some damage control. */
|
||||
if ( iter == maxIter && !found_lower && nBits > maxBits ) {
|
||||
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
|
||||
|
||||
/* Keep gains the same as the last frame. */
|
||||
psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
|
||||
for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
|
||||
psEnc->sCmn.indices.GainsIndices[ i ] = 4;
|
||||
}
|
||||
if (condCoding != CODE_CONDITIONALLY) {
|
||||
psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
|
||||
}
|
||||
psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
|
||||
psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
|
||||
/* Clear all pulses. */
|
||||
for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
|
||||
psEnc->sCmn.pulses[ i ] = 0;
|
||||
}
|
||||
|
||||
silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
|
||||
|
||||
silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
|
||||
psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
|
||||
|
||||
nBits = ec_tell( psRangeEnc );
|
||||
}
|
||||
|
||||
if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -227,7 +262,7 @@ opus_int silk_encode_frame_FIX(
|
|||
if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
|
||||
/* Restore output state from earlier iteration that did meet the bitrate budget */
|
||||
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
|
||||
silk_assert( sRangeEnc_copy2.offs <= 1275 );
|
||||
celt_assert( sRangeEnc_copy2.offs <= 1275 );
|
||||
silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
|
||||
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
|
||||
psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
|
||||
|
|
@ -255,7 +290,7 @@ opus_int silk_encode_frame_FIX(
|
|||
gainsID_lower = gainsID;
|
||||
/* Copy part of the output state */
|
||||
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
|
||||
silk_assert( psRangeEnc->offs <= 1275 );
|
||||
celt_assert( psRangeEnc->offs <= 1275 );
|
||||
silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
|
||||
silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
|
||||
LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
|
||||
|
|
@ -265,15 +300,35 @@ opus_int silk_encode_frame_FIX(
|
|||
break;
|
||||
}
|
||||
|
||||
if ( !found_lower && nBits > maxBits ) {
|
||||
int j;
|
||||
for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
|
||||
int sum=0;
|
||||
for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
|
||||
sum += abs( psEnc->sCmn.pulses[j] );
|
||||
}
|
||||
if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
|
||||
best_sum[i] = sum;
|
||||
best_gain_mult[i] = gainMult_Q8;
|
||||
} else {
|
||||
gain_lock[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( ( found_lower & found_upper ) == 0 ) {
|
||||
/* Adjust gain according to high-rate rate/distortion curve */
|
||||
opus_int32 gain_factor_Q16;
|
||||
gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
|
||||
gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) );
|
||||
if( nBits > maxBits ) {
|
||||
gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
|
||||
if (gainMult_Q8 < 16384) {
|
||||
gainMult_Q8 *= 2;
|
||||
} else {
|
||||
gainMult_Q8 = 32767;
|
||||
}
|
||||
} else {
|
||||
opus_int32 gain_factor_Q16;
|
||||
gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
|
||||
gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
|
||||
}
|
||||
gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
|
||||
|
||||
} else {
|
||||
/* Adjust gain by interpolating */
|
||||
gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower );
|
||||
|
|
@ -287,7 +342,13 @@ opus_int silk_encode_frame_FIX(
|
|||
}
|
||||
|
||||
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
|
||||
sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 );
|
||||
opus_int16 tmp;
|
||||
if ( gain_lock[i] ) {
|
||||
tmp = best_gain_mult[i];
|
||||
} else {
|
||||
tmp = gainMult_Q8;
|
||||
}
|
||||
sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
|
||||
}
|
||||
|
||||
/* Quantize gains */
|
||||
|
|
@ -331,7 +392,7 @@ opus_int silk_encode_frame_FIX(
|
|||
static OPUS_INLINE void silk_LBRR_encode_FIX(
|
||||
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
|
||||
silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */
|
||||
const opus_int32 xfw_Q3[], /* I Input signal */
|
||||
const opus_int16 x16[], /* I Input signal */
|
||||
opus_int condCoding /* I The type of conditional coding used so far for this frame */
|
||||
)
|
||||
{
|
||||
|
|
@ -370,14 +431,14 @@ static OPUS_INLINE void silk_LBRR_encode_FIX(
|
|||
/* Noise shaping quantization */
|
||||
/*****************************************/
|
||||
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3,
|
||||
silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
|
||||
psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
|
||||
psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
|
||||
psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
|
||||
psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
|
||||
} else {
|
||||
silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3,
|
||||
silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
|
||||
psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
|
||||
psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
|
||||
psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
|
||||
psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ void silk_find_LPC_FIX(
|
|||
silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
|
||||
|
||||
/* Convert to LPC for residual energy evaluation */
|
||||
silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder );
|
||||
silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
|
||||
|
||||
/* Calculate residual energy with NLSF interpolation */
|
||||
silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder, psEncC->arch );
|
||||
|
|
@ -146,6 +146,6 @@ void silk_find_LPC_FIX(
|
|||
silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder );
|
||||
}
|
||||
|
||||
silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
|
||||
celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,214 +32,68 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "main_FIX.h"
|
||||
#include "tuning_parameters.h"
|
||||
|
||||
/* Head room for correlations */
|
||||
#define LTP_CORRS_HEAD_ROOM 2
|
||||
|
||||
void silk_fit_LTP(
|
||||
opus_int32 LTP_coefs_Q16[ LTP_ORDER ],
|
||||
opus_int16 LTP_coefs_Q14[ LTP_ORDER ]
|
||||
);
|
||||
|
||||
void silk_find_LTP_FIX(
|
||||
opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
|
||||
opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
|
||||
opus_int *LTPredCodGain_Q7, /* O LTP coding gain */
|
||||
const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */
|
||||
opus_int32 XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Correlation matrix */
|
||||
opus_int32 xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ], /* O Correlation vector */
|
||||
const opus_int16 r_ptr[], /* I Residual signal after LPC */
|
||||
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
|
||||
const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */
|
||||
const opus_int subfr_length, /* I subframe length */
|
||||
const opus_int nb_subfr, /* I number of subframes */
|
||||
const opus_int mem_offset, /* I number of samples in LTP memory */
|
||||
opus_int corr_rshifts[ MAX_NB_SUBFR ], /* O right shifts applied to correlations */
|
||||
const opus_int subfr_length, /* I Subframe length */
|
||||
const opus_int nb_subfr, /* I Number of subframes */
|
||||
int arch /* I Run-time architecture */
|
||||
)
|
||||
{
|
||||
opus_int i, k, lshift;
|
||||
const opus_int16 *r_ptr, *lag_ptr;
|
||||
opus_int16 *b_Q14_ptr;
|
||||
opus_int i, k, extra_shifts;
|
||||
opus_int xx_shifts, xX_shifts, XX_shifts;
|
||||
const opus_int16 *lag_ptr;
|
||||
opus_int32 *XXLTP_Q17_ptr, *xXLTP_Q17_ptr;
|
||||
opus_int32 xx, nrg, temp;
|
||||
|
||||
opus_int32 regu;
|
||||
opus_int32 *WLTP_ptr;
|
||||
opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26;
|
||||
opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits;
|
||||
|
||||
opus_int32 temp32, denom32;
|
||||
opus_int extra_shifts;
|
||||
opus_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs;
|
||||
opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16;
|
||||
opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ];
|
||||
opus_int32 wd, m_Q12;
|
||||
|
||||
b_Q14_ptr = b_Q14;
|
||||
WLTP_ptr = WLTP;
|
||||
r_ptr = &r_lpc[ mem_offset ];
|
||||
xXLTP_Q17_ptr = xXLTP_Q17;
|
||||
XXLTP_Q17_ptr = XXLTP_Q17;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
|
||||
|
||||
silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */
|
||||
|
||||
/* Assure headroom */
|
||||
LZs = silk_CLZ32( rr[k] );
|
||||
if( LZs < LTP_CORRS_HEAD_ROOM ) {
|
||||
rr[ k ] = silk_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs );
|
||||
rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs );
|
||||
}
|
||||
corr_rshifts[ k ] = rr_shifts;
|
||||
silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ], arch ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */
|
||||
|
||||
/* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */
|
||||
silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ], arch ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */
|
||||
if( corr_rshifts[ k ] > rr_shifts ) {
|
||||
rr[ k ] = silk_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */
|
||||
}
|
||||
silk_assert( rr[ k ] >= 0 );
|
||||
|
||||
regu = 1;
|
||||
regu = silk_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
|
||||
regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
|
||||
regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
|
||||
silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER );
|
||||
|
||||
silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */
|
||||
|
||||
/* Limit and store in Q14 */
|
||||
silk_fit_LTP( b_Q16, b_Q14_ptr );
|
||||
|
||||
/* Calculate residual energy */
|
||||
nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */
|
||||
|
||||
/* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */
|
||||
extra_shifts = silk_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM );
|
||||
denom32 = silk_LSHIFT_SAT32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */
|
||||
silk_RSHIFT( silk_SMULWB( (opus_int32)subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */
|
||||
denom32 = silk_max( denom32, 1 );
|
||||
silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX ); /* Wght always < 0.5 in Q0 */
|
||||
temp32 = silk_DIV32( silk_LSHIFT( (opus_int32)Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */
|
||||
temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */
|
||||
|
||||
/* Limit temp such that the below scaling never wraps around */
|
||||
WLTP_max = 0;
|
||||
for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
|
||||
WLTP_max = silk_max( WLTP_ptr[ i ], WLTP_max );
|
||||
}
|
||||
lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */
|
||||
silk_assert( 26 - 18 + lshift >= 0 );
|
||||
if( 26 - 18 + lshift < 31 ) {
|
||||
temp32 = silk_min_32( temp32, silk_LSHIFT( (opus_int32)1, 26 - 18 + lshift ) );
|
||||
}
|
||||
|
||||
silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */
|
||||
|
||||
w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */
|
||||
silk_assert( w[k] >= 0 );
|
||||
|
||||
r_ptr += subfr_length;
|
||||
b_Q14_ptr += LTP_ORDER;
|
||||
WLTP_ptr += LTP_ORDER * LTP_ORDER;
|
||||
}
|
||||
|
||||
maxRshifts = 0;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
maxRshifts = silk_max_int( corr_rshifts[ k ], maxRshifts );
|
||||
}
|
||||
|
||||
/* Compute LTP coding gain */
|
||||
if( LTPredCodGain_Q7 != NULL ) {
|
||||
LPC_LTP_res_nrg = 0;
|
||||
LPC_res_nrg = 0;
|
||||
silk_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
LPC_res_nrg = silk_ADD32( LPC_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */
|
||||
LPC_LTP_res_nrg = silk_ADD32( LPC_LTP_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */
|
||||
}
|
||||
LPC_LTP_res_nrg = silk_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */
|
||||
|
||||
div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 );
|
||||
*LTPredCodGain_Q7 = ( opus_int )silk_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) );
|
||||
|
||||
silk_assert( *LTPredCodGain_Q7 == ( opus_int )silk_SAT16( silk_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) );
|
||||
}
|
||||
|
||||
/* smoothing */
|
||||
/* d = sum( B, 1 ); */
|
||||
b_Q14_ptr = b_Q14;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
d_Q14[ k ] = 0;
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
d_Q14[ k ] += b_Q14_ptr[ i ];
|
||||
}
|
||||
b_Q14_ptr += LTP_ORDER;
|
||||
}
|
||||
|
||||
/* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */
|
||||
|
||||
/* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */
|
||||
max_abs_d_Q14 = 0;
|
||||
max_w_bits = 0;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
max_abs_d_Q14 = silk_max_32( max_abs_d_Q14, silk_abs( d_Q14[ k ] ) );
|
||||
/* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */
|
||||
/* Find bits needed in Q( 18 - maxRshifts ) */
|
||||
max_w_bits = silk_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts );
|
||||
}
|
||||
|
||||
/* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -silk_int16_MIN */
|
||||
silk_assert( max_abs_d_Q14 <= ( 5 << 15 ) );
|
||||
|
||||
/* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */
|
||||
extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14;
|
||||
|
||||
/* Subtract what we got available; bits in output var plus maxRshifts */
|
||||
extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */
|
||||
extra_shifts = silk_max_int( extra_shifts, 0 );
|
||||
|
||||
maxRshifts_wxtra = maxRshifts + extra_shifts;
|
||||
|
||||
temp32 = silk_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */
|
||||
wd = 0;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
/* w has at least 2 bits of headroom so no overflow should happen */
|
||||
temp32 = silk_ADD32( temp32, silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */
|
||||
wd = silk_ADD32( wd, silk_LSHIFT( silk_SMULWW( silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */
|
||||
}
|
||||
m_Q12 = silk_DIV32_varQ( wd, temp32, 12 );
|
||||
|
||||
b_Q14_ptr = b_Q14;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
/* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */
|
||||
if( 2 - corr_rshifts[k] > 0 ) {
|
||||
temp32 = silk_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] );
|
||||
silk_sum_sqr_shift( &xx, &xx_shifts, r_ptr, subfr_length + LTP_ORDER ); /* xx in Q( -xx_shifts ) */
|
||||
silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, XXLTP_Q17_ptr, &nrg, &XX_shifts, arch ); /* XXLTP_Q17_ptr and nrg in Q( -XX_shifts ) */
|
||||
extra_shifts = xx_shifts - XX_shifts;
|
||||
if( extra_shifts > 0 ) {
|
||||
/* Shift XX */
|
||||
xX_shifts = xx_shifts;
|
||||
for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
|
||||
XXLTP_Q17_ptr[ i ] = silk_RSHIFT32( XXLTP_Q17_ptr[ i ], extra_shifts ); /* Q( -xX_shifts ) */
|
||||
}
|
||||
nrg = silk_RSHIFT32( nrg, extra_shifts ); /* Q( -xX_shifts ) */
|
||||
} else if( extra_shifts < 0 ) {
|
||||
/* Shift xx */
|
||||
xX_shifts = XX_shifts;
|
||||
xx = silk_RSHIFT32( xx, -extra_shifts ); /* Q( -xX_shifts ) */
|
||||
} else {
|
||||
temp32 = silk_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 );
|
||||
xX_shifts = xx_shifts;
|
||||
}
|
||||
silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xXLTP_Q17_ptr, xX_shifts, arch ); /* xXLTP_Q17_ptr in Q( -xX_shifts ) */
|
||||
|
||||
g_Q26 = silk_MUL(
|
||||
silk_DIV32(
|
||||
SILK_FIX_CONST( LTP_SMOOTHING, 26 ),
|
||||
silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */
|
||||
silk_LSHIFT_SAT32( silk_SUB_SAT32( (opus_int32)m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */
|
||||
|
||||
temp32 = 0;
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */
|
||||
temp32 += delta_b_Q14[ i ]; /* Q14 */
|
||||
/* At this point all correlations are in Q(-xX_shifts) */
|
||||
temp = silk_SMLAWB( 1, nrg, SILK_FIX_CONST( LTP_CORR_INV_MAX, 16 ) );
|
||||
temp = silk_max( temp, xx );
|
||||
TIC(div)
|
||||
#if 0
|
||||
for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
|
||||
XXLTP_Q17_ptr[ i ] = silk_DIV32_varQ( XXLTP_Q17_ptr[ i ], temp, 17 );
|
||||
}
|
||||
temp32 = silk_DIV32( g_Q26, temp32 ); /* Q14 -> Q12 */
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
b_Q14_ptr[ i ] = silk_LIMIT_32( (opus_int32)b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 );
|
||||
xXLTP_Q17_ptr[ i ] = silk_DIV32_varQ( xXLTP_Q17_ptr[ i ], temp, 17 );
|
||||
}
|
||||
b_Q14_ptr += LTP_ORDER;
|
||||
}
|
||||
}
|
||||
|
||||
void silk_fit_LTP(
|
||||
opus_int32 LTP_coefs_Q16[ LTP_ORDER ],
|
||||
opus_int16 LTP_coefs_Q14[ LTP_ORDER ]
|
||||
)
|
||||
{
|
||||
opus_int i;
|
||||
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
LTP_coefs_Q14[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) );
|
||||
#else
|
||||
for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
|
||||
XXLTP_Q17_ptr[ i ] = (opus_int32)( silk_LSHIFT64( (opus_int64)XXLTP_Q17_ptr[ i ], 17 ) / temp );
|
||||
}
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
xXLTP_Q17_ptr[ i ] = (opus_int32)( silk_LSHIFT64( (opus_int64)xXLTP_Q17_ptr[ i ], 17 ) / temp );
|
||||
}
|
||||
#endif
|
||||
TOC(div)
|
||||
r_ptr += subfr_length;
|
||||
XXLTP_Q17_ptr += LTP_ORDER * LTP_ORDER;
|
||||
xXLTP_Q17_ptr += LTP_ORDER;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ void silk_find_pitch_lags_FIX(
|
|||
{
|
||||
opus_int buf_len, i, scale;
|
||||
opus_int32 thrhld_Q13, res_nrg;
|
||||
const opus_int16 *x_buf, *x_buf_ptr;
|
||||
const opus_int16 *x_ptr;
|
||||
VARDECL( opus_int16, Wsig );
|
||||
opus_int16 *Wsig_ptr;
|
||||
opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ];
|
||||
|
|
@ -59,9 +59,7 @@ void silk_find_pitch_lags_FIX(
|
|||
buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
|
||||
|
||||
/* Safety check */
|
||||
silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
|
||||
|
||||
x_buf = x - psEnc->sCmn.ltp_mem_length;
|
||||
celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
|
||||
|
||||
/*************************************/
|
||||
/* Estimate LPC AR coefficients */
|
||||
|
|
@ -72,19 +70,19 @@ void silk_find_pitch_lags_FIX(
|
|||
ALLOC( Wsig, psEnc->sCmn.pitch_LPC_win_length, opus_int16 );
|
||||
|
||||
/* First LA_LTP samples */
|
||||
x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length;
|
||||
x_ptr = x + buf_len - psEnc->sCmn.pitch_LPC_win_length;
|
||||
Wsig_ptr = Wsig;
|
||||
silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch );
|
||||
silk_apply_sine_window( Wsig_ptr, x_ptr, 1, psEnc->sCmn.la_pitch );
|
||||
|
||||
/* Middle un - windowed samples */
|
||||
Wsig_ptr += psEnc->sCmn.la_pitch;
|
||||
x_buf_ptr += psEnc->sCmn.la_pitch;
|
||||
silk_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) );
|
||||
x_ptr += psEnc->sCmn.la_pitch;
|
||||
silk_memcpy( Wsig_ptr, x_ptr, ( psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) );
|
||||
|
||||
/* Last LA_LTP samples */
|
||||
Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
|
||||
x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
|
||||
silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch );
|
||||
x_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
|
||||
silk_apply_sine_window( Wsig_ptr, x_ptr, 2, psEnc->sCmn.la_pitch );
|
||||
|
||||
/* Calculate autocorrelation sequence */
|
||||
silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1, arch );
|
||||
|
|
@ -112,7 +110,7 @@ void silk_find_pitch_lags_FIX(
|
|||
/*****************************************/
|
||||
/* LPC analysis filtering */
|
||||
/*****************************************/
|
||||
silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch );
|
||||
silk_LPC_analysis_filter( res, x, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch );
|
||||
|
||||
if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) {
|
||||
/* Threshold for pitch estimator */
|
||||
|
|
|
|||
|
|
@ -41,13 +41,12 @@ void silk_find_pred_coefs_FIX(
|
|||
)
|
||||
{
|
||||
opus_int i;
|
||||
opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ];
|
||||
opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ];
|
||||
opus_int16 NLSF_Q15[ MAX_LPC_ORDER ];
|
||||
const opus_int16 *x_ptr;
|
||||
opus_int16 *x_pre_ptr;
|
||||
VARDECL( opus_int16, LPC_in_pre );
|
||||
opus_int32 tmp, min_gain_Q16, minInvGain_Q30;
|
||||
opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ];
|
||||
opus_int32 min_gain_Q16, minInvGain_Q30;
|
||||
SAVE_STACK;
|
||||
|
||||
/* weighting for weighted least squares */
|
||||
|
|
@ -61,13 +60,11 @@ void silk_find_pred_coefs_FIX(
|
|||
/* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */
|
||||
invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 );
|
||||
|
||||
/* Ensure Wght_Q15 a minimum value 1 */
|
||||
invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 363 );
|
||||
/* Limit inverse */
|
||||
invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 100 );
|
||||
|
||||
/* Square the inverted gains */
|
||||
silk_assert( invGains_Q16[ i ] == silk_SAT16( invGains_Q16[ i ] ) );
|
||||
tmp = silk_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] );
|
||||
Wght_Q15[ i ] = silk_RSHIFT( tmp, 1 );
|
||||
|
||||
/* Invert the inverted and normalized gains */
|
||||
local_gains[ i ] = silk_DIV32( ( (opus_int32)1 << 16 ), invGains_Q16[ i ] );
|
||||
|
|
@ -77,24 +74,24 @@ void silk_find_pred_coefs_FIX(
|
|||
psEnc->sCmn.nb_subfr * psEnc->sCmn.predictLPCOrder
|
||||
+ psEnc->sCmn.frame_length, opus_int16 );
|
||||
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
|
||||
VARDECL( opus_int32, WLTP );
|
||||
VARDECL( opus_int32, xXLTP_Q17 );
|
||||
VARDECL( opus_int32, XXLTP_Q17 );
|
||||
|
||||
/**********/
|
||||
/* VOICED */
|
||||
/**********/
|
||||
silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
|
||||
celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
|
||||
|
||||
ALLOC( WLTP, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 );
|
||||
ALLOC( xXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER, opus_int32 );
|
||||
ALLOC( XXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 );
|
||||
|
||||
/* LTP analysis */
|
||||
silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7,
|
||||
res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length,
|
||||
psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift, psEnc->sCmn.arch );
|
||||
silk_find_LTP_FIX( XXLTP_Q17, xXLTP_Q17, res_pitch,
|
||||
psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
|
||||
|
||||
/* Quantize LTP gain parameters */
|
||||
silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
|
||||
&psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr,
|
||||
psEnc->sCmn.arch);
|
||||
&psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain_Q7, XXLTP_Q17, xXLTP_Q17, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
|
||||
|
||||
/* Control LTP scaling */
|
||||
silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl, condCoding );
|
||||
|
|
|
|||
|
|
@ -39,14 +39,15 @@ void silk_k2a(
|
|||
)
|
||||
{
|
||||
opus_int k, n;
|
||||
opus_int32 Atmp[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 rc, tmp1, tmp2;
|
||||
|
||||
for( k = 0; k < order; k++ ) {
|
||||
for( n = 0; n < k; n++ ) {
|
||||
Atmp[ n ] = A_Q24[ n ];
|
||||
}
|
||||
for( n = 0; n < k; n++ ) {
|
||||
A_Q24[ n ] = silk_SMLAWB( A_Q24[ n ], silk_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] );
|
||||
rc = rc_Q15[ k ];
|
||||
for( n = 0; n < (k + 1) >> 1; n++ ) {
|
||||
tmp1 = A_Q24[ n ];
|
||||
tmp2 = A_Q24[ k - n - 1 ];
|
||||
A_Q24[ n ] = silk_SMLAWB( tmp1, silk_LSHIFT( tmp2, 1 ), rc );
|
||||
A_Q24[ k - n - 1 ] = silk_SMLAWB( tmp2, silk_LSHIFT( tmp1, 1 ), rc );
|
||||
}
|
||||
A_Q24[ k ] = -silk_LSHIFT( (opus_int32)rc_Q15[ k ], 9 );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,15 +39,16 @@ void silk_k2a_Q16(
|
|||
)
|
||||
{
|
||||
opus_int k, n;
|
||||
opus_int32 Atmp[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 rc, tmp1, tmp2;
|
||||
|
||||
for( k = 0; k < order; k++ ) {
|
||||
for( n = 0; n < k; n++ ) {
|
||||
Atmp[ n ] = A_Q24[ n ];
|
||||
rc = rc_Q16[ k ];
|
||||
for( n = 0; n < (k + 1) >> 1; n++ ) {
|
||||
tmp1 = A_Q24[ n ];
|
||||
tmp2 = A_Q24[ k - n - 1 ];
|
||||
A_Q24[ n ] = silk_SMLAWW( tmp1, tmp2, rc );
|
||||
A_Q24[ k - n - 1 ] = silk_SMLAWW( tmp2, tmp1, rc );
|
||||
}
|
||||
for( n = 0; n < k; n++ ) {
|
||||
A_Q24[ n ] = silk_SMLAWW( A_Q24[ n ], Atmp[ k - n - 1 ], rc_Q16[ k ] );
|
||||
}
|
||||
A_Q24[ k ] = -silk_LSHIFT( rc_Q16[ k ], 8 );
|
||||
A_Q24[ k ] = -silk_LSHIFT( rc, 8 );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "debug.h"
|
||||
#include "entenc.h"
|
||||
|
||||
#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \
|
||||
|| defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
|
||||
#include "fixed/arm/warped_autocorrelation_FIX_arm.h"
|
||||
#endif
|
||||
|
||||
#ifndef FORCE_CPP_BUILD
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
|
@ -47,6 +52,9 @@ extern "C"
|
|||
#define silk_encode_do_VAD_Fxx silk_encode_do_VAD_FIX
|
||||
#define silk_encode_frame_Fxx silk_encode_frame_FIX
|
||||
|
||||
#define QC 10
|
||||
#define QS 13
|
||||
|
||||
/*********************/
|
||||
/* Encoder Functions */
|
||||
/*********************/
|
||||
|
|
@ -58,7 +66,8 @@ void silk_HP_variable_cutoff(
|
|||
|
||||
/* Encoder main function */
|
||||
void silk_encode_do_VAD_FIX(
|
||||
silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */
|
||||
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
|
||||
opus_int activity /* I Decision of Opus voice activity detector */
|
||||
);
|
||||
|
||||
/* Encoder main function */
|
||||
|
|
@ -81,33 +90,11 @@ opus_int silk_init_encoder(
|
|||
opus_int silk_control_encoder(
|
||||
silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */
|
||||
silk_EncControlStruct *encControl, /* I Control structure */
|
||||
const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
|
||||
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
|
||||
const opus_int channelNb, /* I Channel number */
|
||||
const opus_int force_fs_kHz
|
||||
);
|
||||
|
||||
/****************/
|
||||
/* Prefiltering */
|
||||
/****************/
|
||||
void silk_prefilter_FIX(
|
||||
silk_encoder_state_FIX *psEnc, /* I/O Encoder state */
|
||||
const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */
|
||||
opus_int32 xw_Q10[], /* O Weighted signal */
|
||||
const opus_int16 x[] /* I Speech signal */
|
||||
);
|
||||
|
||||
void silk_warped_LPC_analysis_filter_FIX_c(
|
||||
opus_int32 state[], /* I/O State [order + 1] */
|
||||
opus_int32 res_Q2[], /* O Residual signal [length] */
|
||||
const opus_int16 coef_Q13[], /* I Coefficients [order] */
|
||||
const opus_int16 input[], /* I Input signal [length] */
|
||||
const opus_int16 lambda_Q16, /* I Warping factor */
|
||||
const opus_int length, /* I Length of input signal */
|
||||
const opus_int order /* I Filter order (even) */
|
||||
);
|
||||
|
||||
|
||||
/**************************/
|
||||
/* Noise shaping analysis */
|
||||
/**************************/
|
||||
|
|
@ -121,7 +108,7 @@ void silk_noise_shape_analysis_FIX(
|
|||
);
|
||||
|
||||
/* Autocorrelations for a warped frequency axis */
|
||||
void silk_warped_autocorrelation_FIX(
|
||||
void silk_warped_autocorrelation_FIX_c(
|
||||
opus_int32 *corr, /* O Result [order + 1] */
|
||||
opus_int *scale, /* O Scaling of the correlation vector */
|
||||
const opus_int16 *input, /* I Input data to correlate */
|
||||
|
|
@ -130,6 +117,11 @@ void silk_warped_autocorrelation_FIX(
|
|||
const opus_int order /* I Correlation order (even) */
|
||||
);
|
||||
|
||||
#if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
|
||||
#define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
|
||||
((void)(arch), silk_warped_autocorrelation_FIX_c(corr, scale, input, warping_Q16, length, order))
|
||||
#endif
|
||||
|
||||
/* Calculation of LTP state scaling */
|
||||
void silk_LTP_scale_ctrl_FIX(
|
||||
silk_encoder_state_FIX *psEnc, /* I/O encoder state */
|
||||
|
|
@ -168,16 +160,12 @@ void silk_find_LPC_FIX(
|
|||
|
||||
/* LTP analysis */
|
||||
void silk_find_LTP_FIX(
|
||||
opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
|
||||
opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
|
||||
opus_int *LTPredCodGain_Q7, /* O LTP coding gain */
|
||||
const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */
|
||||
opus_int32 XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Correlation matrix */
|
||||
opus_int32 xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ], /* O Correlation vector */
|
||||
const opus_int16 r_lpc[], /* I Residual signal after LPC */
|
||||
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
|
||||
const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */
|
||||
const opus_int subfr_length, /* I subframe length */
|
||||
const opus_int nb_subfr, /* I number of subframes */
|
||||
const opus_int mem_offset, /* I number of samples in LTP memory */
|
||||
opus_int corr_rshifts[ MAX_NB_SUBFR ], /* O right shifts applied to correlations */
|
||||
const opus_int subfr_length, /* I Subframe length */
|
||||
const opus_int nb_subfr, /* I Number of subframes */
|
||||
int arch /* I Run-time architecture */
|
||||
);
|
||||
|
||||
|
|
@ -231,9 +219,9 @@ void silk_corrMatrix_FIX(
|
|||
const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */
|
||||
const opus_int L, /* I Length of vectors */
|
||||
const opus_int order, /* I Max lag for correlation */
|
||||
const opus_int head_room, /* I Desired headroom */
|
||||
opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */
|
||||
opus_int *rshifts, /* I/O Right shifts of correlations */
|
||||
opus_int32 *nrg, /* O Energy of x vector */
|
||||
opus_int *rshifts, /* O Right shifts of correlations */
|
||||
int arch /* I Run-time architecture */
|
||||
);
|
||||
|
||||
|
|
@ -248,22 +236,6 @@ void silk_corrVector_FIX(
|
|||
int arch /* I Run-time architecture */
|
||||
);
|
||||
|
||||
/* Add noise to matrix diagonal */
|
||||
void silk_regularize_correlations_FIX(
|
||||
opus_int32 *XX, /* I/O Correlation matrices */
|
||||
opus_int32 *xx, /* I/O Correlation values */
|
||||
opus_int32 noise, /* I Noise to add */
|
||||
opus_int D /* I Dimension of XX */
|
||||
);
|
||||
|
||||
/* Solves Ax = b, assuming A is symmetric */
|
||||
void silk_solve_LDL_FIX(
|
||||
opus_int32 *A, /* I Pointer to symetric square matrix A */
|
||||
opus_int M, /* I Size of matrix */
|
||||
const opus_int32 *b, /* I Pointer to b vector */
|
||||
opus_int32 *x_Q16 /* O Pointer to x solution vector */
|
||||
);
|
||||
|
||||
#ifndef FORCE_CPP_BUILD
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ void silk_noise_shape_analysis_FIX(
|
|||
|
||||
if( psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
/* Calculate warped auto correlation */
|
||||
silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
|
||||
silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder, arch );
|
||||
} else {
|
||||
/* Calculate regular auto correlation */
|
||||
silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch );
|
||||
|
|
@ -224,8 +224,8 @@ void silk_noise_shape_analysis_FIX(
|
|||
silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
|
||||
|
||||
/* Ratio of prediction gains, in energy domain */
|
||||
pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
|
||||
nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
|
||||
pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder, arch );
|
||||
nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder, arch );
|
||||
|
||||
/*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
|
||||
pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
|
||||
|
|
|
|||
|
|
@ -1,184 +0,0 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
#ifndef __PREFILTER_FIX_MIPSR1_H__
|
||||
#define __PREFILTER_FIX_MIPSR1_H__
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main_FIX.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "tuning_parameters.h"
|
||||
|
||||
#define OVERRIDE_silk_warped_LPC_analysis_filter_FIX
|
||||
void silk_warped_LPC_analysis_filter_FIX(
|
||||
opus_int32 state[], /* I/O State [order + 1] */
|
||||
opus_int32 res_Q2[], /* O Residual signal [length] */
|
||||
const opus_int16 coef_Q13[], /* I Coefficients [order] */
|
||||
const opus_int16 input[], /* I Input signal [length] */
|
||||
const opus_int16 lambda_Q16, /* I Warping factor */
|
||||
const opus_int length, /* I Length of input signal */
|
||||
const opus_int order, /* I Filter order (even) */
|
||||
int arch
|
||||
)
|
||||
{
|
||||
opus_int n, i;
|
||||
opus_int32 acc_Q11, acc_Q22, tmp1, tmp2, tmp3, tmp4;
|
||||
opus_int32 state_cur, state_next;
|
||||
|
||||
(void)arch;
|
||||
|
||||
/* Order must be even */
|
||||
/* Length must be even */
|
||||
|
||||
silk_assert( ( order & 1 ) == 0 );
|
||||
silk_assert( ( length & 1 ) == 0 );
|
||||
|
||||
for( n = 0; n < length; n+=2 ) {
|
||||
/* Output of lowpass section */
|
||||
tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
|
||||
state_cur = silk_LSHIFT( input[ n ], 14 );
|
||||
/* Output of allpass section */
|
||||
tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
|
||||
state_next = tmp2;
|
||||
acc_Q11 = silk_RSHIFT( order, 1 );
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
|
||||
|
||||
|
||||
/* Output of lowpass section */
|
||||
tmp4 = silk_SMLAWB( state_cur, state_next, lambda_Q16 );
|
||||
state[ 0 ] = silk_LSHIFT( input[ n+1 ], 14 );
|
||||
/* Output of allpass section */
|
||||
tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 );
|
||||
state[ 1 ] = tmp4;
|
||||
acc_Q22 = silk_RSHIFT( order, 1 );
|
||||
acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ 0 ] );
|
||||
|
||||
/* Loop over allpass sections */
|
||||
for( i = 2; i < order; i += 2 ) {
|
||||
/* Output of allpass section */
|
||||
tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
|
||||
state_cur = tmp1;
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
|
||||
/* Output of allpass section */
|
||||
tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
|
||||
state_next = tmp2;
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
|
||||
|
||||
|
||||
/* Output of allpass section */
|
||||
tmp4 = silk_SMLAWB( state_cur, state_next - tmp3, lambda_Q16 );
|
||||
state[ i ] = tmp3;
|
||||
acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ i - 1 ] );
|
||||
/* Output of allpass section */
|
||||
tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 );
|
||||
state[ i + 1 ] = tmp4;
|
||||
acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ i ] );
|
||||
}
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
|
||||
res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
|
||||
|
||||
state[ order ] = tmp3;
|
||||
acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ order - 1 ] );
|
||||
res_Q2[ n+1 ] = silk_LSHIFT( (opus_int32)input[ n+1 ], 2 ) - silk_RSHIFT_ROUND( acc_Q22, 9 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Prefilter for finding Quantizer input signal */
|
||||
#define OVERRIDE_silk_prefilt_FIX
|
||||
static inline void silk_prefilt_FIX(
|
||||
silk_prefilter_state_FIX *P, /* I/O state */
|
||||
opus_int32 st_res_Q12[], /* I short term residual signal */
|
||||
opus_int32 xw_Q3[], /* O prefiltered signal */
|
||||
opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
|
||||
opus_int Tilt_Q14, /* I Tilt shaping coeficient */
|
||||
opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
|
||||
opus_int lag, /* I Lag for harmonic shaping */
|
||||
opus_int length /* I Length of signals */
|
||||
)
|
||||
{
|
||||
opus_int i, idx, LTP_shp_buf_idx;
|
||||
opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10;
|
||||
opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12;
|
||||
opus_int16 *LTP_shp_buf;
|
||||
|
||||
/* To speed up use temp variables instead of using the struct */
|
||||
LTP_shp_buf = P->sLTP_shp;
|
||||
LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
|
||||
sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12;
|
||||
sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12;
|
||||
|
||||
if( lag > 0 ) {
|
||||
for( i = 0; i < length; i++ ) {
|
||||
/* unrolled loop */
|
||||
silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
|
||||
idx = lag + LTP_shp_buf_idx;
|
||||
n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
|
||||
n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
|
||||
n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
|
||||
|
||||
n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
|
||||
n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
|
||||
|
||||
sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
|
||||
sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) );
|
||||
|
||||
LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
|
||||
LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
|
||||
|
||||
xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < length; i++ ) {
|
||||
|
||||
n_LTP_Q12 = 0;
|
||||
|
||||
n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
|
||||
n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
|
||||
|
||||
sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
|
||||
sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) );
|
||||
|
||||
LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
|
||||
LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
|
||||
|
||||
xw_Q3[i] = silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 9 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy temp variable back to state */
|
||||
P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12;
|
||||
P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12;
|
||||
P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
|
||||
}
|
||||
|
||||
#endif /* __PREFILTER_FIX_MIPSR1_H__ */
|
||||
|
|
@ -41,8 +41,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define QS 14
|
||||
|
||||
/* Autocorrelations for a warped frequency axis */
|
||||
#define OVERRIDE_silk_warped_autocorrelation_FIX
|
||||
void silk_warped_autocorrelation_FIX(
|
||||
#define OVERRIDE_silk_warped_autocorrelation_FIX_c
|
||||
void silk_warped_autocorrelation_FIX_c(
|
||||
opus_int32 *corr, /* O Result [order + 1] */
|
||||
opus_int *scale, /* O Scaling of the correlation vector */
|
||||
const opus_int16 *input, /* I Input data to correlate */
|
||||
|
|
|
|||
|
|
@ -57,88 +57,79 @@ static OPUS_INLINE opus_int32 warped_gain( /* gain in Q16*/
|
|||
/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */
|
||||
/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
|
||||
static OPUS_INLINE void limit_warped_coefs(
|
||||
opus_int32 *coefs_syn_Q24,
|
||||
opus_int32 *coefs_ana_Q24,
|
||||
opus_int32 *coefs_Q24,
|
||||
opus_int lambda_Q16,
|
||||
opus_int32 limit_Q24,
|
||||
opus_int order
|
||||
) {
|
||||
opus_int i, iter, ind = 0;
|
||||
opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16;
|
||||
opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_Q16;
|
||||
opus_int32 nom_Q16, den_Q24;
|
||||
opus_int32 limit_Q20, maxabs_Q20;
|
||||
|
||||
/* Convert to monic coefficients */
|
||||
lambda_Q16 = -lambda_Q16;
|
||||
for( i = order - 1; i > 0; i-- ) {
|
||||
coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
|
||||
coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
|
||||
coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
|
||||
}
|
||||
lambda_Q16 = -lambda_Q16;
|
||||
nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
|
||||
den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
|
||||
gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
|
||||
den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
|
||||
gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
|
||||
nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
|
||||
den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_Q24[ 0 ], lambda_Q16 );
|
||||
gain_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
|
||||
for( i = 0; i < order; i++ ) {
|
||||
coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
|
||||
coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
|
||||
coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
|
||||
}
|
||||
|
||||
limit_Q20 = silk_RSHIFT(limit_Q24, 4);
|
||||
for( iter = 0; iter < 10; iter++ ) {
|
||||
/* Find maximum absolute value */
|
||||
maxabs_Q24 = -1;
|
||||
for( i = 0; i < order; i++ ) {
|
||||
tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) );
|
||||
tmp = silk_abs_int32( coefs_Q24[ i ] );
|
||||
if( tmp > maxabs_Q24 ) {
|
||||
maxabs_Q24 = tmp;
|
||||
ind = i;
|
||||
}
|
||||
}
|
||||
if( maxabs_Q24 <= limit_Q24 ) {
|
||||
/* Use Q20 to avoid any overflow when multiplying by (ind + 1) later. */
|
||||
maxabs_Q20 = silk_RSHIFT(maxabs_Q24, 4);
|
||||
if( maxabs_Q20 <= limit_Q20 ) {
|
||||
/* Coefficients are within range - done */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert back to true warped coefficients */
|
||||
for( i = 1; i < order; i++ ) {
|
||||
coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
|
||||
coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
|
||||
coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
|
||||
}
|
||||
gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 );
|
||||
gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 );
|
||||
gain_Q16 = silk_INVERSE32_varQ( gain_Q16, 32 );
|
||||
for( i = 0; i < order; i++ ) {
|
||||
coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
|
||||
coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
|
||||
coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
|
||||
}
|
||||
|
||||
/* Apply bandwidth expansion */
|
||||
chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ(
|
||||
silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ),
|
||||
silk_MUL( maxabs_Q24, ind + 1 ), 22 );
|
||||
silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 );
|
||||
silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 );
|
||||
silk_SMULWB( maxabs_Q20 - limit_Q20, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ),
|
||||
silk_MUL( maxabs_Q20, ind + 1 ), 22 );
|
||||
silk_bwexpander_32( coefs_Q24, order, chirp_Q16 );
|
||||
|
||||
/* Convert to monic warped coefficients */
|
||||
lambda_Q16 = -lambda_Q16;
|
||||
for( i = order - 1; i > 0; i-- ) {
|
||||
coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
|
||||
coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
|
||||
coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
|
||||
}
|
||||
lambda_Q16 = -lambda_Q16;
|
||||
nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
|
||||
den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
|
||||
gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
|
||||
den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
|
||||
gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
|
||||
den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_Q24[ 0 ], lambda_Q16 );
|
||||
gain_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
|
||||
for( i = 0; i < order; i++ ) {
|
||||
coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
|
||||
coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
|
||||
coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
|
||||
}
|
||||
}
|
||||
silk_assert( 0 );
|
||||
}
|
||||
|
||||
#if defined(MIPSr1_ASM)
|
||||
/* Disable MIPS version until it's updated. */
|
||||
#if 0 && defined(MIPSr1_ASM)
|
||||
#include "mips/noise_shape_analysis_FIX_mipsr1.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -155,14 +146,13 @@ void silk_noise_shape_analysis_FIX(
|
|||
)
|
||||
{
|
||||
silk_shape_state_FIX *psShapeSt = &psEnc->sShape;
|
||||
opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0;
|
||||
opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32;
|
||||
opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
|
||||
opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
|
||||
opus_int k, i, nSamples, nSegs, Qnrg, b_Q14, warping_Q16, scale = 0;
|
||||
opus_int32 SNR_adj_dB_Q7, HarmShapeGain_Q16, Tilt_Q16, tmp32;
|
||||
opus_int32 nrg, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
|
||||
opus_int32 BWExp_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
|
||||
opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
|
||||
opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ];
|
||||
opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ];
|
||||
opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ];
|
||||
opus_int32 AR_Q24[ MAX_SHAPE_LPC_ORDER ];
|
||||
VARDECL( opus_int16, x_windowed );
|
||||
const opus_int16 *x_ptr, *pitch_res_ptr;
|
||||
SAVE_STACK;
|
||||
|
|
@ -209,14 +199,14 @@ void silk_noise_shape_analysis_FIX(
|
|||
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
|
||||
/* Initially set to 0; may be overruled in process_gains(..) */
|
||||
psEnc->sCmn.indices.quantOffsetType = 0;
|
||||
psEncCtrl->sparseness_Q8 = 0;
|
||||
} else {
|
||||
/* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
|
||||
nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 );
|
||||
energy_variation_Q7 = 0;
|
||||
log_energy_prev_Q7 = 0;
|
||||
pitch_res_ptr = pitch_res;
|
||||
for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
|
||||
nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
|
||||
for( k = 0; k < nSegs; k++ ) {
|
||||
silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples );
|
||||
nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/
|
||||
|
||||
|
|
@ -228,18 +218,12 @@ void silk_noise_shape_analysis_FIX(
|
|||
pitch_res_ptr += nSamples;
|
||||
}
|
||||
|
||||
psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 -
|
||||
SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 );
|
||||
|
||||
/* Set quantization offset depending on sparseness measure */
|
||||
if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) {
|
||||
if( energy_variation_Q7 > SILK_FIX_CONST( ENERGY_VARIATION_THRESHOLD_QNT_OFFSET, 7 ) * (nSegs-1) ) {
|
||||
psEnc->sCmn.indices.quantOffsetType = 0;
|
||||
} else {
|
||||
psEnc->sCmn.indices.quantOffsetType = 1;
|
||||
}
|
||||
|
||||
/* Increase coding SNR for sparse signals */
|
||||
SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) );
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
|
@ -247,14 +231,8 @@ void silk_noise_shape_analysis_FIX(
|
|||
/*******************************/
|
||||
/* More BWE for signals with high prediction gain */
|
||||
strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) );
|
||||
BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ),
|
||||
BWExp_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ),
|
||||
silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 );
|
||||
delta_Q16 = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ),
|
||||
SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) );
|
||||
BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 );
|
||||
BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 );
|
||||
/* BWExp1 will be applied after BWExp2, so make it relative */
|
||||
BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) );
|
||||
|
||||
if( psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
/* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
|
||||
|
|
@ -284,7 +262,7 @@ void silk_noise_shape_analysis_FIX(
|
|||
|
||||
if( psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
/* Calculate warped auto correlation */
|
||||
silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
|
||||
silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder, arch );
|
||||
} else {
|
||||
/* Calculate regular auto correlation */
|
||||
silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch );
|
||||
|
|
@ -299,7 +277,7 @@ void silk_noise_shape_analysis_FIX(
|
|||
silk_assert( nrg >= 0 );
|
||||
|
||||
/* Convert reflection coefficients to prediction coefficients */
|
||||
silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );
|
||||
silk_k2a_Q16( AR_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );
|
||||
|
||||
Qnrg = -scale; /* range: -12...30*/
|
||||
silk_assert( Qnrg >= -12 );
|
||||
|
|
@ -318,40 +296,34 @@ void silk_noise_shape_analysis_FIX(
|
|||
|
||||
if( psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
/* Adjust gain for warping */
|
||||
gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder );
|
||||
silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 );
|
||||
if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) {
|
||||
psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX;
|
||||
gain_mult_Q16 = warped_gain( AR_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder );
|
||||
silk_assert( psEncCtrl->Gains_Q16[ k ] > 0 );
|
||||
if( psEncCtrl->Gains_Q16[ k ] < SILK_FIX_CONST( 0.25, 16 ) ) {
|
||||
psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
|
||||
} else {
|
||||
psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
|
||||
psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 );
|
||||
if ( psEncCtrl->Gains_Q16[ k ] >= ( silk_int32_MAX >> 1 ) ) {
|
||||
psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX;
|
||||
} else {
|
||||
psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT32( psEncCtrl->Gains_Q16[ k ], 1 );
|
||||
}
|
||||
}
|
||||
silk_assert( psEncCtrl->Gains_Q16[ k ] > 0 );
|
||||
}
|
||||
|
||||
/* Bandwidth expansion for synthesis filter shaping */
|
||||
silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 );
|
||||
/* Bandwidth expansion */
|
||||
silk_bwexpander_32( AR_Q24, psEnc->sCmn.shapingLPCOrder, BWExp_Q16 );
|
||||
|
||||
/* Compute noise shaping filter coefficients */
|
||||
silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) );
|
||||
if( psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
/* Convert to monic warped prediction coefficients and limit absolute values */
|
||||
limit_warped_coefs( AR_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
|
||||
|
||||
/* Bandwidth expansion for analysis filter shaping */
|
||||
silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) );
|
||||
silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
|
||||
|
||||
/* Ratio of prediction gains, in energy domain */
|
||||
pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
|
||||
nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
|
||||
|
||||
/*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
|
||||
pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
|
||||
psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 );
|
||||
|
||||
/* Convert to monic warped prediction coefficients and limit absolute values */
|
||||
limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
|
||||
|
||||
/* Convert from Q24 to Q13 and store in int16 */
|
||||
for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {
|
||||
psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) );
|
||||
psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) );
|
||||
/* Convert from Q24 to Q13 and store in int16 */
|
||||
for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {
|
||||
psEncCtrl->AR_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR_Q24[ i ], 11 ) );
|
||||
}
|
||||
} else {
|
||||
silk_LPC_fit( &psEncCtrl->AR_Q13[ k * MAX_SHAPE_LPC_ORDER ], AR_Q24, 13, 24, psEnc->sCmn.shapingLPCOrder );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -368,11 +340,6 @@ void silk_noise_shape_analysis_FIX(
|
|||
psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 );
|
||||
}
|
||||
|
||||
gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ),
|
||||
psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 );
|
||||
for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
|
||||
psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] );
|
||||
}
|
||||
|
||||
/************************************************/
|
||||
/* Control low-frequency shaping and noise tilt */
|
||||
|
|
@ -410,14 +377,6 @@ void silk_noise_shape_analysis_FIX(
|
|||
/****************************/
|
||||
/* HARMONIC SHAPING CONTROL */
|
||||
/****************************/
|
||||
/* Control boosting of harmonic frequencies */
|
||||
HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ),
|
||||
psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) );
|
||||
|
||||
/* More harmonic boost for noisy input signals */
|
||||
HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16,
|
||||
SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) );
|
||||
|
||||
if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
|
||||
/* More harmonic noise shaping for high bitrates or noisy input */
|
||||
HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ),
|
||||
|
|
@ -435,14 +394,11 @@ void silk_noise_shape_analysis_FIX(
|
|||
/* Smooth over subframes */
|
||||
/*************************/
|
||||
for( k = 0; k < MAX_NB_SUBFR; k++ ) {
|
||||
psShapeSt->HarmBoost_smth_Q16 =
|
||||
silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
|
||||
psShapeSt->HarmShapeGain_smth_Q16 =
|
||||
silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
|
||||
psShapeSt->Tilt_smth_Q16 =
|
||||
silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
|
||||
|
||||
psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 );
|
||||
psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 );
|
||||
psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ static void silk_P_Ana_calc_energy_st3(
|
|||
/* FIXED POINT CORE PITCH ANALYSIS FUNCTION */
|
||||
/*************************************************************/
|
||||
opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */
|
||||
const opus_int16 *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
|
||||
const opus_int16 *frame_unscaled, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
|
||||
opus_int *pitch_out, /* O 4 pitch lag values */
|
||||
opus_int16 *lagIndex, /* O Lag Index */
|
||||
opus_int8 *contourIndex, /* O Pitch contour Index */
|
||||
|
|
@ -94,16 +94,17 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
int arch /* I Run-time architecture */
|
||||
)
|
||||
{
|
||||
VARDECL( opus_int16, frame_8kHz );
|
||||
VARDECL( opus_int16, frame_8kHz_buf );
|
||||
VARDECL( opus_int16, frame_4kHz );
|
||||
VARDECL( opus_int16, frame_scaled );
|
||||
opus_int32 filt_state[ 6 ];
|
||||
const opus_int16 *input_frame_ptr;
|
||||
const opus_int16 *frame, *frame_8kHz;
|
||||
opus_int i, k, d, j;
|
||||
VARDECL( opus_int16, C );
|
||||
VARDECL( opus_int32, xcorr32 );
|
||||
const opus_int16 *target_ptr, *basis_ptr;
|
||||
opus_int32 cross_corr, normalizer, energy, shift, energy_basis, energy_target;
|
||||
opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp;
|
||||
opus_int32 cross_corr, normalizer, energy, energy_basis, energy_target;
|
||||
opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp, shift;
|
||||
VARDECL( opus_int16, d_comp );
|
||||
opus_int32 sum, threshold, lag_counter;
|
||||
opus_int CBimax, CBimax_new, CBimax_old, lag, start_lag, end_lag, lag_new;
|
||||
|
|
@ -119,12 +120,13 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
opus_int32 delta_lag_log2_sqr_Q7, lag_log2_Q7, prevLag_log2_Q7, prev_lag_bias_Q13;
|
||||
const opus_int8 *Lag_CB_ptr;
|
||||
SAVE_STACK;
|
||||
|
||||
/* Check for valid sampling frequency */
|
||||
silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
|
||||
celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
|
||||
|
||||
/* Check for valid complexity setting */
|
||||
silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
|
||||
silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) );
|
||||
silk_assert( search_thres2_Q13 >= 0 && search_thres2_Q13 <= (1<<13) );
|
||||
|
|
@ -137,17 +139,33 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
min_lag = PE_MIN_LAG_MS * Fs_kHz;
|
||||
max_lag = PE_MAX_LAG_MS * Fs_kHz - 1;
|
||||
|
||||
/* Downscale input if necessary */
|
||||
silk_sum_sqr_shift( &energy, &shift, frame_unscaled, frame_length );
|
||||
shift += 3 - silk_CLZ32( energy ); /* at least two bits headroom */
|
||||
ALLOC( frame_scaled, frame_length, opus_int16 );
|
||||
if( shift > 0 ) {
|
||||
shift = silk_RSHIFT( shift + 1, 1 );
|
||||
for( i = 0; i < frame_length; i++ ) {
|
||||
frame_scaled[ i ] = silk_RSHIFT( frame_unscaled[ i ], shift );
|
||||
}
|
||||
frame = frame_scaled;
|
||||
} else {
|
||||
frame = frame_unscaled;
|
||||
}
|
||||
|
||||
ALLOC( frame_8kHz_buf, ( Fs_kHz == 8 ) ? 1 : frame_length_8kHz, opus_int16 );
|
||||
/* Resample from input sampled at Fs_kHz to 8 kHz */
|
||||
ALLOC( frame_8kHz, frame_length_8kHz, opus_int16 );
|
||||
if( Fs_kHz == 16 ) {
|
||||
silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
|
||||
silk_resampler_down2( filt_state, frame_8kHz, frame, frame_length );
|
||||
silk_resampler_down2( filt_state, frame_8kHz_buf, frame, frame_length );
|
||||
frame_8kHz = frame_8kHz_buf;
|
||||
} else if( Fs_kHz == 12 ) {
|
||||
silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) );
|
||||
silk_resampler_down2_3( filt_state, frame_8kHz, frame, frame_length );
|
||||
silk_resampler_down2_3( filt_state, frame_8kHz_buf, frame, frame_length );
|
||||
frame_8kHz = frame_8kHz_buf;
|
||||
} else {
|
||||
silk_assert( Fs_kHz == 8 );
|
||||
silk_memcpy( frame_8kHz, frame, frame_length_8kHz * sizeof(opus_int16) );
|
||||
celt_assert( Fs_kHz == 8 );
|
||||
frame_8kHz = frame;
|
||||
}
|
||||
|
||||
/* Decimate again to 4 kHz */
|
||||
|
|
@ -160,19 +178,6 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Scale 4 kHz signal down to prevent correlations measures from overflowing
|
||||
** find scaling as max scaling for each 8kHz(?) subframe
|
||||
*******************************************************************************/
|
||||
|
||||
/* Inner product is calculated with different lengths, so scale for the worst case */
|
||||
silk_sum_sqr_shift( &energy, &shift, frame_4kHz, frame_length_4kHz );
|
||||
if( shift > 0 ) {
|
||||
shift = silk_RSHIFT( shift, 1 );
|
||||
for( i = 0; i < frame_length_4kHz; i++ ) {
|
||||
frame_4kHz[ i ] = silk_RSHIFT( frame_4kHz[ i ], shift );
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FIRST STAGE, operating in 4 khz
|
||||
|
|
@ -183,14 +188,14 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
target_ptr = &frame_4kHz[ silk_LSHIFT( SF_LENGTH_4KHZ, 2 ) ];
|
||||
for( k = 0; k < nb_subfr >> 1; k++ ) {
|
||||
/* Check that we are within range of the array */
|
||||
silk_assert( target_ptr >= frame_4kHz );
|
||||
silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
|
||||
celt_assert( target_ptr >= frame_4kHz );
|
||||
celt_assert( target_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
|
||||
|
||||
basis_ptr = target_ptr - MIN_LAG_4KHZ;
|
||||
|
||||
/* Check that we are within range of the array */
|
||||
silk_assert( basis_ptr >= frame_4kHz );
|
||||
silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
|
||||
celt_assert( basis_ptr >= frame_4kHz );
|
||||
celt_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
|
||||
|
||||
celt_pitch_xcorr( target_ptr, target_ptr - MAX_LAG_4KHZ, xcorr32, SF_LENGTH_8KHZ, MAX_LAG_4KHZ - MIN_LAG_4KHZ + 1, arch );
|
||||
|
||||
|
|
@ -244,7 +249,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
|
||||
/* Sort */
|
||||
length_d_srch = silk_ADD_LSHIFT32( 4, complexity, 1 );
|
||||
silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
|
||||
celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
|
||||
silk_insertion_sort_decreasing_int16( C, d_srch, CSTRIDE_4KHZ,
|
||||
length_d_srch );
|
||||
|
||||
|
|
@ -269,7 +274,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
break;
|
||||
}
|
||||
}
|
||||
silk_assert( length_d_srch > 0 );
|
||||
celt_assert( length_d_srch > 0 );
|
||||
|
||||
ALLOC( d_comp, D_COMP_STRIDE, opus_int16 );
|
||||
for( i = D_COMP_MIN; i < D_COMP_MAX; i++ ) {
|
||||
|
|
@ -311,18 +316,6 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation
|
||||
*************************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
** Scale signal down to avoid correlations measures from overflowing
|
||||
*******************************************************************************/
|
||||
/* find scaling as max scaling for each subframe */
|
||||
silk_sum_sqr_shift( &energy, &shift, frame_8kHz, frame_length_8kHz );
|
||||
if( shift > 0 ) {
|
||||
shift = silk_RSHIFT( shift, 1 );
|
||||
for( i = 0; i < frame_length_8kHz; i++ ) {
|
||||
frame_8kHz[ i ] = silk_RSHIFT( frame_8kHz[ i ], shift );
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
* Find energy of each subframe projected onto its history, for a range of delays
|
||||
*********************************************************************************/
|
||||
|
|
@ -332,8 +325,8 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
|
||||
/* Check that we are within range of the array */
|
||||
silk_assert( target_ptr >= frame_8kHz );
|
||||
silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz );
|
||||
celt_assert( target_ptr >= frame_8kHz );
|
||||
celt_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz );
|
||||
|
||||
energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ, arch ), 1 );
|
||||
for( j = 0; j < length_d_comp; j++ ) {
|
||||
|
|
@ -462,24 +455,6 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
silk_assert( *LTPCorr_Q15 >= 0 );
|
||||
|
||||
if( Fs_kHz > 8 ) {
|
||||
VARDECL( opus_int16, scratch_mem );
|
||||
/***************************************************************************/
|
||||
/* Scale input signal down to avoid correlations measures from overflowing */
|
||||
/***************************************************************************/
|
||||
/* find scaling as max scaling for each subframe */
|
||||
silk_sum_sqr_shift( &energy, &shift, frame, frame_length );
|
||||
ALLOC( scratch_mem, shift > 0 ? frame_length : ALLOC_NONE, opus_int16 );
|
||||
if( shift > 0 ) {
|
||||
/* Move signal to scratch mem because the input signal should be unchanged */
|
||||
shift = silk_RSHIFT( shift, 1 );
|
||||
for( i = 0; i < frame_length; i++ ) {
|
||||
scratch_mem[ i ] = silk_RSHIFT( frame[ i ], shift );
|
||||
}
|
||||
input_frame_ptr = scratch_mem;
|
||||
} else {
|
||||
input_frame_ptr = frame;
|
||||
}
|
||||
|
||||
/* Search in original signal */
|
||||
|
||||
CBimax_old = CBimax;
|
||||
|
|
@ -519,14 +494,14 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
/* Calculate the correlations and energies needed in stage 3 */
|
||||
ALLOC( energies_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals );
|
||||
ALLOC( cross_corr_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals );
|
||||
silk_P_Ana_calc_corr_st3( cross_corr_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch );
|
||||
silk_P_Ana_calc_energy_st3( energies_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch );
|
||||
silk_P_Ana_calc_corr_st3( cross_corr_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
|
||||
silk_P_Ana_calc_energy_st3( energies_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
|
||||
|
||||
lag_counter = 0;
|
||||
silk_assert( lag == silk_SAT16( lag ) );
|
||||
contour_bias_Q15 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 15 ), lag );
|
||||
|
||||
target_ptr = &input_frame_ptr[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
|
||||
target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
|
||||
energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, nb_subfr * sf_length, arch ), 1 );
|
||||
for( d = start_lag; d <= end_lag; d++ ) {
|
||||
for( j = 0; j < nb_cbk_search; j++ ) {
|
||||
|
|
@ -575,7 +550,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
|
|||
*lagIndex = (opus_int16)( lag - MIN_LAG_8KHZ );
|
||||
*contourIndex = (opus_int8)CBimax;
|
||||
}
|
||||
silk_assert( *lagIndex >= 0 );
|
||||
celt_assert( *lagIndex >= 0 );
|
||||
/* return as voiced */
|
||||
RESTORE_STACK;
|
||||
return 0;
|
||||
|
|
@ -612,8 +587,8 @@ static void silk_P_Ana_calc_corr_st3(
|
|||
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
|
||||
SAVE_STACK;
|
||||
|
||||
silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
|
||||
if( nb_subfr == PE_MAX_NB_SUBFR ) {
|
||||
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
|
||||
|
|
@ -621,7 +596,7 @@ static void silk_P_Ana_calc_corr_st3(
|
|||
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
|
||||
cbk_size = PE_NB_CBKS_STAGE3_MAX;
|
||||
} else {
|
||||
silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
|
||||
celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
|
||||
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
|
||||
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
|
||||
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
|
||||
|
|
@ -637,7 +612,7 @@ static void silk_P_Ana_calc_corr_st3(
|
|||
/* Calculate the correlations for each subframe */
|
||||
lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 );
|
||||
lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 );
|
||||
silk_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
|
||||
celt_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
|
||||
celt_pitch_xcorr( target_ptr, target_ptr - start_lag - lag_high, xcorr32, sf_length, lag_high - lag_low + 1, arch );
|
||||
for( j = lag_low; j <= lag_high; j++ ) {
|
||||
silk_assert( lag_counter < SCRATCH_SIZE );
|
||||
|
|
@ -684,8 +659,8 @@ static void silk_P_Ana_calc_energy_st3(
|
|||
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
|
||||
SAVE_STACK;
|
||||
|
||||
silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
|
||||
if( nb_subfr == PE_MAX_NB_SUBFR ) {
|
||||
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
|
||||
|
|
@ -693,7 +668,7 @@ static void silk_P_Ana_calc_energy_st3(
|
|||
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
|
||||
cbk_size = PE_NB_CBKS_STAGE3_MAX;
|
||||
} else {
|
||||
silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
|
||||
celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
|
||||
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
|
||||
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
|
||||
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
|
||||
|
|
|
|||
|
|
@ -1,221 +0,0 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main_FIX.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "tuning_parameters.h"
|
||||
|
||||
#if defined(MIPSr1_ASM)
|
||||
#include "mips/prefilter_FIX_mipsr1.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(OVERRIDE_silk_warped_LPC_analysis_filter_FIX)
|
||||
#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
|
||||
((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
|
||||
#endif
|
||||
|
||||
/* Prefilter for finding Quantizer input signal */
|
||||
static OPUS_INLINE void silk_prefilt_FIX(
|
||||
silk_prefilter_state_FIX *P, /* I/O state */
|
||||
opus_int32 st_res_Q12[], /* I short term residual signal */
|
||||
opus_int32 xw_Q3[], /* O prefiltered signal */
|
||||
opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
|
||||
opus_int Tilt_Q14, /* I Tilt shaping coeficient */
|
||||
opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
|
||||
opus_int lag, /* I Lag for harmonic shaping */
|
||||
opus_int length /* I Length of signals */
|
||||
);
|
||||
|
||||
void silk_warped_LPC_analysis_filter_FIX_c(
|
||||
opus_int32 state[], /* I/O State [order + 1] */
|
||||
opus_int32 res_Q2[], /* O Residual signal [length] */
|
||||
const opus_int16 coef_Q13[], /* I Coefficients [order] */
|
||||
const opus_int16 input[], /* I Input signal [length] */
|
||||
const opus_int16 lambda_Q16, /* I Warping factor */
|
||||
const opus_int length, /* I Length of input signal */
|
||||
const opus_int order /* I Filter order (even) */
|
||||
)
|
||||
{
|
||||
opus_int n, i;
|
||||
opus_int32 acc_Q11, tmp1, tmp2;
|
||||
|
||||
/* Order must be even */
|
||||
silk_assert( ( order & 1 ) == 0 );
|
||||
|
||||
for( n = 0; n < length; n++ ) {
|
||||
/* Output of lowpass section */
|
||||
tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
|
||||
state[ 0 ] = silk_LSHIFT( input[ n ], 14 );
|
||||
/* Output of allpass section */
|
||||
tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
|
||||
state[ 1 ] = tmp2;
|
||||
acc_Q11 = silk_RSHIFT( order, 1 );
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
|
||||
/* Loop over allpass sections */
|
||||
for( i = 2; i < order; i += 2 ) {
|
||||
/* Output of allpass section */
|
||||
tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
|
||||
state[ i ] = tmp1;
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
|
||||
/* Output of allpass section */
|
||||
tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
|
||||
state[ i + 1 ] = tmp2;
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
|
||||
}
|
||||
state[ order ] = tmp1;
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
|
||||
res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
|
||||
}
|
||||
}
|
||||
|
||||
void silk_prefilter_FIX(
|
||||
silk_encoder_state_FIX *psEnc, /* I/O Encoder state */
|
||||
const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */
|
||||
opus_int32 xw_Q3[], /* O Weighted signal */
|
||||
const opus_int16 x[] /* I Speech signal */
|
||||
)
|
||||
{
|
||||
silk_prefilter_state_FIX *P = &psEnc->sPrefilt;
|
||||
opus_int j, k, lag;
|
||||
opus_int32 tmp_32;
|
||||
const opus_int16 *AR1_shp_Q13;
|
||||
const opus_int16 *px;
|
||||
opus_int32 *pxw_Q3;
|
||||
opus_int HarmShapeGain_Q12, Tilt_Q14;
|
||||
opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14;
|
||||
VARDECL( opus_int32, x_filt_Q12 );
|
||||
VARDECL( opus_int32, st_res_Q2 );
|
||||
opus_int16 B_Q10[ 2 ];
|
||||
SAVE_STACK;
|
||||
|
||||
/* Set up pointers */
|
||||
px = x;
|
||||
pxw_Q3 = xw_Q3;
|
||||
lag = P->lagPrev;
|
||||
ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 );
|
||||
ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 );
|
||||
for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
|
||||
/* Update Variables that change per sub frame */
|
||||
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
|
||||
lag = psEncCtrl->pitchL[ k ];
|
||||
}
|
||||
|
||||
/* Noise shape parameters */
|
||||
HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] );
|
||||
silk_assert( HarmShapeGain_Q12 >= 0 );
|
||||
HarmShapeFIRPacked_Q12 = silk_RSHIFT( HarmShapeGain_Q12, 2 );
|
||||
HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 );
|
||||
Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ];
|
||||
LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ];
|
||||
AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ];
|
||||
|
||||
/* Short term FIR filtering*/
|
||||
silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px,
|
||||
psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder, psEnc->sCmn.arch );
|
||||
|
||||
/* Reduce (mainly) low frequencies during harmonic emphasis */
|
||||
B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 );
|
||||
tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */
|
||||
tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */
|
||||
tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */
|
||||
tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 ); /* Q10 */
|
||||
B_Q10[ 1 ]= silk_SAT16( tmp_32 );
|
||||
x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] );
|
||||
for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) {
|
||||
x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] );
|
||||
}
|
||||
P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ];
|
||||
|
||||
silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length );
|
||||
|
||||
px += psEnc->sCmn.subfr_length;
|
||||
pxw_Q3 += psEnc->sCmn.subfr_length;
|
||||
}
|
||||
|
||||
P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
#ifndef OVERRIDE_silk_prefilt_FIX
|
||||
/* Prefilter for finding Quantizer input signal */
|
||||
static OPUS_INLINE void silk_prefilt_FIX(
|
||||
silk_prefilter_state_FIX *P, /* I/O state */
|
||||
opus_int32 st_res_Q12[], /* I short term residual signal */
|
||||
opus_int32 xw_Q3[], /* O prefiltered signal */
|
||||
opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
|
||||
opus_int Tilt_Q14, /* I Tilt shaping coeficient */
|
||||
opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
|
||||
opus_int lag, /* I Lag for harmonic shaping */
|
||||
opus_int length /* I Length of signals */
|
||||
)
|
||||
{
|
||||
opus_int i, idx, LTP_shp_buf_idx;
|
||||
opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10;
|
||||
opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12;
|
||||
opus_int16 *LTP_shp_buf;
|
||||
|
||||
/* To speed up use temp variables instead of using the struct */
|
||||
LTP_shp_buf = P->sLTP_shp;
|
||||
LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
|
||||
sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12;
|
||||
sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12;
|
||||
|
||||
for( i = 0; i < length; i++ ) {
|
||||
if( lag > 0 ) {
|
||||
/* unrolled loop */
|
||||
silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
|
||||
idx = lag + LTP_shp_buf_idx;
|
||||
n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
|
||||
n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
|
||||
n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
|
||||
} else {
|
||||
n_LTP_Q12 = 0;
|
||||
}
|
||||
|
||||
n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
|
||||
n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
|
||||
|
||||
sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
|
||||
sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) );
|
||||
|
||||
LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
|
||||
LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
|
||||
|
||||
xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 );
|
||||
}
|
||||
|
||||
/* Copy temp variable back to state */
|
||||
P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12;
|
||||
P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12;
|
||||
P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
|
||||
}
|
||||
#endif /* OVERRIDE_silk_prefilt_FIX */
|
||||
|
|
@ -47,10 +47,10 @@ opus_int32 silk_residual_energy16_covar_FIX(
|
|||
const opus_int32 *pRow;
|
||||
|
||||
/* Safety checks */
|
||||
silk_assert( D >= 0 );
|
||||
silk_assert( D <= 16 );
|
||||
silk_assert( cQ > 0 );
|
||||
silk_assert( cQ < 16 );
|
||||
celt_assert( D >= 0 );
|
||||
celt_assert( D <= 16 );
|
||||
celt_assert( cQ > 0 );
|
||||
celt_assert( cQ < 16 );
|
||||
|
||||
lshifts = 16 - cQ;
|
||||
Qxtra = lshifts;
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ void silk_residual_energy_FIX(
|
|||
|
||||
/* Filter input to create the LPC residual for each frame half, and measure subframe energies */
|
||||
ALLOC( LPC_res, ( MAX_NB_SUBFR >> 1 ) * offset, opus_int16 );
|
||||
silk_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr );
|
||||
celt_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr );
|
||||
for( i = 0; i < nb_subfr >> 1; i++ ) {
|
||||
/* Calculate half frame LPC residual signal including preceding samples */
|
||||
silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order, arch );
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ opus_int32 silk_schur64( /* O returns residual ene
|
|||
opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
|
||||
opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31;
|
||||
|
||||
silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
|
||||
celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
|
||||
|
||||
/* Check for invalid input */
|
||||
if( c[ 0 ] <= 0 ) {
|
||||
|
|
@ -51,9 +51,10 @@ opus_int32 silk_schur64( /* O returns residual ene
|
|||
return 0;
|
||||
}
|
||||
|
||||
for( k = 0; k < order + 1; k++ ) {
|
||||
k = 0;
|
||||
do {
|
||||
C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ];
|
||||
}
|
||||
} while( ++k <= order );
|
||||
|
||||
for( k = 0; k < order; k++ ) {
|
||||
/* Check that we won't be getting an unstable rc, otherwise stop here. */
|
||||
|
|
|
|||
|
|
@ -43,28 +43,29 @@ opus_int32 silk_schur( /* O Returns residual ene
|
|||
opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
|
||||
opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15;
|
||||
|
||||
silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
|
||||
celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
|
||||
|
||||
/* Get number of leading zeros */
|
||||
lz = silk_CLZ32( c[ 0 ] );
|
||||
|
||||
/* Copy correlations and adjust level to Q30 */
|
||||
k = 0;
|
||||
if( lz < 2 ) {
|
||||
/* lz must be 1, so shift one to the right */
|
||||
for( k = 0; k < order + 1; k++ ) {
|
||||
do {
|
||||
C[ k ][ 0 ] = C[ k ][ 1 ] = silk_RSHIFT( c[ k ], 1 );
|
||||
}
|
||||
} while( ++k <= order );
|
||||
} else if( lz > 2 ) {
|
||||
/* Shift to the left */
|
||||
lz -= 2;
|
||||
for( k = 0; k < order + 1; k++ ) {
|
||||
do {
|
||||
C[ k ][ 0 ] = C[ k ][ 1 ] = silk_LSHIFT( c[ k ], lz );
|
||||
}
|
||||
} while( ++k <= order );
|
||||
} else {
|
||||
/* No need to shift */
|
||||
for( k = 0; k < order + 1; k++ ) {
|
||||
do {
|
||||
C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ];
|
||||
}
|
||||
} while( ++k <= order );
|
||||
}
|
||||
|
||||
for( k = 0; k < order; k++ ) {
|
||||
|
|
|
|||
|
|
@ -1,249 +0,0 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "main_FIX.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "tuning_parameters.h"
|
||||
|
||||
/*****************************/
|
||||
/* Internal function headers */
|
||||
/*****************************/
|
||||
|
||||
typedef struct {
|
||||
opus_int32 Q36_part;
|
||||
opus_int32 Q48_part;
|
||||
} inv_D_t;
|
||||
|
||||
/* Factorize square matrix A into LDL form */
|
||||
static OPUS_INLINE void silk_LDL_factorize_FIX(
|
||||
opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */
|
||||
opus_int M, /* I Size of Matrix */
|
||||
opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */
|
||||
inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */
|
||||
);
|
||||
|
||||
/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */
|
||||
static OPUS_INLINE void silk_LS_SolveFirst_FIX(
|
||||
const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
|
||||
opus_int M, /* I Dim of Matrix equation */
|
||||
const opus_int32 *b, /* I b Vector */
|
||||
opus_int32 *x_Q16 /* O x Vector */
|
||||
);
|
||||
|
||||
/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */
|
||||
static OPUS_INLINE void silk_LS_SolveLast_FIX(
|
||||
const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
|
||||
const opus_int M, /* I Dim of Matrix equation */
|
||||
const opus_int32 *b, /* I b Vector */
|
||||
opus_int32 *x_Q16 /* O x Vector */
|
||||
);
|
||||
|
||||
static OPUS_INLINE void silk_LS_divide_Q16_FIX(
|
||||
opus_int32 T[], /* I/O Numenator vector */
|
||||
inv_D_t *inv_D, /* I 1 / D vector */
|
||||
opus_int M /* I dimension */
|
||||
);
|
||||
|
||||
/* Solves Ax = b, assuming A is symmetric */
|
||||
void silk_solve_LDL_FIX(
|
||||
opus_int32 *A, /* I Pointer to symetric square matrix A */
|
||||
opus_int M, /* I Size of matrix */
|
||||
const opus_int32 *b, /* I Pointer to b vector */
|
||||
opus_int32 *x_Q16 /* O Pointer to x solution vector */
|
||||
)
|
||||
{
|
||||
VARDECL( opus_int32, L_Q16 );
|
||||
opus_int32 Y[ MAX_MATRIX_SIZE ];
|
||||
inv_D_t inv_D[ MAX_MATRIX_SIZE ];
|
||||
SAVE_STACK;
|
||||
|
||||
silk_assert( M <= MAX_MATRIX_SIZE );
|
||||
ALLOC( L_Q16, M * M, opus_int32 );
|
||||
|
||||
/***************************************************
|
||||
Factorize A by LDL such that A = L*D*L',
|
||||
where L is lower triangular with ones on diagonal
|
||||
****************************************************/
|
||||
silk_LDL_factorize_FIX( A, M, L_Q16, inv_D );
|
||||
|
||||
/****************************************************
|
||||
* substitute D*L'*x = Y. ie:
|
||||
L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b
|
||||
******************************************************/
|
||||
silk_LS_SolveFirst_FIX( L_Q16, M, b, Y );
|
||||
|
||||
/****************************************************
|
||||
D*L'*x = Y <=> L'*x = inv(D)*Y, because D is
|
||||
diagonal just multiply with 1/d_i
|
||||
****************************************************/
|
||||
silk_LS_divide_Q16_FIX( Y, inv_D, M );
|
||||
|
||||
/****************************************************
|
||||
x = inv(L') * inv(D) * Y
|
||||
*****************************************************/
|
||||
silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 );
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
static OPUS_INLINE void silk_LDL_factorize_FIX(
|
||||
opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */
|
||||
opus_int M, /* I Size of Matrix */
|
||||
opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */
|
||||
inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */
|
||||
)
|
||||
{
|
||||
opus_int i, j, k, status, loop_count;
|
||||
const opus_int32 *ptr1, *ptr2;
|
||||
opus_int32 diag_min_value, tmp_32, err;
|
||||
opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ];
|
||||
opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48;
|
||||
|
||||
silk_assert( M <= MAX_MATRIX_SIZE );
|
||||
|
||||
status = 1;
|
||||
diag_min_value = silk_max_32( silk_SMMUL( silk_ADD_SAT32( A[ 0 ], A[ silk_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 );
|
||||
for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) {
|
||||
status = 0;
|
||||
for( j = 0; j < M; j++ ) {
|
||||
ptr1 = matrix_adr( L_Q16, j, 0, M );
|
||||
tmp_32 = 0;
|
||||
for( i = 0; i < j; i++ ) {
|
||||
v_Q0[ i ] = silk_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */
|
||||
tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */
|
||||
}
|
||||
tmp_32 = silk_SUB32( matrix_ptr( A, j, j, M ), tmp_32 );
|
||||
|
||||
if( tmp_32 < diag_min_value ) {
|
||||
tmp_32 = silk_SUB32( silk_SMULBB( loop_count + 1, diag_min_value ), tmp_32 );
|
||||
/* Matrix not positive semi-definite, or ill conditioned */
|
||||
for( i = 0; i < M; i++ ) {
|
||||
matrix_ptr( A, i, i, M ) = silk_ADD32( matrix_ptr( A, i, i, M ), tmp_32 );
|
||||
}
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
D_Q0[ j ] = tmp_32; /* always < max(Correlation) */
|
||||
|
||||
/* two-step division */
|
||||
one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */
|
||||
one_div_diag_Q40 = silk_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */
|
||||
err = silk_SUB32( (opus_int32)1 << 24, silk_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */
|
||||
one_div_diag_Q48 = silk_SMULWW( err, one_div_diag_Q40 ); /* Q48 */
|
||||
|
||||
/* Save 1/Ds */
|
||||
inv_D[ j ].Q36_part = one_div_diag_Q36;
|
||||
inv_D[ j ].Q48_part = one_div_diag_Q48;
|
||||
|
||||
matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */
|
||||
ptr1 = matrix_adr( A, j, 0, M );
|
||||
ptr2 = matrix_adr( L_Q16, j + 1, 0, M );
|
||||
for( i = j + 1; i < M; i++ ) {
|
||||
tmp_32 = 0;
|
||||
for( k = 0; k < j; k++ ) {
|
||||
tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */
|
||||
}
|
||||
tmp_32 = silk_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */
|
||||
|
||||
/* tmp_32 / D_Q0[j] : Divide to Q16 */
|
||||
matrix_ptr( L_Q16, i, j, M ) = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ),
|
||||
silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) );
|
||||
|
||||
/* go to next column */
|
||||
ptr2 += M;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
silk_assert( status == 0 );
|
||||
}
|
||||
|
||||
static OPUS_INLINE void silk_LS_divide_Q16_FIX(
|
||||
opus_int32 T[], /* I/O Numenator vector */
|
||||
inv_D_t *inv_D, /* I 1 / D vector */
|
||||
opus_int M /* I dimension */
|
||||
)
|
||||
{
|
||||
opus_int i;
|
||||
opus_int32 tmp_32;
|
||||
opus_int32 one_div_diag_Q36, one_div_diag_Q48;
|
||||
|
||||
for( i = 0; i < M; i++ ) {
|
||||
one_div_diag_Q36 = inv_D[ i ].Q36_part;
|
||||
one_div_diag_Q48 = inv_D[ i ].Q48_part;
|
||||
|
||||
tmp_32 = T[ i ];
|
||||
T[ i ] = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */
|
||||
static OPUS_INLINE void silk_LS_SolveFirst_FIX(
|
||||
const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
|
||||
opus_int M, /* I Dim of Matrix equation */
|
||||
const opus_int32 *b, /* I b Vector */
|
||||
opus_int32 *x_Q16 /* O x Vector */
|
||||
)
|
||||
{
|
||||
opus_int i, j;
|
||||
const opus_int32 *ptr32;
|
||||
opus_int32 tmp_32;
|
||||
|
||||
for( i = 0; i < M; i++ ) {
|
||||
ptr32 = matrix_adr( L_Q16, i, 0, M );
|
||||
tmp_32 = 0;
|
||||
for( j = 0; j < i; j++ ) {
|
||||
tmp_32 = silk_SMLAWW( tmp_32, ptr32[ j ], x_Q16[ j ] );
|
||||
}
|
||||
x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */
|
||||
static OPUS_INLINE void silk_LS_SolveLast_FIX(
|
||||
const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
|
||||
const opus_int M, /* I Dim of Matrix equation */
|
||||
const opus_int32 *b, /* I b Vector */
|
||||
opus_int32 *x_Q16 /* O x Vector */
|
||||
)
|
||||
{
|
||||
opus_int i, j;
|
||||
const opus_int32 *ptr32;
|
||||
opus_int32 tmp_32;
|
||||
|
||||
for( i = M - 1; i >= 0; i-- ) {
|
||||
ptr32 = matrix_adr( L_Q16, 0, i, M );
|
||||
tmp_32 = 0;
|
||||
for( j = M - 1; j > i; j-- ) {
|
||||
tmp_32 = silk_SMLAWW( tmp_32, ptr32[ silk_SMULBB( j, M ) ], x_Q16[ j ] );
|
||||
}
|
||||
x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 );
|
||||
}
|
||||
}
|
||||
|
|
@ -47,31 +47,17 @@ typedef struct {
|
|||
opus_int32 Tilt_smth_Q16;
|
||||
} silk_shape_state_FIX;
|
||||
|
||||
/********************************/
|
||||
/* Prefilter state */
|
||||
/********************************/
|
||||
typedef struct {
|
||||
opus_int16 sLTP_shp[ LTP_BUF_LENGTH ];
|
||||
opus_int32 sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ];
|
||||
opus_int sLTP_shp_buf_idx;
|
||||
opus_int32 sLF_AR_shp_Q12;
|
||||
opus_int32 sLF_MA_shp_Q12;
|
||||
opus_int32 sHarmHP_Q2;
|
||||
opus_int32 rand_seed;
|
||||
opus_int lagPrev;
|
||||
} silk_prefilter_state_FIX;
|
||||
|
||||
/********************************/
|
||||
/* Encoder state FIX */
|
||||
/********************************/
|
||||
typedef struct {
|
||||
silk_encoder_state sCmn; /* Common struct, shared with floating-point code */
|
||||
silk_shape_state_FIX sShape; /* Shape state */
|
||||
silk_prefilter_state_FIX sPrefilt; /* Prefilter State */
|
||||
|
||||
/* Buffer for find pitch and noise shape analysis */
|
||||
silk_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
|
||||
opus_int LTPCorr_Q15; /* Normalized correlation from pitch lag estimator */
|
||||
opus_int32 resNrgSmth;
|
||||
} silk_encoder_state_FIX;
|
||||
|
||||
/************************/
|
||||
|
|
@ -87,11 +73,8 @@ typedef struct {
|
|||
|
||||
/* Noise shaping parameters */
|
||||
/* Testing */
|
||||
silk_DWORD_ALIGN opus_int16 AR1_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
|
||||
silk_DWORD_ALIGN opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
|
||||
silk_DWORD_ALIGN opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
|
||||
opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */
|
||||
opus_int GainsPre_Q14[ MAX_NB_SUBFR ];
|
||||
opus_int HarmBoost_Q14[ MAX_NB_SUBFR ];
|
||||
opus_int Tilt_Q14[ MAX_NB_SUBFR ];
|
||||
opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ];
|
||||
opus_int Lambda_Q10;
|
||||
|
|
@ -99,7 +82,6 @@ typedef struct {
|
|||
opus_int coding_quality_Q14;
|
||||
|
||||
/* measures */
|
||||
opus_int sparseness_Q8;
|
||||
opus_int32 predGain_Q16;
|
||||
opus_int LTPredCodGain_Q7;
|
||||
opus_int32 ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ opus_int32 silk_inner_prod_aligned(
|
|||
#endif
|
||||
}
|
||||
|
||||
opus_int64 silk_inner_prod16_aligned_64_c(
|
||||
opus_int64 silk_inner_prod16_c(
|
||||
const opus_int16 *inVec1, /* I input vector 1 */
|
||||
const opus_int16 *inVec2, /* I input vector 2 */
|
||||
const opus_int len /* I vector lengths */
|
||||
|
|
|
|||
|
|
@ -31,17 +31,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "main_FIX.h"
|
||||
|
||||
#define QC 10
|
||||
#define QS 14
|
||||
|
||||
#if defined(MIPSr1_ASM)
|
||||
#include "mips/warped_autocorrelation_FIX_mipsr1.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef OVERRIDE_silk_warped_autocorrelation_FIX
|
||||
/* Autocorrelations for a warped frequency axis */
|
||||
void silk_warped_autocorrelation_FIX(
|
||||
#ifndef OVERRIDE_silk_warped_autocorrelation_FIX_c
|
||||
void silk_warped_autocorrelation_FIX_c(
|
||||
opus_int32 *corr, /* O Result [order + 1] */
|
||||
opus_int *scale, /* O Scaling of the correlation vector */
|
||||
const opus_int16 *input, /* I Input data to correlate */
|
||||
|
|
@ -56,7 +53,7 @@ void silk_warped_autocorrelation_FIX(
|
|||
opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
|
||||
|
||||
/* Order must be even */
|
||||
silk_assert( ( order & 1 ) == 0 );
|
||||
celt_assert( ( order & 1 ) == 0 );
|
||||
silk_assert( 2 * QS - QC >= 0 );
|
||||
|
||||
/* Loop over samples */
|
||||
|
|
@ -92,4 +89,4 @@ void silk_warped_autocorrelation_FIX(
|
|||
}
|
||||
silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/
|
||||
}
|
||||
#endif /* OVERRIDE_silk_warped_autocorrelation_FIX */
|
||||
#endif /* OVERRIDE_silk_warped_autocorrelation_FIX_c */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2014, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang
|
||||
/* Copyright (c) 2014-2020, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang FrancisQuiers
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */
|
||||
|
||||
#define QA 25
|
||||
#define N_BITS_HEAD_ROOM 2
|
||||
#define N_BITS_HEAD_ROOM 3
|
||||
#define MIN_RSHIFTS -16
|
||||
#define MAX_RSHIFTS (32 - QA)
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ void silk_burg_modified_sse4_1(
|
|||
int arch /* I Run-time architecture */
|
||||
)
|
||||
{
|
||||
opus_int k, n, s, lz, rshifts, rshifts_extra, reached_max_gain;
|
||||
opus_int k, n, s, lz, rshifts, reached_max_gain;
|
||||
opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2;
|
||||
const opus_int16 *x_ptr;
|
||||
opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ];
|
||||
|
|
@ -68,30 +68,26 @@ void silk_burg_modified_sse4_1(
|
|||
opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ];
|
||||
opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ];
|
||||
opus_int32 xcorr[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int64 C0_64;
|
||||
|
||||
__m128i FIRST_3210, LAST_3210, ATMP_3210, TMP1_3210, TMP2_3210, T1_3210, T2_3210, PTR_3210, SUBFR_3210, X1_3210, X2_3210;
|
||||
__m128i CONST1 = _mm_set1_epi32(1);
|
||||
|
||||
silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
|
||||
celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
|
||||
|
||||
/* Compute autocorrelations, added over subframes */
|
||||
silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length );
|
||||
if( rshifts > MAX_RSHIFTS ) {
|
||||
C0 = silk_LSHIFT32( C0, rshifts - MAX_RSHIFTS );
|
||||
silk_assert( C0 > 0 );
|
||||
rshifts = MAX_RSHIFTS;
|
||||
C0_64 = silk_inner_prod16( x, x, subfr_length*nb_subfr, arch );
|
||||
lz = silk_CLZ64(C0_64);
|
||||
rshifts = 32 + 1 + N_BITS_HEAD_ROOM - lz;
|
||||
if (rshifts > MAX_RSHIFTS) rshifts = MAX_RSHIFTS;
|
||||
if (rshifts < MIN_RSHIFTS) rshifts = MIN_RSHIFTS;
|
||||
|
||||
if (rshifts > 0) {
|
||||
C0 = (opus_int32)silk_RSHIFT64(C0_64, rshifts );
|
||||
} else {
|
||||
lz = silk_CLZ32( C0 ) - 1;
|
||||
rshifts_extra = N_BITS_HEAD_ROOM - lz;
|
||||
if( rshifts_extra > 0 ) {
|
||||
rshifts_extra = silk_min( rshifts_extra, MAX_RSHIFTS - rshifts );
|
||||
C0 = silk_RSHIFT32( C0, rshifts_extra );
|
||||
} else {
|
||||
rshifts_extra = silk_max( rshifts_extra, MIN_RSHIFTS - rshifts );
|
||||
C0 = silk_LSHIFT32( C0, -rshifts_extra );
|
||||
}
|
||||
rshifts += rshifts_extra;
|
||||
C0 = silk_LSHIFT32((opus_int32)C0_64, -rshifts );
|
||||
}
|
||||
|
||||
CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */
|
||||
silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) );
|
||||
if( rshifts > 0 ) {
|
||||
|
|
@ -99,7 +95,7 @@ void silk_burg_modified_sse4_1(
|
|||
x_ptr = x + s * subfr_length;
|
||||
for( n = 1; n < D + 1; n++ ) {
|
||||
C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64(
|
||||
silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts );
|
||||
silk_inner_prod16( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -203,8 +199,11 @@ void silk_burg_modified_sse4_1(
|
|||
C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */
|
||||
C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */
|
||||
Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */
|
||||
tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */
|
||||
tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */
|
||||
/* We sometimes get overflows in the multiplications (even beyond +/- 2^32),
|
||||
but they cancel each other and the real result seems to always fit in a 32-bit
|
||||
signed integer. This was determined experimentally, not theoretically (unfortunately). */
|
||||
tmp1 = silk_MLA_ovflw( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */
|
||||
tmp2 = silk_MLA_ovflw( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */
|
||||
}
|
||||
|
||||
tmp1 = -tmp1; /* Q17 */
|
||||
|
|
@ -350,7 +349,7 @@ void silk_burg_modified_sse4_1(
|
|||
if( rshifts > 0 ) {
|
||||
for( s = 0; s < nb_subfr; s++ ) {
|
||||
x_ptr = x + s * subfr_length;
|
||||
C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D, arch ), rshifts );
|
||||
C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16( x_ptr, x_ptr, D, arch ), rshifts );
|
||||
}
|
||||
} else {
|
||||
for( s = 0; s < nb_subfr; s++ ) {
|
||||
|
|
@ -374,4 +373,28 @@ void silk_burg_modified_sse4_1(
|
|||
*res_nrg = silk_SMLAWW( nrg, silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ), -tmp1 );/* Q( -rshifts ) */
|
||||
*res_nrg_Q = -rshifts;
|
||||
}
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
{
|
||||
opus_int32 res_nrg_c = 0;
|
||||
opus_int res_nrg_Q_c = 0;
|
||||
opus_int32 A_Q16_c[ MAX_LPC_ORDER ] = {0};
|
||||
|
||||
silk_burg_modified_c(
|
||||
&res_nrg_c,
|
||||
&res_nrg_Q_c,
|
||||
A_Q16_c,
|
||||
x,
|
||||
minInvGain_Q30,
|
||||
subfr_length,
|
||||
nb_subfr,
|
||||
D,
|
||||
0
|
||||
);
|
||||
|
||||
silk_assert( *res_nrg == res_nrg_c );
|
||||
silk_assert( *res_nrg_Q == res_nrg_Q_c );
|
||||
silk_assert( !memcmp( A_Q16, A_Q16_c, D * sizeof( *A_Q16 ) ) );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
/* Copyright (c) 2014, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <xmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#include <smmintrin.h>
|
||||
#include "main.h"
|
||||
#include "celt/x86/x86cpu.h"
|
||||
|
||||
void silk_warped_LPC_analysis_filter_FIX_sse4_1(
|
||||
opus_int32 state[], /* I/O State [order + 1] */
|
||||
opus_int32 res_Q2[], /* O Residual signal [length] */
|
||||
const opus_int16 coef_Q13[], /* I Coefficients [order] */
|
||||
const opus_int16 input[], /* I Input signal [length] */
|
||||
const opus_int16 lambda_Q16, /* I Warping factor */
|
||||
const opus_int length, /* I Length of input signal */
|
||||
const opus_int order /* I Filter order (even) */
|
||||
)
|
||||
{
|
||||
opus_int n, i;
|
||||
opus_int32 acc_Q11, tmp1, tmp2;
|
||||
|
||||
/* Order must be even */
|
||||
silk_assert( ( order & 1 ) == 0 );
|
||||
|
||||
if (order == 10)
|
||||
{
|
||||
if (0 == lambda_Q16)
|
||||
{
|
||||
__m128i coef_Q13_3210, coef_Q13_7654;
|
||||
__m128i coef_Q13_0123, coef_Q13_4567;
|
||||
__m128i state_0123, state_4567;
|
||||
__m128i xmm_product1, xmm_product2;
|
||||
__m128i xmm_tempa, xmm_tempb;
|
||||
|
||||
register opus_int32 sum;
|
||||
register opus_int32 state_8, state_9, state_a;
|
||||
register opus_int64 coef_Q13_8, coef_Q13_9;
|
||||
|
||||
silk_assert( length > 0 );
|
||||
|
||||
coef_Q13_3210 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 0 ] );
|
||||
coef_Q13_7654 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 4 ] );
|
||||
|
||||
coef_Q13_0123 = _mm_shuffle_epi32( coef_Q13_3210, _MM_SHUFFLE( 0, 1, 2, 3 ) );
|
||||
coef_Q13_4567 = _mm_shuffle_epi32( coef_Q13_7654, _MM_SHUFFLE( 0, 1, 2, 3 ) );
|
||||
|
||||
coef_Q13_8 = (opus_int64) coef_Q13[ 8 ];
|
||||
coef_Q13_9 = (opus_int64) coef_Q13[ 9 ];
|
||||
|
||||
state_0123 = _mm_loadu_si128( (__m128i *)(&state[ 0 ] ) );
|
||||
state_4567 = _mm_loadu_si128( (__m128i *)(&state[ 4 ] ) );
|
||||
|
||||
state_0123 = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) );
|
||||
state_4567 = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) );
|
||||
|
||||
state_8 = state[ 8 ];
|
||||
state_9 = state[ 9 ];
|
||||
state_a = 0;
|
||||
|
||||
for( n = 0; n < length; n++ )
|
||||
{
|
||||
xmm_product1 = _mm_mul_epi32( coef_Q13_0123, state_0123 ); /* 64-bit multiply, only 2 pairs */
|
||||
xmm_product2 = _mm_mul_epi32( coef_Q13_4567, state_4567 );
|
||||
|
||||
xmm_tempa = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) );
|
||||
xmm_tempb = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) );
|
||||
|
||||
xmm_product1 = _mm_srli_epi64( xmm_product1, 16 ); /* >> 16, zero extending works */
|
||||
xmm_product2 = _mm_srli_epi64( xmm_product2, 16 );
|
||||
|
||||
xmm_tempa = _mm_mul_epi32( coef_Q13_3210, xmm_tempa );
|
||||
xmm_tempb = _mm_mul_epi32( coef_Q13_7654, xmm_tempb );
|
||||
|
||||
xmm_tempa = _mm_srli_epi64( xmm_tempa, 16 );
|
||||
xmm_tempb = _mm_srli_epi64( xmm_tempb, 16 );
|
||||
|
||||
xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_product1 );
|
||||
xmm_tempb = _mm_add_epi32( xmm_tempb, xmm_product2 );
|
||||
xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_tempb );
|
||||
|
||||
sum = (coef_Q13_8 * state_8) >> 16;
|
||||
sum += (coef_Q13_9 * state_9) >> 16;
|
||||
|
||||
xmm_tempa = _mm_add_epi32( xmm_tempa, _mm_shuffle_epi32( xmm_tempa, _MM_SHUFFLE( 0, 0, 0, 2 ) ) );
|
||||
sum += _mm_cvtsi128_si32( xmm_tempa);
|
||||
res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( ( 5 + sum ), 9);
|
||||
|
||||
/* move right */
|
||||
state_a = state_9;
|
||||
state_9 = state_8;
|
||||
state_8 = _mm_cvtsi128_si32( state_4567 );
|
||||
state_4567 = _mm_alignr_epi8( state_0123, state_4567, 4 );
|
||||
|
||||
state_0123 = _mm_alignr_epi8( _mm_cvtsi32_si128( silk_LSHIFT( input[ n ], 14 ) ), state_0123, 4 );
|
||||
}
|
||||
|
||||
_mm_storeu_si128( (__m128i *)( &state[ 0 ] ), _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ) );
|
||||
_mm_storeu_si128( (__m128i *)( &state[ 4 ] ), _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ) );
|
||||
state[ 8 ] = state_8;
|
||||
state[ 9 ] = state_9;
|
||||
state[ 10 ] = state_a;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for( n = 0; n < length; n++ ) {
|
||||
/* Output of lowpass section */
|
||||
tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
|
||||
state[ 0 ] = silk_LSHIFT( input[ n ], 14 );
|
||||
/* Output of allpass section */
|
||||
tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
|
||||
state[ 1 ] = tmp2;
|
||||
acc_Q11 = silk_RSHIFT( order, 1 );
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
|
||||
/* Loop over allpass sections */
|
||||
for( i = 2; i < order; i += 2 ) {
|
||||
/* Output of allpass section */
|
||||
tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
|
||||
state[ i ] = tmp1;
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
|
||||
/* Output of allpass section */
|
||||
tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
|
||||
state[ i + 1 ] = tmp2;
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
|
||||
}
|
||||
state[ order ] = tmp1;
|
||||
acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
|
||||
res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
|
||||
}
|
||||
}
|
||||
|
|
@ -37,39 +37,36 @@
|
|||
#include "SigProc_FIX.h"
|
||||
#include "pitch.h"
|
||||
|
||||
opus_int64 silk_inner_prod16_aligned_64_sse4_1(
|
||||
opus_int64 silk_inner_prod16_sse4_1(
|
||||
const opus_int16 *inVec1, /* I input vector 1 */
|
||||
const opus_int16 *inVec2, /* I input vector 2 */
|
||||
const opus_int len /* I vector lengths */
|
||||
)
|
||||
{
|
||||
opus_int i, dataSize8;
|
||||
opus_int i, dataSize4;
|
||||
opus_int64 sum;
|
||||
|
||||
__m128i xmm_tempa;
|
||||
__m128i inVec1_76543210, acc1;
|
||||
__m128i inVec2_76543210, acc2;
|
||||
__m128i xmm_prod_20, xmm_prod_31;
|
||||
__m128i inVec1_3210, acc1;
|
||||
__m128i inVec2_3210, acc2;
|
||||
|
||||
sum = 0;
|
||||
dataSize8 = len & ~7;
|
||||
dataSize4 = len & ~3;
|
||||
|
||||
acc1 = _mm_setzero_si128();
|
||||
acc2 = _mm_setzero_si128();
|
||||
|
||||
for( i = 0; i < dataSize8; i += 8 ) {
|
||||
inVec1_76543210 = _mm_loadu_si128( (__m128i *)(&inVec1[i + 0] ) );
|
||||
inVec2_76543210 = _mm_loadu_si128( (__m128i *)(&inVec2[i + 0] ) );
|
||||
for( i = 0; i < dataSize4; i += 4 ) {
|
||||
inVec1_3210 = OP_CVTEPI16_EPI32_M64( &inVec1[i + 0] );
|
||||
inVec2_3210 = OP_CVTEPI16_EPI32_M64( &inVec2[i + 0] );
|
||||
xmm_prod_20 = _mm_mul_epi32( inVec1_3210, inVec2_3210 );
|
||||
|
||||
/* only when all 4 operands are -32768 (0x8000), this results in wrap around */
|
||||
inVec1_76543210 = _mm_madd_epi16( inVec1_76543210, inVec2_76543210 );
|
||||
inVec1_3210 = _mm_shuffle_epi32( inVec1_3210, _MM_SHUFFLE( 0, 3, 2, 1 ) );
|
||||
inVec2_3210 = _mm_shuffle_epi32( inVec2_3210, _MM_SHUFFLE( 0, 3, 2, 1 ) );
|
||||
xmm_prod_31 = _mm_mul_epi32( inVec1_3210, inVec2_3210 );
|
||||
|
||||
xmm_tempa = _mm_cvtepi32_epi64( inVec1_76543210 );
|
||||
/* equal shift right 8 bytes */
|
||||
inVec1_76543210 = _mm_shuffle_epi32( inVec1_76543210, _MM_SHUFFLE( 0, 0, 3, 2 ) );
|
||||
inVec1_76543210 = _mm_cvtepi32_epi64( inVec1_76543210 );
|
||||
|
||||
acc1 = _mm_add_epi64( acc1, xmm_tempa );
|
||||
acc2 = _mm_add_epi64( acc2, inVec1_76543210 );
|
||||
acc1 = _mm_add_epi64( acc1, xmm_prod_20 );
|
||||
acc2 = _mm_add_epi64( acc2, xmm_prod_31 );
|
||||
}
|
||||
|
||||
acc1 = _mm_add_epi64( acc1, acc2 );
|
||||
|
|
@ -84,5 +81,12 @@ opus_int64 silk_inner_prod16_aligned_64_sse4_1(
|
|||
sum = silk_SMLABB( sum, inVec1[ i ], inVec2[ i ] );
|
||||
}
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
{
|
||||
opus_int64 sum_c = silk_inner_prod16_c( inVec1, inVec2, len );
|
||||
silk_assert( sum == sum_c );
|
||||
}
|
||||
#endif
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
|
@ -215,7 +215,7 @@ void silk_LPC_analysis_filter_FLP(
|
|||
const opus_int Order /* I LPC order */
|
||||
)
|
||||
{
|
||||
silk_assert( Order <= length );
|
||||
celt_assert( Order <= length );
|
||||
|
||||
switch( Order ) {
|
||||
case 6:
|
||||
|
|
@ -239,7 +239,7 @@ void silk_LPC_analysis_filter_FLP(
|
|||
break;
|
||||
|
||||
default:
|
||||
silk_assert( 0 );
|
||||
celt_assert( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "SigProc_FIX.h"
|
||||
#include "SigProc_FLP.h"
|
||||
|
||||
#define RC_THRESHOLD 0.9999f
|
||||
#include "define.h"
|
||||
|
||||
/* compute inverse of LPC prediction gain, and */
|
||||
/* test if LPC coefficients are stable (all poles within unit circle) */
|
||||
|
|
@ -43,34 +42,32 @@ silk_float silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction ga
|
|||
)
|
||||
{
|
||||
opus_int k, n;
|
||||
double invGain, rc, rc_mult1, rc_mult2;
|
||||
silk_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ];
|
||||
silk_float *Aold, *Anew;
|
||||
double invGain, rc, rc_mult1, rc_mult2, tmp1, tmp2;
|
||||
silk_float Atmp[ SILK_MAX_ORDER_LPC ];
|
||||
|
||||
Anew = Atmp[ order & 1 ];
|
||||
silk_memcpy( Anew, A, order * sizeof(silk_float) );
|
||||
silk_memcpy( Atmp, A, order * sizeof(silk_float) );
|
||||
|
||||
invGain = 1.0;
|
||||
for( k = order - 1; k > 0; k-- ) {
|
||||
rc = -Anew[ k ];
|
||||
if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
|
||||
rc = -Atmp[ k ];
|
||||
rc_mult1 = 1.0f - rc * rc;
|
||||
invGain *= rc_mult1;
|
||||
if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
|
||||
return 0.0f;
|
||||
}
|
||||
rc_mult1 = 1.0f - rc * rc;
|
||||
rc_mult2 = 1.0f / rc_mult1;
|
||||
invGain *= rc_mult1;
|
||||
/* swap pointers */
|
||||
Aold = Anew;
|
||||
Anew = Atmp[ k & 1 ];
|
||||
for( n = 0; n < k; n++ ) {
|
||||
Anew[ n ] = (silk_float)( ( Aold[ n ] - Aold[ k - n - 1 ] * rc ) * rc_mult2 );
|
||||
for( n = 0; n < (k + 1) >> 1; n++ ) {
|
||||
tmp1 = Atmp[ n ];
|
||||
tmp2 = Atmp[ k - n - 1 ];
|
||||
Atmp[ n ] = (silk_float)( ( tmp1 - tmp2 * rc ) * rc_mult2 );
|
||||
Atmp[ k - n - 1 ] = (silk_float)( ( tmp2 - tmp1 * rc ) * rc_mult2 );
|
||||
}
|
||||
}
|
||||
rc = -Anew[ 0 ];
|
||||
if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
|
||||
return 0.0f;
|
||||
}
|
||||
rc = -Atmp[ 0 ];
|
||||
rc_mult1 = 1.0f - rc * rc;
|
||||
invGain *= rc_mult1;
|
||||
if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
|
||||
return 0.0f;
|
||||
}
|
||||
return (silk_float)invGain;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,13 +68,6 @@ void silk_k2a_FLP(
|
|||
opus_int32 order /* I prediction order */
|
||||
);
|
||||
|
||||
/* Solve the normal equations using the Levinson-Durbin recursion */
|
||||
silk_float silk_levinsondurbin_FLP( /* O prediction error energy */
|
||||
silk_float A[], /* O prediction coefficients [order] */
|
||||
const silk_float corr[], /* I input auto-correlations [order + 1] */
|
||||
const opus_int order /* I prediction order */
|
||||
);
|
||||
|
||||
/* compute autocorrelation */
|
||||
void silk_autocorrelation_FLP(
|
||||
silk_float *results, /* O result (length correlationCount) */
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ void silk_apply_sine_window_FLP(
|
|||
opus_int k;
|
||||
silk_float freq, c, S0, S1;
|
||||
|
||||
silk_assert( win_type == 1 || win_type == 2 );
|
||||
celt_assert( win_type == 1 || win_type == 2 );
|
||||
|
||||
/* Length must be multiple of 4 */
|
||||
silk_assert( ( length & 3 ) == 0 );
|
||||
celt_assert( ( length & 3 ) == 0 );
|
||||
|
||||
freq = PI / ( length + 1 );
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy
|
|||
double CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ];
|
||||
double Af[ SILK_MAX_ORDER_LPC ];
|
||||
|
||||
silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
|
||||
celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
|
||||
|
||||
/* Compute autocorrelations, added over subframes */
|
||||
C0 = silk_energy_FLP( x, nb_subfr * subfr_length );
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "main_FLP.h"
|
||||
#include "tuning_parameters.h"
|
||||
|
||||
|
|
@ -41,21 +42,28 @@ static OPUS_INLINE void silk_LBRR_encode_FLP(
|
|||
);
|
||||
|
||||
void silk_encode_do_VAD_FLP(
|
||||
silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */
|
||||
silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
|
||||
opus_int activity /* I Decision of Opus voice activity detector */
|
||||
)
|
||||
{
|
||||
const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
|
||||
|
||||
/****************************/
|
||||
/* Voice Activity Detection */
|
||||
/****************************/
|
||||
silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
|
||||
/* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
|
||||
if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
|
||||
psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* Convert speech activity into VAD and DTX flags */
|
||||
/**************************************************/
|
||||
if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) {
|
||||
if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
|
||||
psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
|
||||
psEnc->sCmn.noSpeechCounter++;
|
||||
if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) {
|
||||
if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
|
||||
psEnc->sCmn.inDTX = 0;
|
||||
} else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
|
||||
psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
|
||||
|
|
@ -85,7 +93,6 @@ opus_int silk_encode_frame_FLP(
|
|||
silk_encoder_control_FLP sEncCtrl;
|
||||
opus_int i, iter, maxIter, found_upper, found_lower, ret = 0;
|
||||
silk_float *x_frame, *res_pitch_frame;
|
||||
silk_float xfw[ MAX_FRAME_LENGTH ];
|
||||
silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
|
||||
ec_enc sRangeEnc_copy, sRangeEnc_copy2;
|
||||
silk_nsq_state sNSQ_copy, sNSQ_copy2;
|
||||
|
|
@ -97,6 +104,9 @@ opus_int silk_encode_frame_FLP(
|
|||
opus_int8 LastGainIndex_copy2;
|
||||
opus_int32 pGains_Q16[ MAX_NB_SUBFR ];
|
||||
opus_uint8 ec_buf_copy[ 1275 ];
|
||||
opus_int gain_lock[ MAX_NB_SUBFR ] = {0};
|
||||
opus_int16 best_gain_mult[ MAX_NB_SUBFR ];
|
||||
opus_int best_sum[ MAX_NB_SUBFR ];
|
||||
|
||||
/* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
|
||||
LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
|
||||
|
|
@ -139,22 +149,17 @@ opus_int silk_encode_frame_FLP(
|
|||
/***************************************************/
|
||||
/* Find linear prediction coefficients (LPC + LTP) */
|
||||
/***************************************************/
|
||||
silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding );
|
||||
silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
|
||||
|
||||
/****************************************/
|
||||
/* Process gains */
|
||||
/****************************************/
|
||||
silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding );
|
||||
|
||||
/*****************************************/
|
||||
/* Prefiltering for noise shaper */
|
||||
/*****************************************/
|
||||
silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame );
|
||||
|
||||
/****************************************/
|
||||
/* Low Bitrate Redundant Encoding */
|
||||
/****************************************/
|
||||
silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding );
|
||||
silk_LBRR_encode_FLP( psEnc, &sEncCtrl, x_frame, condCoding );
|
||||
|
||||
/* Loop over quantizer and entroy coding to control bitrate */
|
||||
maxIter = 6;
|
||||
|
|
@ -188,7 +193,11 @@ opus_int silk_encode_frame_FLP(
|
|||
/*****************************************/
|
||||
/* Noise shaping quantization */
|
||||
/*****************************************/
|
||||
silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw );
|
||||
silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, x_frame );
|
||||
|
||||
if ( iter == maxIter && !found_lower ) {
|
||||
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
/* Encode Parameters */
|
||||
|
|
@ -203,6 +212,33 @@ opus_int silk_encode_frame_FLP(
|
|||
|
||||
nBits = ec_tell( psRangeEnc );
|
||||
|
||||
/* If we still bust after the last iteration, do some damage control. */
|
||||
if ( iter == maxIter && !found_lower && nBits > maxBits ) {
|
||||
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
|
||||
|
||||
/* Keep gains the same as the last frame. */
|
||||
psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
|
||||
for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
|
||||
psEnc->sCmn.indices.GainsIndices[ i ] = 4;
|
||||
}
|
||||
if (condCoding != CODE_CONDITIONALLY) {
|
||||
psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
|
||||
}
|
||||
psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
|
||||
psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
|
||||
/* Clear all pulses. */
|
||||
for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
|
||||
psEnc->sCmn.pulses[ i ] = 0;
|
||||
}
|
||||
|
||||
silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
|
||||
|
||||
silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
|
||||
psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
|
||||
|
||||
nBits = ec_tell( psRangeEnc );
|
||||
}
|
||||
|
||||
if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -212,7 +248,7 @@ opus_int silk_encode_frame_FLP(
|
|||
if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
|
||||
/* Restore output state from earlier iteration that did meet the bitrate budget */
|
||||
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
|
||||
silk_assert( sRangeEnc_copy2.offs <= 1275 );
|
||||
celt_assert( sRangeEnc_copy2.offs <= 1275 );
|
||||
silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
|
||||
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
|
||||
psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
|
||||
|
|
@ -223,7 +259,9 @@ opus_int silk_encode_frame_FLP(
|
|||
if( nBits > maxBits ) {
|
||||
if( found_lower == 0 && iter >= 2 ) {
|
||||
/* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
|
||||
sEncCtrl.Lambda *= 1.5f;
|
||||
sEncCtrl.Lambda = silk_max_float(sEncCtrl.Lambda*1.5f, 1.5f);
|
||||
/* Reducing dithering can help us hit the target. */
|
||||
psEnc->sCmn.indices.quantOffsetType = 0;
|
||||
found_upper = 0;
|
||||
gainsID_upper = -1;
|
||||
} else {
|
||||
|
|
@ -240,7 +278,7 @@ opus_int silk_encode_frame_FLP(
|
|||
gainsID_lower = gainsID;
|
||||
/* Copy part of the output state */
|
||||
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
|
||||
silk_assert( psRangeEnc->offs <= 1275 );
|
||||
celt_assert( psRangeEnc->offs <= 1275 );
|
||||
silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
|
||||
silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
|
||||
LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
|
||||
|
|
@ -250,15 +288,34 @@ opus_int silk_encode_frame_FLP(
|
|||
break;
|
||||
}
|
||||
|
||||
if ( !found_lower && nBits > maxBits ) {
|
||||
int j;
|
||||
for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
|
||||
int sum=0;
|
||||
for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
|
||||
sum += abs( psEnc->sCmn.pulses[j] );
|
||||
}
|
||||
if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
|
||||
best_sum[i] = sum;
|
||||
best_gain_mult[i] = gainMult_Q8;
|
||||
} else {
|
||||
gain_lock[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( ( found_lower & found_upper ) == 0 ) {
|
||||
/* Adjust gain according to high-rate rate/distortion curve */
|
||||
opus_int32 gain_factor_Q16;
|
||||
gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
|
||||
gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) );
|
||||
if( nBits > maxBits ) {
|
||||
gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
|
||||
if (gainMult_Q8 < 16384) {
|
||||
gainMult_Q8 *= 2;
|
||||
} else {
|
||||
gainMult_Q8 = 32767;
|
||||
}
|
||||
} else {
|
||||
opus_int32 gain_factor_Q16;
|
||||
gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
|
||||
gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
|
||||
}
|
||||
gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
|
||||
} else {
|
||||
/* Adjust gain by interpolating */
|
||||
gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower );
|
||||
|
|
@ -272,7 +329,13 @@ opus_int silk_encode_frame_FLP(
|
|||
}
|
||||
|
||||
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
|
||||
pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 );
|
||||
opus_int16 tmp;
|
||||
if ( gain_lock[i] ) {
|
||||
tmp = best_gain_mult[i];
|
||||
} else {
|
||||
tmp = gainMult_Q8;
|
||||
}
|
||||
pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
|
||||
}
|
||||
|
||||
/* Quantize gains */
|
||||
|
|
|
|||
|
|
@ -37,13 +37,12 @@ double silk_energy_FLP(
|
|||
opus_int dataSize
|
||||
)
|
||||
{
|
||||
opus_int i, dataSize4;
|
||||
opus_int i;
|
||||
double result;
|
||||
|
||||
/* 4x unrolled loop */
|
||||
result = 0.0;
|
||||
dataSize4 = dataSize & 0xFFFC;
|
||||
for( i = 0; i < dataSize4; i += 4 ) {
|
||||
for( i = 0; i < dataSize - 3; i += 4 ) {
|
||||
result += data[ i + 0 ] * (double)data[ i + 0 ] +
|
||||
data[ i + 1 ] * (double)data[ i + 1 ] +
|
||||
data[ i + 2 ] * (double)data[ i + 2 ] +
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ void silk_find_LPC_FLP(
|
|||
silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
|
||||
|
||||
/* Convert to LPC for residual energy evaluation */
|
||||
silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder );
|
||||
silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
|
||||
|
||||
/* Calculate residual energy with LSF interpolation */
|
||||
silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, psEncC->predictLPCOrder );
|
||||
|
|
@ -99,6 +99,6 @@ void silk_find_LPC_FLP(
|
|||
silk_A2NLSF_FLP( NLSF_Q15, a, psEncC->predictLPCOrder );
|
||||
}
|
||||
|
||||
silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
|
||||
celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
|
||||
( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,100 +33,32 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "tuning_parameters.h"
|
||||
|
||||
void silk_find_LTP_FLP(
|
||||
silk_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
|
||||
silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
|
||||
silk_float *LTPredCodGain, /* O LTP coding gain */
|
||||
const silk_float r_lpc[], /* I LPC residual */
|
||||
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
|
||||
const silk_float Wght[ MAX_NB_SUBFR ], /* I Weights */
|
||||
silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
|
||||
silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* O Weight for LTP quantization */
|
||||
const silk_float r_ptr[], /* I LPC residual */
|
||||
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
|
||||
const opus_int subfr_length, /* I Subframe length */
|
||||
const opus_int nb_subfr, /* I number of subframes */
|
||||
const opus_int mem_offset /* I Number of samples in LTP memory */
|
||||
const opus_int nb_subfr /* I number of subframes */
|
||||
)
|
||||
{
|
||||
opus_int i, k;
|
||||
silk_float *b_ptr, temp, *WLTP_ptr;
|
||||
silk_float LPC_res_nrg, LPC_LTP_res_nrg;
|
||||
silk_float d[ MAX_NB_SUBFR ], m, g, delta_b[ LTP_ORDER ];
|
||||
silk_float w[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], regu;
|
||||
silk_float Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ];
|
||||
const silk_float *r_ptr, *lag_ptr;
|
||||
opus_int k;
|
||||
silk_float *xX_ptr, *XX_ptr;
|
||||
const silk_float *lag_ptr;
|
||||
silk_float xx, temp;
|
||||
|
||||
b_ptr = b;
|
||||
WLTP_ptr = WLTP;
|
||||
r_ptr = &r_lpc[ mem_offset ];
|
||||
xX_ptr = xX;
|
||||
XX_ptr = XX;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
|
||||
silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, XX_ptr );
|
||||
silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xX_ptr );
|
||||
xx = ( silk_float )silk_energy_FLP( r_ptr, subfr_length + LTP_ORDER );
|
||||
temp = 1.0f / silk_max( xx, LTP_CORR_INV_MAX * 0.5f * ( XX_ptr[ 0 ] + XX_ptr[ 24 ] ) + 1.0f );
|
||||
silk_scale_vector_FLP( XX_ptr, temp, LTP_ORDER * LTP_ORDER );
|
||||
silk_scale_vector_FLP( xX_ptr, temp, LTP_ORDER );
|
||||
|
||||
silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, WLTP_ptr );
|
||||
silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr );
|
||||
|
||||
rr[ k ] = ( silk_float )silk_energy_FLP( r_ptr, subfr_length );
|
||||
regu = 1.0f + rr[ k ] +
|
||||
matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ) +
|
||||
matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER );
|
||||
regu *= LTP_DAMPING / 3;
|
||||
silk_regularize_correlations_FLP( WLTP_ptr, &rr[ k ], regu, LTP_ORDER );
|
||||
silk_solve_LDL_FLP( WLTP_ptr, LTP_ORDER, Rr, b_ptr );
|
||||
|
||||
/* Calculate residual energy */
|
||||
nrg[ k ] = silk_residual_energy_covar_FLP( b_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER );
|
||||
|
||||
temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length );
|
||||
silk_scale_vector_FLP( WLTP_ptr, temp, LTP_ORDER * LTP_ORDER );
|
||||
w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER / 2, LTP_ORDER / 2, LTP_ORDER );
|
||||
|
||||
r_ptr += subfr_length;
|
||||
b_ptr += LTP_ORDER;
|
||||
WLTP_ptr += LTP_ORDER * LTP_ORDER;
|
||||
}
|
||||
|
||||
/* Compute LTP coding gain */
|
||||
if( LTPredCodGain != NULL ) {
|
||||
LPC_LTP_res_nrg = 1e-6f;
|
||||
LPC_res_nrg = 0.0f;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
LPC_res_nrg += rr[ k ] * Wght[ k ];
|
||||
LPC_LTP_res_nrg += nrg[ k ] * Wght[ k ];
|
||||
}
|
||||
|
||||
silk_assert( LPC_LTP_res_nrg > 0 );
|
||||
*LTPredCodGain = 3.0f * silk_log2( LPC_res_nrg / LPC_LTP_res_nrg );
|
||||
}
|
||||
|
||||
/* Smoothing */
|
||||
/* d = sum( B, 1 ); */
|
||||
b_ptr = b;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
d[ k ] = 0;
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
d[ k ] += b_ptr[ i ];
|
||||
}
|
||||
b_ptr += LTP_ORDER;
|
||||
}
|
||||
/* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */
|
||||
temp = 1e-3f;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
temp += w[ k ];
|
||||
}
|
||||
m = 0;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
m += d[ k ] * w[ k ];
|
||||
}
|
||||
m = m / temp;
|
||||
|
||||
b_ptr = b;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
g = LTP_SMOOTHING / ( LTP_SMOOTHING + w[ k ] ) * ( m - d[ k ] );
|
||||
temp = 0;
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
delta_b[ i ] = silk_max_float( b_ptr[ i ], 0.1f );
|
||||
temp += delta_b[ i ];
|
||||
}
|
||||
temp = g / temp;
|
||||
for( i = 0; i < LTP_ORDER; i++ ) {
|
||||
b_ptr[ i ] = b_ptr[ i ] + delta_b[ i ] * temp;
|
||||
}
|
||||
b_ptr += LTP_ORDER;
|
||||
r_ptr += subfr_length;
|
||||
XX_ptr += LTP_ORDER * LTP_ORDER;
|
||||
xX_ptr += LTP_ORDER;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ void silk_find_pitch_lags_FLP(
|
|||
buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
|
||||
|
||||
/* Safety check */
|
||||
silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
|
||||
celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
|
||||
|
||||
x_buf = x - psEnc->sCmn.ltp_mem_length;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,9 @@ void silk_find_pred_coefs_FLP(
|
|||
)
|
||||
{
|
||||
opus_int i;
|
||||
silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
|
||||
silk_float invGains[ MAX_NB_SUBFR ], Wght[ MAX_NB_SUBFR ];
|
||||
silk_float XXLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
|
||||
silk_float xXLTP[ MAX_NB_SUBFR * LTP_ORDER ];
|
||||
silk_float invGains[ MAX_NB_SUBFR ];
|
||||
opus_int16 NLSF_Q15[ MAX_LPC_ORDER ];
|
||||
const silk_float *x_ptr;
|
||||
silk_float *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ];
|
||||
|
|
@ -52,23 +53,20 @@ void silk_find_pred_coefs_FLP(
|
|||
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
|
||||
silk_assert( psEncCtrl->Gains[ i ] > 0.0f );
|
||||
invGains[ i ] = 1.0f / psEncCtrl->Gains[ i ];
|
||||
Wght[ i ] = invGains[ i ] * invGains[ i ];
|
||||
}
|
||||
|
||||
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
|
||||
/**********/
|
||||
/* VOICED */
|
||||
/**********/
|
||||
silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
|
||||
celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
|
||||
|
||||
/* LTP analysis */
|
||||
silk_find_LTP_FLP( psEncCtrl->LTPCoef, WLTP, &psEncCtrl->LTPredCodGain, res_pitch,
|
||||
psEncCtrl->pitchL, Wght, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length );
|
||||
silk_find_LTP_FLP( XXLTP, xXLTP, res_pitch, psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr );
|
||||
|
||||
/* Quantize LTP gain parameters */
|
||||
silk_quant_LTP_gains_FLP( psEncCtrl->LTPCoef, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
|
||||
&psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr,
|
||||
psEnc->sCmn.arch );
|
||||
&psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain, XXLTP, xXLTP, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
|
||||
|
||||
/* Control LTP scaling */
|
||||
silk_LTP_scale_ctrl_FLP( psEnc, psEncCtrl, condCoding );
|
||||
|
|
|
|||
|
|
@ -38,13 +38,12 @@ double silk_inner_product_FLP(
|
|||
opus_int dataSize
|
||||
)
|
||||
{
|
||||
opus_int i, dataSize4;
|
||||
opus_int i;
|
||||
double result;
|
||||
|
||||
/* 4x unrolled loop */
|
||||
result = 0.0;
|
||||
dataSize4 = dataSize & 0xFFFC;
|
||||
for( i = 0; i < dataSize4; i += 4 ) {
|
||||
for( i = 0; i < dataSize - 3; i += 4 ) {
|
||||
result += data1[ i + 0 ] * (double)data2[ i + 0 ] +
|
||||
data1[ i + 1 ] * (double)data2[ i + 1 ] +
|
||||
data1[ i + 2 ] * (double)data2[ i + 2 ] +
|
||||
|
|
|
|||
|
|
@ -39,15 +39,16 @@ void silk_k2a_FLP(
|
|||
)
|
||||
{
|
||||
opus_int k, n;
|
||||
silk_float Atmp[ SILK_MAX_ORDER_LPC ];
|
||||
silk_float rck, tmp1, tmp2;
|
||||
|
||||
for( k = 0; k < order; k++ ) {
|
||||
for( n = 0; n < k; n++ ) {
|
||||
Atmp[ n ] = A[ n ];
|
||||
rck = rc[ k ];
|
||||
for( n = 0; n < (k + 1) >> 1; n++ ) {
|
||||
tmp1 = A[ n ];
|
||||
tmp2 = A[ k - n - 1 ];
|
||||
A[ n ] = tmp1 + tmp2 * rck;
|
||||
A[ k - n - 1 ] = tmp2 + tmp1 * rck;
|
||||
}
|
||||
for( n = 0; n < k; n++ ) {
|
||||
A[ n ] += Atmp[ k - n - 1 ] * rc[ k ];
|
||||
}
|
||||
A[ k ] = -rc[ k ];
|
||||
A[ k ] = -rck;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,81 +0,0 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "SigProc_FLP.h"
|
||||
|
||||
/* Solve the normal equations using the Levinson-Durbin recursion */
|
||||
silk_float silk_levinsondurbin_FLP( /* O prediction error energy */
|
||||
silk_float A[], /* O prediction coefficients [order] */
|
||||
const silk_float corr[], /* I input auto-correlations [order + 1] */
|
||||
const opus_int order /* I prediction order */
|
||||
)
|
||||
{
|
||||
opus_int i, mHalf, m;
|
||||
silk_float min_nrg, nrg, t, km, Atmp1, Atmp2;
|
||||
|
||||
min_nrg = 1e-12f * corr[ 0 ] + 1e-9f;
|
||||
nrg = corr[ 0 ];
|
||||
nrg = silk_max_float(min_nrg, nrg);
|
||||
A[ 0 ] = corr[ 1 ] / nrg;
|
||||
nrg -= A[ 0 ] * corr[ 1 ];
|
||||
nrg = silk_max_float(min_nrg, nrg);
|
||||
|
||||
for( m = 1; m < order; m++ )
|
||||
{
|
||||
t = corr[ m + 1 ];
|
||||
for( i = 0; i < m; i++ ) {
|
||||
t -= A[ i ] * corr[ m - i ];
|
||||
}
|
||||
|
||||
/* reflection coefficient */
|
||||
km = t / nrg;
|
||||
|
||||
/* residual energy */
|
||||
nrg -= km * t;
|
||||
nrg = silk_max_float(min_nrg, nrg);
|
||||
|
||||
mHalf = m >> 1;
|
||||
for( i = 0; i < mHalf; i++ ) {
|
||||
Atmp1 = A[ i ];
|
||||
Atmp2 = A[ m - i - 1 ];
|
||||
A[ m - i - 1 ] -= km * Atmp1;
|
||||
A[ i ] -= km * Atmp2;
|
||||
}
|
||||
if( m & 1 ) {
|
||||
A[ mHalf ] -= km * A[ mHalf ];
|
||||
}
|
||||
A[ m ] = km;
|
||||
}
|
||||
|
||||
/* return the residual energy */
|
||||
return nrg;
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +56,8 @@ void silk_HP_variable_cutoff(
|
|||
|
||||
/* Encoder main function */
|
||||
void silk_encode_do_VAD_FLP(
|
||||
silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */
|
||||
silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
|
||||
opus_int activity /* I Decision of Opus voice activity detector */
|
||||
);
|
||||
|
||||
/* Encoder main function */
|
||||
|
|
@ -79,22 +80,11 @@ opus_int silk_init_encoder(
|
|||
opus_int silk_control_encoder(
|
||||
silk_encoder_state_FLP *psEnc, /* I/O Pointer to Silk encoder state FLP */
|
||||
silk_EncControlStruct *encControl, /* I Control structure */
|
||||
const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
|
||||
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
|
||||
const opus_int channelNb, /* I Channel number */
|
||||
const opus_int force_fs_kHz
|
||||
);
|
||||
|
||||
/****************/
|
||||
/* Prefiltering */
|
||||
/****************/
|
||||
void silk_prefilter_FLP(
|
||||
silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
|
||||
const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */
|
||||
silk_float xw[], /* O Weighted signal */
|
||||
const silk_float x[] /* I Speech signal */
|
||||
);
|
||||
|
||||
/**************************/
|
||||
/* Noise shaping analysis */
|
||||
/**************************/
|
||||
|
|
@ -153,15 +143,12 @@ void silk_find_LPC_FLP(
|
|||
|
||||
/* LTP analysis */
|
||||
void silk_find_LTP_FLP(
|
||||
silk_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
|
||||
silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
|
||||
silk_float *LTPredCodGain, /* O LTP coding gain */
|
||||
const silk_float r_lpc[], /* I LPC residual */
|
||||
silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
|
||||
silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* O Weight for LTP quantization */
|
||||
const silk_float r_ptr[], /* I LPC residual */
|
||||
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
|
||||
const silk_float Wght[ MAX_NB_SUBFR ], /* I Weights */
|
||||
const opus_int subfr_length, /* I Subframe length */
|
||||
const opus_int nb_subfr, /* I number of subframes */
|
||||
const opus_int mem_offset /* I Number of samples in LTP memory */
|
||||
const opus_int nb_subfr /* I number of subframes */
|
||||
);
|
||||
|
||||
void silk_LTP_analysis_filter_FLP(
|
||||
|
|
@ -198,14 +185,15 @@ void silk_LPC_analysis_filter_FLP(
|
|||
|
||||
/* LTP tap quantizer */
|
||||
void silk_quant_LTP_gains_FLP(
|
||||
silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (Un-)quantized LTP gains */
|
||||
silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
|
||||
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */
|
||||
opus_int8 *periodicity_index, /* O Periodicity index */
|
||||
opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
|
||||
const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */
|
||||
const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */
|
||||
const opus_int lowComplexity, /* I Flag for low complexity */
|
||||
const opus_int nb_subfr, /* I number of subframes */
|
||||
silk_float *pred_gain_dB, /* O LTP prediction gain */
|
||||
const silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Correlation matrix */
|
||||
const silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* I Correlation vector */
|
||||
const opus_int subfr_len, /* I Number of samples per subframe */
|
||||
const opus_int nb_subfr, /* I Number of subframes */
|
||||
int arch /* I Run-time architecture */
|
||||
);
|
||||
|
||||
|
|
@ -245,22 +233,6 @@ void silk_corrVector_FLP(
|
|||
silk_float *Xt /* O X'*t correlation vector [order] */
|
||||
);
|
||||
|
||||
/* Add noise to matrix diagonal */
|
||||
void silk_regularize_correlations_FLP(
|
||||
silk_float *XX, /* I/O Correlation matrices */
|
||||
silk_float *xx, /* I/O Correlation values */
|
||||
const silk_float noise, /* I Noise energy to add */
|
||||
const opus_int D /* I Dimension of XX */
|
||||
);
|
||||
|
||||
/* Function to solve linear equation Ax = b, where A is an MxM symmetric matrix */
|
||||
void silk_solve_LDL_FLP(
|
||||
silk_float *A, /* I/O Symmetric square matrix, out: reg. */
|
||||
const opus_int M, /* I Size of matrix */
|
||||
const silk_float *b, /* I Pointer to b vector */
|
||||
silk_float *x /* O Pointer to x solution vector */
|
||||
);
|
||||
|
||||
/* Apply sine window to signal vector. */
|
||||
/* Window types: */
|
||||
/* 1 -> sine window from 0 to pi/2 */
|
||||
|
|
@ -285,7 +257,8 @@ void silk_A2NLSF_FLP(
|
|||
void silk_NLSF2A_FLP(
|
||||
silk_float *pAR, /* O LPC coefficients [ LPC_order ] */
|
||||
const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */
|
||||
const opus_int LPC_order /* I LPC order */
|
||||
const opus_int LPC_order, /* I LPC order */
|
||||
int arch /* I Run-time architecture */
|
||||
);
|
||||
|
||||
/* Limit, stabilize, and quantize NLSFs */
|
||||
|
|
|
|||
|
|
@ -55,25 +55,21 @@ static OPUS_INLINE silk_float warped_gain(
|
|||
/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */
|
||||
/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
|
||||
static OPUS_INLINE void warped_true2monic_coefs(
|
||||
silk_float *coefs_syn,
|
||||
silk_float *coefs_ana,
|
||||
silk_float *coefs,
|
||||
silk_float lambda,
|
||||
silk_float limit,
|
||||
opus_int order
|
||||
) {
|
||||
opus_int i, iter, ind = 0;
|
||||
silk_float tmp, maxabs, chirp, gain_syn, gain_ana;
|
||||
silk_float tmp, maxabs, chirp, gain;
|
||||
|
||||
/* Convert to monic coefficients */
|
||||
for( i = order - 1; i > 0; i-- ) {
|
||||
coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];
|
||||
coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];
|
||||
coefs[ i - 1 ] -= lambda * coefs[ i ];
|
||||
}
|
||||
gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] );
|
||||
gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] );
|
||||
gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
|
||||
for( i = 0; i < order; i++ ) {
|
||||
coefs_syn[ i ] *= gain_syn;
|
||||
coefs_ana[ i ] *= gain_ana;
|
||||
coefs[ i ] *= gain;
|
||||
}
|
||||
|
||||
/* Limit */
|
||||
|
|
@ -81,7 +77,7 @@ static OPUS_INLINE void warped_true2monic_coefs(
|
|||
/* Find maximum absolute value */
|
||||
maxabs = -1.0f;
|
||||
for( i = 0; i < order; i++ ) {
|
||||
tmp = silk_max( silk_abs_float( coefs_syn[ i ] ), silk_abs_float( coefs_ana[ i ] ) );
|
||||
tmp = silk_abs_float( coefs[ i ] );
|
||||
if( tmp > maxabs ) {
|
||||
maxabs = tmp;
|
||||
ind = i;
|
||||
|
|
@ -94,36 +90,59 @@ static OPUS_INLINE void warped_true2monic_coefs(
|
|||
|
||||
/* Convert back to true warped coefficients */
|
||||
for( i = 1; i < order; i++ ) {
|
||||
coefs_syn[ i - 1 ] += lambda * coefs_syn[ i ];
|
||||
coefs_ana[ i - 1 ] += lambda * coefs_ana[ i ];
|
||||
coefs[ i - 1 ] += lambda * coefs[ i ];
|
||||
}
|
||||
gain_syn = 1.0f / gain_syn;
|
||||
gain_ana = 1.0f / gain_ana;
|
||||
gain = 1.0f / gain;
|
||||
for( i = 0; i < order; i++ ) {
|
||||
coefs_syn[ i ] *= gain_syn;
|
||||
coefs_ana[ i ] *= gain_ana;
|
||||
coefs[ i ] *= gain;
|
||||
}
|
||||
|
||||
/* Apply bandwidth expansion */
|
||||
chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
|
||||
silk_bwexpander_FLP( coefs_syn, order, chirp );
|
||||
silk_bwexpander_FLP( coefs_ana, order, chirp );
|
||||
silk_bwexpander_FLP( coefs, order, chirp );
|
||||
|
||||
/* Convert to monic warped coefficients */
|
||||
for( i = order - 1; i > 0; i-- ) {
|
||||
coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];
|
||||
coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];
|
||||
coefs[ i - 1 ] -= lambda * coefs[ i ];
|
||||
}
|
||||
gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] );
|
||||
gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] );
|
||||
gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
|
||||
for( i = 0; i < order; i++ ) {
|
||||
coefs_syn[ i ] *= gain_syn;
|
||||
coefs_ana[ i ] *= gain_ana;
|
||||
coefs[ i ] *= gain;
|
||||
}
|
||||
}
|
||||
silk_assert( 0 );
|
||||
}
|
||||
|
||||
static OPUS_INLINE void limit_coefs(
|
||||
silk_float *coefs,
|
||||
silk_float limit,
|
||||
opus_int order
|
||||
) {
|
||||
opus_int i, iter, ind = 0;
|
||||
silk_float tmp, maxabs, chirp;
|
||||
|
||||
for( iter = 0; iter < 10; iter++ ) {
|
||||
/* Find maximum absolute value */
|
||||
maxabs = -1.0f;
|
||||
for( i = 0; i < order; i++ ) {
|
||||
tmp = silk_abs_float( coefs[ i ] );
|
||||
if( tmp > maxabs ) {
|
||||
maxabs = tmp;
|
||||
ind = i;
|
||||
}
|
||||
}
|
||||
if( maxabs <= limit ) {
|
||||
/* Coefficients are within range - done */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Apply bandwidth expansion */
|
||||
chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
|
||||
silk_bwexpander_FLP( coefs, order, chirp );
|
||||
}
|
||||
silk_assert( 0 );
|
||||
}
|
||||
|
||||
/* Compute noise shaping coefficients and initial gain values */
|
||||
void silk_noise_shape_analysis_FLP(
|
||||
silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
|
||||
|
|
@ -133,12 +152,13 @@ void silk_noise_shape_analysis_FLP(
|
|||
)
|
||||
{
|
||||
silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
|
||||
opus_int k, nSamples;
|
||||
silk_float SNR_adj_dB, HarmBoost, HarmShapeGain, Tilt;
|
||||
silk_float nrg, pre_nrg, log_energy, log_energy_prev, energy_variation;
|
||||
silk_float delta, BWExp1, BWExp2, gain_mult, gain_add, strength, b, warping;
|
||||
opus_int k, nSamples, nSegs;
|
||||
silk_float SNR_adj_dB, HarmShapeGain, Tilt;
|
||||
silk_float nrg, log_energy, log_energy_prev, energy_variation;
|
||||
silk_float BWExp, gain_mult, gain_add, strength, b, warping;
|
||||
silk_float x_windowed[ SHAPE_LPC_WIN_MAX ];
|
||||
silk_float auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
|
||||
silk_float rc[ MAX_SHAPE_LPC_ORDER + 1 ];
|
||||
const silk_float *x_ptr, *pitch_res_ptr;
|
||||
|
||||
/* Point to start of first LPC analysis block */
|
||||
|
|
@ -176,14 +196,14 @@ void silk_noise_shape_analysis_FLP(
|
|||
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
|
||||
/* Initially set to 0; may be overruled in process_gains(..) */
|
||||
psEnc->sCmn.indices.quantOffsetType = 0;
|
||||
psEncCtrl->sparseness = 0.0f;
|
||||
} else {
|
||||
/* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
|
||||
nSamples = 2 * psEnc->sCmn.fs_kHz;
|
||||
energy_variation = 0.0f;
|
||||
log_energy_prev = 0.0f;
|
||||
pitch_res_ptr = pitch_res;
|
||||
for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
|
||||
nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
|
||||
for( k = 0; k < nSegs; k++ ) {
|
||||
nrg = ( silk_float )nSamples + ( silk_float )silk_energy_FLP( pitch_res_ptr, nSamples );
|
||||
log_energy = silk_log2( nrg );
|
||||
if( k > 0 ) {
|
||||
|
|
@ -192,17 +212,13 @@ void silk_noise_shape_analysis_FLP(
|
|||
log_energy_prev = log_energy;
|
||||
pitch_res_ptr += nSamples;
|
||||
}
|
||||
psEncCtrl->sparseness = silk_sigmoid( 0.4f * ( energy_variation - 5.0f ) );
|
||||
|
||||
/* Set quantization offset depending on sparseness measure */
|
||||
if( psEncCtrl->sparseness > SPARSENESS_THRESHOLD_QNT_OFFSET ) {
|
||||
if( energy_variation > ENERGY_VARIATION_THRESHOLD_QNT_OFFSET * (nSegs-1) ) {
|
||||
psEnc->sCmn.indices.quantOffsetType = 0;
|
||||
} else {
|
||||
psEnc->sCmn.indices.quantOffsetType = 1;
|
||||
}
|
||||
|
||||
/* Increase coding SNR for sparse signals */
|
||||
SNR_adj_dB += SPARSE_SNR_INCR_dB * ( psEncCtrl->sparseness - 0.5f );
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
|
@ -210,19 +226,10 @@ void silk_noise_shape_analysis_FLP(
|
|||
/*******************************/
|
||||
/* More BWE for signals with high prediction gain */
|
||||
strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain; /* between 0.0 and 1.0 */
|
||||
BWExp1 = BWExp2 = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
|
||||
delta = LOW_RATE_BANDWIDTH_EXPANSION_DELTA * ( 1.0f - 0.75f * psEncCtrl->coding_quality );
|
||||
BWExp1 -= delta;
|
||||
BWExp2 += delta;
|
||||
/* BWExp1 will be applied after BWExp2, so make it relative */
|
||||
BWExp1 /= BWExp2;
|
||||
BWExp = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
|
||||
|
||||
if( psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
/* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
|
||||
warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
|
||||
} else {
|
||||
warping = 0.0f;
|
||||
}
|
||||
/* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
|
||||
warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
|
||||
|
||||
/********************************************/
|
||||
/* Compute noise shaping AR coefs and gains */
|
||||
|
|
@ -252,37 +259,28 @@ void silk_noise_shape_analysis_FLP(
|
|||
}
|
||||
|
||||
/* Add white noise, as a fraction of energy */
|
||||
auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION;
|
||||
auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION + 1.0f;
|
||||
|
||||
/* Convert correlations to prediction coefficients, and compute residual energy */
|
||||
nrg = silk_levinsondurbin_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], auto_corr, psEnc->sCmn.shapingLPCOrder );
|
||||
nrg = silk_schur_FLP( rc, auto_corr, psEnc->sCmn.shapingLPCOrder );
|
||||
silk_k2a_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], rc, psEnc->sCmn.shapingLPCOrder );
|
||||
psEncCtrl->Gains[ k ] = ( silk_float )sqrt( nrg );
|
||||
|
||||
if( psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
/* Adjust gain for warping */
|
||||
psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
|
||||
psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
|
||||
}
|
||||
|
||||
/* Bandwidth expansion for synthesis filter shaping */
|
||||
silk_bwexpander_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp2 );
|
||||
silk_bwexpander_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp );
|
||||
|
||||
/* Compute noise shaping filter coefficients */
|
||||
silk_memcpy(
|
||||
&psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ],
|
||||
&psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ],
|
||||
psEnc->sCmn.shapingLPCOrder * sizeof( silk_float ) );
|
||||
|
||||
/* Bandwidth expansion for analysis filter shaping */
|
||||
silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 );
|
||||
|
||||
/* Ratio of prediction gains, in energy domain */
|
||||
pre_nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
|
||||
nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
|
||||
psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg );
|
||||
|
||||
/* Convert to monic warped prediction coefficients and limit absolute values */
|
||||
warped_true2monic_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ],
|
||||
warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
|
||||
if( psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
/* Convert to monic warped prediction coefficients and limit absolute values */
|
||||
warped_true2monic_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
|
||||
} else {
|
||||
/* Limit absolute values */
|
||||
limit_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], 3.999f, psEnc->sCmn.shapingLPCOrder );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************/
|
||||
|
|
@ -296,11 +294,6 @@ void silk_noise_shape_analysis_FLP(
|
|||
psEncCtrl->Gains[ k ] += gain_add;
|
||||
}
|
||||
|
||||
gain_mult = 1.0f + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT;
|
||||
for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
|
||||
psEncCtrl->GainsPre[ k ] *= gain_mult;
|
||||
}
|
||||
|
||||
/************************************************/
|
||||
/* Control low-frequency shaping and noise tilt */
|
||||
/************************************************/
|
||||
|
|
@ -331,12 +324,6 @@ void silk_noise_shape_analysis_FLP(
|
|||
/****************************/
|
||||
/* HARMONIC SHAPING CONTROL */
|
||||
/****************************/
|
||||
/* Control boosting of harmonic frequencies */
|
||||
HarmBoost = LOW_RATE_HARMONIC_BOOST * ( 1.0f - psEncCtrl->coding_quality ) * psEnc->LTPCorr;
|
||||
|
||||
/* More harmonic boost for noisy input signals */
|
||||
HarmBoost += LOW_INPUT_QUALITY_HARMONIC_BOOST * ( 1.0f - psEncCtrl->input_quality );
|
||||
|
||||
if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
|
||||
/* Harmonic noise shaping */
|
||||
HarmShapeGain = HARMONIC_SHAPING;
|
||||
|
|
@ -355,8 +342,6 @@ void silk_noise_shape_analysis_FLP(
|
|||
/* Smooth over subframes */
|
||||
/*************************/
|
||||
for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
|
||||
psShapeSt->HarmBoost_smth += SUBFR_SMTH_COEF * ( HarmBoost - psShapeSt->HarmBoost_smth );
|
||||
psEncCtrl->HarmBoost[ k ] = psShapeSt->HarmBoost_smth;
|
||||
psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth );
|
||||
psEncCtrl->HarmShapeGain[ k ] = psShapeSt->HarmShapeGain_smth;
|
||||
psShapeSt->Tilt_smth += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth );
|
||||
|
|
|
|||
|
|
@ -109,11 +109,11 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
|
|||
const opus_int8 *Lag_CB_ptr;
|
||||
|
||||
/* Check for valid sampling frequency */
|
||||
silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
|
||||
celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
|
||||
|
||||
/* Check for valid complexity setting */
|
||||
silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
|
||||
silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f );
|
||||
silk_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f );
|
||||
|
|
@ -148,7 +148,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
|
|||
silk_resampler_down2_3( filt_state, frame_8_FIX, frame_12_FIX, frame_length );
|
||||
silk_short2float_array( frame_8kHz, frame_8_FIX, frame_length_8kHz );
|
||||
} else {
|
||||
silk_assert( Fs_kHz == 8 );
|
||||
celt_assert( Fs_kHz == 8 );
|
||||
silk_float2short_array( frame_8_FIX, frame, frame_length_8kHz );
|
||||
}
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
|
|||
|
||||
/* Low-pass filter */
|
||||
for( i = frame_length_4kHz - 1; i > 0; i-- ) {
|
||||
frame_4kHz[ i ] += frame_4kHz[ i - 1 ];
|
||||
frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
@ -169,14 +169,14 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
|
|||
target_ptr = &frame_4kHz[ silk_LSHIFT( sf_length_4kHz, 2 ) ];
|
||||
for( k = 0; k < nb_subfr >> 1; k++ ) {
|
||||
/* Check that we are within range of the array */
|
||||
silk_assert( target_ptr >= frame_4kHz );
|
||||
silk_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
|
||||
celt_assert( target_ptr >= frame_4kHz );
|
||||
celt_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
|
||||
|
||||
basis_ptr = target_ptr - min_lag_4kHz;
|
||||
|
||||
/* Check that we are within range of the array */
|
||||
silk_assert( basis_ptr >= frame_4kHz );
|
||||
silk_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
|
||||
celt_assert( basis_ptr >= frame_4kHz );
|
||||
celt_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
|
||||
|
||||
celt_pitch_xcorr( target_ptr, target_ptr-max_lag_4kHz, xcorr, sf_length_8kHz, max_lag_4kHz - min_lag_4kHz + 1, arch );
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
|
|||
|
||||
/* Sort */
|
||||
length_d_srch = 4 + 2 * complexity;
|
||||
silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
|
||||
celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
|
||||
silk_insertion_sort_decreasing_FLP( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch );
|
||||
|
||||
/* Escape if correlation is very low already here */
|
||||
|
|
@ -238,7 +238,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
|
|||
break;
|
||||
}
|
||||
}
|
||||
silk_assert( length_d_srch > 0 );
|
||||
celt_assert( length_d_srch > 0 );
|
||||
|
||||
for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) {
|
||||
d_comp[ i ] = 0;
|
||||
|
|
@ -471,7 +471,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
|
|||
*lagIndex = (opus_int16)( lag - min_lag_8kHz );
|
||||
*contourIndex = (opus_int8)CBimax;
|
||||
}
|
||||
silk_assert( *lagIndex >= 0 );
|
||||
celt_assert( *lagIndex >= 0 );
|
||||
/* return as voiced */
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -506,8 +506,8 @@ static void silk_P_Ana_calc_corr_st3(
|
|||
opus_val32 xcorr[ SCRATCH_SIZE ];
|
||||
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
|
||||
|
||||
silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
|
||||
if( nb_subfr == PE_MAX_NB_SUBFR ) {
|
||||
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
|
||||
|
|
@ -515,7 +515,7 @@ static void silk_P_Ana_calc_corr_st3(
|
|||
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
|
||||
cbk_size = PE_NB_CBKS_STAGE3_MAX;
|
||||
} else {
|
||||
silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
|
||||
celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
|
||||
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
|
||||
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
|
||||
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
|
||||
|
|
@ -572,8 +572,8 @@ static void silk_P_Ana_calc_energy_st3(
|
|||
silk_float scratch_mem[ SCRATCH_SIZE ];
|
||||
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
|
||||
|
||||
silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
|
||||
celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
|
||||
|
||||
if( nb_subfr == PE_MAX_NB_SUBFR ) {
|
||||
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
|
||||
|
|
@ -581,7 +581,7 @@ static void silk_P_Ana_calc_energy_st3(
|
|||
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
|
||||
cbk_size = PE_NB_CBKS_STAGE3_MAX;
|
||||
} else {
|
||||
silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
|
||||
celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
|
||||
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
|
||||
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
|
||||
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue