Mercurial > libavcodec.hg
comparison truespeech.c @ 3006:4007989367bc libavcodec
TrueSpeech compatible audio decoder by Konstantin Shishkov
author | diego |
---|---|
date | Tue, 03 Jan 2006 02:30:38 +0000 |
parents | |
children | 0b546eab515d |
comparison
equal
deleted
inserted
replaced
3005:6f6f307cffac | 3006:4007989367bc |
---|---|
1 /* | |
2 * DSP Group TrueSpeech compatible decoder | |
3 * Copyright (c) 2005 Konstantin Shishkov | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 #include "avcodec.h" | |
20 | |
21 #include "truespeech_data.h" | |
22 /** | |
23 * @file truespeech.c | |
24 * TrueSpeech decoder. | |
25 */ | |
26 | |
27 /** | |
28 * TrueSpeech decoder context | |
29 */ | |
30 typedef struct { | |
31 /* input data */ | |
32 int16_t vector[8]; //< input vector: 5/5/4/4/4/3/3/3 | |
33 int offset1[2]; //< 8-bit value, used in one copying offset | |
34 int offset2[4]; //< 7-bit value, encodes offsets for copying and for two-point filter | |
35 int pulseoff[4]; //< 4-bit offset of pulse values block | |
36 int pulsepos[4]; //< 27-bit variable, encodes 7 pulse positions | |
37 int pulseval[4]; //< 7x2-bit pulse values | |
38 int flag; //< 1-bit flag, shows how to choose filters | |
39 /* temporary data */ | |
40 int filtbuf[146]; // some big vector used for storing filters | |
41 int prevfilt[8]; // filter from previous frame | |
42 int16_t tmp1[8]; // coefficients for adding to out | |
43 int16_t tmp2[8]; // coefficients for adding to out | |
44 int16_t tmp3[8]; // coefficients for adding to out | |
45 int16_t cvector[8]; // correlated input vector | |
46 int filtval; // gain value for one function | |
47 int16_t newvec[60]; // tmp vector | |
48 int16_t filters[32]; // filters for every subframe | |
49 } TSContext; | |
50 | |
51 static int truespeech_decode_init(AVCodecContext * avctx) | |
52 { | |
53 // TSContext *c = avctx->priv_data; | |
54 | |
55 return 0; | |
56 } | |
57 | |
58 static void truespeech_read_frame(TSContext *dec, uint8_t *input) | |
59 { | |
60 uint32_t t; | |
61 | |
62 /* first dword */ | |
63 t = LE_32(input); | |
64 input += 4; | |
65 | |
66 dec->flag = t & 1; | |
67 | |
68 dec->vector[0] = ts_codebook[0][(t >> 1) & 0x1F]; | |
69 dec->vector[1] = ts_codebook[1][(t >> 6) & 0x1F]; | |
70 dec->vector[2] = ts_codebook[2][(t >> 11) & 0xF]; | |
71 dec->vector[3] = ts_codebook[3][(t >> 15) & 0xF]; | |
72 dec->vector[4] = ts_codebook[4][(t >> 19) & 0xF]; | |
73 dec->vector[5] = ts_codebook[5][(t >> 23) & 0x7]; | |
74 dec->vector[6] = ts_codebook[6][(t >> 26) & 0x7]; | |
75 dec->vector[7] = ts_codebook[7][(t >> 29) & 0x7]; | |
76 | |
77 /* second dword */ | |
78 t = LE_32(input); | |
79 input += 4; | |
80 | |
81 dec->offset2[0] = (t >> 0) & 0x7F; | |
82 dec->offset2[1] = (t >> 7) & 0x7F; | |
83 dec->offset2[2] = (t >> 14) & 0x7F; | |
84 dec->offset2[3] = (t >> 21) & 0x7F; | |
85 | |
86 dec->offset1[0] = ((t >> 28) & 0xF) << 4; | |
87 | |
88 /* third dword */ | |
89 t = LE_32(input); | |
90 input += 4; | |
91 | |
92 dec->pulseval[0] = (t >> 0) & 0x3FFF; | |
93 dec->pulseval[1] = (t >> 14) & 0x3FFF; | |
94 | |
95 dec->offset1[1] = (t >> 28) & 0x0F; | |
96 | |
97 /* fourth dword */ | |
98 t = LE_32(input); | |
99 input += 4; | |
100 | |
101 dec->pulseval[2] = (t >> 0) & 0x3FFF; | |
102 dec->pulseval[3] = (t >> 14) & 0x3FFF; | |
103 | |
104 dec->offset1[1] |= ((t >> 28) & 0x0F) << 4; | |
105 | |
106 /* fifth dword */ | |
107 t = LE_32(input); | |
108 input += 4; | |
109 | |
110 dec->pulsepos[0] = (t >> 4) & 0x7FFFFFF; | |
111 | |
112 dec->pulseoff[0] = (t >> 0) & 0xF; | |
113 | |
114 dec->offset1[0] |= (t >> 31) & 1; | |
115 | |
116 /* sixth dword */ | |
117 t = LE_32(input); | |
118 input += 4; | |
119 | |
120 dec->pulsepos[1] = (t >> 4) & 0x7FFFFFF; | |
121 | |
122 dec->pulseoff[1] = (t >> 0) & 0xF; | |
123 | |
124 dec->offset1[0] |= ((t >> 31) & 1) << 1; | |
125 | |
126 /* seventh dword */ | |
127 t = LE_32(input); | |
128 input += 4; | |
129 | |
130 dec->pulsepos[2] = (t >> 4) & 0x7FFFFFF; | |
131 | |
132 dec->pulseoff[2] = (t >> 0) & 0xF; | |
133 | |
134 dec->offset1[0] |= ((t >> 31) & 1) << 2; | |
135 | |
136 /* eighth dword */ | |
137 t = LE_32(input); | |
138 input += 4; | |
139 | |
140 dec->pulsepos[3] = (t >> 4) & 0x7FFFFFF; | |
141 | |
142 dec->pulseoff[3] = (t >> 0) & 0xF; | |
143 | |
144 dec->offset1[0] |= ((t >> 31) & 1) << 3; | |
145 | |
146 } | |
147 | |
148 static void truespeech_correlate_filter(TSContext *dec) | |
149 { | |
150 int16_t tmp[8]; | |
151 int i, j; | |
152 | |
153 for(i = 0; i < 8; i++){ | |
154 if(i > 0){ | |
155 memcpy(tmp, dec->cvector, i * 2); | |
156 for(j = 0; j < i; j++) | |
157 dec->cvector[j] = ((tmp[i - j - 1] * dec->vector[i]) + | |
158 (dec->cvector[j] << 15) + 0x4000) >> 15; | |
159 } | |
160 dec->cvector[i] = (8 - dec->vector[i]) >> 3; | |
161 } | |
162 for(i = 0; i < 8; i++) | |
163 dec->cvector[i] = (dec->cvector[i] * ts_230[i]) >> 15; | |
164 | |
165 dec->filtval = dec->vector[0]; | |
166 } | |
167 | |
168 static void truespeech_filters_merge(TSContext *dec) | |
169 { | |
170 int i; | |
171 | |
172 if(!dec->flag){ | |
173 for(i = 0; i < 8; i++){ | |
174 dec->filters[i + 0] = dec->prevfilt[i]; | |
175 dec->filters[i + 8] = dec->prevfilt[i]; | |
176 } | |
177 }else{ | |
178 for(i = 0; i < 8; i++){ | |
179 dec->filters[i + 0]=(dec->cvector[i] * 21846 + dec->prevfilt[i] * 10923 + 16384) >> 15; | |
180 dec->filters[i + 8]=(dec->cvector[i] * 10923 + dec->prevfilt[i] * 21846 + 16384) >> 15; | |
181 } | |
182 } | |
183 for(i = 0; i < 8; i++){ | |
184 dec->filters[i + 16] = dec->cvector[i]; | |
185 dec->filters[i + 24] = dec->cvector[i]; | |
186 } | |
187 } | |
188 | |
189 static void truespeech_apply_twopoint_filter(TSContext *dec, int quart) | |
190 { | |
191 int16_t tmp[146 + 60], *ptr0, *ptr1, *filter; | |
192 int i, t, off; | |
193 | |
194 t = dec->offset2[quart]; | |
195 if(t == 127){ | |
196 memset(dec->newvec, 0, 60 * 2); | |
197 return; | |
198 } | |
199 for(i = 0; i < 146; i++) | |
200 tmp[i] = dec->filtbuf[i]; | |
201 off = (t / 25) + dec->offset1[quart >> 1] + 18; | |
202 ptr0 = tmp + 145 - off; | |
203 ptr1 = tmp + 146; | |
204 filter = ts_240 + (t % 25) * 2; | |
205 for(i = 0; i < 60; i++){ | |
206 t = (ptr0[0] * filter[0] + ptr0[1] * filter[1] + 0x2000) >> 14; | |
207 ptr0++; | |
208 dec->newvec[i] = t; | |
209 ptr1[i] = t; | |
210 } | |
211 } | |
212 | |
213 static void truespeech_place_pulses(TSContext *dec, int16_t *out, int quart) | |
214 { | |
215 int16_t tmp[7]; | |
216 int i, j, t; | |
217 int16_t *ptr1, *ptr2; | |
218 int coef; | |
219 | |
220 memset(out, 0, 60 * 2); | |
221 for(i = 0; i < 7; i++) { | |
222 t = dec->pulseval[quart] & 3; | |
223 dec->pulseval[quart] >>= 2; | |
224 tmp[6 - i] = ts_562[dec->pulseoff[quart] * 4 + t]; | |
225 } | |
226 | |
227 coef = dec->pulsepos[quart] >> 15; | |
228 ptr1 = ts_140 + 30; | |
229 ptr2 = tmp; | |
230 for(i = 0, j = 3; (i < 30) && (j > 0); i++){ | |
231 t = *ptr1++; | |
232 if(coef >= t) | |
233 coef -= t; | |
234 else{ | |
235 out[i] = *ptr2++; | |
236 ptr1 += 30; | |
237 j--; | |
238 } | |
239 } | |
240 coef = dec->pulsepos[quart] & 0x7FFF; | |
241 ptr1 = ts_140; | |
242 for(i = 30, j = 4; (i < 60) && (j > 0); i++){ | |
243 t = *ptr1++; | |
244 if(coef >= t) | |
245 coef -= t; | |
246 else{ | |
247 out[i] = *ptr2++; | |
248 ptr1 += 30; | |
249 j--; | |
250 } | |
251 } | |
252 | |
253 } | |
254 | |
255 static void truespeech_update_filters(TSContext *dec, int16_t *out, int quart) | |
256 { | |
257 int i; | |
258 | |
259 for(i = 0; i < 86; i++) | |
260 dec->filtbuf[i] = dec->filtbuf[i + 60]; | |
261 for(i = 0; i < 60; i++){ | |
262 dec->filtbuf[i + 86] = out[i] + dec->newvec[i] - (dec->newvec[i] >> 3); | |
263 out[i] += dec->newvec[i]; | |
264 } | |
265 } | |
266 | |
267 static void truespeech_synth(TSContext *dec, int16_t *out, int quart) | |
268 { | |
269 int i,k; | |
270 int t[8]; | |
271 int16_t *ptr0, *ptr1; | |
272 | |
273 ptr0 = dec->tmp1; | |
274 ptr1 = dec->filters + quart * 8; | |
275 for(i = 0; i < 60; i++){ | |
276 int sum = 0; | |
277 for(k = 0; k < 8; k++) | |
278 sum += ptr0[k] * ptr1[k]; | |
279 sum = (sum + (out[i] << 12) + 0x800) >> 12; | |
280 out[i] = clip(sum, -0x7FFE, 0x7FFE); | |
281 for(k = 7; k > 0; k--) | |
282 ptr0[k] = ptr0[k - 1]; | |
283 ptr0[0] = out[i]; | |
284 } | |
285 | |
286 for(i = 0; i < 8; i++) | |
287 t[i] = (ts_5E2[i] * ptr1[i]) >> 15; | |
288 | |
289 ptr0 = dec->tmp2; | |
290 for(i = 0; i < 60; i++){ | |
291 int sum = 0; | |
292 for(k = 0; k < 8; k++) | |
293 sum += ptr0[k] * t[k]; | |
294 for(k = 7; k > 0; k--) | |
295 ptr0[k] = ptr0[k - 1]; | |
296 ptr0[0] = out[i]; | |
297 out[i] = ((out[i] << 12) - sum) >> 12; | |
298 } | |
299 | |
300 for(i = 0; i < 8; i++) | |
301 t[i] = (ts_5F2[i] * ptr1[i]) >> 15; | |
302 | |
303 ptr0 = dec->tmp3; | |
304 for(i = 0; i < 60; i++){ | |
305 int sum = out[i] << 12; | |
306 for(k = 0; k < 8; k++) | |
307 sum += ptr0[k] * t[k]; | |
308 for(k = 7; k > 0; k--) | |
309 ptr0[k] = ptr0[k - 1]; | |
310 ptr0[0] = clip((sum + 0x800) >> 12, -0x7FFE, 0x7FFE); | |
311 | |
312 sum = ((ptr0[1] * (dec->filtval - (dec->filtval >> 2))) >> 4) + sum; | |
313 sum = sum - (sum >> 3); | |
314 out[i] = clip((sum + 0x800) >> 12, -0x7FFE, 0x7FFE); | |
315 } | |
316 } | |
317 | |
318 static void truespeech_save_prevvec(TSContext *c) | |
319 { | |
320 int i; | |
321 | |
322 for(i = 0; i < 8; i++) | |
323 c->prevfilt[i] = c->cvector[i]; | |
324 } | |
325 | |
326 static int truespeech_decode_frame(AVCodecContext *avctx, | |
327 void *data, int *data_size, | |
328 uint8_t *buf, int buf_size) | |
329 { | |
330 TSContext *c = avctx->priv_data; | |
331 | |
332 int i; | |
333 short *samples = data; | |
334 int consumed = 0; | |
335 int16_t out_buf[240]; | |
336 | |
337 if (!buf_size) | |
338 return 0; | |
339 | |
340 while (consumed < buf_size) { | |
341 truespeech_read_frame(c, buf + consumed); | |
342 consumed += 32; | |
343 | |
344 truespeech_correlate_filter(c); | |
345 truespeech_filters_merge(c); | |
346 | |
347 memset(out_buf, 0, 240 * 2); | |
348 for(i = 0; i < 4; i++) { | |
349 truespeech_apply_twopoint_filter(c, i); | |
350 truespeech_place_pulses(c, out_buf + i * 60, i); | |
351 truespeech_update_filters(c, out_buf + i * 60, i); | |
352 truespeech_synth(c, out_buf + i * 60, i); | |
353 } | |
354 | |
355 truespeech_save_prevvec(c); | |
356 | |
357 /* finally output decoded frame */ | |
358 for(i = 0; i < 240; i++) | |
359 *samples++ = out_buf[i]; | |
360 | |
361 } | |
362 | |
363 *data_size = consumed * 15; | |
364 | |
365 return buf_size; | |
366 } | |
367 | |
368 AVCodec truespeech_decoder = { | |
369 "truespeech", | |
370 CODEC_TYPE_AUDIO, | |
371 CODEC_ID_TRUESPEECH, | |
372 sizeof(TSContext), | |
373 truespeech_decode_init, | |
374 NULL, | |
375 NULL, | |
376 truespeech_decode_frame, | |
377 }; |