1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * AMR wideband decoder
3cabdff1aSopenharmony_ci * Copyright (c) 2010 Marcelo Galvao Povoa
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A particular PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci/**
23cabdff1aSopenharmony_ci * @file
24cabdff1aSopenharmony_ci * AMR wideband decoder
25cabdff1aSopenharmony_ci */
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h"
28cabdff1aSopenharmony_ci#include "libavutil/common.h"
29cabdff1aSopenharmony_ci#include "libavutil/float_dsp.h"
30cabdff1aSopenharmony_ci#include "libavutil/lfg.h"
31cabdff1aSopenharmony_ci
32cabdff1aSopenharmony_ci#include "avcodec.h"
33cabdff1aSopenharmony_ci#include "lsp.h"
34cabdff1aSopenharmony_ci#include "celp_filters.h"
35cabdff1aSopenharmony_ci#include "celp_math.h"
36cabdff1aSopenharmony_ci#include "acelp_filters.h"
37cabdff1aSopenharmony_ci#include "acelp_vectors.h"
38cabdff1aSopenharmony_ci#include "acelp_pitch_delay.h"
39cabdff1aSopenharmony_ci#include "codec_internal.h"
40cabdff1aSopenharmony_ci#include "internal.h"
41cabdff1aSopenharmony_ci
42cabdff1aSopenharmony_ci#define AMR_USE_16BIT_TABLES
43cabdff1aSopenharmony_ci#include "amr.h"
44cabdff1aSopenharmony_ci
45cabdff1aSopenharmony_ci#include "amrwbdata.h"
46cabdff1aSopenharmony_ci#include "mips/amrwbdec_mips.h"
47cabdff1aSopenharmony_ci
48cabdff1aSopenharmony_citypedef struct AMRWBContext {
49cabdff1aSopenharmony_ci    AMRWBFrame                             frame; ///< AMRWB parameters decoded from bitstream
50cabdff1aSopenharmony_ci    enum Mode                        fr_cur_mode; ///< mode index of current frame
51cabdff1aSopenharmony_ci    uint8_t                           fr_quality; ///< frame quality index (FQI)
52cabdff1aSopenharmony_ci    float                      isf_cur[LP_ORDER]; ///< working ISF vector from current frame
53cabdff1aSopenharmony_ci    float                   isf_q_past[LP_ORDER]; ///< quantized ISF vector of the previous frame
54cabdff1aSopenharmony_ci    float               isf_past_final[LP_ORDER]; ///< final processed ISF vector of the previous frame
55cabdff1aSopenharmony_ci    double                      isp[4][LP_ORDER]; ///< ISP vectors from current frame
56cabdff1aSopenharmony_ci    double               isp_sub4_past[LP_ORDER]; ///< ISP vector for the 4th subframe of the previous frame
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_ci    float                   lp_coef[4][LP_ORDER]; ///< Linear Prediction Coefficients from ISP vector
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_ci    uint8_t                       base_pitch_lag; ///< integer part of pitch lag for the next relative subframe
61cabdff1aSopenharmony_ci    uint8_t                        pitch_lag_int; ///< integer part of pitch lag of the previous subframe
62cabdff1aSopenharmony_ci
63cabdff1aSopenharmony_ci    float excitation_buf[AMRWB_P_DELAY_MAX + LP_ORDER + 2 + AMRWB_SFR_SIZE]; ///< current excitation and all necessary excitation history
64cabdff1aSopenharmony_ci    float                            *excitation; ///< points to current excitation in excitation_buf[]
65cabdff1aSopenharmony_ci
66cabdff1aSopenharmony_ci    float           pitch_vector[AMRWB_SFR_SIZE]; ///< adaptive codebook (pitch) vector for current subframe
67cabdff1aSopenharmony_ci    float           fixed_vector[AMRWB_SFR_SIZE]; ///< algebraic codebook (fixed) vector for current subframe
68cabdff1aSopenharmony_ci
69cabdff1aSopenharmony_ci    float                    prediction_error[4]; ///< quantified prediction errors {20log10(^gamma_gc)} for previous four subframes
70cabdff1aSopenharmony_ci    float                          pitch_gain[6]; ///< quantified pitch gains for the current and previous five subframes
71cabdff1aSopenharmony_ci    float                          fixed_gain[2]; ///< quantified fixed gains for the current and previous subframes
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_ci    float                              tilt_coef; ///< {beta_1} related to the voicing of the previous subframe
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_ci    float                 prev_sparse_fixed_gain; ///< previous fixed gain; used by anti-sparseness to determine "onset"
76cabdff1aSopenharmony_ci    uint8_t                    prev_ir_filter_nr; ///< previous impulse response filter "impNr": 0 - strong, 1 - medium, 2 - none
77cabdff1aSopenharmony_ci    float                           prev_tr_gain; ///< previous initial gain used by noise enhancer for threshold
78cabdff1aSopenharmony_ci
79cabdff1aSopenharmony_ci    float samples_az[LP_ORDER + AMRWB_SFR_SIZE];         ///< low-band samples and memory from synthesis at 12.8kHz
80cabdff1aSopenharmony_ci    float samples_up[UPS_MEM_SIZE + AMRWB_SFR_SIZE];     ///< low-band samples and memory processed for upsampling
81cabdff1aSopenharmony_ci    float samples_hb[LP_ORDER_16k + AMRWB_SFR_SIZE_16k]; ///< high-band samples and memory from synthesis at 16kHz
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_ci    float          hpf_31_mem[2], hpf_400_mem[2]; ///< previous values in the high pass filters
84cabdff1aSopenharmony_ci    float                           demph_mem[1]; ///< previous value in the de-emphasis filter
85cabdff1aSopenharmony_ci    float               bpf_6_7_mem[HB_FIR_SIZE]; ///< previous values in the high-band band pass filter
86cabdff1aSopenharmony_ci    float                 lpf_7_mem[HB_FIR_SIZE]; ///< previous values in the high-band low pass filter
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_ci    AVLFG                                   prng; ///< random number generator for white noise excitation
89cabdff1aSopenharmony_ci    uint8_t                          first_frame; ///< flag active during decoding of the first frame
90cabdff1aSopenharmony_ci    ACELPFContext                     acelpf_ctx; ///< context for filters for ACELP-based codecs
91cabdff1aSopenharmony_ci    ACELPVContext                     acelpv_ctx; ///< context for vector operations for ACELP-based codecs
92cabdff1aSopenharmony_ci    CELPFContext                       celpf_ctx; ///< context for filters for CELP-based codecs
93cabdff1aSopenharmony_ci    CELPMContext                       celpm_ctx; ///< context for fixed point math operations
94cabdff1aSopenharmony_ci
95cabdff1aSopenharmony_ci} AMRWBContext;
96cabdff1aSopenharmony_ci
97cabdff1aSopenharmony_citypedef struct AMRWBChannelsContext {
98cabdff1aSopenharmony_ci    AMRWBContext ch[2];
99cabdff1aSopenharmony_ci} AMRWBChannelsContext;
100cabdff1aSopenharmony_ci
101cabdff1aSopenharmony_cistatic av_cold int amrwb_decode_init(AVCodecContext *avctx)
102cabdff1aSopenharmony_ci{
103cabdff1aSopenharmony_ci    AMRWBChannelsContext *s = avctx->priv_data;
104cabdff1aSopenharmony_ci    int i;
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ci    if (avctx->ch_layout.nb_channels > 2) {
107cabdff1aSopenharmony_ci        avpriv_report_missing_feature(avctx, ">2 channel AMR");
108cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
109cabdff1aSopenharmony_ci    }
110cabdff1aSopenharmony_ci
111cabdff1aSopenharmony_ci    if (!avctx->ch_layout.nb_channels) {
112cabdff1aSopenharmony_ci        av_channel_layout_uninit(&avctx->ch_layout);
113cabdff1aSopenharmony_ci        avctx->ch_layout      = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
114cabdff1aSopenharmony_ci    }
115cabdff1aSopenharmony_ci    if (!avctx->sample_rate)
116cabdff1aSopenharmony_ci        avctx->sample_rate = 16000;
117cabdff1aSopenharmony_ci    avctx->sample_fmt     = AV_SAMPLE_FMT_FLTP;
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci    for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
120cabdff1aSopenharmony_ci        AMRWBContext *ctx = &s->ch[ch];
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci        av_lfg_init(&ctx->prng, 1);
123cabdff1aSopenharmony_ci
124cabdff1aSopenharmony_ci        ctx->excitation  = &ctx->excitation_buf[AMRWB_P_DELAY_MAX + LP_ORDER + 1];
125cabdff1aSopenharmony_ci        ctx->first_frame = 1;
126cabdff1aSopenharmony_ci
127cabdff1aSopenharmony_ci        for (i = 0; i < LP_ORDER; i++)
128cabdff1aSopenharmony_ci            ctx->isf_past_final[i] = isf_init[i] * (1.0f / (1 << 15));
129cabdff1aSopenharmony_ci
130cabdff1aSopenharmony_ci        for (i = 0; i < 4; i++)
131cabdff1aSopenharmony_ci            ctx->prediction_error[i] = MIN_ENERGY;
132cabdff1aSopenharmony_ci
133cabdff1aSopenharmony_ci        ff_acelp_filter_init(&ctx->acelpf_ctx);
134cabdff1aSopenharmony_ci        ff_acelp_vectors_init(&ctx->acelpv_ctx);
135cabdff1aSopenharmony_ci        ff_celp_filter_init(&ctx->celpf_ctx);
136cabdff1aSopenharmony_ci        ff_celp_math_init(&ctx->celpm_ctx);
137cabdff1aSopenharmony_ci    }
138cabdff1aSopenharmony_ci
139cabdff1aSopenharmony_ci    return 0;
140cabdff1aSopenharmony_ci}
141cabdff1aSopenharmony_ci
142cabdff1aSopenharmony_ci/**
143cabdff1aSopenharmony_ci * Decode the frame header in the "MIME/storage" format. This format
144cabdff1aSopenharmony_ci * is simpler and does not carry the auxiliary frame information.
145cabdff1aSopenharmony_ci *
146cabdff1aSopenharmony_ci * @param[in] ctx                  The Context
147cabdff1aSopenharmony_ci * @param[in] buf                  Pointer to the input buffer
148cabdff1aSopenharmony_ci *
149cabdff1aSopenharmony_ci * @return The decoded header length in bytes
150cabdff1aSopenharmony_ci */
151cabdff1aSopenharmony_cistatic int decode_mime_header(AMRWBContext *ctx, const uint8_t *buf)
152cabdff1aSopenharmony_ci{
153cabdff1aSopenharmony_ci    /* Decode frame header (1st octet) */
154cabdff1aSopenharmony_ci    ctx->fr_cur_mode  = buf[0] >> 3 & 0x0F;
155cabdff1aSopenharmony_ci    ctx->fr_quality   = (buf[0] & 0x4) == 0x4;
156cabdff1aSopenharmony_ci
157cabdff1aSopenharmony_ci    return 1;
158cabdff1aSopenharmony_ci}
159cabdff1aSopenharmony_ci
160cabdff1aSopenharmony_ci/**
161cabdff1aSopenharmony_ci * Decode quantized ISF vectors using 36-bit indexes (6K60 mode only).
162cabdff1aSopenharmony_ci *
163cabdff1aSopenharmony_ci * @param[in]  ind                 Array of 5 indexes
164cabdff1aSopenharmony_ci * @param[out] isf_q               Buffer for isf_q[LP_ORDER]
165cabdff1aSopenharmony_ci */
166cabdff1aSopenharmony_cistatic void decode_isf_indices_36b(uint16_t *ind, float *isf_q)
167cabdff1aSopenharmony_ci{
168cabdff1aSopenharmony_ci    int i;
169cabdff1aSopenharmony_ci
170cabdff1aSopenharmony_ci    for (i = 0; i < 9; i++)
171cabdff1aSopenharmony_ci        isf_q[i]      = dico1_isf[ind[0]][i]      * (1.0f / (1 << 15));
172cabdff1aSopenharmony_ci
173cabdff1aSopenharmony_ci    for (i = 0; i < 7; i++)
174cabdff1aSopenharmony_ci        isf_q[i + 9]  = dico2_isf[ind[1]][i]      * (1.0f / (1 << 15));
175cabdff1aSopenharmony_ci
176cabdff1aSopenharmony_ci    for (i = 0; i < 5; i++)
177cabdff1aSopenharmony_ci        isf_q[i]     += dico21_isf_36b[ind[2]][i] * (1.0f / (1 << 15));
178cabdff1aSopenharmony_ci
179cabdff1aSopenharmony_ci    for (i = 0; i < 4; i++)
180cabdff1aSopenharmony_ci        isf_q[i + 5] += dico22_isf_36b[ind[3]][i] * (1.0f / (1 << 15));
181cabdff1aSopenharmony_ci
182cabdff1aSopenharmony_ci    for (i = 0; i < 7; i++)
183cabdff1aSopenharmony_ci        isf_q[i + 9] += dico23_isf_36b[ind[4]][i] * (1.0f / (1 << 15));
184cabdff1aSopenharmony_ci}
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci/**
187cabdff1aSopenharmony_ci * Decode quantized ISF vectors using 46-bit indexes (except 6K60 mode).
188cabdff1aSopenharmony_ci *
189cabdff1aSopenharmony_ci * @param[in]  ind                 Array of 7 indexes
190cabdff1aSopenharmony_ci * @param[out] isf_q               Buffer for isf_q[LP_ORDER]
191cabdff1aSopenharmony_ci */
192cabdff1aSopenharmony_cistatic void decode_isf_indices_46b(uint16_t *ind, float *isf_q)
193cabdff1aSopenharmony_ci{
194cabdff1aSopenharmony_ci    int i;
195cabdff1aSopenharmony_ci
196cabdff1aSopenharmony_ci    for (i = 0; i < 9; i++)
197cabdff1aSopenharmony_ci        isf_q[i]       = dico1_isf[ind[0]][i]  * (1.0f / (1 << 15));
198cabdff1aSopenharmony_ci
199cabdff1aSopenharmony_ci    for (i = 0; i < 7; i++)
200cabdff1aSopenharmony_ci        isf_q[i + 9]   = dico2_isf[ind[1]][i]  * (1.0f / (1 << 15));
201cabdff1aSopenharmony_ci
202cabdff1aSopenharmony_ci    for (i = 0; i < 3; i++)
203cabdff1aSopenharmony_ci        isf_q[i]      += dico21_isf[ind[2]][i] * (1.0f / (1 << 15));
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci    for (i = 0; i < 3; i++)
206cabdff1aSopenharmony_ci        isf_q[i + 3]  += dico22_isf[ind[3]][i] * (1.0f / (1 << 15));
207cabdff1aSopenharmony_ci
208cabdff1aSopenharmony_ci    for (i = 0; i < 3; i++)
209cabdff1aSopenharmony_ci        isf_q[i + 6]  += dico23_isf[ind[4]][i] * (1.0f / (1 << 15));
210cabdff1aSopenharmony_ci
211cabdff1aSopenharmony_ci    for (i = 0; i < 3; i++)
212cabdff1aSopenharmony_ci        isf_q[i + 9]  += dico24_isf[ind[5]][i] * (1.0f / (1 << 15));
213cabdff1aSopenharmony_ci
214cabdff1aSopenharmony_ci    for (i = 0; i < 4; i++)
215cabdff1aSopenharmony_ci        isf_q[i + 12] += dico25_isf[ind[6]][i] * (1.0f / (1 << 15));
216cabdff1aSopenharmony_ci}
217cabdff1aSopenharmony_ci
218cabdff1aSopenharmony_ci/**
219cabdff1aSopenharmony_ci * Apply mean and past ISF values using the prediction factor.
220cabdff1aSopenharmony_ci * Updates past ISF vector.
221cabdff1aSopenharmony_ci *
222cabdff1aSopenharmony_ci * @param[in,out] isf_q            Current quantized ISF
223cabdff1aSopenharmony_ci * @param[in,out] isf_past         Past quantized ISF
224cabdff1aSopenharmony_ci */
225cabdff1aSopenharmony_cistatic void isf_add_mean_and_past(float *isf_q, float *isf_past)
226cabdff1aSopenharmony_ci{
227cabdff1aSopenharmony_ci    int i;
228cabdff1aSopenharmony_ci    float tmp;
229cabdff1aSopenharmony_ci
230cabdff1aSopenharmony_ci    for (i = 0; i < LP_ORDER; i++) {
231cabdff1aSopenharmony_ci        tmp = isf_q[i];
232cabdff1aSopenharmony_ci        isf_q[i] += isf_mean[i] * (1.0f / (1 << 15));
233cabdff1aSopenharmony_ci        isf_q[i] += PRED_FACTOR * isf_past[i];
234cabdff1aSopenharmony_ci        isf_past[i] = tmp;
235cabdff1aSopenharmony_ci    }
236cabdff1aSopenharmony_ci}
237cabdff1aSopenharmony_ci
238cabdff1aSopenharmony_ci/**
239cabdff1aSopenharmony_ci * Interpolate the fourth ISP vector from current and past frames
240cabdff1aSopenharmony_ci * to obtain an ISP vector for each subframe.
241cabdff1aSopenharmony_ci *
242cabdff1aSopenharmony_ci * @param[in,out] isp_q            ISPs for each subframe
243cabdff1aSopenharmony_ci * @param[in]     isp4_past        Past ISP for subframe 4
244cabdff1aSopenharmony_ci */
245cabdff1aSopenharmony_cistatic void interpolate_isp(double isp_q[4][LP_ORDER], const double *isp4_past)
246cabdff1aSopenharmony_ci{
247cabdff1aSopenharmony_ci    int i, k;
248cabdff1aSopenharmony_ci
249cabdff1aSopenharmony_ci    for (k = 0; k < 3; k++) {
250cabdff1aSopenharmony_ci        float c = isfp_inter[k];
251cabdff1aSopenharmony_ci        for (i = 0; i < LP_ORDER; i++)
252cabdff1aSopenharmony_ci            isp_q[k][i] = (1.0 - c) * isp4_past[i] + c * isp_q[3][i];
253cabdff1aSopenharmony_ci    }
254cabdff1aSopenharmony_ci}
255cabdff1aSopenharmony_ci
256cabdff1aSopenharmony_ci/**
257cabdff1aSopenharmony_ci * Decode an adaptive codebook index into pitch lag (except 6k60, 8k85 modes).
258cabdff1aSopenharmony_ci * Calculate integer lag and fractional lag always using 1/4 resolution.
259cabdff1aSopenharmony_ci * In 1st and 3rd subframes the index is relative to last subframe integer lag.
260cabdff1aSopenharmony_ci *
261cabdff1aSopenharmony_ci * @param[out]    lag_int          Decoded integer pitch lag
262cabdff1aSopenharmony_ci * @param[out]    lag_frac         Decoded fractional pitch lag
263cabdff1aSopenharmony_ci * @param[in]     pitch_index      Adaptive codebook pitch index
264cabdff1aSopenharmony_ci * @param[in,out] base_lag_int     Base integer lag used in relative subframes
265cabdff1aSopenharmony_ci * @param[in]     subframe         Current subframe index (0 to 3)
266cabdff1aSopenharmony_ci */
267cabdff1aSopenharmony_cistatic void decode_pitch_lag_high(int *lag_int, int *lag_frac, int pitch_index,
268cabdff1aSopenharmony_ci                                  uint8_t *base_lag_int, int subframe)
269cabdff1aSopenharmony_ci{
270cabdff1aSopenharmony_ci    if (subframe == 0 || subframe == 2) {
271cabdff1aSopenharmony_ci        if (pitch_index < 376) {
272cabdff1aSopenharmony_ci            *lag_int  = (pitch_index + 137) >> 2;
273cabdff1aSopenharmony_ci            *lag_frac = pitch_index - (*lag_int << 2) + 136;
274cabdff1aSopenharmony_ci        } else if (pitch_index < 440) {
275cabdff1aSopenharmony_ci            *lag_int  = (pitch_index + 257 - 376) >> 1;
276cabdff1aSopenharmony_ci            *lag_frac = (pitch_index - (*lag_int << 1) + 256 - 376) * 2;
277cabdff1aSopenharmony_ci            /* the actual resolution is 1/2 but expressed as 1/4 */
278cabdff1aSopenharmony_ci        } else {
279cabdff1aSopenharmony_ci            *lag_int  = pitch_index - 280;
280cabdff1aSopenharmony_ci            *lag_frac = 0;
281cabdff1aSopenharmony_ci        }
282cabdff1aSopenharmony_ci        /* minimum lag for next subframe */
283cabdff1aSopenharmony_ci        *base_lag_int = av_clip(*lag_int - 8 - (*lag_frac < 0),
284cabdff1aSopenharmony_ci                                AMRWB_P_DELAY_MIN, AMRWB_P_DELAY_MAX - 15);
285cabdff1aSopenharmony_ci        // XXX: the spec states clearly that *base_lag_int should be
286cabdff1aSopenharmony_ci        // the nearest integer to *lag_int (minus 8), but the ref code
287cabdff1aSopenharmony_ci        // actually always uses its floor, I'm following the latter
288cabdff1aSopenharmony_ci    } else {
289cabdff1aSopenharmony_ci        *lag_int  = (pitch_index + 1) >> 2;
290cabdff1aSopenharmony_ci        *lag_frac = pitch_index - (*lag_int << 2);
291cabdff1aSopenharmony_ci        *lag_int += *base_lag_int;
292cabdff1aSopenharmony_ci    }
293cabdff1aSopenharmony_ci}
294cabdff1aSopenharmony_ci
295cabdff1aSopenharmony_ci/**
296cabdff1aSopenharmony_ci * Decode an adaptive codebook index into pitch lag for 8k85 and 6k60 modes.
297cabdff1aSopenharmony_ci * The description is analogous to decode_pitch_lag_high, but in 6k60 the
298cabdff1aSopenharmony_ci * relative index is used for all subframes except the first.
299cabdff1aSopenharmony_ci */
300cabdff1aSopenharmony_cistatic void decode_pitch_lag_low(int *lag_int, int *lag_frac, int pitch_index,
301cabdff1aSopenharmony_ci                                 uint8_t *base_lag_int, int subframe, enum Mode mode)
302cabdff1aSopenharmony_ci{
303cabdff1aSopenharmony_ci    if (subframe == 0 || (subframe == 2 && mode != MODE_6k60)) {
304cabdff1aSopenharmony_ci        if (pitch_index < 116) {
305cabdff1aSopenharmony_ci            *lag_int  = (pitch_index + 69) >> 1;
306cabdff1aSopenharmony_ci            *lag_frac = (pitch_index - (*lag_int << 1) + 68) * 2;
307cabdff1aSopenharmony_ci        } else {
308cabdff1aSopenharmony_ci            *lag_int  = pitch_index - 24;
309cabdff1aSopenharmony_ci            *lag_frac = 0;
310cabdff1aSopenharmony_ci        }
311cabdff1aSopenharmony_ci        // XXX: same problem as before
312cabdff1aSopenharmony_ci        *base_lag_int = av_clip(*lag_int - 8 - (*lag_frac < 0),
313cabdff1aSopenharmony_ci                                AMRWB_P_DELAY_MIN, AMRWB_P_DELAY_MAX - 15);
314cabdff1aSopenharmony_ci    } else {
315cabdff1aSopenharmony_ci        *lag_int  = (pitch_index + 1) >> 1;
316cabdff1aSopenharmony_ci        *lag_frac = (pitch_index - (*lag_int << 1)) * 2;
317cabdff1aSopenharmony_ci        *lag_int += *base_lag_int;
318cabdff1aSopenharmony_ci    }
319cabdff1aSopenharmony_ci}
320cabdff1aSopenharmony_ci
321cabdff1aSopenharmony_ci/**
322cabdff1aSopenharmony_ci * Find the pitch vector by interpolating the past excitation at the
323cabdff1aSopenharmony_ci * pitch delay, which is obtained in this function.
324cabdff1aSopenharmony_ci *
325cabdff1aSopenharmony_ci * @param[in,out] ctx              The context
326cabdff1aSopenharmony_ci * @param[in]     amr_subframe     Current subframe data
327cabdff1aSopenharmony_ci * @param[in]     subframe         Current subframe index (0 to 3)
328cabdff1aSopenharmony_ci */
329cabdff1aSopenharmony_cistatic void decode_pitch_vector(AMRWBContext *ctx,
330cabdff1aSopenharmony_ci                                const AMRWBSubFrame *amr_subframe,
331cabdff1aSopenharmony_ci                                const int subframe)
332cabdff1aSopenharmony_ci{
333cabdff1aSopenharmony_ci    int pitch_lag_int, pitch_lag_frac;
334cabdff1aSopenharmony_ci    int i;
335cabdff1aSopenharmony_ci    float *exc     = ctx->excitation;
336cabdff1aSopenharmony_ci    enum Mode mode = ctx->fr_cur_mode;
337cabdff1aSopenharmony_ci
338cabdff1aSopenharmony_ci    if (mode <= MODE_8k85) {
339cabdff1aSopenharmony_ci        decode_pitch_lag_low(&pitch_lag_int, &pitch_lag_frac, amr_subframe->adap,
340cabdff1aSopenharmony_ci                              &ctx->base_pitch_lag, subframe, mode);
341cabdff1aSopenharmony_ci    } else
342cabdff1aSopenharmony_ci        decode_pitch_lag_high(&pitch_lag_int, &pitch_lag_frac, amr_subframe->adap,
343cabdff1aSopenharmony_ci                              &ctx->base_pitch_lag, subframe);
344cabdff1aSopenharmony_ci
345cabdff1aSopenharmony_ci    ctx->pitch_lag_int = pitch_lag_int;
346cabdff1aSopenharmony_ci    pitch_lag_int += pitch_lag_frac > 0;
347cabdff1aSopenharmony_ci
348cabdff1aSopenharmony_ci    /* Calculate the pitch vector by interpolating the past excitation at the
349cabdff1aSopenharmony_ci       pitch lag using a hamming windowed sinc function */
350cabdff1aSopenharmony_ci    ctx->acelpf_ctx.acelp_interpolatef(exc,
351cabdff1aSopenharmony_ci                          exc + 1 - pitch_lag_int,
352cabdff1aSopenharmony_ci                          ac_inter, 4,
353cabdff1aSopenharmony_ci                          pitch_lag_frac + (pitch_lag_frac > 0 ? 0 : 4),
354cabdff1aSopenharmony_ci                          LP_ORDER, AMRWB_SFR_SIZE + 1);
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_ci    /* Check which pitch signal path should be used
357cabdff1aSopenharmony_ci     * 6k60 and 8k85 modes have the ltp flag set to 0 */
358cabdff1aSopenharmony_ci    if (amr_subframe->ltp) {
359cabdff1aSopenharmony_ci        memcpy(ctx->pitch_vector, exc, AMRWB_SFR_SIZE * sizeof(float));
360cabdff1aSopenharmony_ci    } else {
361cabdff1aSopenharmony_ci        for (i = 0; i < AMRWB_SFR_SIZE; i++)
362cabdff1aSopenharmony_ci            ctx->pitch_vector[i] = 0.18 * exc[i - 1] + 0.64 * exc[i] +
363cabdff1aSopenharmony_ci                                   0.18 * exc[i + 1];
364cabdff1aSopenharmony_ci        memcpy(exc, ctx->pitch_vector, AMRWB_SFR_SIZE * sizeof(float));
365cabdff1aSopenharmony_ci    }
366cabdff1aSopenharmony_ci}
367cabdff1aSopenharmony_ci
368cabdff1aSopenharmony_ci/** Get x bits in the index interval [lsb,lsb+len-1] inclusive */
369cabdff1aSopenharmony_ci#define BIT_STR(x,lsb,len) av_mod_uintp2((x) >> (lsb), (len))
370cabdff1aSopenharmony_ci
371cabdff1aSopenharmony_ci/** Get the bit at specified position */
372cabdff1aSopenharmony_ci#define BIT_POS(x, p) (((x) >> (p)) & 1)
373cabdff1aSopenharmony_ci
374cabdff1aSopenharmony_ci/**
375cabdff1aSopenharmony_ci * The next six functions decode_[i]p_track decode exactly i pulses
376cabdff1aSopenharmony_ci * positions and amplitudes (-1 or 1) in a subframe track using
377cabdff1aSopenharmony_ci * an encoded pulse indexing (TS 26.190 section 5.8.2).
378cabdff1aSopenharmony_ci *
379cabdff1aSopenharmony_ci * The results are given in out[], in which a negative number means
380cabdff1aSopenharmony_ci * amplitude -1 and vice versa (i.e., ampl(x) = x / abs(x) ).
381cabdff1aSopenharmony_ci *
382cabdff1aSopenharmony_ci * @param[out] out                 Output buffer (writes i elements)
383cabdff1aSopenharmony_ci * @param[in]  code                Pulse index (no. of bits varies, see below)
384cabdff1aSopenharmony_ci * @param[in]  m                   (log2) Number of potential positions
385cabdff1aSopenharmony_ci * @param[in]  off                 Offset for decoded positions
386cabdff1aSopenharmony_ci */
387cabdff1aSopenharmony_cistatic inline void decode_1p_track(int *out, int code, int m, int off)
388cabdff1aSopenharmony_ci{
389cabdff1aSopenharmony_ci    int pos = BIT_STR(code, 0, m) + off; ///code: m+1 bits
390cabdff1aSopenharmony_ci
391cabdff1aSopenharmony_ci    out[0] = BIT_POS(code, m) ? -pos : pos;
392cabdff1aSopenharmony_ci}
393cabdff1aSopenharmony_ci
394cabdff1aSopenharmony_cistatic inline void decode_2p_track(int *out, int code, int m, int off) ///code: 2m+1 bits
395cabdff1aSopenharmony_ci{
396cabdff1aSopenharmony_ci    int pos0 = BIT_STR(code, m, m) + off;
397cabdff1aSopenharmony_ci    int pos1 = BIT_STR(code, 0, m) + off;
398cabdff1aSopenharmony_ci
399cabdff1aSopenharmony_ci    out[0] = BIT_POS(code, 2*m) ? -pos0 : pos0;
400cabdff1aSopenharmony_ci    out[1] = BIT_POS(code, 2*m) ? -pos1 : pos1;
401cabdff1aSopenharmony_ci    out[1] = pos0 > pos1 ? -out[1] : out[1];
402cabdff1aSopenharmony_ci}
403cabdff1aSopenharmony_ci
404cabdff1aSopenharmony_cistatic void decode_3p_track(int *out, int code, int m, int off) ///code: 3m+1 bits
405cabdff1aSopenharmony_ci{
406cabdff1aSopenharmony_ci    int half_2p = BIT_POS(code, 2*m - 1) << (m - 1);
407cabdff1aSopenharmony_ci
408cabdff1aSopenharmony_ci    decode_2p_track(out, BIT_STR(code, 0, 2*m - 1),
409cabdff1aSopenharmony_ci                    m - 1, off + half_2p);
410cabdff1aSopenharmony_ci    decode_1p_track(out + 2, BIT_STR(code, 2*m, m + 1), m, off);
411cabdff1aSopenharmony_ci}
412cabdff1aSopenharmony_ci
413cabdff1aSopenharmony_cistatic void decode_4p_track(int *out, int code, int m, int off) ///code: 4m bits
414cabdff1aSopenharmony_ci{
415cabdff1aSopenharmony_ci    int half_4p, subhalf_2p;
416cabdff1aSopenharmony_ci    int b_offset = 1 << (m - 1);
417cabdff1aSopenharmony_ci
418cabdff1aSopenharmony_ci    switch (BIT_STR(code, 4*m - 2, 2)) { /* case ID (2 bits) */
419cabdff1aSopenharmony_ci    case 0: /* 0 pulses in A, 4 pulses in B or vice versa */
420cabdff1aSopenharmony_ci        half_4p = BIT_POS(code, 4*m - 3) << (m - 1); // which has 4 pulses
421cabdff1aSopenharmony_ci        subhalf_2p = BIT_POS(code, 2*m - 3) << (m - 2);
422cabdff1aSopenharmony_ci
423cabdff1aSopenharmony_ci        decode_2p_track(out, BIT_STR(code, 0, 2*m - 3),
424cabdff1aSopenharmony_ci                        m - 2, off + half_4p + subhalf_2p);
425cabdff1aSopenharmony_ci        decode_2p_track(out + 2, BIT_STR(code, 2*m - 2, 2*m - 1),
426cabdff1aSopenharmony_ci                        m - 1, off + half_4p);
427cabdff1aSopenharmony_ci        break;
428cabdff1aSopenharmony_ci    case 1: /* 1 pulse in A, 3 pulses in B */
429cabdff1aSopenharmony_ci        decode_1p_track(out, BIT_STR(code,  3*m - 2, m),
430cabdff1aSopenharmony_ci                        m - 1, off);
431cabdff1aSopenharmony_ci        decode_3p_track(out + 1, BIT_STR(code, 0, 3*m - 2),
432cabdff1aSopenharmony_ci                        m - 1, off + b_offset);
433cabdff1aSopenharmony_ci        break;
434cabdff1aSopenharmony_ci    case 2: /* 2 pulses in each half */
435cabdff1aSopenharmony_ci        decode_2p_track(out, BIT_STR(code, 2*m - 1, 2*m - 1),
436cabdff1aSopenharmony_ci                        m - 1, off);
437cabdff1aSopenharmony_ci        decode_2p_track(out + 2, BIT_STR(code, 0, 2*m - 1),
438cabdff1aSopenharmony_ci                        m - 1, off + b_offset);
439cabdff1aSopenharmony_ci        break;
440cabdff1aSopenharmony_ci    case 3: /* 3 pulses in A, 1 pulse in B */
441cabdff1aSopenharmony_ci        decode_3p_track(out, BIT_STR(code, m, 3*m - 2),
442cabdff1aSopenharmony_ci                        m - 1, off);
443cabdff1aSopenharmony_ci        decode_1p_track(out + 3, BIT_STR(code, 0, m),
444cabdff1aSopenharmony_ci                        m - 1, off + b_offset);
445cabdff1aSopenharmony_ci        break;
446cabdff1aSopenharmony_ci    }
447cabdff1aSopenharmony_ci}
448cabdff1aSopenharmony_ci
449cabdff1aSopenharmony_cistatic void decode_5p_track(int *out, int code, int m, int off) ///code: 5m bits
450cabdff1aSopenharmony_ci{
451cabdff1aSopenharmony_ci    int half_3p = BIT_POS(code, 5*m - 1) << (m - 1);
452cabdff1aSopenharmony_ci
453cabdff1aSopenharmony_ci    decode_3p_track(out, BIT_STR(code, 2*m + 1, 3*m - 2),
454cabdff1aSopenharmony_ci                    m - 1, off + half_3p);
455cabdff1aSopenharmony_ci
456cabdff1aSopenharmony_ci    decode_2p_track(out + 3, BIT_STR(code, 0, 2*m + 1), m, off);
457cabdff1aSopenharmony_ci}
458cabdff1aSopenharmony_ci
459cabdff1aSopenharmony_cistatic void decode_6p_track(int *out, int code, int m, int off) ///code: 6m-2 bits
460cabdff1aSopenharmony_ci{
461cabdff1aSopenharmony_ci    int b_offset = 1 << (m - 1);
462cabdff1aSopenharmony_ci    /* which half has more pulses in cases 0 to 2 */
463cabdff1aSopenharmony_ci    int half_more  = BIT_POS(code, 6*m - 5) << (m - 1);
464cabdff1aSopenharmony_ci    int half_other = b_offset - half_more;
465cabdff1aSopenharmony_ci
466cabdff1aSopenharmony_ci    switch (BIT_STR(code, 6*m - 4, 2)) { /* case ID (2 bits) */
467cabdff1aSopenharmony_ci    case 0: /* 0 pulses in A, 6 pulses in B or vice versa */
468cabdff1aSopenharmony_ci        decode_1p_track(out, BIT_STR(code, 0, m),
469cabdff1aSopenharmony_ci                        m - 1, off + half_more);
470cabdff1aSopenharmony_ci        decode_5p_track(out + 1, BIT_STR(code, m, 5*m - 5),
471cabdff1aSopenharmony_ci                        m - 1, off + half_more);
472cabdff1aSopenharmony_ci        break;
473cabdff1aSopenharmony_ci    case 1: /* 1 pulse in A, 5 pulses in B or vice versa */
474cabdff1aSopenharmony_ci        decode_1p_track(out, BIT_STR(code, 0, m),
475cabdff1aSopenharmony_ci                        m - 1, off + half_other);
476cabdff1aSopenharmony_ci        decode_5p_track(out + 1, BIT_STR(code, m, 5*m - 5),
477cabdff1aSopenharmony_ci                        m - 1, off + half_more);
478cabdff1aSopenharmony_ci        break;
479cabdff1aSopenharmony_ci    case 2: /* 2 pulses in A, 4 pulses in B or vice versa */
480cabdff1aSopenharmony_ci        decode_2p_track(out, BIT_STR(code, 0, 2*m - 1),
481cabdff1aSopenharmony_ci                        m - 1, off + half_other);
482cabdff1aSopenharmony_ci        decode_4p_track(out + 2, BIT_STR(code, 2*m - 1, 4*m - 4),
483cabdff1aSopenharmony_ci                        m - 1, off + half_more);
484cabdff1aSopenharmony_ci        break;
485cabdff1aSopenharmony_ci    case 3: /* 3 pulses in A, 3 pulses in B */
486cabdff1aSopenharmony_ci        decode_3p_track(out, BIT_STR(code, 3*m - 2, 3*m - 2),
487cabdff1aSopenharmony_ci                        m - 1, off);
488cabdff1aSopenharmony_ci        decode_3p_track(out + 3, BIT_STR(code, 0, 3*m - 2),
489cabdff1aSopenharmony_ci                        m - 1, off + b_offset);
490cabdff1aSopenharmony_ci        break;
491cabdff1aSopenharmony_ci    }
492cabdff1aSopenharmony_ci}
493cabdff1aSopenharmony_ci
494cabdff1aSopenharmony_ci/**
495cabdff1aSopenharmony_ci * Decode the algebraic codebook index to pulse positions and signs,
496cabdff1aSopenharmony_ci * then construct the algebraic codebook vector.
497cabdff1aSopenharmony_ci *
498cabdff1aSopenharmony_ci * @param[out] fixed_vector        Buffer for the fixed codebook excitation
499cabdff1aSopenharmony_ci * @param[in]  pulse_hi            MSBs part of the pulse index array (higher modes only)
500cabdff1aSopenharmony_ci * @param[in]  pulse_lo            LSBs part of the pulse index array
501cabdff1aSopenharmony_ci * @param[in]  mode                Mode of the current frame
502cabdff1aSopenharmony_ci */
503cabdff1aSopenharmony_cistatic void decode_fixed_vector(float *fixed_vector, const uint16_t *pulse_hi,
504cabdff1aSopenharmony_ci                                const uint16_t *pulse_lo, const enum Mode mode)
505cabdff1aSopenharmony_ci{
506cabdff1aSopenharmony_ci    /* sig_pos stores for each track the decoded pulse position indexes
507cabdff1aSopenharmony_ci     * (1-based) multiplied by its corresponding amplitude (+1 or -1) */
508cabdff1aSopenharmony_ci    int sig_pos[4][6];
509cabdff1aSopenharmony_ci    int spacing = (mode == MODE_6k60) ? 2 : 4;
510cabdff1aSopenharmony_ci    int i, j;
511cabdff1aSopenharmony_ci
512cabdff1aSopenharmony_ci    switch (mode) {
513cabdff1aSopenharmony_ci    case MODE_6k60:
514cabdff1aSopenharmony_ci        for (i = 0; i < 2; i++)
515cabdff1aSopenharmony_ci            decode_1p_track(sig_pos[i], pulse_lo[i], 5, 1);
516cabdff1aSopenharmony_ci        break;
517cabdff1aSopenharmony_ci    case MODE_8k85:
518cabdff1aSopenharmony_ci        for (i = 0; i < 4; i++)
519cabdff1aSopenharmony_ci            decode_1p_track(sig_pos[i], pulse_lo[i], 4, 1);
520cabdff1aSopenharmony_ci        break;
521cabdff1aSopenharmony_ci    case MODE_12k65:
522cabdff1aSopenharmony_ci        for (i = 0; i < 4; i++)
523cabdff1aSopenharmony_ci            decode_2p_track(sig_pos[i], pulse_lo[i], 4, 1);
524cabdff1aSopenharmony_ci        break;
525cabdff1aSopenharmony_ci    case MODE_14k25:
526cabdff1aSopenharmony_ci        for (i = 0; i < 2; i++)
527cabdff1aSopenharmony_ci            decode_3p_track(sig_pos[i], pulse_lo[i], 4, 1);
528cabdff1aSopenharmony_ci        for (i = 2; i < 4; i++)
529cabdff1aSopenharmony_ci            decode_2p_track(sig_pos[i], pulse_lo[i], 4, 1);
530cabdff1aSopenharmony_ci        break;
531cabdff1aSopenharmony_ci    case MODE_15k85:
532cabdff1aSopenharmony_ci        for (i = 0; i < 4; i++)
533cabdff1aSopenharmony_ci            decode_3p_track(sig_pos[i], pulse_lo[i], 4, 1);
534cabdff1aSopenharmony_ci        break;
535cabdff1aSopenharmony_ci    case MODE_18k25:
536cabdff1aSopenharmony_ci        for (i = 0; i < 4; i++)
537cabdff1aSopenharmony_ci            decode_4p_track(sig_pos[i], (int) pulse_lo[i] +
538cabdff1aSopenharmony_ci                           ((int) pulse_hi[i] << 14), 4, 1);
539cabdff1aSopenharmony_ci        break;
540cabdff1aSopenharmony_ci    case MODE_19k85:
541cabdff1aSopenharmony_ci        for (i = 0; i < 2; i++)
542cabdff1aSopenharmony_ci            decode_5p_track(sig_pos[i], (int) pulse_lo[i] +
543cabdff1aSopenharmony_ci                           ((int) pulse_hi[i] << 10), 4, 1);
544cabdff1aSopenharmony_ci        for (i = 2; i < 4; i++)
545cabdff1aSopenharmony_ci            decode_4p_track(sig_pos[i], (int) pulse_lo[i] +
546cabdff1aSopenharmony_ci                           ((int) pulse_hi[i] << 14), 4, 1);
547cabdff1aSopenharmony_ci        break;
548cabdff1aSopenharmony_ci    case MODE_23k05:
549cabdff1aSopenharmony_ci    case MODE_23k85:
550cabdff1aSopenharmony_ci        for (i = 0; i < 4; i++)
551cabdff1aSopenharmony_ci            decode_6p_track(sig_pos[i], (int) pulse_lo[i] +
552cabdff1aSopenharmony_ci                           ((int) pulse_hi[i] << 11), 4, 1);
553cabdff1aSopenharmony_ci        break;
554cabdff1aSopenharmony_ci    }
555cabdff1aSopenharmony_ci
556cabdff1aSopenharmony_ci    memset(fixed_vector, 0, sizeof(float) * AMRWB_SFR_SIZE);
557cabdff1aSopenharmony_ci
558cabdff1aSopenharmony_ci    for (i = 0; i < 4; i++)
559cabdff1aSopenharmony_ci        for (j = 0; j < pulses_nb_per_mode_tr[mode][i]; j++) {
560cabdff1aSopenharmony_ci            int pos = (FFABS(sig_pos[i][j]) - 1) * spacing + i;
561cabdff1aSopenharmony_ci
562cabdff1aSopenharmony_ci            fixed_vector[pos] += sig_pos[i][j] < 0 ? -1.0 : 1.0;
563cabdff1aSopenharmony_ci        }
564cabdff1aSopenharmony_ci}
565cabdff1aSopenharmony_ci
566cabdff1aSopenharmony_ci/**
567cabdff1aSopenharmony_ci * Decode pitch gain and fixed gain correction factor.
568cabdff1aSopenharmony_ci *
569cabdff1aSopenharmony_ci * @param[in]  vq_gain             Vector-quantized index for gains
570cabdff1aSopenharmony_ci * @param[in]  mode                Mode of the current frame
571cabdff1aSopenharmony_ci * @param[out] fixed_gain_factor   Decoded fixed gain correction factor
572cabdff1aSopenharmony_ci * @param[out] pitch_gain          Decoded pitch gain
573cabdff1aSopenharmony_ci */
574cabdff1aSopenharmony_cistatic void decode_gains(const uint8_t vq_gain, const enum Mode mode,
575cabdff1aSopenharmony_ci                         float *fixed_gain_factor, float *pitch_gain)
576cabdff1aSopenharmony_ci{
577cabdff1aSopenharmony_ci    const int16_t *gains = (mode <= MODE_8k85 ? qua_gain_6b[vq_gain] :
578cabdff1aSopenharmony_ci                                                qua_gain_7b[vq_gain]);
579cabdff1aSopenharmony_ci
580cabdff1aSopenharmony_ci    *pitch_gain        = gains[0] * (1.0f / (1 << 14));
581cabdff1aSopenharmony_ci    *fixed_gain_factor = gains[1] * (1.0f / (1 << 11));
582cabdff1aSopenharmony_ci}
583cabdff1aSopenharmony_ci
584cabdff1aSopenharmony_ci/**
585cabdff1aSopenharmony_ci * Apply pitch sharpening filters to the fixed codebook vector.
586cabdff1aSopenharmony_ci *
587cabdff1aSopenharmony_ci * @param[in]     ctx              The context
588cabdff1aSopenharmony_ci * @param[in,out] fixed_vector     Fixed codebook excitation
589cabdff1aSopenharmony_ci */
590cabdff1aSopenharmony_ci// XXX: Spec states this procedure should be applied when the pitch
591cabdff1aSopenharmony_ci// lag is less than 64, but this checking seems absent in reference and AMR-NB
592cabdff1aSopenharmony_cistatic void pitch_sharpening(AMRWBContext *ctx, float *fixed_vector)
593cabdff1aSopenharmony_ci{
594cabdff1aSopenharmony_ci    int i;
595cabdff1aSopenharmony_ci
596cabdff1aSopenharmony_ci    /* Tilt part */
597cabdff1aSopenharmony_ci    for (i = AMRWB_SFR_SIZE - 1; i != 0; i--)
598cabdff1aSopenharmony_ci        fixed_vector[i] -= fixed_vector[i - 1] * ctx->tilt_coef;
599cabdff1aSopenharmony_ci
600cabdff1aSopenharmony_ci    /* Periodicity enhancement part */
601cabdff1aSopenharmony_ci    for (i = ctx->pitch_lag_int; i < AMRWB_SFR_SIZE; i++)
602cabdff1aSopenharmony_ci        fixed_vector[i] += fixed_vector[i - ctx->pitch_lag_int] * 0.85;
603cabdff1aSopenharmony_ci}
604cabdff1aSopenharmony_ci
605cabdff1aSopenharmony_ci/**
606cabdff1aSopenharmony_ci * Calculate the voicing factor (-1.0 = unvoiced to 1.0 = voiced).
607cabdff1aSopenharmony_ci *
608cabdff1aSopenharmony_ci * @param[in] p_vector, f_vector   Pitch and fixed excitation vectors
609cabdff1aSopenharmony_ci * @param[in] p_gain, f_gain       Pitch and fixed gains
610cabdff1aSopenharmony_ci * @param[in] ctx                  The context
611cabdff1aSopenharmony_ci */
612cabdff1aSopenharmony_ci// XXX: There is something wrong with the precision here! The magnitudes
613cabdff1aSopenharmony_ci// of the energies are not correct. Please check the reference code carefully
614cabdff1aSopenharmony_cistatic float voice_factor(float *p_vector, float p_gain,
615cabdff1aSopenharmony_ci                          float *f_vector, float f_gain,
616cabdff1aSopenharmony_ci                          CELPMContext *ctx)
617cabdff1aSopenharmony_ci{
618cabdff1aSopenharmony_ci    double p_ener = (double) ctx->dot_productf(p_vector, p_vector,
619cabdff1aSopenharmony_ci                                                          AMRWB_SFR_SIZE) *
620cabdff1aSopenharmony_ci                    p_gain * p_gain;
621cabdff1aSopenharmony_ci    double f_ener = (double) ctx->dot_productf(f_vector, f_vector,
622cabdff1aSopenharmony_ci                                                          AMRWB_SFR_SIZE) *
623cabdff1aSopenharmony_ci                    f_gain * f_gain;
624cabdff1aSopenharmony_ci
625cabdff1aSopenharmony_ci    return (p_ener - f_ener) / (p_ener + f_ener + 0.01);
626cabdff1aSopenharmony_ci}
627cabdff1aSopenharmony_ci
628cabdff1aSopenharmony_ci/**
629cabdff1aSopenharmony_ci * Reduce fixed vector sparseness by smoothing with one of three IR filters,
630cabdff1aSopenharmony_ci * also known as "adaptive phase dispersion".
631cabdff1aSopenharmony_ci *
632cabdff1aSopenharmony_ci * @param[in]     ctx              The context
633cabdff1aSopenharmony_ci * @param[in,out] fixed_vector     Unfiltered fixed vector
634cabdff1aSopenharmony_ci * @param[out]    buf              Space for modified vector if necessary
635cabdff1aSopenharmony_ci *
636cabdff1aSopenharmony_ci * @return The potentially overwritten filtered fixed vector address
637cabdff1aSopenharmony_ci */
638cabdff1aSopenharmony_cistatic float *anti_sparseness(AMRWBContext *ctx,
639cabdff1aSopenharmony_ci                              float *fixed_vector, float *buf)
640cabdff1aSopenharmony_ci{
641cabdff1aSopenharmony_ci    int ir_filter_nr;
642cabdff1aSopenharmony_ci
643cabdff1aSopenharmony_ci    if (ctx->fr_cur_mode > MODE_8k85) // no filtering in higher modes
644cabdff1aSopenharmony_ci        return fixed_vector;
645cabdff1aSopenharmony_ci
646cabdff1aSopenharmony_ci    if (ctx->pitch_gain[0] < 0.6) {
647cabdff1aSopenharmony_ci        ir_filter_nr = 0;      // strong filtering
648cabdff1aSopenharmony_ci    } else if (ctx->pitch_gain[0] < 0.9) {
649cabdff1aSopenharmony_ci        ir_filter_nr = 1;      // medium filtering
650cabdff1aSopenharmony_ci    } else
651cabdff1aSopenharmony_ci        ir_filter_nr = 2;      // no filtering
652cabdff1aSopenharmony_ci
653cabdff1aSopenharmony_ci    /* detect 'onset' */
654cabdff1aSopenharmony_ci    if (ctx->fixed_gain[0] > 3.0 * ctx->fixed_gain[1]) {
655cabdff1aSopenharmony_ci        if (ir_filter_nr < 2)
656cabdff1aSopenharmony_ci            ir_filter_nr++;
657cabdff1aSopenharmony_ci    } else {
658cabdff1aSopenharmony_ci        int i, count = 0;
659cabdff1aSopenharmony_ci
660cabdff1aSopenharmony_ci        for (i = 0; i < 6; i++)
661cabdff1aSopenharmony_ci            if (ctx->pitch_gain[i] < 0.6)
662cabdff1aSopenharmony_ci                count++;
663cabdff1aSopenharmony_ci
664cabdff1aSopenharmony_ci        if (count > 2)
665cabdff1aSopenharmony_ci            ir_filter_nr = 0;
666cabdff1aSopenharmony_ci
667cabdff1aSopenharmony_ci        if (ir_filter_nr > ctx->prev_ir_filter_nr + 1)
668cabdff1aSopenharmony_ci            ir_filter_nr--;
669cabdff1aSopenharmony_ci    }
670cabdff1aSopenharmony_ci
671cabdff1aSopenharmony_ci    /* update ir filter strength history */
672cabdff1aSopenharmony_ci    ctx->prev_ir_filter_nr = ir_filter_nr;
673cabdff1aSopenharmony_ci
674cabdff1aSopenharmony_ci    ir_filter_nr += (ctx->fr_cur_mode == MODE_8k85);
675cabdff1aSopenharmony_ci
676cabdff1aSopenharmony_ci    if (ir_filter_nr < 2) {
677cabdff1aSopenharmony_ci        int i;
678cabdff1aSopenharmony_ci        const float *coef = ir_filters_lookup[ir_filter_nr];
679cabdff1aSopenharmony_ci
680cabdff1aSopenharmony_ci        /* Circular convolution code in the reference
681cabdff1aSopenharmony_ci         * decoder was modified to avoid using one
682cabdff1aSopenharmony_ci         * extra array. The filtered vector is given by:
683cabdff1aSopenharmony_ci         *
684cabdff1aSopenharmony_ci         * c2(n) = sum(i,0,len-1){ c(i) * coef( (n - i + len) % len ) }
685cabdff1aSopenharmony_ci         */
686cabdff1aSopenharmony_ci
687cabdff1aSopenharmony_ci        memset(buf, 0, sizeof(float) * AMRWB_SFR_SIZE);
688cabdff1aSopenharmony_ci        for (i = 0; i < AMRWB_SFR_SIZE; i++)
689cabdff1aSopenharmony_ci            if (fixed_vector[i])
690cabdff1aSopenharmony_ci                ff_celp_circ_addf(buf, buf, coef, i, fixed_vector[i],
691cabdff1aSopenharmony_ci                                  AMRWB_SFR_SIZE);
692cabdff1aSopenharmony_ci        fixed_vector = buf;
693cabdff1aSopenharmony_ci    }
694cabdff1aSopenharmony_ci
695cabdff1aSopenharmony_ci    return fixed_vector;
696cabdff1aSopenharmony_ci}
697cabdff1aSopenharmony_ci
698cabdff1aSopenharmony_ci/**
699cabdff1aSopenharmony_ci * Calculate a stability factor {teta} based on distance between
700cabdff1aSopenharmony_ci * current and past isf. A value of 1 shows maximum signal stability.
701cabdff1aSopenharmony_ci */
702cabdff1aSopenharmony_cistatic float stability_factor(const float *isf, const float *isf_past)
703cabdff1aSopenharmony_ci{
704cabdff1aSopenharmony_ci    int i;
705cabdff1aSopenharmony_ci    float acc = 0.0;
706cabdff1aSopenharmony_ci
707cabdff1aSopenharmony_ci    for (i = 0; i < LP_ORDER - 1; i++)
708cabdff1aSopenharmony_ci        acc += (isf[i] - isf_past[i]) * (isf[i] - isf_past[i]);
709cabdff1aSopenharmony_ci
710cabdff1aSopenharmony_ci    // XXX: This part is not so clear from the reference code
711cabdff1aSopenharmony_ci    // the result is more accurate changing the "/ 256" to "* 512"
712cabdff1aSopenharmony_ci    return FFMAX(0.0, 1.25 - acc * 0.8 * 512);
713cabdff1aSopenharmony_ci}
714cabdff1aSopenharmony_ci
715cabdff1aSopenharmony_ci/**
716cabdff1aSopenharmony_ci * Apply a non-linear fixed gain smoothing in order to reduce
717cabdff1aSopenharmony_ci * fluctuation in the energy of excitation.
718cabdff1aSopenharmony_ci *
719cabdff1aSopenharmony_ci * @param[in]     fixed_gain       Unsmoothed fixed gain
720cabdff1aSopenharmony_ci * @param[in,out] prev_tr_gain     Previous threshold gain (updated)
721cabdff1aSopenharmony_ci * @param[in]     voice_fac        Frame voicing factor
722cabdff1aSopenharmony_ci * @param[in]     stab_fac         Frame stability factor
723cabdff1aSopenharmony_ci *
724cabdff1aSopenharmony_ci * @return The smoothed gain
725cabdff1aSopenharmony_ci */
726cabdff1aSopenharmony_cistatic float noise_enhancer(float fixed_gain, float *prev_tr_gain,
727cabdff1aSopenharmony_ci                            float voice_fac,  float stab_fac)
728cabdff1aSopenharmony_ci{
729cabdff1aSopenharmony_ci    float sm_fac = 0.5 * (1 - voice_fac) * stab_fac;
730cabdff1aSopenharmony_ci    float g0;
731cabdff1aSopenharmony_ci
732cabdff1aSopenharmony_ci    // XXX: the following fixed-point constants used to in(de)crement
733cabdff1aSopenharmony_ci    // gain by 1.5dB were taken from the reference code, maybe it could
734cabdff1aSopenharmony_ci    // be simpler
735cabdff1aSopenharmony_ci    if (fixed_gain < *prev_tr_gain) {
736cabdff1aSopenharmony_ci        g0 = FFMIN(*prev_tr_gain, fixed_gain + fixed_gain *
737cabdff1aSopenharmony_ci                     (6226 * (1.0f / (1 << 15)))); // +1.5 dB
738cabdff1aSopenharmony_ci    } else
739cabdff1aSopenharmony_ci        g0 = FFMAX(*prev_tr_gain, fixed_gain *
740cabdff1aSopenharmony_ci                    (27536 * (1.0f / (1 << 15)))); // -1.5 dB
741cabdff1aSopenharmony_ci
742cabdff1aSopenharmony_ci    *prev_tr_gain = g0; // update next frame threshold
743cabdff1aSopenharmony_ci
744cabdff1aSopenharmony_ci    return sm_fac * g0 + (1 - sm_fac) * fixed_gain;
745cabdff1aSopenharmony_ci}
746cabdff1aSopenharmony_ci
747cabdff1aSopenharmony_ci/**
748cabdff1aSopenharmony_ci * Filter the fixed_vector to emphasize the higher frequencies.
749cabdff1aSopenharmony_ci *
750cabdff1aSopenharmony_ci * @param[in,out] fixed_vector     Fixed codebook vector
751cabdff1aSopenharmony_ci * @param[in]     voice_fac        Frame voicing factor
752cabdff1aSopenharmony_ci */
753cabdff1aSopenharmony_cistatic void pitch_enhancer(float *fixed_vector, float voice_fac)
754cabdff1aSopenharmony_ci{
755cabdff1aSopenharmony_ci    int i;
756cabdff1aSopenharmony_ci    float cpe  = 0.125 * (1 + voice_fac);
757cabdff1aSopenharmony_ci    float last = fixed_vector[0]; // holds c(i - 1)
758cabdff1aSopenharmony_ci
759cabdff1aSopenharmony_ci    fixed_vector[0] -= cpe * fixed_vector[1];
760cabdff1aSopenharmony_ci
761cabdff1aSopenharmony_ci    for (i = 1; i < AMRWB_SFR_SIZE - 1; i++) {
762cabdff1aSopenharmony_ci        float cur = fixed_vector[i];
763cabdff1aSopenharmony_ci
764cabdff1aSopenharmony_ci        fixed_vector[i] -= cpe * (last + fixed_vector[i + 1]);
765cabdff1aSopenharmony_ci        last = cur;
766cabdff1aSopenharmony_ci    }
767cabdff1aSopenharmony_ci
768cabdff1aSopenharmony_ci    fixed_vector[AMRWB_SFR_SIZE - 1] -= cpe * last;
769cabdff1aSopenharmony_ci}
770cabdff1aSopenharmony_ci
771cabdff1aSopenharmony_ci/**
772cabdff1aSopenharmony_ci * Conduct 16th order linear predictive coding synthesis from excitation.
773cabdff1aSopenharmony_ci *
774cabdff1aSopenharmony_ci * @param[in]     ctx              Pointer to the AMRWBContext
775cabdff1aSopenharmony_ci * @param[in]     lpc              Pointer to the LPC coefficients
776cabdff1aSopenharmony_ci * @param[out]    excitation       Buffer for synthesis final excitation
777cabdff1aSopenharmony_ci * @param[in]     fixed_gain       Fixed codebook gain for synthesis
778cabdff1aSopenharmony_ci * @param[in]     fixed_vector     Algebraic codebook vector
779cabdff1aSopenharmony_ci * @param[in,out] samples          Pointer to the output samples and memory
780cabdff1aSopenharmony_ci */
781cabdff1aSopenharmony_cistatic void synthesis(AMRWBContext *ctx, float *lpc, float *excitation,
782cabdff1aSopenharmony_ci                      float fixed_gain, const float *fixed_vector,
783cabdff1aSopenharmony_ci                      float *samples)
784cabdff1aSopenharmony_ci{
785cabdff1aSopenharmony_ci    ctx->acelpv_ctx.weighted_vector_sumf(excitation, ctx->pitch_vector, fixed_vector,
786cabdff1aSopenharmony_ci                            ctx->pitch_gain[0], fixed_gain, AMRWB_SFR_SIZE);
787cabdff1aSopenharmony_ci
788cabdff1aSopenharmony_ci    /* emphasize pitch vector contribution in low bitrate modes */
789cabdff1aSopenharmony_ci    if (ctx->pitch_gain[0] > 0.5 && ctx->fr_cur_mode <= MODE_8k85) {
790cabdff1aSopenharmony_ci        int i;
791cabdff1aSopenharmony_ci        float energy = ctx->celpm_ctx.dot_productf(excitation, excitation,
792cabdff1aSopenharmony_ci                                                    AMRWB_SFR_SIZE);
793cabdff1aSopenharmony_ci
794cabdff1aSopenharmony_ci        // XXX: Weird part in both ref code and spec. A unknown parameter
795cabdff1aSopenharmony_ci        // {beta} seems to be identical to the current pitch gain
796cabdff1aSopenharmony_ci        float pitch_factor = 0.25 * ctx->pitch_gain[0] * ctx->pitch_gain[0];
797cabdff1aSopenharmony_ci
798cabdff1aSopenharmony_ci        for (i = 0; i < AMRWB_SFR_SIZE; i++)
799cabdff1aSopenharmony_ci            excitation[i] += pitch_factor * ctx->pitch_vector[i];
800cabdff1aSopenharmony_ci
801cabdff1aSopenharmony_ci        ff_scale_vector_to_given_sum_of_squares(excitation, excitation,
802cabdff1aSopenharmony_ci                                                energy, AMRWB_SFR_SIZE);
803cabdff1aSopenharmony_ci    }
804cabdff1aSopenharmony_ci
805cabdff1aSopenharmony_ci    ctx->celpf_ctx.celp_lp_synthesis_filterf(samples, lpc, excitation,
806cabdff1aSopenharmony_ci                                 AMRWB_SFR_SIZE, LP_ORDER);
807cabdff1aSopenharmony_ci}
808cabdff1aSopenharmony_ci
809cabdff1aSopenharmony_ci/**
810cabdff1aSopenharmony_ci * Apply to synthesis a de-emphasis filter of the form:
811cabdff1aSopenharmony_ci * H(z) = 1 / (1 - m * z^-1)
812cabdff1aSopenharmony_ci *
813cabdff1aSopenharmony_ci * @param[out]    out              Output buffer
814cabdff1aSopenharmony_ci * @param[in]     in               Input samples array with in[-1]
815cabdff1aSopenharmony_ci * @param[in]     m                Filter coefficient
816cabdff1aSopenharmony_ci * @param[in,out] mem              State from last filtering
817cabdff1aSopenharmony_ci */
818cabdff1aSopenharmony_cistatic void de_emphasis(float *out, float *in, float m, float mem[1])
819cabdff1aSopenharmony_ci{
820cabdff1aSopenharmony_ci    int i;
821cabdff1aSopenharmony_ci
822cabdff1aSopenharmony_ci    out[0] = in[0] + m * mem[0];
823cabdff1aSopenharmony_ci
824cabdff1aSopenharmony_ci    for (i = 1; i < AMRWB_SFR_SIZE; i++)
825cabdff1aSopenharmony_ci         out[i] = in[i] + out[i - 1] * m;
826cabdff1aSopenharmony_ci
827cabdff1aSopenharmony_ci    mem[0] = out[AMRWB_SFR_SIZE - 1];
828cabdff1aSopenharmony_ci}
829cabdff1aSopenharmony_ci
830cabdff1aSopenharmony_ci/**
831cabdff1aSopenharmony_ci * Upsample a signal by 5/4 ratio (from 12.8kHz to 16kHz) using
832cabdff1aSopenharmony_ci * a FIR interpolation filter. Uses past data from before *in address.
833cabdff1aSopenharmony_ci *
834cabdff1aSopenharmony_ci * @param[out] out                 Buffer for interpolated signal
835cabdff1aSopenharmony_ci * @param[in]  in                  Current signal data (length 0.8*o_size)
836cabdff1aSopenharmony_ci * @param[in]  o_size              Output signal length
837cabdff1aSopenharmony_ci * @param[in] ctx                  The context
838cabdff1aSopenharmony_ci */
839cabdff1aSopenharmony_cistatic void upsample_5_4(float *out, const float *in, int o_size, CELPMContext *ctx)
840cabdff1aSopenharmony_ci{
841cabdff1aSopenharmony_ci    const float *in0 = in - UPS_FIR_SIZE + 1;
842cabdff1aSopenharmony_ci    int i, j, k;
843cabdff1aSopenharmony_ci    int int_part = 0, frac_part;
844cabdff1aSopenharmony_ci
845cabdff1aSopenharmony_ci    i = 0;
846cabdff1aSopenharmony_ci    for (j = 0; j < o_size / 5; j++) {
847cabdff1aSopenharmony_ci        out[i] = in[int_part];
848cabdff1aSopenharmony_ci        frac_part = 4;
849cabdff1aSopenharmony_ci        i++;
850cabdff1aSopenharmony_ci
851cabdff1aSopenharmony_ci        for (k = 1; k < 5; k++) {
852cabdff1aSopenharmony_ci            out[i] = ctx->dot_productf(in0 + int_part,
853cabdff1aSopenharmony_ci                                                  upsample_fir[4 - frac_part],
854cabdff1aSopenharmony_ci                                                  UPS_MEM_SIZE);
855cabdff1aSopenharmony_ci            int_part++;
856cabdff1aSopenharmony_ci            frac_part--;
857cabdff1aSopenharmony_ci            i++;
858cabdff1aSopenharmony_ci        }
859cabdff1aSopenharmony_ci    }
860cabdff1aSopenharmony_ci}
861cabdff1aSopenharmony_ci
862cabdff1aSopenharmony_ci/**
863cabdff1aSopenharmony_ci * Calculate the high-band gain based on encoded index (23k85 mode) or
864cabdff1aSopenharmony_ci * on the low-band speech signal and the Voice Activity Detection flag.
865cabdff1aSopenharmony_ci *
866cabdff1aSopenharmony_ci * @param[in] ctx                  The context
867cabdff1aSopenharmony_ci * @param[in] synth                LB speech synthesis at 12.8k
868cabdff1aSopenharmony_ci * @param[in] hb_idx               Gain index for mode 23k85 only
869cabdff1aSopenharmony_ci * @param[in] vad                  VAD flag for the frame
870cabdff1aSopenharmony_ci */
871cabdff1aSopenharmony_cistatic float find_hb_gain(AMRWBContext *ctx, const float *synth,
872cabdff1aSopenharmony_ci                          uint16_t hb_idx, uint8_t vad)
873cabdff1aSopenharmony_ci{
874cabdff1aSopenharmony_ci    int wsp = (vad > 0);
875cabdff1aSopenharmony_ci    float tilt;
876cabdff1aSopenharmony_ci    float tmp;
877cabdff1aSopenharmony_ci
878cabdff1aSopenharmony_ci    if (ctx->fr_cur_mode == MODE_23k85)
879cabdff1aSopenharmony_ci        return qua_hb_gain[hb_idx] * (1.0f / (1 << 14));
880cabdff1aSopenharmony_ci
881cabdff1aSopenharmony_ci    tmp = ctx->celpm_ctx.dot_productf(synth, synth + 1, AMRWB_SFR_SIZE - 1);
882cabdff1aSopenharmony_ci
883cabdff1aSopenharmony_ci    if (tmp > 0) {
884cabdff1aSopenharmony_ci        tilt = tmp / ctx->celpm_ctx.dot_productf(synth, synth, AMRWB_SFR_SIZE);
885cabdff1aSopenharmony_ci    } else
886cabdff1aSopenharmony_ci        tilt = 0;
887cabdff1aSopenharmony_ci
888cabdff1aSopenharmony_ci    /* return gain bounded by [0.1, 1.0] */
889cabdff1aSopenharmony_ci    return av_clipf((1.0 - tilt) * (1.25 - 0.25 * wsp), 0.1, 1.0);
890cabdff1aSopenharmony_ci}
891cabdff1aSopenharmony_ci
892cabdff1aSopenharmony_ci/**
893cabdff1aSopenharmony_ci * Generate the high-band excitation with the same energy from the lower
894cabdff1aSopenharmony_ci * one and scaled by the given gain.
895cabdff1aSopenharmony_ci *
896cabdff1aSopenharmony_ci * @param[in]  ctx                 The context
897cabdff1aSopenharmony_ci * @param[out] hb_exc              Buffer for the excitation
898cabdff1aSopenharmony_ci * @param[in]  synth_exc           Low-band excitation used for synthesis
899cabdff1aSopenharmony_ci * @param[in]  hb_gain             Wanted excitation gain
900cabdff1aSopenharmony_ci */
901cabdff1aSopenharmony_cistatic void scaled_hb_excitation(AMRWBContext *ctx, float *hb_exc,
902cabdff1aSopenharmony_ci                                 const float *synth_exc, float hb_gain)
903cabdff1aSopenharmony_ci{
904cabdff1aSopenharmony_ci    int i;
905cabdff1aSopenharmony_ci    float energy = ctx->celpm_ctx.dot_productf(synth_exc, synth_exc,
906cabdff1aSopenharmony_ci                                                AMRWB_SFR_SIZE);
907cabdff1aSopenharmony_ci
908cabdff1aSopenharmony_ci    /* Generate a white-noise excitation */
909cabdff1aSopenharmony_ci    for (i = 0; i < AMRWB_SFR_SIZE_16k; i++)
910cabdff1aSopenharmony_ci        hb_exc[i] = 32768.0 - (uint16_t) av_lfg_get(&ctx->prng);
911cabdff1aSopenharmony_ci
912cabdff1aSopenharmony_ci    ff_scale_vector_to_given_sum_of_squares(hb_exc, hb_exc,
913cabdff1aSopenharmony_ci                                            energy * hb_gain * hb_gain,
914cabdff1aSopenharmony_ci                                            AMRWB_SFR_SIZE_16k);
915cabdff1aSopenharmony_ci}
916cabdff1aSopenharmony_ci
917cabdff1aSopenharmony_ci/**
918cabdff1aSopenharmony_ci * Calculate the auto-correlation for the ISF difference vector.
919cabdff1aSopenharmony_ci */
920cabdff1aSopenharmony_cistatic float auto_correlation(float *diff_isf, float mean, int lag)
921cabdff1aSopenharmony_ci{
922cabdff1aSopenharmony_ci    int i;
923cabdff1aSopenharmony_ci    float sum = 0.0;
924cabdff1aSopenharmony_ci
925cabdff1aSopenharmony_ci    for (i = 7; i < LP_ORDER - 2; i++) {
926cabdff1aSopenharmony_ci        float prod = (diff_isf[i] - mean) * (diff_isf[i - lag] - mean);
927cabdff1aSopenharmony_ci        sum += prod * prod;
928cabdff1aSopenharmony_ci    }
929cabdff1aSopenharmony_ci    return sum;
930cabdff1aSopenharmony_ci}
931cabdff1aSopenharmony_ci
932cabdff1aSopenharmony_ci/**
933cabdff1aSopenharmony_ci * Extrapolate a ISF vector to the 16kHz range (20th order LP)
934cabdff1aSopenharmony_ci * used at mode 6k60 LP filter for the high frequency band.
935cabdff1aSopenharmony_ci *
936cabdff1aSopenharmony_ci * @param[out] isf Buffer for extrapolated isf; contains LP_ORDER
937cabdff1aSopenharmony_ci *                 values on input
938cabdff1aSopenharmony_ci */
939cabdff1aSopenharmony_cistatic void extrapolate_isf(float isf[LP_ORDER_16k])
940cabdff1aSopenharmony_ci{
941cabdff1aSopenharmony_ci    float diff_isf[LP_ORDER - 2], diff_mean;
942cabdff1aSopenharmony_ci    float corr_lag[3];
943cabdff1aSopenharmony_ci    float est, scale;
944cabdff1aSopenharmony_ci    int i, j, i_max_corr;
945cabdff1aSopenharmony_ci
946cabdff1aSopenharmony_ci    isf[LP_ORDER_16k - 1] = isf[LP_ORDER - 1];
947cabdff1aSopenharmony_ci
948cabdff1aSopenharmony_ci    /* Calculate the difference vector */
949cabdff1aSopenharmony_ci    for (i = 0; i < LP_ORDER - 2; i++)
950cabdff1aSopenharmony_ci        diff_isf[i] = isf[i + 1] - isf[i];
951cabdff1aSopenharmony_ci
952cabdff1aSopenharmony_ci    diff_mean = 0.0;
953cabdff1aSopenharmony_ci    for (i = 2; i < LP_ORDER - 2; i++)
954cabdff1aSopenharmony_ci        diff_mean += diff_isf[i] * (1.0f / (LP_ORDER - 4));
955cabdff1aSopenharmony_ci
956cabdff1aSopenharmony_ci    /* Find which is the maximum autocorrelation */
957cabdff1aSopenharmony_ci    i_max_corr = 0;
958cabdff1aSopenharmony_ci    for (i = 0; i < 3; i++) {
959cabdff1aSopenharmony_ci        corr_lag[i] = auto_correlation(diff_isf, diff_mean, i + 2);
960cabdff1aSopenharmony_ci
961cabdff1aSopenharmony_ci        if (corr_lag[i] > corr_lag[i_max_corr])
962cabdff1aSopenharmony_ci            i_max_corr = i;
963cabdff1aSopenharmony_ci    }
964cabdff1aSopenharmony_ci    i_max_corr++;
965cabdff1aSopenharmony_ci
966cabdff1aSopenharmony_ci    for (i = LP_ORDER - 1; i < LP_ORDER_16k - 1; i++)
967cabdff1aSopenharmony_ci        isf[i] = isf[i - 1] + isf[i - 1 - i_max_corr]
968cabdff1aSopenharmony_ci                            - isf[i - 2 - i_max_corr];
969cabdff1aSopenharmony_ci
970cabdff1aSopenharmony_ci    /* Calculate an estimate for ISF(18) and scale ISF based on the error */
971cabdff1aSopenharmony_ci    est   = 7965 + (isf[2] - isf[3] - isf[4]) / 6.0;
972cabdff1aSopenharmony_ci    scale = 0.5 * (FFMIN(est, 7600) - isf[LP_ORDER - 2]) /
973cabdff1aSopenharmony_ci            (isf[LP_ORDER_16k - 2] - isf[LP_ORDER - 2]);
974cabdff1aSopenharmony_ci
975cabdff1aSopenharmony_ci    for (i = LP_ORDER - 1, j = 0; i < LP_ORDER_16k - 1; i++, j++)
976cabdff1aSopenharmony_ci        diff_isf[j] = scale * (isf[i] - isf[i - 1]);
977cabdff1aSopenharmony_ci
978cabdff1aSopenharmony_ci    /* Stability insurance */
979cabdff1aSopenharmony_ci    for (i = 1; i < LP_ORDER_16k - LP_ORDER; i++)
980cabdff1aSopenharmony_ci        if (diff_isf[i] + diff_isf[i - 1] < 5.0) {
981cabdff1aSopenharmony_ci            if (diff_isf[i] > diff_isf[i - 1]) {
982cabdff1aSopenharmony_ci                diff_isf[i - 1] = 5.0 - diff_isf[i];
983cabdff1aSopenharmony_ci            } else
984cabdff1aSopenharmony_ci                diff_isf[i] = 5.0 - diff_isf[i - 1];
985cabdff1aSopenharmony_ci        }
986cabdff1aSopenharmony_ci
987cabdff1aSopenharmony_ci    for (i = LP_ORDER - 1, j = 0; i < LP_ORDER_16k - 1; i++, j++)
988cabdff1aSopenharmony_ci        isf[i] = isf[i - 1] + diff_isf[j] * (1.0f / (1 << 15));
989cabdff1aSopenharmony_ci
990cabdff1aSopenharmony_ci    /* Scale the ISF vector for 16000 Hz */
991cabdff1aSopenharmony_ci    for (i = 0; i < LP_ORDER_16k - 1; i++)
992cabdff1aSopenharmony_ci        isf[i] *= 0.8;
993cabdff1aSopenharmony_ci}
994cabdff1aSopenharmony_ci
995cabdff1aSopenharmony_ci/**
996cabdff1aSopenharmony_ci * Spectral expand the LP coefficients using the equation:
997cabdff1aSopenharmony_ci *   y[i] = x[i] * (gamma ** i)
998cabdff1aSopenharmony_ci *
999cabdff1aSopenharmony_ci * @param[out] out                 Output buffer (may use input array)
1000cabdff1aSopenharmony_ci * @param[in]  lpc                 LP coefficients array
1001cabdff1aSopenharmony_ci * @param[in]  gamma               Weighting factor
1002cabdff1aSopenharmony_ci * @param[in]  size                LP array size
1003cabdff1aSopenharmony_ci */
1004cabdff1aSopenharmony_cistatic void lpc_weighting(float *out, const float *lpc, float gamma, int size)
1005cabdff1aSopenharmony_ci{
1006cabdff1aSopenharmony_ci    int i;
1007cabdff1aSopenharmony_ci    float fac = gamma;
1008cabdff1aSopenharmony_ci
1009cabdff1aSopenharmony_ci    for (i = 0; i < size; i++) {
1010cabdff1aSopenharmony_ci        out[i] = lpc[i] * fac;
1011cabdff1aSopenharmony_ci        fac   *= gamma;
1012cabdff1aSopenharmony_ci    }
1013cabdff1aSopenharmony_ci}
1014cabdff1aSopenharmony_ci
1015cabdff1aSopenharmony_ci/**
1016cabdff1aSopenharmony_ci * Conduct 20th order linear predictive coding synthesis for the high
1017cabdff1aSopenharmony_ci * frequency band excitation at 16kHz.
1018cabdff1aSopenharmony_ci *
1019cabdff1aSopenharmony_ci * @param[in]     ctx              The context
1020cabdff1aSopenharmony_ci * @param[in]     subframe         Current subframe index (0 to 3)
1021cabdff1aSopenharmony_ci * @param[in,out] samples          Pointer to the output speech samples
1022cabdff1aSopenharmony_ci * @param[in]     exc              Generated white-noise scaled excitation
1023cabdff1aSopenharmony_ci * @param[in]     isf              Current frame isf vector
1024cabdff1aSopenharmony_ci * @param[in]     isf_past         Past frame final isf vector
1025cabdff1aSopenharmony_ci */
1026cabdff1aSopenharmony_cistatic void hb_synthesis(AMRWBContext *ctx, int subframe, float *samples,
1027cabdff1aSopenharmony_ci                         const float *exc, const float *isf, const float *isf_past)
1028cabdff1aSopenharmony_ci{
1029cabdff1aSopenharmony_ci    float hb_lpc[LP_ORDER_16k];
1030cabdff1aSopenharmony_ci    enum Mode mode = ctx->fr_cur_mode;
1031cabdff1aSopenharmony_ci
1032cabdff1aSopenharmony_ci    if (mode == MODE_6k60) {
1033cabdff1aSopenharmony_ci        float e_isf[LP_ORDER_16k]; // ISF vector for extrapolation
1034cabdff1aSopenharmony_ci        double e_isp[LP_ORDER_16k];
1035cabdff1aSopenharmony_ci
1036cabdff1aSopenharmony_ci        ctx->acelpv_ctx.weighted_vector_sumf(e_isf, isf_past, isf, isfp_inter[subframe],
1037cabdff1aSopenharmony_ci                                1.0 - isfp_inter[subframe], LP_ORDER);
1038cabdff1aSopenharmony_ci
1039cabdff1aSopenharmony_ci        extrapolate_isf(e_isf);
1040cabdff1aSopenharmony_ci
1041cabdff1aSopenharmony_ci        e_isf[LP_ORDER_16k - 1] *= 2.0;
1042cabdff1aSopenharmony_ci        ff_acelp_lsf2lspd(e_isp, e_isf, LP_ORDER_16k);
1043cabdff1aSopenharmony_ci        ff_amrwb_lsp2lpc(e_isp, hb_lpc, LP_ORDER_16k);
1044cabdff1aSopenharmony_ci
1045cabdff1aSopenharmony_ci        lpc_weighting(hb_lpc, hb_lpc, 0.9, LP_ORDER_16k);
1046cabdff1aSopenharmony_ci    } else {
1047cabdff1aSopenharmony_ci        lpc_weighting(hb_lpc, ctx->lp_coef[subframe], 0.6, LP_ORDER);
1048cabdff1aSopenharmony_ci    }
1049cabdff1aSopenharmony_ci
1050cabdff1aSopenharmony_ci    ctx->celpf_ctx.celp_lp_synthesis_filterf(samples, hb_lpc, exc, AMRWB_SFR_SIZE_16k,
1051cabdff1aSopenharmony_ci                                 (mode == MODE_6k60) ? LP_ORDER_16k : LP_ORDER);
1052cabdff1aSopenharmony_ci}
1053cabdff1aSopenharmony_ci
1054cabdff1aSopenharmony_ci/**
1055cabdff1aSopenharmony_ci * Apply a 15th order filter to high-band samples.
1056cabdff1aSopenharmony_ci * The filter characteristic depends on the given coefficients.
1057cabdff1aSopenharmony_ci *
1058cabdff1aSopenharmony_ci * @param[out]    out              Buffer for filtered output
1059cabdff1aSopenharmony_ci * @param[in]     fir_coef         Filter coefficients
1060cabdff1aSopenharmony_ci * @param[in,out] mem              State from last filtering (updated)
1061cabdff1aSopenharmony_ci * @param[in]     in               Input speech data (high-band)
1062cabdff1aSopenharmony_ci *
1063cabdff1aSopenharmony_ci * @remark It is safe to pass the same array in in and out parameters
1064cabdff1aSopenharmony_ci */
1065cabdff1aSopenharmony_ci
1066cabdff1aSopenharmony_ci#ifndef hb_fir_filter
1067cabdff1aSopenharmony_cistatic void hb_fir_filter(float *out, const float fir_coef[HB_FIR_SIZE + 1],
1068cabdff1aSopenharmony_ci                          float mem[HB_FIR_SIZE], const float *in)
1069cabdff1aSopenharmony_ci{
1070cabdff1aSopenharmony_ci    int i, j;
1071cabdff1aSopenharmony_ci    float data[AMRWB_SFR_SIZE_16k + HB_FIR_SIZE]; // past and current samples
1072cabdff1aSopenharmony_ci
1073cabdff1aSopenharmony_ci    memcpy(data, mem, HB_FIR_SIZE * sizeof(float));
1074cabdff1aSopenharmony_ci    memcpy(data + HB_FIR_SIZE, in, AMRWB_SFR_SIZE_16k * sizeof(float));
1075cabdff1aSopenharmony_ci
1076cabdff1aSopenharmony_ci    for (i = 0; i < AMRWB_SFR_SIZE_16k; i++) {
1077cabdff1aSopenharmony_ci        out[i] = 0.0;
1078cabdff1aSopenharmony_ci        for (j = 0; j <= HB_FIR_SIZE; j++)
1079cabdff1aSopenharmony_ci            out[i] += data[i + j] * fir_coef[j];
1080cabdff1aSopenharmony_ci    }
1081cabdff1aSopenharmony_ci
1082cabdff1aSopenharmony_ci    memcpy(mem, data + AMRWB_SFR_SIZE_16k, HB_FIR_SIZE * sizeof(float));
1083cabdff1aSopenharmony_ci}
1084cabdff1aSopenharmony_ci#endif /* hb_fir_filter */
1085cabdff1aSopenharmony_ci
1086cabdff1aSopenharmony_ci/**
1087cabdff1aSopenharmony_ci * Update context state before the next subframe.
1088cabdff1aSopenharmony_ci */
1089cabdff1aSopenharmony_cistatic void update_sub_state(AMRWBContext *ctx)
1090cabdff1aSopenharmony_ci{
1091cabdff1aSopenharmony_ci    memmove(&ctx->excitation_buf[0], &ctx->excitation_buf[AMRWB_SFR_SIZE],
1092cabdff1aSopenharmony_ci            (AMRWB_P_DELAY_MAX + LP_ORDER + 1) * sizeof(float));
1093cabdff1aSopenharmony_ci
1094cabdff1aSopenharmony_ci    memmove(&ctx->pitch_gain[1], &ctx->pitch_gain[0], 5 * sizeof(float));
1095cabdff1aSopenharmony_ci    memmove(&ctx->fixed_gain[1], &ctx->fixed_gain[0], 1 * sizeof(float));
1096cabdff1aSopenharmony_ci
1097cabdff1aSopenharmony_ci    memmove(&ctx->samples_az[0], &ctx->samples_az[AMRWB_SFR_SIZE],
1098cabdff1aSopenharmony_ci            LP_ORDER * sizeof(float));
1099cabdff1aSopenharmony_ci    memmove(&ctx->samples_up[0], &ctx->samples_up[AMRWB_SFR_SIZE],
1100cabdff1aSopenharmony_ci            UPS_MEM_SIZE * sizeof(float));
1101cabdff1aSopenharmony_ci    memmove(&ctx->samples_hb[0], &ctx->samples_hb[AMRWB_SFR_SIZE_16k],
1102cabdff1aSopenharmony_ci            LP_ORDER_16k * sizeof(float));
1103cabdff1aSopenharmony_ci}
1104cabdff1aSopenharmony_ci
1105cabdff1aSopenharmony_cistatic int amrwb_decode_frame(AVCodecContext *avctx, AVFrame *frame,
1106cabdff1aSopenharmony_ci                              int *got_frame_ptr, AVPacket *avpkt)
1107cabdff1aSopenharmony_ci{
1108cabdff1aSopenharmony_ci    AMRWBChannelsContext *s  = avctx->priv_data;
1109cabdff1aSopenharmony_ci    const uint8_t *buf = avpkt->data;
1110cabdff1aSopenharmony_ci    int buf_size       = avpkt->size;
1111cabdff1aSopenharmony_ci    int sub, i, ret;
1112cabdff1aSopenharmony_ci
1113cabdff1aSopenharmony_ci    /* get output buffer */
1114cabdff1aSopenharmony_ci    frame->nb_samples = 4 * AMRWB_SFR_SIZE_16k;
1115cabdff1aSopenharmony_ci    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
1116cabdff1aSopenharmony_ci        return ret;
1117cabdff1aSopenharmony_ci
1118cabdff1aSopenharmony_ci    for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
1119cabdff1aSopenharmony_ci        AMRWBContext *ctx  = &s->ch[ch];
1120cabdff1aSopenharmony_ci        AMRWBFrame   *cf   = &ctx->frame;
1121cabdff1aSopenharmony_ci        int expected_fr_size, header_size;
1122cabdff1aSopenharmony_ci        float spare_vector[AMRWB_SFR_SIZE];      // extra stack space to hold result from anti-sparseness processing
1123cabdff1aSopenharmony_ci        float fixed_gain_factor;                 // fixed gain correction factor (gamma)
1124cabdff1aSopenharmony_ci        float *synth_fixed_vector;               // pointer to the fixed vector that synthesis should use
1125cabdff1aSopenharmony_ci        float synth_fixed_gain;                  // the fixed gain that synthesis should use
1126cabdff1aSopenharmony_ci        float voice_fac, stab_fac;               // parameters used for gain smoothing
1127cabdff1aSopenharmony_ci        float synth_exc[AMRWB_SFR_SIZE];         // post-processed excitation for synthesis
1128cabdff1aSopenharmony_ci        float hb_exc[AMRWB_SFR_SIZE_16k];        // excitation for the high frequency band
1129cabdff1aSopenharmony_ci        float hb_samples[AMRWB_SFR_SIZE_16k];    // filtered high-band samples from synthesis
1130cabdff1aSopenharmony_ci        float hb_gain;
1131cabdff1aSopenharmony_ci        float *buf_out = (float *)frame->extended_data[ch];
1132cabdff1aSopenharmony_ci
1133cabdff1aSopenharmony_ci        header_size      = decode_mime_header(ctx, buf);
1134cabdff1aSopenharmony_ci        expected_fr_size = ((cf_sizes_wb[ctx->fr_cur_mode] + 7) >> 3) + 1;
1135cabdff1aSopenharmony_ci
1136cabdff1aSopenharmony_ci        if (!ctx->fr_quality)
1137cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Encountered a bad or corrupted frame\n");
1138cabdff1aSopenharmony_ci
1139cabdff1aSopenharmony_ci        if (ctx->fr_cur_mode == NO_DATA || !ctx->fr_quality) {
1140cabdff1aSopenharmony_ci            /* The specification suggests a "random signal" and
1141cabdff1aSopenharmony_ci               "a muting technique" to "gradually decrease the output level". */
1142cabdff1aSopenharmony_ci            av_samples_set_silence(&frame->extended_data[ch], 0, frame->nb_samples, 1, AV_SAMPLE_FMT_FLT);
1143cabdff1aSopenharmony_ci            buf += expected_fr_size;
1144cabdff1aSopenharmony_ci            buf_size -= expected_fr_size;
1145cabdff1aSopenharmony_ci            continue;
1146cabdff1aSopenharmony_ci        }
1147cabdff1aSopenharmony_ci        if (ctx->fr_cur_mode > MODE_SID) {
1148cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR,
1149cabdff1aSopenharmony_ci                   "Invalid mode %d\n", ctx->fr_cur_mode);
1150cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1151cabdff1aSopenharmony_ci        }
1152cabdff1aSopenharmony_ci
1153cabdff1aSopenharmony_ci        if (buf_size < expected_fr_size) {
1154cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR,
1155cabdff1aSopenharmony_ci                   "Frame too small (%d bytes). Truncated file?\n", buf_size);
1156cabdff1aSopenharmony_ci            *got_frame_ptr = 0;
1157cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1158cabdff1aSopenharmony_ci        }
1159cabdff1aSopenharmony_ci
1160cabdff1aSopenharmony_ci        if (ctx->fr_cur_mode == MODE_SID) { /* Comfort noise frame */
1161cabdff1aSopenharmony_ci            avpriv_request_sample(avctx, "SID mode");
1162cabdff1aSopenharmony_ci            return AVERROR_PATCHWELCOME;
1163cabdff1aSopenharmony_ci        }
1164cabdff1aSopenharmony_ci
1165cabdff1aSopenharmony_ci        ff_amr_bit_reorder((uint16_t *) &ctx->frame, sizeof(AMRWBFrame),
1166cabdff1aSopenharmony_ci                           buf + header_size, amr_bit_orderings_by_mode[ctx->fr_cur_mode]);
1167cabdff1aSopenharmony_ci
1168cabdff1aSopenharmony_ci        /* Decode the quantized ISF vector */
1169cabdff1aSopenharmony_ci        if (ctx->fr_cur_mode == MODE_6k60) {
1170cabdff1aSopenharmony_ci            decode_isf_indices_36b(cf->isp_id, ctx->isf_cur);
1171cabdff1aSopenharmony_ci        } else {
1172cabdff1aSopenharmony_ci            decode_isf_indices_46b(cf->isp_id, ctx->isf_cur);
1173cabdff1aSopenharmony_ci        }
1174cabdff1aSopenharmony_ci
1175cabdff1aSopenharmony_ci        isf_add_mean_and_past(ctx->isf_cur, ctx->isf_q_past);
1176cabdff1aSopenharmony_ci        ff_set_min_dist_lsf(ctx->isf_cur, MIN_ISF_SPACING, LP_ORDER - 1);
1177cabdff1aSopenharmony_ci
1178cabdff1aSopenharmony_ci        stab_fac = stability_factor(ctx->isf_cur, ctx->isf_past_final);
1179cabdff1aSopenharmony_ci
1180cabdff1aSopenharmony_ci        ctx->isf_cur[LP_ORDER - 1] *= 2.0;
1181cabdff1aSopenharmony_ci        ff_acelp_lsf2lspd(ctx->isp[3], ctx->isf_cur, LP_ORDER);
1182cabdff1aSopenharmony_ci
1183cabdff1aSopenharmony_ci        /* Generate a ISP vector for each subframe */
1184cabdff1aSopenharmony_ci        if (ctx->first_frame) {
1185cabdff1aSopenharmony_ci            ctx->first_frame = 0;
1186cabdff1aSopenharmony_ci            memcpy(ctx->isp_sub4_past, ctx->isp[3], LP_ORDER * sizeof(double));
1187cabdff1aSopenharmony_ci        }
1188cabdff1aSopenharmony_ci        interpolate_isp(ctx->isp, ctx->isp_sub4_past);
1189cabdff1aSopenharmony_ci
1190cabdff1aSopenharmony_ci        for (sub = 0; sub < 4; sub++)
1191cabdff1aSopenharmony_ci            ff_amrwb_lsp2lpc(ctx->isp[sub], ctx->lp_coef[sub], LP_ORDER);
1192cabdff1aSopenharmony_ci
1193cabdff1aSopenharmony_ci        for (sub = 0; sub < 4; sub++) {
1194cabdff1aSopenharmony_ci            const AMRWBSubFrame *cur_subframe = &cf->subframe[sub];
1195cabdff1aSopenharmony_ci            float *sub_buf = buf_out + sub * AMRWB_SFR_SIZE_16k;
1196cabdff1aSopenharmony_ci
1197cabdff1aSopenharmony_ci            /* Decode adaptive codebook (pitch vector) */
1198cabdff1aSopenharmony_ci            decode_pitch_vector(ctx, cur_subframe, sub);
1199cabdff1aSopenharmony_ci            /* Decode innovative codebook (fixed vector) */
1200cabdff1aSopenharmony_ci            decode_fixed_vector(ctx->fixed_vector, cur_subframe->pul_ih,
1201cabdff1aSopenharmony_ci                                cur_subframe->pul_il, ctx->fr_cur_mode);
1202cabdff1aSopenharmony_ci
1203cabdff1aSopenharmony_ci            pitch_sharpening(ctx, ctx->fixed_vector);
1204cabdff1aSopenharmony_ci
1205cabdff1aSopenharmony_ci            decode_gains(cur_subframe->vq_gain, ctx->fr_cur_mode,
1206cabdff1aSopenharmony_ci                         &fixed_gain_factor, &ctx->pitch_gain[0]);
1207cabdff1aSopenharmony_ci
1208cabdff1aSopenharmony_ci            ctx->fixed_gain[0] =
1209cabdff1aSopenharmony_ci                ff_amr_set_fixed_gain(fixed_gain_factor,
1210cabdff1aSopenharmony_ci                                      ctx->celpm_ctx.dot_productf(ctx->fixed_vector,
1211cabdff1aSopenharmony_ci                                                                  ctx->fixed_vector,
1212cabdff1aSopenharmony_ci                                                                  AMRWB_SFR_SIZE) /
1213cabdff1aSopenharmony_ci                                      AMRWB_SFR_SIZE,
1214cabdff1aSopenharmony_ci                                      ctx->prediction_error,
1215cabdff1aSopenharmony_ci                                      ENERGY_MEAN, energy_pred_fac);
1216cabdff1aSopenharmony_ci
1217cabdff1aSopenharmony_ci            /* Calculate voice factor and store tilt for next subframe */
1218cabdff1aSopenharmony_ci            voice_fac      = voice_factor(ctx->pitch_vector, ctx->pitch_gain[0],
1219cabdff1aSopenharmony_ci                                          ctx->fixed_vector, ctx->fixed_gain[0],
1220cabdff1aSopenharmony_ci                                          &ctx->celpm_ctx);
1221cabdff1aSopenharmony_ci            ctx->tilt_coef = voice_fac * 0.25 + 0.25;
1222cabdff1aSopenharmony_ci
1223cabdff1aSopenharmony_ci            /* Construct current excitation */
1224cabdff1aSopenharmony_ci            for (i = 0; i < AMRWB_SFR_SIZE; i++) {
1225cabdff1aSopenharmony_ci                ctx->excitation[i] *= ctx->pitch_gain[0];
1226cabdff1aSopenharmony_ci                ctx->excitation[i] += ctx->fixed_gain[0] * ctx->fixed_vector[i];
1227cabdff1aSopenharmony_ci                ctx->excitation[i] = truncf(ctx->excitation[i]);
1228cabdff1aSopenharmony_ci            }
1229cabdff1aSopenharmony_ci
1230cabdff1aSopenharmony_ci            /* Post-processing of excitation elements */
1231cabdff1aSopenharmony_ci            synth_fixed_gain = noise_enhancer(ctx->fixed_gain[0], &ctx->prev_tr_gain,
1232cabdff1aSopenharmony_ci                                              voice_fac, stab_fac);
1233cabdff1aSopenharmony_ci
1234cabdff1aSopenharmony_ci            synth_fixed_vector = anti_sparseness(ctx, ctx->fixed_vector,
1235cabdff1aSopenharmony_ci                                                 spare_vector);
1236cabdff1aSopenharmony_ci
1237cabdff1aSopenharmony_ci            pitch_enhancer(synth_fixed_vector, voice_fac);
1238cabdff1aSopenharmony_ci
1239cabdff1aSopenharmony_ci            synthesis(ctx, ctx->lp_coef[sub], synth_exc, synth_fixed_gain,
1240cabdff1aSopenharmony_ci                      synth_fixed_vector, &ctx->samples_az[LP_ORDER]);
1241cabdff1aSopenharmony_ci
1242cabdff1aSopenharmony_ci            /* Synthesis speech post-processing */
1243cabdff1aSopenharmony_ci            de_emphasis(&ctx->samples_up[UPS_MEM_SIZE],
1244cabdff1aSopenharmony_ci                        &ctx->samples_az[LP_ORDER], PREEMPH_FAC, ctx->demph_mem);
1245cabdff1aSopenharmony_ci
1246cabdff1aSopenharmony_ci            ctx->acelpf_ctx.acelp_apply_order_2_transfer_function(&ctx->samples_up[UPS_MEM_SIZE],
1247cabdff1aSopenharmony_ci                                                                  &ctx->samples_up[UPS_MEM_SIZE], hpf_zeros, hpf_31_poles,
1248cabdff1aSopenharmony_ci                                                                  hpf_31_gain, ctx->hpf_31_mem, AMRWB_SFR_SIZE);
1249cabdff1aSopenharmony_ci
1250cabdff1aSopenharmony_ci            upsample_5_4(sub_buf, &ctx->samples_up[UPS_FIR_SIZE],
1251cabdff1aSopenharmony_ci                         AMRWB_SFR_SIZE_16k, &ctx->celpm_ctx);
1252cabdff1aSopenharmony_ci
1253cabdff1aSopenharmony_ci            /* High frequency band (6.4 - 7.0 kHz) generation part */
1254cabdff1aSopenharmony_ci            ctx->acelpf_ctx.acelp_apply_order_2_transfer_function(hb_samples,
1255cabdff1aSopenharmony_ci                                                                  &ctx->samples_up[UPS_MEM_SIZE], hpf_zeros, hpf_400_poles,
1256cabdff1aSopenharmony_ci                                                                  hpf_400_gain, ctx->hpf_400_mem, AMRWB_SFR_SIZE);
1257cabdff1aSopenharmony_ci
1258cabdff1aSopenharmony_ci            hb_gain = find_hb_gain(ctx, hb_samples,
1259cabdff1aSopenharmony_ci                                   cur_subframe->hb_gain, cf->vad);
1260cabdff1aSopenharmony_ci
1261cabdff1aSopenharmony_ci            scaled_hb_excitation(ctx, hb_exc, synth_exc, hb_gain);
1262cabdff1aSopenharmony_ci
1263cabdff1aSopenharmony_ci            hb_synthesis(ctx, sub, &ctx->samples_hb[LP_ORDER_16k],
1264cabdff1aSopenharmony_ci                         hb_exc, ctx->isf_cur, ctx->isf_past_final);
1265cabdff1aSopenharmony_ci
1266cabdff1aSopenharmony_ci            /* High-band post-processing filters */
1267cabdff1aSopenharmony_ci            hb_fir_filter(hb_samples, bpf_6_7_coef, ctx->bpf_6_7_mem,
1268cabdff1aSopenharmony_ci                          &ctx->samples_hb[LP_ORDER_16k]);
1269cabdff1aSopenharmony_ci
1270cabdff1aSopenharmony_ci            if (ctx->fr_cur_mode == MODE_23k85)
1271cabdff1aSopenharmony_ci                hb_fir_filter(hb_samples, lpf_7_coef, ctx->lpf_7_mem,
1272cabdff1aSopenharmony_ci                              hb_samples);
1273cabdff1aSopenharmony_ci
1274cabdff1aSopenharmony_ci            /* Add the low and high frequency bands */
1275cabdff1aSopenharmony_ci            for (i = 0; i < AMRWB_SFR_SIZE_16k; i++)
1276cabdff1aSopenharmony_ci                sub_buf[i] = (sub_buf[i] + hb_samples[i]) * (1.0f / (1 << 15));
1277cabdff1aSopenharmony_ci
1278cabdff1aSopenharmony_ci            /* Update buffers and history */
1279cabdff1aSopenharmony_ci            update_sub_state(ctx);
1280cabdff1aSopenharmony_ci        }
1281cabdff1aSopenharmony_ci
1282cabdff1aSopenharmony_ci        /* update state for next frame */
1283cabdff1aSopenharmony_ci        memcpy(ctx->isp_sub4_past, ctx->isp[3], LP_ORDER * sizeof(ctx->isp[3][0]));
1284cabdff1aSopenharmony_ci        memcpy(ctx->isf_past_final, ctx->isf_cur, LP_ORDER * sizeof(float));
1285cabdff1aSopenharmony_ci
1286cabdff1aSopenharmony_ci        buf += expected_fr_size;
1287cabdff1aSopenharmony_ci        buf_size -= expected_fr_size;
1288cabdff1aSopenharmony_ci    }
1289cabdff1aSopenharmony_ci
1290cabdff1aSopenharmony_ci    *got_frame_ptr = 1;
1291cabdff1aSopenharmony_ci
1292cabdff1aSopenharmony_ci    return avpkt->size;
1293cabdff1aSopenharmony_ci}
1294cabdff1aSopenharmony_ci
1295cabdff1aSopenharmony_ciconst FFCodec ff_amrwb_decoder = {
1296cabdff1aSopenharmony_ci    .p.name         = "amrwb",
1297cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("AMR-WB (Adaptive Multi-Rate WideBand)"),
1298cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_AUDIO,
1299cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_AMR_WB,
1300cabdff1aSopenharmony_ci    .priv_data_size = sizeof(AMRWBChannelsContext),
1301cabdff1aSopenharmony_ci    .init           = amrwb_decode_init,
1302cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(amrwb_decode_frame),
1303cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
1304cabdff1aSopenharmony_ci    .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT,
1305cabdff1aSopenharmony_ci                                                     AV_SAMPLE_FMT_NONE },
1306cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
1307cabdff1aSopenharmony_ci};
1308