Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * LPC utility code | |
3 | * Copyright (c) 2006 Justin Ruggles <justin.ruggles@gmail.com> | |
4 | * | |
5 | * This file is part of FFmpeg. | |
6 | * | |
7 | * FFmpeg is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * FFmpeg is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with FFmpeg; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | #ifndef AVCODEC_LPC_H | |
23 | #define AVCODEC_LPC_H | |
24 | ||
25 | #include <stdint.h> | |
26 | #include "libavutil/avassert.h" | |
f6fa7814 | 27 | #include "libavutil/lls.h" |
2ba45a60 DM |
28 | |
29 | #define ORDER_METHOD_EST 0 | |
30 | #define ORDER_METHOD_2LEVEL 1 | |
31 | #define ORDER_METHOD_4LEVEL 2 | |
32 | #define ORDER_METHOD_8LEVEL 3 | |
33 | #define ORDER_METHOD_SEARCH 4 | |
34 | #define ORDER_METHOD_LOG 5 | |
35 | ||
36 | #define MIN_LPC_ORDER 1 | |
37 | #define MAX_LPC_ORDER 32 | |
38 | ||
39 | /** | |
40 | * LPC analysis type | |
41 | */ | |
42 | enum FFLPCType { | |
43 | FF_LPC_TYPE_DEFAULT = -1, ///< use the codec default LPC type | |
44 | FF_LPC_TYPE_NONE = 0, ///< do not use LPC prediction or use all zero coefficients | |
45 | FF_LPC_TYPE_FIXED = 1, ///< fixed LPC coefficients | |
46 | FF_LPC_TYPE_LEVINSON = 2, ///< Levinson-Durbin recursion | |
47 | FF_LPC_TYPE_CHOLESKY = 3, ///< Cholesky factorization | |
48 | FF_LPC_TYPE_NB , ///< Not part of ABI | |
49 | }; | |
50 | ||
51 | typedef struct LPCContext { | |
52 | int blocksize; | |
53 | int max_order; | |
54 | enum FFLPCType lpc_type; | |
55 | double *windowed_buffer; | |
56 | double *windowed_samples; | |
57 | ||
58 | /** | |
59 | * Apply a Welch window to an array of input samples. | |
60 | * The output samples have the same scale as the input, but are in double | |
61 | * sample format. | |
62 | * @param data input samples | |
63 | * @param len number of input samples | |
64 | * @param w_data output samples | |
65 | */ | |
66 | void (*lpc_apply_welch_window)(const int32_t *data, int len, | |
67 | double *w_data); | |
68 | /** | |
69 | * Perform autocorrelation on input samples with delay of 0 to lag. | |
70 | * @param data input samples. | |
71 | * constraints: no alignment needed, but must have at | |
72 | * least lag*sizeof(double) valid bytes preceding it, and | |
73 | * size must be at least (len+1)*sizeof(double) if data is | |
74 | * 16-byte aligned or (len+2)*sizeof(double) if data is | |
75 | * unaligned. | |
76 | * @param len number of input samples to process | |
77 | * @param lag maximum delay to calculate | |
78 | * @param autoc output autocorrelation coefficients. | |
79 | * constraints: array size must be at least lag+1. | |
80 | */ | |
81 | void (*lpc_compute_autocorr)(const double *data, int len, int lag, | |
82 | double *autoc); | |
f6fa7814 DM |
83 | |
84 | // TODO: these should be allocated to reduce ABI compatibility issues | |
85 | LLSModel lls_models[2]; | |
2ba45a60 DM |
86 | } LPCContext; |
87 | ||
88 | ||
89 | /** | |
90 | * Calculate LPC coefficients for multiple orders | |
91 | */ | |
92 | int ff_lpc_calc_coefs(LPCContext *s, | |
93 | const int32_t *samples, int blocksize, int min_order, | |
94 | int max_order, int precision, | |
95 | int32_t coefs[][MAX_LPC_ORDER], int *shift, | |
96 | enum FFLPCType lpc_type, int lpc_passes, | |
97 | int omethod, int max_shift, int zero_shift); | |
98 | ||
99 | int ff_lpc_calc_ref_coefs(LPCContext *s, | |
100 | const int32_t *samples, int order, double *ref); | |
101 | ||
102 | /** | |
103 | * Initialize LPCContext. | |
104 | */ | |
105 | int ff_lpc_init(LPCContext *s, int blocksize, int max_order, | |
106 | enum FFLPCType lpc_type); | |
107 | void ff_lpc_init_x86(LPCContext *s); | |
108 | ||
109 | /** | |
110 | * Uninitialize LPCContext. | |
111 | */ | |
112 | void ff_lpc_end(LPCContext *s); | |
113 | ||
114 | #ifdef LPC_USE_DOUBLE | |
115 | #define LPC_TYPE double | |
116 | #else | |
117 | #define LPC_TYPE float | |
118 | #endif | |
119 | ||
120 | /** | |
121 | * Schur recursion. | |
122 | * Produces reflection coefficients from autocorrelation data. | |
123 | */ | |
124 | static inline void compute_ref_coefs(const LPC_TYPE *autoc, int max_order, | |
125 | LPC_TYPE *ref, LPC_TYPE *error) | |
126 | { | |
127 | int i, j; | |
128 | LPC_TYPE err; | |
129 | LPC_TYPE gen0[MAX_LPC_ORDER], gen1[MAX_LPC_ORDER]; | |
130 | ||
131 | for (i = 0; i < max_order; i++) | |
132 | gen0[i] = gen1[i] = autoc[i + 1]; | |
133 | ||
134 | err = autoc[0]; | |
135 | ref[0] = -gen1[0] / err; | |
136 | err += gen1[0] * ref[0]; | |
137 | if (error) | |
138 | error[0] = err; | |
139 | for (i = 1; i < max_order; i++) { | |
140 | for (j = 0; j < max_order - i; j++) { | |
141 | gen1[j] = gen1[j + 1] + ref[i - 1] * gen0[j]; | |
142 | gen0[j] = gen1[j + 1] * ref[i - 1] + gen0[j]; | |
143 | } | |
144 | ref[i] = -gen1[0] / err; | |
145 | err += gen1[0] * ref[i]; | |
146 | if (error) | |
147 | error[i] = err; | |
148 | } | |
149 | } | |
150 | ||
151 | /** | |
152 | * Levinson-Durbin recursion. | |
153 | * Produce LPC coefficients from autocorrelation data. | |
154 | */ | |
155 | static inline int compute_lpc_coefs(const LPC_TYPE *autoc, int max_order, | |
156 | LPC_TYPE *lpc, int lpc_stride, int fail, | |
157 | int normalize) | |
158 | { | |
159 | int i, j; | |
f6fa7814 | 160 | LPC_TYPE err = 0; |
2ba45a60 DM |
161 | LPC_TYPE *lpc_last = lpc; |
162 | ||
163 | av_assert2(normalize || !fail); | |
164 | ||
165 | if (normalize) | |
166 | err = *autoc++; | |
167 | ||
168 | if (fail && (autoc[max_order - 1] == 0 || err <= 0)) | |
169 | return -1; | |
170 | ||
171 | for(i=0; i<max_order; i++) { | |
172 | LPC_TYPE r = -autoc[i]; | |
173 | ||
174 | if (normalize) { | |
175 | for(j=0; j<i; j++) | |
176 | r -= lpc_last[j] * autoc[i-j-1]; | |
177 | ||
178 | r /= err; | |
179 | err *= 1.0 - (r * r); | |
180 | } | |
181 | ||
182 | lpc[i] = r; | |
183 | ||
184 | for(j=0; j < (i+1)>>1; j++) { | |
185 | LPC_TYPE f = lpc_last[ j]; | |
186 | LPC_TYPE b = lpc_last[i-1-j]; | |
187 | lpc[ j] = f + r * b; | |
188 | lpc[i-1-j] = b + r * f; | |
189 | } | |
190 | ||
191 | if (fail && err < 0) | |
192 | return -1; | |
193 | ||
194 | lpc_last = lpc; | |
195 | lpc += lpc_stride; | |
196 | } | |
197 | ||
198 | return 0; | |
199 | } | |
200 | ||
201 | #endif /* AVCODEC_LPC_H */ |