xref: /third_party/ffmpeg/libavcodec/lpc.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * LPC utility code
3cabdff1aSopenharmony_ci * Copyright (c) 2006  Justin Ruggles <justin.ruggles@gmail.com>
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#include "libavutil/common.h"
23cabdff1aSopenharmony_ci#include "libavutil/lls.h"
24cabdff1aSopenharmony_ci#include "libavutil/mem_internal.h"
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#define LPC_USE_DOUBLE
27cabdff1aSopenharmony_ci#include "lpc.h"
28cabdff1aSopenharmony_ci#include "libavutil/avassert.h"
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_ci
31cabdff1aSopenharmony_ci/**
32cabdff1aSopenharmony_ci * Apply Welch window function to audio block
33cabdff1aSopenharmony_ci */
34cabdff1aSopenharmony_cistatic void lpc_apply_welch_window_c(const int32_t *data, int len,
35cabdff1aSopenharmony_ci                                     double *w_data)
36cabdff1aSopenharmony_ci{
37cabdff1aSopenharmony_ci    int i, n2;
38cabdff1aSopenharmony_ci    double w;
39cabdff1aSopenharmony_ci    double c;
40cabdff1aSopenharmony_ci
41cabdff1aSopenharmony_ci    n2 = (len >> 1);
42cabdff1aSopenharmony_ci    c = 2.0 / (len - 1.0);
43cabdff1aSopenharmony_ci
44cabdff1aSopenharmony_ci    if (len & 1) {
45cabdff1aSopenharmony_ci        for(i=0; i<n2; i++) {
46cabdff1aSopenharmony_ci            w = c - i - 1.0;
47cabdff1aSopenharmony_ci            w = 1.0 - (w * w);
48cabdff1aSopenharmony_ci            w_data[i] = data[i] * w;
49cabdff1aSopenharmony_ci            w_data[len-1-i] = data[len-1-i] * w;
50cabdff1aSopenharmony_ci        }
51cabdff1aSopenharmony_ci        return;
52cabdff1aSopenharmony_ci    }
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_ci    w_data+=n2;
55cabdff1aSopenharmony_ci      data+=n2;
56cabdff1aSopenharmony_ci    for(i=0; i<n2; i++) {
57cabdff1aSopenharmony_ci        w = c - n2 + i;
58cabdff1aSopenharmony_ci        w = 1.0 - (w * w);
59cabdff1aSopenharmony_ci        w_data[-i-1] = data[-i-1] * w;
60cabdff1aSopenharmony_ci        w_data[+i  ] = data[+i  ] * w;
61cabdff1aSopenharmony_ci    }
62cabdff1aSopenharmony_ci}
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_ci/**
65cabdff1aSopenharmony_ci * Calculate autocorrelation data from audio samples
66cabdff1aSopenharmony_ci * A Welch window function is applied before calculation.
67cabdff1aSopenharmony_ci */
68cabdff1aSopenharmony_cistatic void lpc_compute_autocorr_c(const double *data, int len, int lag,
69cabdff1aSopenharmony_ci                                   double *autoc)
70cabdff1aSopenharmony_ci{
71cabdff1aSopenharmony_ci    int i, j;
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_ci    for(j=0; j<lag; j+=2){
74cabdff1aSopenharmony_ci        double sum0 = 1.0, sum1 = 1.0;
75cabdff1aSopenharmony_ci        for(i=j; i<len; i++){
76cabdff1aSopenharmony_ci            sum0 += data[i] * data[i-j];
77cabdff1aSopenharmony_ci            sum1 += data[i] * data[i-j-1];
78cabdff1aSopenharmony_ci        }
79cabdff1aSopenharmony_ci        autoc[j  ] = sum0;
80cabdff1aSopenharmony_ci        autoc[j+1] = sum1;
81cabdff1aSopenharmony_ci    }
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_ci    if(j==lag){
84cabdff1aSopenharmony_ci        double sum = 1.0;
85cabdff1aSopenharmony_ci        for(i=j-1; i<len; i+=2){
86cabdff1aSopenharmony_ci            sum += data[i  ] * data[i-j  ]
87cabdff1aSopenharmony_ci                 + data[i+1] * data[i-j+1];
88cabdff1aSopenharmony_ci        }
89cabdff1aSopenharmony_ci        autoc[j] = sum;
90cabdff1aSopenharmony_ci    }
91cabdff1aSopenharmony_ci}
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_ci/**
94cabdff1aSopenharmony_ci * Quantize LPC coefficients
95cabdff1aSopenharmony_ci */
96cabdff1aSopenharmony_cistatic void quantize_lpc_coefs(double *lpc_in, int order, int precision,
97cabdff1aSopenharmony_ci                               int32_t *lpc_out, int *shift, int min_shift,
98cabdff1aSopenharmony_ci                               int max_shift, int zero_shift)
99cabdff1aSopenharmony_ci{
100cabdff1aSopenharmony_ci    int i;
101cabdff1aSopenharmony_ci    double cmax, error;
102cabdff1aSopenharmony_ci    int32_t qmax;
103cabdff1aSopenharmony_ci    int sh;
104cabdff1aSopenharmony_ci
105cabdff1aSopenharmony_ci    /* define maximum levels */
106cabdff1aSopenharmony_ci    qmax = (1 << (precision - 1)) - 1;
107cabdff1aSopenharmony_ci
108cabdff1aSopenharmony_ci    /* find maximum coefficient value */
109cabdff1aSopenharmony_ci    cmax = 0.0;
110cabdff1aSopenharmony_ci    for(i=0; i<order; i++) {
111cabdff1aSopenharmony_ci        cmax= FFMAX(cmax, fabs(lpc_in[i]));
112cabdff1aSopenharmony_ci    }
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_ci    /* if maximum value quantizes to zero, return all zeros */
115cabdff1aSopenharmony_ci    if(cmax * (1 << max_shift) < 1.0) {
116cabdff1aSopenharmony_ci        *shift = zero_shift;
117cabdff1aSopenharmony_ci        memset(lpc_out, 0, sizeof(int32_t) * order);
118cabdff1aSopenharmony_ci        return;
119cabdff1aSopenharmony_ci    }
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci    /* calculate level shift which scales max coeff to available bits */
122cabdff1aSopenharmony_ci    sh = max_shift;
123cabdff1aSopenharmony_ci    while((cmax * (1 << sh) > qmax) && (sh > min_shift)) {
124cabdff1aSopenharmony_ci        sh--;
125cabdff1aSopenharmony_ci    }
126cabdff1aSopenharmony_ci
127cabdff1aSopenharmony_ci    /* since negative shift values are unsupported in decoder, scale down
128cabdff1aSopenharmony_ci       coefficients instead */
129cabdff1aSopenharmony_ci    if(sh == 0 && cmax > qmax) {
130cabdff1aSopenharmony_ci        double scale = ((double)qmax) / cmax;
131cabdff1aSopenharmony_ci        for(i=0; i<order; i++) {
132cabdff1aSopenharmony_ci            lpc_in[i] *= scale;
133cabdff1aSopenharmony_ci        }
134cabdff1aSopenharmony_ci    }
135cabdff1aSopenharmony_ci
136cabdff1aSopenharmony_ci    /* output quantized coefficients and level shift */
137cabdff1aSopenharmony_ci    error=0;
138cabdff1aSopenharmony_ci    for(i=0; i<order; i++) {
139cabdff1aSopenharmony_ci        error -= lpc_in[i] * (1 << sh);
140cabdff1aSopenharmony_ci        lpc_out[i] = av_clip(lrintf(error), -qmax, qmax);
141cabdff1aSopenharmony_ci        error -= lpc_out[i];
142cabdff1aSopenharmony_ci    }
143cabdff1aSopenharmony_ci    *shift = sh;
144cabdff1aSopenharmony_ci}
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_cistatic int estimate_best_order(double *ref, int min_order, int max_order)
147cabdff1aSopenharmony_ci{
148cabdff1aSopenharmony_ci    int i, est;
149cabdff1aSopenharmony_ci
150cabdff1aSopenharmony_ci    est = min_order;
151cabdff1aSopenharmony_ci    for(i=max_order-1; i>=min_order-1; i--) {
152cabdff1aSopenharmony_ci        if(ref[i] > 0.10) {
153cabdff1aSopenharmony_ci            est = i+1;
154cabdff1aSopenharmony_ci            break;
155cabdff1aSopenharmony_ci        }
156cabdff1aSopenharmony_ci    }
157cabdff1aSopenharmony_ci    return est;
158cabdff1aSopenharmony_ci}
159cabdff1aSopenharmony_ci
160cabdff1aSopenharmony_ciint ff_lpc_calc_ref_coefs(LPCContext *s,
161cabdff1aSopenharmony_ci                          const int32_t *samples, int order, double *ref)
162cabdff1aSopenharmony_ci{
163cabdff1aSopenharmony_ci    double autoc[MAX_LPC_ORDER + 1];
164cabdff1aSopenharmony_ci
165cabdff1aSopenharmony_ci    s->lpc_apply_welch_window(samples, s->blocksize, s->windowed_samples);
166cabdff1aSopenharmony_ci    s->lpc_compute_autocorr(s->windowed_samples, s->blocksize, order, autoc);
167cabdff1aSopenharmony_ci    compute_ref_coefs(autoc, order, ref, NULL);
168cabdff1aSopenharmony_ci
169cabdff1aSopenharmony_ci    return order;
170cabdff1aSopenharmony_ci}
171cabdff1aSopenharmony_ci
172cabdff1aSopenharmony_cidouble ff_lpc_calc_ref_coefs_f(LPCContext *s, const float *samples, int len,
173cabdff1aSopenharmony_ci                               int order, double *ref)
174cabdff1aSopenharmony_ci{
175cabdff1aSopenharmony_ci    int i;
176cabdff1aSopenharmony_ci    double signal = 0.0f, avg_err = 0.0f;
177cabdff1aSopenharmony_ci    double autoc[MAX_LPC_ORDER+1] = {0}, error[MAX_LPC_ORDER+1] = {0};
178cabdff1aSopenharmony_ci    const double a = 0.5f, b = 1.0f - a;
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci    /* Apply windowing */
181cabdff1aSopenharmony_ci    for (i = 0; i <= len / 2; i++) {
182cabdff1aSopenharmony_ci        double weight = a - b*cos((2*M_PI*i)/(len - 1));
183cabdff1aSopenharmony_ci        s->windowed_samples[i] = weight*samples[i];
184cabdff1aSopenharmony_ci        s->windowed_samples[len-1-i] = weight*samples[len-1-i];
185cabdff1aSopenharmony_ci    }
186cabdff1aSopenharmony_ci
187cabdff1aSopenharmony_ci    s->lpc_compute_autocorr(s->windowed_samples, len, order, autoc);
188cabdff1aSopenharmony_ci    signal = autoc[0];
189cabdff1aSopenharmony_ci    compute_ref_coefs(autoc, order, ref, error);
190cabdff1aSopenharmony_ci    for (i = 0; i < order; i++)
191cabdff1aSopenharmony_ci        avg_err = (avg_err + error[i])/2.0f;
192cabdff1aSopenharmony_ci    return avg_err ? signal/avg_err : NAN;
193cabdff1aSopenharmony_ci}
194cabdff1aSopenharmony_ci
195cabdff1aSopenharmony_ci/**
196cabdff1aSopenharmony_ci * Calculate LPC coefficients for multiple orders
197cabdff1aSopenharmony_ci *
198cabdff1aSopenharmony_ci * @param lpc_type LPC method for determining coefficients,
199cabdff1aSopenharmony_ci *                 see #FFLPCType for details
200cabdff1aSopenharmony_ci */
201cabdff1aSopenharmony_ciint ff_lpc_calc_coefs(LPCContext *s,
202cabdff1aSopenharmony_ci                      const int32_t *samples, int blocksize, int min_order,
203cabdff1aSopenharmony_ci                      int max_order, int precision,
204cabdff1aSopenharmony_ci                      int32_t coefs[][MAX_LPC_ORDER], int *shift,
205cabdff1aSopenharmony_ci                      enum FFLPCType lpc_type, int lpc_passes,
206cabdff1aSopenharmony_ci                      int omethod, int min_shift, int max_shift, int zero_shift)
207cabdff1aSopenharmony_ci{
208cabdff1aSopenharmony_ci    double autoc[MAX_LPC_ORDER+1];
209cabdff1aSopenharmony_ci    double ref[MAX_LPC_ORDER] = { 0 };
210cabdff1aSopenharmony_ci    double lpc[MAX_LPC_ORDER][MAX_LPC_ORDER];
211cabdff1aSopenharmony_ci    int i, j, pass = 0;
212cabdff1aSopenharmony_ci    int opt_order;
213cabdff1aSopenharmony_ci
214cabdff1aSopenharmony_ci    av_assert2(max_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER &&
215cabdff1aSopenharmony_ci           lpc_type > FF_LPC_TYPE_FIXED);
216cabdff1aSopenharmony_ci    av_assert0(lpc_type == FF_LPC_TYPE_CHOLESKY || lpc_type == FF_LPC_TYPE_LEVINSON);
217cabdff1aSopenharmony_ci
218cabdff1aSopenharmony_ci    /* reinit LPC context if parameters have changed */
219cabdff1aSopenharmony_ci    if (blocksize != s->blocksize || max_order != s->max_order ||
220cabdff1aSopenharmony_ci        lpc_type  != s->lpc_type) {
221cabdff1aSopenharmony_ci        ff_lpc_end(s);
222cabdff1aSopenharmony_ci        ff_lpc_init(s, blocksize, max_order, lpc_type);
223cabdff1aSopenharmony_ci    }
224cabdff1aSopenharmony_ci
225cabdff1aSopenharmony_ci    if(lpc_passes <= 0)
226cabdff1aSopenharmony_ci        lpc_passes = 2;
227cabdff1aSopenharmony_ci
228cabdff1aSopenharmony_ci    if (lpc_type == FF_LPC_TYPE_LEVINSON || (lpc_type == FF_LPC_TYPE_CHOLESKY && lpc_passes > 1)) {
229cabdff1aSopenharmony_ci        s->lpc_apply_welch_window(samples, blocksize, s->windowed_samples);
230cabdff1aSopenharmony_ci
231cabdff1aSopenharmony_ci        s->lpc_compute_autocorr(s->windowed_samples, blocksize, max_order, autoc);
232cabdff1aSopenharmony_ci
233cabdff1aSopenharmony_ci        compute_lpc_coefs(autoc, max_order, &lpc[0][0], MAX_LPC_ORDER, 0, 1);
234cabdff1aSopenharmony_ci
235cabdff1aSopenharmony_ci        for(i=0; i<max_order; i++)
236cabdff1aSopenharmony_ci            ref[i] = fabs(lpc[i][i]);
237cabdff1aSopenharmony_ci
238cabdff1aSopenharmony_ci        pass++;
239cabdff1aSopenharmony_ci    }
240cabdff1aSopenharmony_ci
241cabdff1aSopenharmony_ci    if (lpc_type == FF_LPC_TYPE_CHOLESKY) {
242cabdff1aSopenharmony_ci        LLSModel *m = s->lls_models;
243cabdff1aSopenharmony_ci        LOCAL_ALIGNED(32, double, var, [FFALIGN(MAX_LPC_ORDER+1,4)]);
244cabdff1aSopenharmony_ci        double av_uninit(weight);
245cabdff1aSopenharmony_ci        memset(var, 0, FFALIGN(MAX_LPC_ORDER+1,4)*sizeof(*var));
246cabdff1aSopenharmony_ci
247cabdff1aSopenharmony_ci        for(j=0; j<max_order; j++)
248cabdff1aSopenharmony_ci            m[0].coeff[max_order-1][j] = -lpc[max_order-1][j];
249cabdff1aSopenharmony_ci
250cabdff1aSopenharmony_ci        for(; pass<lpc_passes; pass++){
251cabdff1aSopenharmony_ci            avpriv_init_lls(&m[pass&1], max_order);
252cabdff1aSopenharmony_ci
253cabdff1aSopenharmony_ci            weight=0;
254cabdff1aSopenharmony_ci            for(i=max_order; i<blocksize; i++){
255cabdff1aSopenharmony_ci                for(j=0; j<=max_order; j++)
256cabdff1aSopenharmony_ci                    var[j]= samples[i-j];
257cabdff1aSopenharmony_ci
258cabdff1aSopenharmony_ci                if(pass){
259cabdff1aSopenharmony_ci                    double eval, inv, rinv;
260cabdff1aSopenharmony_ci                    eval= m[pass&1].evaluate_lls(&m[(pass-1)&1], var+1, max_order-1);
261cabdff1aSopenharmony_ci                    eval= (512>>pass) + fabs(eval - var[0]);
262cabdff1aSopenharmony_ci                    inv = 1/eval;
263cabdff1aSopenharmony_ci                    rinv = sqrt(inv);
264cabdff1aSopenharmony_ci                    for(j=0; j<=max_order; j++)
265cabdff1aSopenharmony_ci                        var[j] *= rinv;
266cabdff1aSopenharmony_ci                    weight += inv;
267cabdff1aSopenharmony_ci                }else
268cabdff1aSopenharmony_ci                    weight++;
269cabdff1aSopenharmony_ci
270cabdff1aSopenharmony_ci                m[pass&1].update_lls(&m[pass&1], var);
271cabdff1aSopenharmony_ci            }
272cabdff1aSopenharmony_ci            avpriv_solve_lls(&m[pass&1], 0.001, 0);
273cabdff1aSopenharmony_ci        }
274cabdff1aSopenharmony_ci
275cabdff1aSopenharmony_ci        for(i=0; i<max_order; i++){
276cabdff1aSopenharmony_ci            for(j=0; j<max_order; j++)
277cabdff1aSopenharmony_ci                lpc[i][j]=-m[(pass-1)&1].coeff[i][j];
278cabdff1aSopenharmony_ci            ref[i]= sqrt(m[(pass-1)&1].variance[i] / weight) * (blocksize - max_order) / 4000;
279cabdff1aSopenharmony_ci        }
280cabdff1aSopenharmony_ci        for(i=max_order-1; i>0; i--)
281cabdff1aSopenharmony_ci            ref[i] = ref[i-1] - ref[i];
282cabdff1aSopenharmony_ci    }
283cabdff1aSopenharmony_ci
284cabdff1aSopenharmony_ci    opt_order = max_order;
285cabdff1aSopenharmony_ci
286cabdff1aSopenharmony_ci    if(omethod == ORDER_METHOD_EST) {
287cabdff1aSopenharmony_ci        opt_order = estimate_best_order(ref, min_order, max_order);
288cabdff1aSopenharmony_ci        i = opt_order-1;
289cabdff1aSopenharmony_ci        quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i],
290cabdff1aSopenharmony_ci                           min_shift, max_shift, zero_shift);
291cabdff1aSopenharmony_ci    } else {
292cabdff1aSopenharmony_ci        for(i=min_order-1; i<max_order; i++) {
293cabdff1aSopenharmony_ci            quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i],
294cabdff1aSopenharmony_ci                               min_shift, max_shift, zero_shift);
295cabdff1aSopenharmony_ci        }
296cabdff1aSopenharmony_ci    }
297cabdff1aSopenharmony_ci
298cabdff1aSopenharmony_ci    return opt_order;
299cabdff1aSopenharmony_ci}
300cabdff1aSopenharmony_ci
301cabdff1aSopenharmony_ciav_cold int ff_lpc_init(LPCContext *s, int blocksize, int max_order,
302cabdff1aSopenharmony_ci                        enum FFLPCType lpc_type)
303cabdff1aSopenharmony_ci{
304cabdff1aSopenharmony_ci    s->blocksize = blocksize;
305cabdff1aSopenharmony_ci    s->max_order = max_order;
306cabdff1aSopenharmony_ci    s->lpc_type  = lpc_type;
307cabdff1aSopenharmony_ci
308cabdff1aSopenharmony_ci    s->windowed_buffer = av_mallocz((blocksize + 2 + FFALIGN(max_order, 4)) *
309cabdff1aSopenharmony_ci                                    sizeof(*s->windowed_samples));
310cabdff1aSopenharmony_ci    if (!s->windowed_buffer)
311cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
312cabdff1aSopenharmony_ci    s->windowed_samples = s->windowed_buffer + FFALIGN(max_order, 4);
313cabdff1aSopenharmony_ci
314cabdff1aSopenharmony_ci    s->lpc_apply_welch_window = lpc_apply_welch_window_c;
315cabdff1aSopenharmony_ci    s->lpc_compute_autocorr   = lpc_compute_autocorr_c;
316cabdff1aSopenharmony_ci
317cabdff1aSopenharmony_ci#if ARCH_X86
318cabdff1aSopenharmony_ci    ff_lpc_init_x86(s);
319cabdff1aSopenharmony_ci#endif
320cabdff1aSopenharmony_ci
321cabdff1aSopenharmony_ci    return 0;
322cabdff1aSopenharmony_ci}
323cabdff1aSopenharmony_ci
324cabdff1aSopenharmony_ciav_cold void ff_lpc_end(LPCContext *s)
325cabdff1aSopenharmony_ci{
326cabdff1aSopenharmony_ci    av_freep(&s->windowed_buffer);
327cabdff1aSopenharmony_ci}
328