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
23 #include "truespeech_data.h"
30 * TrueSpeech decoder context
34 int16_t vector
[8]; //< input vector: 5/5/4/4/4/3/3/3
35 int offset1
[2]; //< 8-bit value, used in one copying offset
36 int offset2
[4]; //< 7-bit value, encodes offsets for copying and for two-point filter
37 int pulseoff
[4]; //< 4-bit offset of pulse values block
38 int pulsepos
[4]; //< 27-bit variable, encodes 7 pulse positions
39 int pulseval
[4]; //< 7x2-bit pulse values
40 int flag
; //< 1-bit flag, shows how to choose filters
42 int filtbuf
[146]; // some big vector used for storing filters
43 int prevfilt
[8]; // filter from previous frame
44 int16_t tmp1
[8]; // coefficients for adding to out
45 int16_t tmp2
[8]; // coefficients for adding to out
46 int16_t tmp3
[8]; // coefficients for adding to out
47 int16_t cvector
[8]; // correlated input vector
48 int filtval
; // gain value for one function
49 int16_t newvec
[60]; // tmp vector
50 int16_t filters
[32]; // filters for every subframe
53 static av_cold
int truespeech_decode_init(AVCodecContext
* avctx
)
55 // TSContext *c = avctx->priv_data;
60 static void truespeech_read_frame(TSContext
*dec
, const uint8_t *input
)
70 dec
->vector
[0] = ts_codebook
[0][(t
>> 1) & 0x1F];
71 dec
->vector
[1] = ts_codebook
[1][(t
>> 6) & 0x1F];
72 dec
->vector
[2] = ts_codebook
[2][(t
>> 11) & 0xF];
73 dec
->vector
[3] = ts_codebook
[3][(t
>> 15) & 0xF];
74 dec
->vector
[4] = ts_codebook
[4][(t
>> 19) & 0xF];
75 dec
->vector
[5] = ts_codebook
[5][(t
>> 23) & 0x7];
76 dec
->vector
[6] = ts_codebook
[6][(t
>> 26) & 0x7];
77 dec
->vector
[7] = ts_codebook
[7][(t
>> 29) & 0x7];
83 dec
->offset2
[0] = (t
>> 0) & 0x7F;
84 dec
->offset2
[1] = (t
>> 7) & 0x7F;
85 dec
->offset2
[2] = (t
>> 14) & 0x7F;
86 dec
->offset2
[3] = (t
>> 21) & 0x7F;
88 dec
->offset1
[0] = ((t
>> 28) & 0xF) << 4;
94 dec
->pulseval
[0] = (t
>> 0) & 0x3FFF;
95 dec
->pulseval
[1] = (t
>> 14) & 0x3FFF;
97 dec
->offset1
[1] = (t
>> 28) & 0x0F;
103 dec
->pulseval
[2] = (t
>> 0) & 0x3FFF;
104 dec
->pulseval
[3] = (t
>> 14) & 0x3FFF;
106 dec
->offset1
[1] |= ((t
>> 28) & 0x0F) << 4;
112 dec
->pulsepos
[0] = (t
>> 4) & 0x7FFFFFF;
114 dec
->pulseoff
[0] = (t
>> 0) & 0xF;
116 dec
->offset1
[0] |= (t
>> 31) & 1;
122 dec
->pulsepos
[1] = (t
>> 4) & 0x7FFFFFF;
124 dec
->pulseoff
[1] = (t
>> 0) & 0xF;
126 dec
->offset1
[0] |= ((t
>> 31) & 1) << 1;
132 dec
->pulsepos
[2] = (t
>> 4) & 0x7FFFFFF;
134 dec
->pulseoff
[2] = (t
>> 0) & 0xF;
136 dec
->offset1
[0] |= ((t
>> 31) & 1) << 2;
142 dec
->pulsepos
[3] = (t
>> 4) & 0x7FFFFFF;
144 dec
->pulseoff
[3] = (t
>> 0) & 0xF;
146 dec
->offset1
[0] |= ((t
>> 31) & 1) << 3;
150 static void truespeech_correlate_filter(TSContext
*dec
)
155 for(i
= 0; i
< 8; i
++){
157 memcpy(tmp
, dec
->cvector
, i
* 2);
158 for(j
= 0; j
< i
; j
++)
159 dec
->cvector
[j
] = ((tmp
[i
- j
- 1] * dec
->vector
[i
]) +
160 (dec
->cvector
[j
] << 15) + 0x4000) >> 15;
162 dec
->cvector
[i
] = (8 - dec
->vector
[i
]) >> 3;
164 for(i
= 0; i
< 8; i
++)
165 dec
->cvector
[i
] = (dec
->cvector
[i
] * ts_230
[i
]) >> 15;
167 dec
->filtval
= dec
->vector
[0];
170 static void truespeech_filters_merge(TSContext
*dec
)
175 for(i
= 0; i
< 8; i
++){
176 dec
->filters
[i
+ 0] = dec
->prevfilt
[i
];
177 dec
->filters
[i
+ 8] = dec
->prevfilt
[i
];
180 for(i
= 0; i
< 8; i
++){
181 dec
->filters
[i
+ 0]=(dec
->cvector
[i
] * 21846 + dec
->prevfilt
[i
] * 10923 + 16384) >> 15;
182 dec
->filters
[i
+ 8]=(dec
->cvector
[i
] * 10923 + dec
->prevfilt
[i
] * 21846 + 16384) >> 15;
185 for(i
= 0; i
< 8; i
++){
186 dec
->filters
[i
+ 16] = dec
->cvector
[i
];
187 dec
->filters
[i
+ 24] = dec
->cvector
[i
];
191 static void truespeech_apply_twopoint_filter(TSContext
*dec
, int quart
)
193 int16_t tmp
[146 + 60], *ptr0
, *ptr1
;
194 const int16_t *filter
;
197 t
= dec
->offset2
[quart
];
199 memset(dec
->newvec
, 0, 60 * 2);
202 for(i
= 0; i
< 146; i
++)
203 tmp
[i
] = dec
->filtbuf
[i
];
204 off
= (t
/ 25) + dec
->offset1
[quart
>> 1] + 18;
205 ptr0
= tmp
+ 145 - off
;
207 filter
= (const int16_t*)ts_240
+ (t
% 25) * 2;
208 for(i
= 0; i
< 60; i
++){
209 t
= (ptr0
[0] * filter
[0] + ptr0
[1] * filter
[1] + 0x2000) >> 14;
216 static void truespeech_place_pulses(TSContext
*dec
, int16_t *out
, int quart
)
224 memset(out
, 0, 60 * 2);
225 for(i
= 0; i
< 7; i
++) {
226 t
= dec
->pulseval
[quart
] & 3;
227 dec
->pulseval
[quart
] >>= 2;
228 tmp
[6 - i
] = ts_562
[dec
->pulseoff
[quart
] * 4 + t
];
231 coef
= dec
->pulsepos
[quart
] >> 15;
232 ptr1
= (const int16_t*)ts_140
+ 30;
234 for(i
= 0, j
= 3; (i
< 30) && (j
> 0); i
++){
244 coef
= dec
->pulsepos
[quart
] & 0x7FFF;
245 ptr1
= (const int16_t*)ts_140
;
246 for(i
= 30, j
= 4; (i
< 60) && (j
> 0); i
++){
259 static void truespeech_update_filters(TSContext
*dec
, int16_t *out
, int quart
)
263 for(i
= 0; i
< 86; i
++)
264 dec
->filtbuf
[i
] = dec
->filtbuf
[i
+ 60];
265 for(i
= 0; i
< 60; i
++){
266 dec
->filtbuf
[i
+ 86] = out
[i
] + dec
->newvec
[i
] - (dec
->newvec
[i
] >> 3);
267 out
[i
] += dec
->newvec
[i
];
271 static void truespeech_synth(TSContext
*dec
, int16_t *out
, int quart
)
275 int16_t *ptr0
, *ptr1
;
278 ptr1
= dec
->filters
+ quart
* 8;
279 for(i
= 0; i
< 60; i
++){
281 for(k
= 0; k
< 8; k
++)
282 sum
+= ptr0
[k
] * ptr1
[k
];
283 sum
= (sum
+ (out
[i
] << 12) + 0x800) >> 12;
284 out
[i
] = av_clip(sum
, -0x7FFE, 0x7FFE);
285 for(k
= 7; k
> 0; k
--)
286 ptr0
[k
] = ptr0
[k
- 1];
290 for(i
= 0; i
< 8; i
++)
291 t
[i
] = (ts_5E2
[i
] * ptr1
[i
]) >> 15;
294 for(i
= 0; i
< 60; i
++){
296 for(k
= 0; k
< 8; k
++)
297 sum
+= ptr0
[k
] * t
[k
];
298 for(k
= 7; k
> 0; k
--)
299 ptr0
[k
] = ptr0
[k
- 1];
301 out
[i
] = ((out
[i
] << 12) - sum
) >> 12;
304 for(i
= 0; i
< 8; i
++)
305 t
[i
] = (ts_5F2
[i
] * ptr1
[i
]) >> 15;
308 for(i
= 0; i
< 60; i
++){
309 int sum
= out
[i
] << 12;
310 for(k
= 0; k
< 8; k
++)
311 sum
+= ptr0
[k
] * t
[k
];
312 for(k
= 7; k
> 0; k
--)
313 ptr0
[k
] = ptr0
[k
- 1];
314 ptr0
[0] = av_clip((sum
+ 0x800) >> 12, -0x7FFE, 0x7FFE);
316 sum
= ((ptr0
[1] * (dec
->filtval
- (dec
->filtval
>> 2))) >> 4) + sum
;
317 sum
= sum
- (sum
>> 3);
318 out
[i
] = av_clip((sum
+ 0x800) >> 12, -0x7FFE, 0x7FFE);
322 static void truespeech_save_prevvec(TSContext
*c
)
326 for(i
= 0; i
< 8; i
++)
327 c
->prevfilt
[i
] = c
->cvector
[i
];
330 static int truespeech_decode_frame(AVCodecContext
*avctx
,
331 void *data
, int *data_size
,
332 const uint8_t *buf
, int buf_size
)
334 TSContext
*c
= avctx
->priv_data
;
337 short *samples
= data
;
339 int16_t out_buf
[240];
345 iterations
= FFMIN(buf_size
/ 32, *data_size
/ 480);
346 for(j
= 0; j
< iterations
; j
++) {
347 truespeech_read_frame(c
, buf
+ consumed
);
350 truespeech_correlate_filter(c
);
351 truespeech_filters_merge(c
);
353 memset(out_buf
, 0, 240 * 2);
354 for(i
= 0; i
< 4; i
++) {
355 truespeech_apply_twopoint_filter(c
, i
);
356 truespeech_place_pulses(c
, out_buf
+ i
* 60, i
);
357 truespeech_update_filters(c
, out_buf
+ i
* 60, i
);
358 truespeech_synth(c
, out_buf
+ i
* 60, i
);
361 truespeech_save_prevvec(c
);
363 /* finally output decoded frame */
364 for(i
= 0; i
< 240; i
++)
365 *samples
++ = out_buf
[i
];
369 *data_size
= consumed
* 15;
374 AVCodec truespeech_decoder
= {
379 truespeech_decode_init
,
382 truespeech_decode_frame
,
383 .long_name
= "DSP Group TrueSpeech",