xref: /aosp_15_r20/external/libopus/silk/NLSF_encode.c (revision a58d3d2adb790c104798cd88c8a3aff4fa8b82cc)
1*a58d3d2aSXin Li /***********************************************************************
2*a58d3d2aSXin Li Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3*a58d3d2aSXin Li Redistribution and use in source and binary forms, with or without
4*a58d3d2aSXin Li modification, are permitted provided that the following conditions
5*a58d3d2aSXin Li are met:
6*a58d3d2aSXin Li - Redistributions of source code must retain the above copyright notice,
7*a58d3d2aSXin Li this list of conditions and the following disclaimer.
8*a58d3d2aSXin Li - Redistributions in binary form must reproduce the above copyright
9*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer in the
10*a58d3d2aSXin Li documentation and/or other materials provided with the distribution.
11*a58d3d2aSXin Li - Neither the name of Internet Society, IETF or IETF Trust, nor the
12*a58d3d2aSXin Li names of specific contributors, may be used to endorse or promote
13*a58d3d2aSXin Li products derived from this software without specific prior written
14*a58d3d2aSXin Li permission.
15*a58d3d2aSXin Li THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16*a58d3d2aSXin Li AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*a58d3d2aSXin Li IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*a58d3d2aSXin Li ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19*a58d3d2aSXin Li LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*a58d3d2aSXin Li CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*a58d3d2aSXin Li SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*a58d3d2aSXin Li INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*a58d3d2aSXin Li CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*a58d3d2aSXin Li ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*a58d3d2aSXin Li POSSIBILITY OF SUCH DAMAGE.
26*a58d3d2aSXin Li ***********************************************************************/
27*a58d3d2aSXin Li 
28*a58d3d2aSXin Li #ifdef HAVE_CONFIG_H
29*a58d3d2aSXin Li #include "config.h"
30*a58d3d2aSXin Li #endif
31*a58d3d2aSXin Li 
32*a58d3d2aSXin Li #include "main.h"
33*a58d3d2aSXin Li #include "stack_alloc.h"
34*a58d3d2aSXin Li 
35*a58d3d2aSXin Li /***********************/
36*a58d3d2aSXin Li /* NLSF vector encoder */
37*a58d3d2aSXin Li /***********************/
silk_NLSF_encode(opus_int8 * NLSFIndices,opus_int16 * pNLSF_Q15,const silk_NLSF_CB_struct * psNLSF_CB,const opus_int16 * pW_Q2,const opus_int NLSF_mu_Q20,const opus_int nSurvivors,const opus_int signalType)38*a58d3d2aSXin Li opus_int32 silk_NLSF_encode(                                    /* O    Returns RD value in Q25                     */
39*a58d3d2aSXin Li           opus_int8             *NLSFIndices,                   /* I    Codebook path vector [ LPC_ORDER + 1 ]      */
40*a58d3d2aSXin Li           opus_int16            *pNLSF_Q15,                     /* I/O  (Un)quantized NLSF vector [ LPC_ORDER ]     */
41*a58d3d2aSXin Li     const silk_NLSF_CB_struct   *psNLSF_CB,                     /* I    Codebook object                             */
42*a58d3d2aSXin Li     const opus_int16            *pW_Q2,                         /* I    NLSF weight vector [ LPC_ORDER ]            */
43*a58d3d2aSXin Li     const opus_int              NLSF_mu_Q20,                    /* I    Rate weight for the RD optimization         */
44*a58d3d2aSXin Li     const opus_int              nSurvivors,                     /* I    Max survivors after first stage             */
45*a58d3d2aSXin Li     const opus_int              signalType                      /* I    Signal type: 0/1/2                          */
46*a58d3d2aSXin Li )
47*a58d3d2aSXin Li {
48*a58d3d2aSXin Li     opus_int         i, s, ind1, bestIndex, prob_Q8, bits_q7;
49*a58d3d2aSXin Li     opus_int32       W_tmp_Q9, ret;
50*a58d3d2aSXin Li     VARDECL( opus_int32, err_Q24 );
51*a58d3d2aSXin Li     VARDECL( opus_int32, RD_Q25 );
52*a58d3d2aSXin Li     VARDECL( opus_int, tempIndices1 );
53*a58d3d2aSXin Li     VARDECL( opus_int8, tempIndices2 );
54*a58d3d2aSXin Li     opus_int16       res_Q10[      MAX_LPC_ORDER ];
55*a58d3d2aSXin Li     opus_int16       NLSF_tmp_Q15[ MAX_LPC_ORDER ];
56*a58d3d2aSXin Li     opus_int16       W_adj_Q5[     MAX_LPC_ORDER ];
57*a58d3d2aSXin Li     opus_uint8       pred_Q8[      MAX_LPC_ORDER ];
58*a58d3d2aSXin Li     opus_int16       ec_ix[        MAX_LPC_ORDER ];
59*a58d3d2aSXin Li     const opus_uint8 *pCB_element, *iCDF_ptr;
60*a58d3d2aSXin Li     const opus_int16 *pCB_Wght_Q9;
61*a58d3d2aSXin Li     SAVE_STACK;
62*a58d3d2aSXin Li 
63*a58d3d2aSXin Li     celt_assert( signalType >= 0 && signalType <= 2 );
64*a58d3d2aSXin Li     silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 );
65*a58d3d2aSXin Li 
66*a58d3d2aSXin Li     /* NLSF stabilization */
67*a58d3d2aSXin Li     silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
68*a58d3d2aSXin Li 
69*a58d3d2aSXin Li     /* First stage: VQ */
70*a58d3d2aSXin Li     ALLOC( err_Q24, psNLSF_CB->nVectors, opus_int32 );
71*a58d3d2aSXin Li     silk_NLSF_VQ( err_Q24, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->CB1_Wght_Q9, psNLSF_CB->nVectors, psNLSF_CB->order );
72*a58d3d2aSXin Li 
73*a58d3d2aSXin Li     /* Sort the quantization errors */
74*a58d3d2aSXin Li     ALLOC( tempIndices1, nSurvivors, opus_int );
75*a58d3d2aSXin Li     silk_insertion_sort_increasing( err_Q24, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
76*a58d3d2aSXin Li 
77*a58d3d2aSXin Li     ALLOC( RD_Q25, nSurvivors, opus_int32 );
78*a58d3d2aSXin Li     ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 );
79*a58d3d2aSXin Li 
80*a58d3d2aSXin Li     /* Loop over survivors */
81*a58d3d2aSXin Li     for( s = 0; s < nSurvivors; s++ ) {
82*a58d3d2aSXin Li         ind1 = tempIndices1[ s ];
83*a58d3d2aSXin Li 
84*a58d3d2aSXin Li         /* Residual after first stage */
85*a58d3d2aSXin Li         pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ];
86*a58d3d2aSXin Li         pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ ind1 * psNLSF_CB->order ];
87*a58d3d2aSXin Li         for( i = 0; i < psNLSF_CB->order; i++ ) {
88*a58d3d2aSXin Li             NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 );
89*a58d3d2aSXin Li             W_tmp_Q9 = pCB_Wght_Q9[ i ];
90*a58d3d2aSXin Li             res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ], W_tmp_Q9 ), 14 );
91*a58d3d2aSXin Li             W_adj_Q5[ i ] = silk_DIV32_varQ( (opus_int32)pW_Q2[ i ], silk_SMULBB( W_tmp_Q9, W_tmp_Q9 ), 21 );
92*a58d3d2aSXin Li         }
93*a58d3d2aSXin Li 
94*a58d3d2aSXin Li         /* Unpack entropy table indices and predictor for current CB1 index */
95*a58d3d2aSXin Li         silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 );
96*a58d3d2aSXin Li 
97*a58d3d2aSXin Li         /* Trellis quantizer */
98*a58d3d2aSXin Li         RD_Q25[ s ] = silk_NLSF_del_dec_quant( &tempIndices2[ s * MAX_LPC_ORDER ], res_Q10, W_adj_Q5, pred_Q8, ec_ix,
99*a58d3d2aSXin Li             psNLSF_CB->ec_Rates_Q5, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB->order );
100*a58d3d2aSXin Li 
101*a58d3d2aSXin Li         /* Add rate for first stage */
102*a58d3d2aSXin Li         iCDF_ptr = &psNLSF_CB->CB1_iCDF[ ( signalType >> 1 ) * psNLSF_CB->nVectors ];
103*a58d3d2aSXin Li         if( ind1 == 0 ) {
104*a58d3d2aSXin Li             prob_Q8 = 256 - iCDF_ptr[ ind1 ];
105*a58d3d2aSXin Li         } else {
106*a58d3d2aSXin Li             prob_Q8 = iCDF_ptr[ ind1 - 1 ] - iCDF_ptr[ ind1 ];
107*a58d3d2aSXin Li         }
108*a58d3d2aSXin Li         bits_q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 );
109*a58d3d2aSXin Li         RD_Q25[ s ] = silk_SMLABB( RD_Q25[ s ], bits_q7, silk_RSHIFT( NLSF_mu_Q20, 2 ) );
110*a58d3d2aSXin Li     }
111*a58d3d2aSXin Li 
112*a58d3d2aSXin Li     /* Find the lowest rate-distortion error */
113*a58d3d2aSXin Li     silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 );
114*a58d3d2aSXin Li 
115*a58d3d2aSXin Li     NLSFIndices[ 0 ] = (opus_int8)tempIndices1[ bestIndex ];
116*a58d3d2aSXin Li     silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) );
117*a58d3d2aSXin Li 
118*a58d3d2aSXin Li     /* Decode */
119*a58d3d2aSXin Li     silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB );
120*a58d3d2aSXin Li 
121*a58d3d2aSXin Li     ret = RD_Q25[ 0 ];
122*a58d3d2aSXin Li     RESTORE_STACK;
123*a58d3d2aSXin Li     return ret;
124*a58d3d2aSXin Li }
125