Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * adaptive and fixed codebook vector operations for ACELP-based codecs | |
3 | * | |
4 | * Copyright (c) 2008 Vladimir Voroshilov | |
5 | * | |
6 | * This file is part of FFmpeg. | |
7 | * | |
8 | * FFmpeg is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2.1 of the License, or (at your option) any later version. | |
12 | * | |
13 | * FFmpeg is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Lesser General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU Lesser General Public | |
19 | * License along with FFmpeg; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 | */ | |
22 | ||
23 | #include <inttypes.h> | |
24 | ||
25 | #include "libavutil/common.h" | |
26 | #include "libavutil/float_dsp.h" | |
27 | #include "avcodec.h" | |
28 | #include "acelp_vectors.h" | |
29 | ||
30 | const uint8_t ff_fc_2pulses_9bits_track1[16] = | |
31 | { | |
32 | 1, 3, | |
33 | 6, 8, | |
34 | 11, 13, | |
35 | 16, 18, | |
36 | 21, 23, | |
37 | 26, 28, | |
38 | 31, 33, | |
39 | 36, 38 | |
40 | }; | |
41 | const uint8_t ff_fc_2pulses_9bits_track1_gray[16] = | |
42 | { | |
43 | 1, 3, | |
44 | 8, 6, | |
45 | 18, 16, | |
46 | 11, 13, | |
47 | 38, 36, | |
48 | 31, 33, | |
49 | 21, 23, | |
50 | 28, 26, | |
51 | }; | |
52 | ||
53 | const uint8_t ff_fc_2pulses_9bits_track2_gray[32] = | |
54 | { | |
55 | 0, 2, | |
56 | 5, 4, | |
57 | 12, 10, | |
58 | 7, 9, | |
59 | 25, 24, | |
60 | 20, 22, | |
61 | 14, 15, | |
62 | 19, 17, | |
63 | 36, 31, | |
64 | 21, 26, | |
65 | 1, 6, | |
66 | 16, 11, | |
67 | 27, 29, | |
68 | 32, 30, | |
69 | 39, 37, | |
70 | 34, 35, | |
71 | }; | |
72 | ||
73 | const uint8_t ff_fc_4pulses_8bits_tracks_13[16] = | |
74 | { | |
75 | 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, | |
76 | }; | |
77 | ||
78 | const uint8_t ff_fc_4pulses_8bits_track_4[32] = | |
79 | { | |
80 | 3, 4, | |
81 | 8, 9, | |
82 | 13, 14, | |
83 | 18, 19, | |
84 | 23, 24, | |
85 | 28, 29, | |
86 | 33, 34, | |
87 | 38, 39, | |
88 | 43, 44, | |
89 | 48, 49, | |
90 | 53, 54, | |
91 | 58, 59, | |
92 | 63, 64, | |
93 | 68, 69, | |
94 | 73, 74, | |
95 | 78, 79, | |
96 | }; | |
97 | ||
98 | const float ff_pow_0_7[10] = { | |
99 | 0.700000, 0.490000, 0.343000, 0.240100, 0.168070, | |
100 | 0.117649, 0.082354, 0.057648, 0.040354, 0.028248 | |
101 | }; | |
102 | ||
103 | const float ff_pow_0_75[10] = { | |
104 | 0.750000, 0.562500, 0.421875, 0.316406, 0.237305, | |
105 | 0.177979, 0.133484, 0.100113, 0.075085, 0.056314 | |
106 | }; | |
107 | ||
108 | const float ff_pow_0_55[10] = { | |
109 | 0.550000, 0.302500, 0.166375, 0.091506, 0.050328, | |
110 | 0.027681, 0.015224, 0.008373, 0.004605, 0.002533 | |
111 | }; | |
112 | ||
113 | const float ff_b60_sinc[61] = { | |
114 | 0.898529 , 0.865051 , 0.769257 , 0.624054 , 0.448639 , 0.265289 , | |
115 | 0.0959167 , -0.0412598 , -0.134338 , -0.178986 , -0.178528 , -0.142609 , | |
116 | -0.0849304 , -0.0205078 , 0.0369568 , 0.0773926 , 0.0955200 , 0.0912781 , | |
117 | 0.0689392 , 0.0357056 , 0.0 , -0.0305481 , -0.0504150 , -0.0570068 , | |
118 | -0.0508423 , -0.0350037 , -0.0141602 , 0.00665283, 0.0230713 , 0.0323486 , | |
119 | 0.0335388 , 0.0275879 , 0.0167847 , 0.00411987, -0.00747681, -0.0156860 , | |
120 | -0.0193481 , -0.0183716 , -0.0137634 , -0.00704956, 0.0 , 0.00582886 , | |
121 | 0.00939941, 0.0103760 , 0.00903320, 0.00604248, 0.00238037, -0.00109863 , | |
122 | -0.00366211, -0.00497437, -0.00503540, -0.00402832, -0.00241089, -0.000579834, | |
123 | 0.00103760, 0.00222778, 0.00277710, 0.00271606, 0.00213623, 0.00115967 , | |
124 | 0. | |
125 | }; | |
126 | ||
127 | void ff_acelp_fc_pulse_per_track( | |
128 | int16_t* fc_v, | |
129 | const uint8_t *tab1, | |
130 | const uint8_t *tab2, | |
131 | int pulse_indexes, | |
132 | int pulse_signs, | |
133 | int pulse_count, | |
134 | int bits) | |
135 | { | |
136 | int mask = (1 << bits) - 1; | |
137 | int i; | |
138 | ||
139 | for(i=0; i<pulse_count; i++) | |
140 | { | |
141 | fc_v[i + tab1[pulse_indexes & mask]] += | |
142 | (pulse_signs & 1) ? 8191 : -8192; // +/-1 in (2.13) | |
143 | ||
144 | pulse_indexes >>= bits; | |
145 | pulse_signs >>= 1; | |
146 | } | |
147 | ||
148 | fc_v[tab2[pulse_indexes]] += (pulse_signs & 1) ? 8191 : -8192; | |
149 | } | |
150 | ||
151 | void ff_decode_10_pulses_35bits(const int16_t *fixed_index, | |
152 | AMRFixed *fixed_sparse, | |
153 | const uint8_t *gray_decode, | |
154 | int half_pulse_count, int bits) | |
155 | { | |
156 | int i; | |
157 | int mask = (1 << bits) - 1; | |
158 | ||
159 | fixed_sparse->no_repeat_mask = 0; | |
160 | fixed_sparse->n = 2 * half_pulse_count; | |
161 | for (i = 0; i < half_pulse_count; i++) { | |
162 | const int pos1 = gray_decode[fixed_index[2*i+1] & mask] + i; | |
163 | const int pos2 = gray_decode[fixed_index[2*i ] & mask] + i; | |
164 | const float sign = (fixed_index[2*i+1] & (1 << bits)) ? -1.0 : 1.0; | |
165 | fixed_sparse->x[2*i+1] = pos1; | |
166 | fixed_sparse->x[2*i ] = pos2; | |
167 | fixed_sparse->y[2*i+1] = sign; | |
168 | fixed_sparse->y[2*i ] = pos2 < pos1 ? -sign : sign; | |
169 | } | |
170 | } | |
171 | ||
172 | void ff_acelp_weighted_vector_sum( | |
173 | int16_t* out, | |
174 | const int16_t *in_a, | |
175 | const int16_t *in_b, | |
176 | int16_t weight_coeff_a, | |
177 | int16_t weight_coeff_b, | |
178 | int16_t rounder, | |
179 | int shift, | |
180 | int length) | |
181 | { | |
182 | int i; | |
183 | ||
184 | // Clipping required here; breaks OVERFLOW test. | |
185 | for(i=0; i<length; i++) | |
186 | out[i] = av_clip_int16(( | |
187 | in_a[i] * weight_coeff_a + | |
188 | in_b[i] * weight_coeff_b + | |
189 | rounder) >> shift); | |
190 | } | |
191 | ||
192 | void ff_weighted_vector_sumf(float *out, const float *in_a, const float *in_b, | |
193 | float weight_coeff_a, float weight_coeff_b, int length) | |
194 | { | |
195 | int i; | |
196 | ||
197 | for(i=0; i<length; i++) | |
198 | out[i] = weight_coeff_a * in_a[i] | |
199 | + weight_coeff_b * in_b[i]; | |
200 | } | |
201 | ||
202 | void ff_adaptive_gain_control(float *out, const float *in, float speech_energ, | |
203 | int size, float alpha, float *gain_mem) | |
204 | { | |
205 | int i; | |
206 | float postfilter_energ = avpriv_scalarproduct_float_c(in, in, size); | |
207 | float gain_scale_factor = 1.0; | |
208 | float mem = *gain_mem; | |
209 | ||
210 | if (postfilter_energ) | |
211 | gain_scale_factor = sqrt(speech_energ / postfilter_energ); | |
212 | ||
213 | gain_scale_factor *= 1.0 - alpha; | |
214 | ||
215 | for (i = 0; i < size; i++) { | |
216 | mem = alpha * mem + gain_scale_factor; | |
217 | out[i] = in[i] * mem; | |
218 | } | |
219 | ||
220 | *gain_mem = mem; | |
221 | } | |
222 | ||
223 | void ff_scale_vector_to_given_sum_of_squares(float *out, const float *in, | |
224 | float sum_of_squares, const int n) | |
225 | { | |
226 | int i; | |
227 | float scalefactor = avpriv_scalarproduct_float_c(in, in, n); | |
228 | if (scalefactor) | |
229 | scalefactor = sqrt(sum_of_squares / scalefactor); | |
230 | for (i = 0; i < n; i++) | |
231 | out[i] = in[i] * scalefactor; | |
232 | } | |
233 | ||
234 | void ff_set_fixed_vector(float *out, const AMRFixed *in, float scale, int size) | |
235 | { | |
236 | int i; | |
237 | ||
238 | for (i=0; i < in->n; i++) { | |
239 | int x = in->x[i], repeats = !((in->no_repeat_mask >> i) & 1); | |
240 | float y = in->y[i] * scale; | |
241 | ||
242 | if (in->pitch_lag > 0) | |
243 | do { | |
244 | out[x] += y; | |
245 | y *= in->pitch_fac; | |
246 | x += in->pitch_lag; | |
247 | } while (x < size && repeats); | |
248 | } | |
249 | } | |
250 | ||
251 | void ff_clear_fixed_vector(float *out, const AMRFixed *in, int size) | |
252 | { | |
253 | int i; | |
254 | ||
255 | for (i=0; i < in->n; i++) { | |
256 | int x = in->x[i], repeats = !((in->no_repeat_mask >> i) & 1); | |
257 | ||
258 | if (in->pitch_lag > 0) | |
259 | do { | |
260 | out[x] = 0.0; | |
261 | x += in->pitch_lag; | |
262 | } while (x < size && repeats); | |
263 | } | |
264 | } | |
265 | ||
266 | void ff_acelp_vectors_init(ACELPVContext *c) | |
267 | { | |
268 | c->weighted_vector_sumf = ff_weighted_vector_sumf; | |
269 | ||
270 | if(HAVE_MIPSFPU) | |
271 | ff_acelp_vectors_init_mips(c); | |
272 | } |