Optimize decodeplane32().
[ffmpeg.git] / libavcodec / truespeech.c
1 /*
2  * DSP Group TrueSpeech compatible decoder
3  * Copyright (c) 2005 Konstantin Shishkov
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 #include "libavutil/intreadwrite.h"
23 #include "avcodec.h"
24
25 #include "truespeech_data.h"
26 /**
27  * @file
28  * TrueSpeech decoder.
29  */
30
31 /**
32  * TrueSpeech decoder context
33  */
34 typedef struct {
35     /* input data */
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
43     /* temporary data */
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
53 } TSContext;
54
55 static av_cold int truespeech_decode_init(AVCodecContext * avctx)
56 {
57 //    TSContext *c = avctx->priv_data;
58
59     avctx->sample_fmt = SAMPLE_FMT_S16;
60     return 0;
61 }
62
63 static void truespeech_read_frame(TSContext *dec, const uint8_t *input)
64 {
65     uint32_t t;
66
67     /* first dword */
68     t = AV_RL32(input);
69     input += 4;
70
71     dec->flag = t & 1;
72
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];
81
82     /* second dword */
83     t = AV_RL32(input);
84     input += 4;
85
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;
90
91     dec->offset1[0] = ((t >> 28) & 0xF) << 4;
92
93     /* third dword */
94     t = AV_RL32(input);
95     input += 4;
96
97     dec->pulseval[0] = (t >>  0) & 0x3FFF;
98     dec->pulseval[1] = (t >> 14) & 0x3FFF;
99
100     dec->offset1[1] = (t >> 28) & 0x0F;
101
102     /* fourth dword */
103     t = AV_RL32(input);
104     input += 4;
105
106     dec->pulseval[2] = (t >>  0) & 0x3FFF;
107     dec->pulseval[3] = (t >> 14) & 0x3FFF;
108
109     dec->offset1[1] |= ((t >> 28) & 0x0F) << 4;
110
111     /* fifth dword */
112     t = AV_RL32(input);
113     input += 4;
114
115     dec->pulsepos[0] = (t >> 4) & 0x7FFFFFF;
116
117     dec->pulseoff[0] = (t >> 0) & 0xF;
118
119     dec->offset1[0] |= (t >> 31) & 1;
120
121     /* sixth dword */
122     t = AV_RL32(input);
123     input += 4;
124
125     dec->pulsepos[1] = (t >> 4) & 0x7FFFFFF;
126
127     dec->pulseoff[1] = (t >> 0) & 0xF;
128
129     dec->offset1[0] |= ((t >> 31) & 1) << 1;
130
131     /* seventh dword */
132     t = AV_RL32(input);
133     input += 4;
134
135     dec->pulsepos[2] = (t >> 4) & 0x7FFFFFF;
136
137     dec->pulseoff[2] = (t >> 0) & 0xF;
138
139     dec->offset1[0] |= ((t >> 31) & 1) << 2;
140
141     /* eighth dword */
142     t = AV_RL32(input);
143     input += 4;
144
145     dec->pulsepos[3] = (t >> 4) & 0x7FFFFFF;
146
147     dec->pulseoff[3] = (t >> 0) & 0xF;
148
149     dec->offset1[0] |= ((t >> 31) & 1) << 3;
150
151 }
152
153 static void truespeech_correlate_filter(TSContext *dec)
154 {
155     int16_t tmp[8];
156     int i, j;
157
158     for(i = 0; i < 8; i++){
159         if(i > 0){
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;
164         }
165         dec->cvector[i] = (8 - dec->vector[i]) >> 3;
166     }
167     for(i = 0; i < 8; i++)
168         dec->cvector[i] = (dec->cvector[i] * ts_230[i]) >> 15;
169
170     dec->filtval = dec->vector[0];
171 }
172
173 static void truespeech_filters_merge(TSContext *dec)
174 {
175     int i;
176
177     if(!dec->flag){
178         for(i = 0; i < 8; i++){
179             dec->filters[i + 0] = dec->prevfilt[i];
180             dec->filters[i + 8] = dec->prevfilt[i];
181         }
182     }else{
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;
186         }
187     }
188     for(i = 0; i < 8; i++){
189         dec->filters[i + 16] = dec->cvector[i];
190         dec->filters[i + 24] = dec->cvector[i];
191     }
192 }
193
194 static void truespeech_apply_twopoint_filter(TSContext *dec, int quart)
195 {
196     int16_t tmp[146 + 60], *ptr0, *ptr1;
197     const int16_t *filter;
198     int i, t, off;
199
200     t = dec->offset2[quart];
201     if(t == 127){
202         memset(dec->newvec, 0, 60 * 2);
203         return;
204     }
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;
209     ptr1 = tmp + 146;
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;
213         ptr0++;
214         dec->newvec[i] = t;
215         ptr1[i] = t;
216     }
217 }
218
219 static void truespeech_place_pulses(TSContext *dec, int16_t *out, int quart)
220 {
221     int16_t tmp[7];
222     int i, j, t;
223     const int16_t *ptr1;
224     int16_t *ptr2;
225     int coef;
226
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];
232     }
233
234     coef = dec->pulsepos[quart] >> 15;
235     ptr1 = (const int16_t*)ts_140 + 30;
236     ptr2 = tmp;
237     for(i = 0, j = 3; (i < 30) && (j > 0); i++){
238         t = *ptr1++;
239         if(coef >= t)
240             coef -= t;
241         else{
242             out[i] = *ptr2++;
243             ptr1 += 30;
244             j--;
245         }
246     }
247     coef = dec->pulsepos[quart] & 0x7FFF;
248     ptr1 = (const int16_t*)ts_140;
249     for(i = 30, j = 4; (i < 60) && (j > 0); i++){
250         t = *ptr1++;
251         if(coef >= t)
252             coef -= t;
253         else{
254             out[i] = *ptr2++;
255             ptr1 += 30;
256             j--;
257         }
258     }
259
260 }
261
262 static void truespeech_update_filters(TSContext *dec, int16_t *out, int quart)
263 {
264     int i;
265
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];
271     }
272 }
273
274 static void truespeech_synth(TSContext *dec, int16_t *out, int quart)
275 {
276     int i,k;
277     int t[8];
278     int16_t *ptr0, *ptr1;
279
280     ptr0 = dec->tmp1;
281     ptr1 = dec->filters + quart * 8;
282     for(i = 0; i < 60; i++){
283         int sum = 0;
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];
290         ptr0[0] = out[i];
291     }
292
293     for(i = 0; i < 8; i++)
294         t[i] = (ts_5E2[i] * ptr1[i]) >> 15;
295
296     ptr0 = dec->tmp2;
297     for(i = 0; i < 60; i++){
298         int sum = 0;
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];
303         ptr0[0] = out[i];
304         out[i] = ((out[i] << 12) - sum) >> 12;
305     }
306
307     for(i = 0; i < 8; i++)
308         t[i] = (ts_5F2[i] * ptr1[i]) >> 15;
309
310     ptr0 = dec->tmp3;
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);
318
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);
322     }
323 }
324
325 static void truespeech_save_prevvec(TSContext *c)
326 {
327     int i;
328
329     for(i = 0; i < 8; i++)
330         c->prevfilt[i] = c->cvector[i];
331 }
332
333 static int truespeech_decode_frame(AVCodecContext *avctx,
334                 void *data, int *data_size,
335                 AVPacket *avpkt)
336 {
337     const uint8_t *buf = avpkt->data;
338     int buf_size = avpkt->size;
339     TSContext *c = avctx->priv_data;
340
341     int i, j;
342     short *samples = data;
343     int consumed = 0;
344     int16_t out_buf[240];
345     int iterations;
346
347     if (!buf_size)
348         return 0;
349
350     iterations = FFMIN(buf_size / 32, *data_size / 480);
351     for(j = 0; j < iterations; j++) {
352         truespeech_read_frame(c, buf + consumed);
353         consumed += 32;
354
355         truespeech_correlate_filter(c);
356         truespeech_filters_merge(c);
357
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);
364         }
365
366         truespeech_save_prevvec(c);
367
368         /* finally output decoded frame */
369         for(i = 0; i < 240; i++)
370             *samples++ = out_buf[i];
371
372     }
373
374     *data_size = consumed * 15;
375
376     return consumed;
377 }
378
379 AVCodec truespeech_decoder = {
380     "truespeech",
381     AVMEDIA_TYPE_AUDIO,
382     CODEC_ID_TRUESPEECH,
383     sizeof(TSContext),
384     truespeech_decode_init,
385     NULL,
386     NULL,
387     truespeech_decode_frame,
388     .long_name = NULL_IF_CONFIG_SMALL("DSP Group TrueSpeech"),
389 };