2 * DSP Group TrueSpeech compatible decoder
3 * Copyright (c) 2005 Konstantin Shishkov
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/intreadwrite.h"
25 #include "truespeech_data.h"
27 * @file libavcodec/truespeech.c
32 * TrueSpeech decoder context
36 int16_t vector
[8]; //< input vector: 5/5/4/4/4/3/3/3
37 int offset1
[2]; //< 8-bit value, used in one copying offset
38 int offset2
[4]; //< 7-bit value, encodes offsets for copying and for two-point filter
39 int pulseoff
[4]; //< 4-bit offset of pulse values block
40 int pulsepos
[4]; //< 27-bit variable, encodes 7 pulse positions
41 int pulseval
[4]; //< 7x2-bit pulse values
42 int flag
; //< 1-bit flag, shows how to choose filters
44 int filtbuf
[146]; // some big vector used for storing filters
45 int prevfilt
[8]; // filter from previous frame
46 int16_t tmp1
[8]; // coefficients for adding to out
47 int16_t tmp2
[8]; // coefficients for adding to out
48 int16_t tmp3
[8]; // coefficients for adding to out
49 int16_t cvector
[8]; // correlated input vector
50 int filtval
; // gain value for one function
51 int16_t newvec
[60]; // tmp vector
52 int16_t filters
[32]; // filters for every subframe
55 static av_cold
int truespeech_decode_init(AVCodecContext
* avctx
)
57 // TSContext *c = avctx->priv_data;
59 avctx
->sample_fmt
= SAMPLE_FMT_S16
;
63 static void truespeech_read_frame(TSContext
*dec
, const uint8_t *input
)
73 dec
->vector
[0] = ts_codebook
[0][(t
>> 1) & 0x1F];
74 dec
->vector
[1] = ts_codebook
[1][(t
>> 6) & 0x1F];
75 dec
->vector
[2] = ts_codebook
[2][(t
>> 11) & 0xF];
76 dec
->vector
[3] = ts_codebook
[3][(t
>> 15) & 0xF];
77 dec
->vector
[4] = ts_codebook
[4][(t
>> 19) & 0xF];
78 dec
->vector
[5] = ts_codebook
[5][(t
>> 23) & 0x7];
79 dec
->vector
[6] = ts_codebook
[6][(t
>> 26) & 0x7];
80 dec
->vector
[7] = ts_codebook
[7][(t
>> 29) & 0x7];
86 dec
->offset2
[0] = (t
>> 0) & 0x7F;
87 dec
->offset2
[1] = (t
>> 7) & 0x7F;
88 dec
->offset2
[2] = (t
>> 14) & 0x7F;
89 dec
->offset2
[3] = (t
>> 21) & 0x7F;
91 dec
->offset1
[0] = ((t
>> 28) & 0xF) << 4;
97 dec
->pulseval
[0] = (t
>> 0) & 0x3FFF;
98 dec
->pulseval
[1] = (t
>> 14) & 0x3FFF;
100 dec
->offset1
[1] = (t
>> 28) & 0x0F;
106 dec
->pulseval
[2] = (t
>> 0) & 0x3FFF;
107 dec
->pulseval
[3] = (t
>> 14) & 0x3FFF;
109 dec
->offset1
[1] |= ((t
>> 28) & 0x0F) << 4;
115 dec
->pulsepos
[0] = (t
>> 4) & 0x7FFFFFF;
117 dec
->pulseoff
[0] = (t
>> 0) & 0xF;
119 dec
->offset1
[0] |= (t
>> 31) & 1;
125 dec
->pulsepos
[1] = (t
>> 4) & 0x7FFFFFF;
127 dec
->pulseoff
[1] = (t
>> 0) & 0xF;
129 dec
->offset1
[0] |= ((t
>> 31) & 1) << 1;
135 dec
->pulsepos
[2] = (t
>> 4) & 0x7FFFFFF;
137 dec
->pulseoff
[2] = (t
>> 0) & 0xF;
139 dec
->offset1
[0] |= ((t
>> 31) & 1) << 2;
145 dec
->pulsepos
[3] = (t
>> 4) & 0x7FFFFFF;
147 dec
->pulseoff
[3] = (t
>> 0) & 0xF;
149 dec
->offset1
[0] |= ((t
>> 31) & 1) << 3;
153 static void truespeech_correlate_filter(TSContext
*dec
)
158 for(i
= 0; i
< 8; i
++){
160 memcpy(tmp
, dec
->cvector
, i
* 2);
161 for(j
= 0; j
< i
; j
++)
162 dec
->cvector
[j
] = ((tmp
[i
- j
- 1] * dec
->vector
[i
]) +
163 (dec
->cvector
[j
] << 15) + 0x4000) >> 15;
165 dec
->cvector
[i
] = (8 - dec
->vector
[i
]) >> 3;
167 for(i
= 0; i
< 8; i
++)
168 dec
->cvector
[i
] = (dec
->cvector
[i
] * ts_230
[i
]) >> 15;
170 dec
->filtval
= dec
->vector
[0];
173 static void truespeech_filters_merge(TSContext
*dec
)
178 for(i
= 0; i
< 8; i
++){
179 dec
->filters
[i
+ 0] = dec
->prevfilt
[i
];
180 dec
->filters
[i
+ 8] = dec
->prevfilt
[i
];
183 for(i
= 0; i
< 8; i
++){
184 dec
->filters
[i
+ 0]=(dec
->cvector
[i
] * 21846 + dec
->prevfilt
[i
] * 10923 + 16384) >> 15;
185 dec
->filters
[i
+ 8]=(dec
->cvector
[i
] * 10923 + dec
->prevfilt
[i
] * 21846 + 16384) >> 15;
188 for(i
= 0; i
< 8; i
++){
189 dec
->filters
[i
+ 16] = dec
->cvector
[i
];
190 dec
->filters
[i
+ 24] = dec
->cvector
[i
];
194 static void truespeech_apply_twopoint_filter(TSContext
*dec
, int quart
)
196 int16_t tmp
[146 + 60], *ptr0
, *ptr1
;
197 const int16_t *filter
;
200 t
= dec
->offset2
[quart
];
202 memset(dec
->newvec
, 0, 60 * 2);
205 for(i
= 0; i
< 146; i
++)
206 tmp
[i
] = dec
->filtbuf
[i
];
207 off
= (t
/ 25) + dec
->offset1
[quart
>> 1] + 18;
208 ptr0
= tmp
+ 145 - off
;
210 filter
= (const int16_t*)ts_240
+ (t
% 25) * 2;
211 for(i
= 0; i
< 60; i
++){
212 t
= (ptr0
[0] * filter
[0] + ptr0
[1] * filter
[1] + 0x2000) >> 14;
219 static void truespeech_place_pulses(TSContext
*dec
, int16_t *out
, int quart
)
227 memset(out
, 0, 60 * 2);
228 for(i
= 0; i
< 7; i
++) {
229 t
= dec
->pulseval
[quart
] & 3;
230 dec
->pulseval
[quart
] >>= 2;
231 tmp
[6 - i
] = ts_562
[dec
->pulseoff
[quart
] * 4 + t
];
234 coef
= dec
->pulsepos
[quart
] >> 15;
235 ptr1
= (const int16_t*)ts_140
+ 30;
237 for(i
= 0, j
= 3; (i
< 30) && (j
> 0); i
++){
247 coef
= dec
->pulsepos
[quart
] & 0x7FFF;
248 ptr1
= (const int16_t*)ts_140
;
249 for(i
= 30, j
= 4; (i
< 60) && (j
> 0); i
++){
262 static void truespeech_update_filters(TSContext
*dec
, int16_t *out
, int quart
)
266 for(i
= 0; i
< 86; i
++)
267 dec
->filtbuf
[i
] = dec
->filtbuf
[i
+ 60];
268 for(i
= 0; i
< 60; i
++){
269 dec
->filtbuf
[i
+ 86] = out
[i
] + dec
->newvec
[i
] - (dec
->newvec
[i
] >> 3);
270 out
[i
] += dec
->newvec
[i
];
274 static void truespeech_synth(TSContext
*dec
, int16_t *out
, int quart
)
278 int16_t *ptr0
, *ptr1
;
281 ptr1
= dec
->filters
+ quart
* 8;
282 for(i
= 0; i
< 60; i
++){
284 for(k
= 0; k
< 8; k
++)
285 sum
+= ptr0
[k
] * ptr1
[k
];
286 sum
= (sum
+ (out
[i
] << 12) + 0x800) >> 12;
287 out
[i
] = av_clip(sum
, -0x7FFE, 0x7FFE);
288 for(k
= 7; k
> 0; k
--)
289 ptr0
[k
] = ptr0
[k
- 1];
293 for(i
= 0; i
< 8; i
++)
294 t
[i
] = (ts_5E2
[i
] * ptr1
[i
]) >> 15;
297 for(i
= 0; i
< 60; i
++){
299 for(k
= 0; k
< 8; k
++)
300 sum
+= ptr0
[k
] * t
[k
];
301 for(k
= 7; k
> 0; k
--)
302 ptr0
[k
] = ptr0
[k
- 1];
304 out
[i
] = ((out
[i
] << 12) - sum
) >> 12;
307 for(i
= 0; i
< 8; i
++)
308 t
[i
] = (ts_5F2
[i
] * ptr1
[i
]) >> 15;
311 for(i
= 0; i
< 60; i
++){
312 int sum
= out
[i
] << 12;
313 for(k
= 0; k
< 8; k
++)
314 sum
+= ptr0
[k
] * t
[k
];
315 for(k
= 7; k
> 0; k
--)
316 ptr0
[k
] = ptr0
[k
- 1];
317 ptr0
[0] = av_clip((sum
+ 0x800) >> 12, -0x7FFE, 0x7FFE);
319 sum
= ((ptr0
[1] * (dec
->filtval
- (dec
->filtval
>> 2))) >> 4) + sum
;
320 sum
= sum
- (sum
>> 3);
321 out
[i
] = av_clip((sum
+ 0x800) >> 12, -0x7FFE, 0x7FFE);
325 static void truespeech_save_prevvec(TSContext
*c
)
329 for(i
= 0; i
< 8; i
++)
330 c
->prevfilt
[i
] = c
->cvector
[i
];
333 static int truespeech_decode_frame(AVCodecContext
*avctx
,
334 void *data
, int *data_size
,
337 const uint8_t *buf
= avpkt
->data
;
338 int buf_size
= avpkt
->size
;
339 TSContext
*c
= avctx
->priv_data
;
342 short *samples
= data
;
344 int16_t out_buf
[240];
350 iterations
= FFMIN(buf_size
/ 32, *data_size
/ 480);
351 for(j
= 0; j
< iterations
; j
++) {
352 truespeech_read_frame(c
, buf
+ consumed
);
355 truespeech_correlate_filter(c
);
356 truespeech_filters_merge(c
);
358 memset(out_buf
, 0, 240 * 2);
359 for(i
= 0; i
< 4; i
++) {
360 truespeech_apply_twopoint_filter(c
, i
);
361 truespeech_place_pulses(c
, out_buf
+ i
* 60, i
);
362 truespeech_update_filters(c
, out_buf
+ i
* 60, i
);
363 truespeech_synth(c
, out_buf
+ i
* 60, i
);
366 truespeech_save_prevvec(c
);
368 /* finally output decoded frame */
369 for(i
= 0; i
< 240; i
++)
370 *samples
++ = out_buf
[i
];
374 *data_size
= consumed
* 15;
379 AVCodec truespeech_decoder
= {
384 truespeech_decode_init
,
387 truespeech_decode_frame
,
388 .long_name
= NULL_IF_CONFIG_SMALL("DSP Group TrueSpeech"),