annotate src/opus-1.3/silk/CNG.c @ 169:223a55898ab9 tip default

Add null config files
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 02 Mar 2020 14:03:47 +0000
parents 4664ac0c1032
children
rev   line source
cannam@154 1 /***********************************************************************
cannam@154 2 Copyright (c) 2006-2011, Skype Limited. All rights reserved.
cannam@154 3 Redistribution and use in source and binary forms, with or without
cannam@154 4 modification, are permitted provided that the following conditions
cannam@154 5 are met:
cannam@154 6 - Redistributions of source code must retain the above copyright notice,
cannam@154 7 this list of conditions and the following disclaimer.
cannam@154 8 - Redistributions in binary form must reproduce the above copyright
cannam@154 9 notice, this list of conditions and the following disclaimer in the
cannam@154 10 documentation and/or other materials provided with the distribution.
cannam@154 11 - Neither the name of Internet Society, IETF or IETF Trust, nor the
cannam@154 12 names of specific contributors, may be used to endorse or promote
cannam@154 13 products derived from this software without specific prior written
cannam@154 14 permission.
cannam@154 15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
cannam@154 16 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
cannam@154 17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
cannam@154 18 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
cannam@154 19 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
cannam@154 20 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
cannam@154 21 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
cannam@154 22 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
cannam@154 23 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
cannam@154 24 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
cannam@154 25 POSSIBILITY OF SUCH DAMAGE.
cannam@154 26 ***********************************************************************/
cannam@154 27
cannam@154 28 #ifdef HAVE_CONFIG_H
cannam@154 29 #include "config.h"
cannam@154 30 #endif
cannam@154 31
cannam@154 32 #include "main.h"
cannam@154 33 #include "stack_alloc.h"
cannam@154 34
cannam@154 35 /* Generates excitation for CNG LPC synthesis */
cannam@154 36 static OPUS_INLINE void silk_CNG_exc(
cannam@154 37 opus_int32 exc_Q14[], /* O CNG excitation signal Q10 */
cannam@154 38 opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */
cannam@154 39 opus_int length, /* I Length */
cannam@154 40 opus_int32 *rand_seed /* I/O Seed to random index generator */
cannam@154 41 )
cannam@154 42 {
cannam@154 43 opus_int32 seed;
cannam@154 44 opus_int i, idx, exc_mask;
cannam@154 45
cannam@154 46 exc_mask = CNG_BUF_MASK_MAX;
cannam@154 47 while( exc_mask > length ) {
cannam@154 48 exc_mask = silk_RSHIFT( exc_mask, 1 );
cannam@154 49 }
cannam@154 50
cannam@154 51 seed = *rand_seed;
cannam@154 52 for( i = 0; i < length; i++ ) {
cannam@154 53 seed = silk_RAND( seed );
cannam@154 54 idx = (opus_int)( silk_RSHIFT( seed, 24 ) & exc_mask );
cannam@154 55 silk_assert( idx >= 0 );
cannam@154 56 silk_assert( idx <= CNG_BUF_MASK_MAX );
cannam@154 57 exc_Q14[ i ] = exc_buf_Q14[ idx ];
cannam@154 58 }
cannam@154 59 *rand_seed = seed;
cannam@154 60 }
cannam@154 61
cannam@154 62 void silk_CNG_Reset(
cannam@154 63 silk_decoder_state *psDec /* I/O Decoder state */
cannam@154 64 )
cannam@154 65 {
cannam@154 66 opus_int i, NLSF_step_Q15, NLSF_acc_Q15;
cannam@154 67
cannam@154 68 NLSF_step_Q15 = silk_DIV32_16( silk_int16_MAX, psDec->LPC_order + 1 );
cannam@154 69 NLSF_acc_Q15 = 0;
cannam@154 70 for( i = 0; i < psDec->LPC_order; i++ ) {
cannam@154 71 NLSF_acc_Q15 += NLSF_step_Q15;
cannam@154 72 psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15;
cannam@154 73 }
cannam@154 74 psDec->sCNG.CNG_smth_Gain_Q16 = 0;
cannam@154 75 psDec->sCNG.rand_seed = 3176576;
cannam@154 76 }
cannam@154 77
cannam@154 78 /* Updates CNG estimate, and applies the CNG when packet was lost */
cannam@154 79 void silk_CNG(
cannam@154 80 silk_decoder_state *psDec, /* I/O Decoder state */
cannam@154 81 silk_decoder_control *psDecCtrl, /* I/O Decoder control */
cannam@154 82 opus_int16 frame[], /* I/O Signal */
cannam@154 83 opus_int length /* I Length of residual */
cannam@154 84 )
cannam@154 85 {
cannam@154 86 opus_int i, subfr;
cannam@154 87 opus_int32 LPC_pred_Q10, max_Gain_Q16, gain_Q16, gain_Q10;
cannam@154 88 opus_int16 A_Q12[ MAX_LPC_ORDER ];
cannam@154 89 silk_CNG_struct *psCNG = &psDec->sCNG;
cannam@154 90 SAVE_STACK;
cannam@154 91
cannam@154 92 if( psDec->fs_kHz != psCNG->fs_kHz ) {
cannam@154 93 /* Reset state */
cannam@154 94 silk_CNG_Reset( psDec );
cannam@154 95
cannam@154 96 psCNG->fs_kHz = psDec->fs_kHz;
cannam@154 97 }
cannam@154 98 if( psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) {
cannam@154 99 /* Update CNG parameters */
cannam@154 100
cannam@154 101 /* Smoothing of LSF's */
cannam@154 102 for( i = 0; i < psDec->LPC_order; i++ ) {
cannam@154 103 psCNG->CNG_smth_NLSF_Q15[ i ] += silk_SMULWB( (opus_int32)psDec->prevNLSF_Q15[ i ] - (opus_int32)psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 );
cannam@154 104 }
cannam@154 105 /* Find the subframe with the highest gain */
cannam@154 106 max_Gain_Q16 = 0;
cannam@154 107 subfr = 0;
cannam@154 108 for( i = 0; i < psDec->nb_subfr; i++ ) {
cannam@154 109 if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) {
cannam@154 110 max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
cannam@154 111 subfr = i;
cannam@154 112 }
cannam@154 113 }
cannam@154 114 /* Update CNG excitation buffer with excitation from this subframe */
cannam@154 115 silk_memmove( &psCNG->CNG_exc_buf_Q14[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q14, ( psDec->nb_subfr - 1 ) * psDec->subfr_length * sizeof( opus_int32 ) );
cannam@154 116 silk_memcpy( psCNG->CNG_exc_buf_Q14, &psDec->exc_Q14[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( opus_int32 ) );
cannam@154 117
cannam@154 118 /* Smooth gains */
cannam@154 119 for( i = 0; i < psDec->nb_subfr; i++ ) {
cannam@154 120 psCNG->CNG_smth_Gain_Q16 += silk_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 );
cannam@154 121 }
cannam@154 122 }
cannam@154 123
cannam@154 124 /* Add CNG when packet is lost or during DTX */
cannam@154 125 if( psDec->lossCnt ) {
cannam@154 126 VARDECL( opus_int32, CNG_sig_Q14 );
cannam@154 127 ALLOC( CNG_sig_Q14, length + MAX_LPC_ORDER, opus_int32 );
cannam@154 128
cannam@154 129 /* Generate CNG excitation */
cannam@154 130 gain_Q16 = silk_SMULWW( psDec->sPLC.randScale_Q14, psDec->sPLC.prevGain_Q16[1] );
cannam@154 131 if( gain_Q16 >= (1 << 21) || psCNG->CNG_smth_Gain_Q16 > (1 << 23) ) {
cannam@154 132 gain_Q16 = silk_SMULTT( gain_Q16, gain_Q16 );
cannam@154 133 gain_Q16 = silk_SUB_LSHIFT32(silk_SMULTT( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
cannam@154 134 gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 16 );
cannam@154 135 } else {
cannam@154 136 gain_Q16 = silk_SMULWW( gain_Q16, gain_Q16 );
cannam@154 137 gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
cannam@154 138 gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
cannam@154 139 }
cannam@154 140 gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
cannam@154 141
cannam@154 142 silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
cannam@154 143
cannam@154 144 /* Convert CNG NLSF to filter representation */
cannam@154 145 silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch );
cannam@154 146
cannam@154 147 /* Generate CNG signal, by synthesis filtering */
cannam@154 148 silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
cannam@154 149 celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
cannam@154 150 for( i = 0; i < length; i++ ) {
cannam@154 151 /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
cannam@154 152 LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
cannam@154 153 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
cannam@154 154 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
cannam@154 155 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
cannam@154 156 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
cannam@154 157 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
cannam@154 158 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
cannam@154 159 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
cannam@154 160 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
cannam@154 161 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
cannam@154 162 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
cannam@154 163 if( psDec->LPC_order == 16 ) {
cannam@154 164 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] );
cannam@154 165 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
cannam@154 166 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
cannam@154 167 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
cannam@154 168 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
cannam@154 169 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
cannam@154 170 }
cannam@154 171
cannam@154 172 /* Update states */
cannam@154 173 CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
cannam@154 174
cannam@154 175 /* Scale with Gain and add to input signal */
cannam@154 176 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 ) ) );
cannam@154 177
cannam@154 178 }
cannam@154 179 silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
cannam@154 180 } else {
cannam@154 181 silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) );
cannam@154 182 }
cannam@154 183 RESTORE_STACK;
cannam@154 184 }