Line | Branch | Exec | Source |
---|---|---|---|
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 <stddef.h> | ||
27 | #include "libavutil/avassert.h" | ||
28 | #include "libavutil/lls.h" | ||
29 | #include "aac_defines.h" | ||
30 | |||
31 | #define ORDER_METHOD_EST 0 | ||
32 | #define ORDER_METHOD_2LEVEL 1 | ||
33 | #define ORDER_METHOD_4LEVEL 2 | ||
34 | #define ORDER_METHOD_8LEVEL 3 | ||
35 | #define ORDER_METHOD_SEARCH 4 | ||
36 | #define ORDER_METHOD_LOG 5 | ||
37 | |||
38 | #define MIN_LPC_ORDER 1 | ||
39 | #define MAX_LPC_ORDER 32 | ||
40 | |||
41 | /** | ||
42 | * LPC analysis type | ||
43 | */ | ||
44 | enum FFLPCType { | ||
45 | FF_LPC_TYPE_DEFAULT = -1, ///< use the codec default LPC type | ||
46 | FF_LPC_TYPE_NONE = 0, ///< do not use LPC prediction or use all zero coefficients | ||
47 | FF_LPC_TYPE_FIXED = 1, ///< fixed LPC coefficients | ||
48 | FF_LPC_TYPE_LEVINSON = 2, ///< Levinson-Durbin recursion | ||
49 | FF_LPC_TYPE_CHOLESKY = 3, ///< Cholesky factorization | ||
50 | FF_LPC_TYPE_NB , ///< Not part of ABI | ||
51 | }; | ||
52 | |||
53 | typedef struct LPCContext { | ||
54 | int blocksize; | ||
55 | int max_order; | ||
56 | enum FFLPCType lpc_type; | ||
57 | double *windowed_buffer; | ||
58 | double *windowed_samples; | ||
59 | |||
60 | /** | ||
61 | * Apply a Welch window to an array of input samples. | ||
62 | * The output samples have the same scale as the input, but are in double | ||
63 | * sample format. | ||
64 | * @param data input samples | ||
65 | * @param len number of input samples | ||
66 | * @param w_data output samples | ||
67 | */ | ||
68 | void (*lpc_apply_welch_window)(const int32_t *data, ptrdiff_t len, | ||
69 | double *w_data); | ||
70 | /** | ||
71 | * Perform autocorrelation on input samples with delay of 0 to lag. | ||
72 | * @param data input samples. | ||
73 | * constraints: no alignment needed, but must have at | ||
74 | * least lag*sizeof(double) valid bytes preceding it, and | ||
75 | * size must be at least (len+1)*sizeof(double) if data is | ||
76 | * 16-byte aligned or (len+2)*sizeof(double) if data is | ||
77 | * unaligned. | ||
78 | * @param len number of input samples to process | ||
79 | * @param lag maximum delay to calculate | ||
80 | * @param autoc output autocorrelation coefficients. | ||
81 | * constraints: array size must be at least lag+1. | ||
82 | */ | ||
83 | void (*lpc_compute_autocorr)(const double *data, ptrdiff_t len, int lag, | ||
84 | double *autoc); | ||
85 | |||
86 | // TODO: these should be allocated to reduce ABI compatibility issues | ||
87 | LLSModel lls_models[2]; | ||
88 | } LPCContext; | ||
89 | |||
90 | |||
91 | /** | ||
92 | * Calculate LPC coefficients for multiple orders | ||
93 | */ | ||
94 | int ff_lpc_calc_coefs(LPCContext *s, | ||
95 | const int32_t *samples, int blocksize, int min_order, | ||
96 | int max_order, int precision, | ||
97 | int32_t coefs[][MAX_LPC_ORDER], int *shift, | ||
98 | enum FFLPCType lpc_type, int lpc_passes, | ||
99 | int omethod, int min_shift, int max_shift, int zero_shift); | ||
100 | |||
101 | int ff_lpc_calc_ref_coefs(LPCContext *s, | ||
102 | const int32_t *samples, int order, double *ref); | ||
103 | |||
104 | double ff_lpc_calc_ref_coefs_f(LPCContext *s, const float *samples, int len, | ||
105 | int order, double *ref); | ||
106 | |||
107 | /** | ||
108 | * Initialize LPCContext. | ||
109 | */ | ||
110 | int ff_lpc_init(LPCContext *s, int blocksize, int max_order, | ||
111 | enum FFLPCType lpc_type); | ||
112 | void ff_lpc_init_x86(LPCContext *s); | ||
113 | |||
114 | /** | ||
115 | * Uninitialize LPCContext. | ||
116 | */ | ||
117 | void ff_lpc_end(LPCContext *s); | ||
118 | |||
119 | #if USE_FIXED | ||
120 | typedef int LPC_TYPE; | ||
121 | typedef unsigned LPC_TYPE_U; | ||
122 | #else | ||
123 | #ifdef LPC_USE_DOUBLE | ||
124 | typedef double LPC_TYPE; | ||
125 | typedef double LPC_TYPE_U; | ||
126 | #else | ||
127 | typedef float LPC_TYPE; | ||
128 | typedef float LPC_TYPE_U; | ||
129 | #endif | ||
130 | #endif // USE_FIXED | ||
131 | |||
132 | /** | ||
133 | * Schur recursion. | ||
134 | * Produces reflection coefficients from autocorrelation data. | ||
135 | */ | ||
136 | 2147 | static inline void compute_ref_coefs(const LPC_TYPE *autoc, int max_order, | |
137 | LPC_TYPE *ref, LPC_TYPE *error) | ||
138 | { | ||
139 | int i, j; | ||
140 | LPC_TYPE err; | ||
141 | LPC_TYPE gen0[MAX_LPC_ORDER], gen1[MAX_LPC_ORDER]; | ||
142 | |||
143 |
2/2✓ Branch 0 taken 24284 times.
✓ Branch 1 taken 2147 times.
|
26431 | for (i = 0; i < max_order; i++) |
144 | 24284 | gen0[i] = gen1[i] = autoc[i + 1]; | |
145 | |||
146 | 2147 | err = autoc[0]; | |
147 |
1/2✓ Branch 0 taken 2147 times.
✗ Branch 1 not taken.
|
2147 | ref[0] = -gen1[0] / ((USE_FIXED || err) ? err : 1); |
148 | 2147 | err += gen1[0] * ref[0]; | |
149 |
1/2✓ Branch 0 taken 2147 times.
✗ Branch 1 not taken.
|
2147 | if (error) |
150 | 2147 | error[0] = err; | |
151 |
2/2✓ Branch 0 taken 22137 times.
✓ Branch 1 taken 2147 times.
|
24284 | for (i = 1; i < max_order; i++) { |
152 |
2/2✓ Branch 0 taken 128382 times.
✓ Branch 1 taken 22137 times.
|
150519 | for (j = 0; j < max_order - i; j++) { |
153 | 128382 | gen1[j] = gen1[j + 1] + ref[i - 1] * gen0[j]; | |
154 | 128382 | gen0[j] = gen1[j + 1] * ref[i - 1] + gen0[j]; | |
155 | } | ||
156 |
2/2✓ Branch 0 taken 21939 times.
✓ Branch 1 taken 198 times.
|
22137 | ref[i] = -gen1[0] / ((USE_FIXED || err) ? err : 1); |
157 | 22137 | err += gen1[0] * ref[i]; | |
158 |
1/2✓ Branch 0 taken 22137 times.
✗ Branch 1 not taken.
|
22137 | if (error) |
159 | 22137 | error[i] = err; | |
160 | } | ||
161 | 2147 | } | |
162 | |||
163 | /** | ||
164 | * Levinson-Durbin recursion. | ||
165 | * Produce LPC coefficients from autocorrelation data. | ||
166 | */ | ||
167 | 37750 | static inline int AAC_RENAME(compute_lpc_coefs)(const LPC_TYPE *autoc, int max_order, | |
168 | LPC_TYPE *lpc, int lpc_stride, int fail, | ||
169 | int normalize) | ||
170 | { | ||
171 | int i, j; | ||
172 | 37750 | LPC_TYPE err = 0; | |
173 | 37750 | LPC_TYPE *lpc_last = lpc; | |
174 | |||
175 | av_assert2(normalize || !fail); | ||
176 | |||
177 |
2/2✓ Branch 0 taken 28785 times.
✓ Branch 1 taken 8965 times.
|
37750 | if (normalize) |
178 | 28785 | err = *autoc++; | |
179 | |||
180 |
5/6✓ Branch 0 taken 19592 times.
✓ Branch 1 taken 18158 times.
✓ Branch 2 taken 19588 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 19588 times.
|
37750 | if (fail && (autoc[max_order - 1] == 0 || err <= 0)) |
181 | 4 | return -1; | |
182 | |||
183 |
2/2✓ Branch 0 taken 607554 times.
✓ Branch 1 taken 37746 times.
|
645300 | for(i=0; i<max_order; i++) { |
184 | 607554 | LPC_TYPE r = AAC_SRA_R(-autoc[i], 5); | |
185 | |||
186 |
2/2✓ Branch 0 taken 548494 times.
✓ Branch 1 taken 59060 times.
|
607554 | if (normalize) { |
187 |
2/2✓ Branch 0 taken 7333175 times.
✓ Branch 1 taken 548494 times.
|
7881669 | for(j=0; j<i; j++) |
188 | 7333175 | r -= lpc_last[j] * autoc[i-j-1]; | |
189 | |||
190 |
1/2✓ Branch 0 taken 548494 times.
✗ Branch 1 not taken.
|
548494 | if (err) |
191 | 548494 | r /= err; | |
192 | 548494 | err *= FIXR(1.0) - (r * r); | |
193 | } | ||
194 | |||
195 | 607554 | lpc[i] = r; | |
196 | |||
197 |
2/2✓ Branch 0 taken 3929725 times.
✓ Branch 1 taken 607554 times.
|
4537279 | for(j=0; j < (i+1)>>1; j++) { |
198 | 3929725 | LPC_TYPE f = lpc_last[ j]; | |
199 | 3929725 | LPC_TYPE b = lpc_last[i-1-j]; | |
200 | 3929725 | lpc[ j] = f + (LPC_TYPE_U)AAC_MUL26(r, b); | |
201 | 3929725 | lpc[i-1-j] = b + (LPC_TYPE_U)AAC_MUL26(r, f); | |
202 | } | ||
203 | |||
204 |
3/4✓ Branch 0 taken 450524 times.
✓ Branch 1 taken 157030 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 450524 times.
|
607554 | if (fail && err < 0) |
205 | ✗ | return -1; | |
206 | |||
207 | 607554 | lpc_last = lpc; | |
208 | 607554 | lpc += lpc_stride; | |
209 | } | ||
210 | |||
211 | 37746 | return 0; | |
212 | } | ||
213 | |||
214 | #endif /* AVCODEC_LPC_H */ | ||
215 |