annotate gsmdec.c @ 12530:63edd10ad4bc libavcodec tip

Try to fix crashes introduced by r25218 r25218 made assumptions about the existence of past reference frames that weren't necessarily true.
author darkshikari
date Tue, 28 Sep 2010 09:06:22 +0000
parents 81871058b27c
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12124
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
1 /*
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
2 * gsm 06.10 decoder
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
3 * Copyright (c) 2010 Reimar Döffinger <Reimar.Doeffinger@gmx.de>
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
4 *
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
5 * This file is part of FFmpeg.
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
6 *
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
11 *
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
15 * Lesser General Public License for more details.
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
16 *
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
20 */
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
21
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
22 /**
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
23 * @file
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
24 * GSM decoder
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
25 */
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
26
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
27 #define ALT_BITSTREAM_READER_LE
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
28 #include "avcodec.h"
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
29 #include "get_bits.h"
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
30
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
31 // input and output sizes in byte
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
32 #define GSM_BLOCK_SIZE 33
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
33 #define GSM_MS_BLOCK_SIZE 65
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
34 #define GSM_FRAME_SIZE 160
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
35
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
36 typedef struct {
12284
81871058b27c Document how the ref_buf is used.
reimar
parents: 12124
diff changeset
37 // Contains first 120 elements from the previous frame
81871058b27c Document how the ref_buf is used.
reimar
parents: 12124
diff changeset
38 // (used by long_term_synth according to the "lag"),
81871058b27c Document how the ref_buf is used.
reimar
parents: 12124
diff changeset
39 // then in the following 160 elements the current
81871058b27c Document how the ref_buf is used.
reimar
parents: 12124
diff changeset
40 // frame is constructed.
12124
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
41 int16_t ref_buf[280];
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
42 int v[9];
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
43 int lar[2][8];
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
44 int lar_idx;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
45 int msr;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
46 } GSMContext;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
47
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
48 static av_cold int gsm_init(AVCodecContext *avctx)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
49 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
50 avctx->channels = 1;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
51 if (!avctx->sample_rate)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
52 avctx->sample_rate = 8000;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
53 avctx->sample_fmt = SAMPLE_FMT_S16;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
54
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
55 switch (avctx->codec_id) {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
56 case CODEC_ID_GSM:
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
57 avctx->frame_size = GSM_FRAME_SIZE;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
58 avctx->block_align = GSM_BLOCK_SIZE;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
59 break;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
60 case CODEC_ID_GSM_MS:
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
61 avctx->frame_size = 2 * GSM_FRAME_SIZE;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
62 avctx->block_align = GSM_MS_BLOCK_SIZE;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
63 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
64
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
65 return 0;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
66 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
67
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
68 static const int16_t dequant_tab[64][8] = {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
69 { -28, -20, -12, -4, 4, 12, 20, 28},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
70 { -56, -40, -24, -8, 8, 24, 40, 56},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
71 { -84, -60, -36, -12, 12, 36, 60, 84},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
72 { -112, -80, -48, -16, 16, 48, 80, 112},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
73 { -140, -100, -60, -20, 20, 60, 100, 140},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
74 { -168, -120, -72, -24, 24, 72, 120, 168},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
75 { -196, -140, -84, -28, 28, 84, 140, 196},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
76 { -224, -160, -96, -32, 32, 96, 160, 224},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
77 { -252, -180, -108, -36, 36, 108, 180, 252},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
78 { -280, -200, -120, -40, 40, 120, 200, 280},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
79 { -308, -220, -132, -44, 44, 132, 220, 308},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
80 { -336, -240, -144, -48, 48, 144, 240, 336},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
81 { -364, -260, -156, -52, 52, 156, 260, 364},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
82 { -392, -280, -168, -56, 56, 168, 280, 392},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
83 { -420, -300, -180, -60, 60, 180, 300, 420},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
84 { -448, -320, -192, -64, 64, 192, 320, 448},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
85 { -504, -360, -216, -72, 72, 216, 360, 504},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
86 { -560, -400, -240, -80, 80, 240, 400, 560},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
87 { -616, -440, -264, -88, 88, 264, 440, 616},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
88 { -672, -480, -288, -96, 96, 288, 480, 672},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
89 { -728, -520, -312, -104, 104, 312, 520, 728},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
90 { -784, -560, -336, -112, 112, 336, 560, 784},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
91 { -840, -600, -360, -120, 120, 360, 600, 840},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
92 { -896, -640, -384, -128, 128, 384, 640, 896},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
93 { -1008, -720, -432, -144, 144, 432, 720, 1008},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
94 { -1120, -800, -480, -160, 160, 480, 800, 1120},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
95 { -1232, -880, -528, -176, 176, 528, 880, 1232},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
96 { -1344, -960, -576, -192, 192, 576, 960, 1344},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
97 { -1456, -1040, -624, -208, 208, 624, 1040, 1456},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
98 { -1568, -1120, -672, -224, 224, 672, 1120, 1568},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
99 { -1680, -1200, -720, -240, 240, 720, 1200, 1680},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
100 { -1792, -1280, -768, -256, 256, 768, 1280, 1792},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
101 { -2016, -1440, -864, -288, 288, 864, 1440, 2016},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
102 { -2240, -1600, -960, -320, 320, 960, 1600, 2240},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
103 { -2464, -1760, -1056, -352, 352, 1056, 1760, 2464},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
104 { -2688, -1920, -1152, -384, 384, 1152, 1920, 2688},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
105 { -2912, -2080, -1248, -416, 416, 1248, 2080, 2912},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
106 { -3136, -2240, -1344, -448, 448, 1344, 2240, 3136},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
107 { -3360, -2400, -1440, -480, 480, 1440, 2400, 3360},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
108 { -3584, -2560, -1536, -512, 512, 1536, 2560, 3584},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
109 { -4032, -2880, -1728, -576, 576, 1728, 2880, 4032},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
110 { -4480, -3200, -1920, -640, 640, 1920, 3200, 4480},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
111 { -4928, -3520, -2112, -704, 704, 2112, 3520, 4928},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
112 { -5376, -3840, -2304, -768, 768, 2304, 3840, 5376},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
113 { -5824, -4160, -2496, -832, 832, 2496, 4160, 5824},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
114 { -6272, -4480, -2688, -896, 896, 2688, 4480, 6272},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
115 { -6720, -4800, -2880, -960, 960, 2880, 4800, 6720},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
116 { -7168, -5120, -3072, -1024, 1024, 3072, 5120, 7168},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
117 { -8063, -5759, -3456, -1152, 1152, 3456, 5760, 8064},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
118 { -8959, -6399, -3840, -1280, 1280, 3840, 6400, 8960},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
119 { -9855, -7039, -4224, -1408, 1408, 4224, 7040, 9856},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
120 {-10751, -7679, -4608, -1536, 1536, 4608, 7680, 10752},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
121 {-11647, -8319, -4992, -1664, 1664, 4992, 8320, 11648},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
122 {-12543, -8959, -5376, -1792, 1792, 5376, 8960, 12544},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
123 {-13439, -9599, -5760, -1920, 1920, 5760, 9600, 13440},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
124 {-14335, -10239, -6144, -2048, 2048, 6144, 10240, 14336},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
125 {-16127, -11519, -6912, -2304, 2304, 6912, 11519, 16127},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
126 {-17919, -12799, -7680, -2560, 2560, 7680, 12799, 17919},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
127 {-19711, -14079, -8448, -2816, 2816, 8448, 14079, 19711},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
128 {-21503, -15359, -9216, -3072, 3072, 9216, 15359, 21503},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
129 {-23295, -16639, -9984, -3328, 3328, 9984, 16639, 23295},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
130 {-25087, -17919, -10752, -3584, 3584, 10752, 17919, 25087},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
131 {-26879, -19199, -11520, -3840, 3840, 11520, 19199, 26879},
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
132 {-28671, -20479, -12288, -4096, 4096, 12288, 20479, 28671}
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
133 };
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
134
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
135 static void apcm_dequant_add(GetBitContext *gb, int16_t *dst)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
136 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
137 int i;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
138 int maxidx = get_bits(gb, 6);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
139 const int16_t *tab = dequant_tab[maxidx];
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
140 for (i = 0; i < 13; i++)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
141 dst[3*i] += tab[get_bits(gb, 3)];
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
142 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
143
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
144 static inline int gsm_mult(int a, int b)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
145 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
146 return (a * b + (1 << 14)) >> 15;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
147 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
148
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
149 static const uint16_t long_term_gain_tab[4] = {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
150 3277, 11469, 21299, 32767
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
151 };
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
152
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
153 static void long_term_synth(int16_t *dst, int lag, int gain_idx)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
154 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
155 int i;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
156 const int16_t *src = dst - lag;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
157 uint16_t gain = long_term_gain_tab[gain_idx];
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
158 for (i = 0; i < 40; i++)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
159 dst[i] = gsm_mult(gain, src[i]);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
160 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
161
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
162 static inline int decode_log_area(int coded, int factor, int offset)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
163 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
164 coded <<= 10;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
165 coded -= offset;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
166 return gsm_mult(coded, factor) << 1;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
167 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
168
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
169 static av_noinline int get_rrp(int filtered)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
170 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
171 int abs = FFABS(filtered);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
172 if (abs < 11059) abs <<= 1;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
173 else if (abs < 20070) abs += 11059;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
174 else abs = (abs >> 2) + 26112;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
175 return filtered < 0 ? -abs : abs;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
176 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
177
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
178 static int filter_value(int in, int rrp[8], int v[9])
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
179 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
180 int i;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
181 for (i = 7; i >= 0; i--) {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
182 in -= gsm_mult(rrp[i], v[i]);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
183 v[i + 1] = v[i] + gsm_mult(rrp[i], in);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
184 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
185 v[0] = in;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
186 return in;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
187 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
188
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
189 static void short_term_synth(GSMContext *ctx, int16_t *dst, const int16_t *src)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
190 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
191 int i;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
192 int rrp[8];
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
193 int *lar = ctx->lar[ctx->lar_idx];
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
194 int *lar_prev = ctx->lar[ctx->lar_idx ^ 1];
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
195 for (i = 0; i < 8; i++)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
196 rrp[i] = get_rrp((lar_prev[i] >> 2) + (lar_prev[i] >> 1) + (lar[i] >> 2));
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
197 for (i = 0; i < 13; i++)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
198 dst[i] = filter_value(src[i], rrp, ctx->v);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
199
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
200 for (i = 0; i < 8; i++)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
201 rrp[i] = get_rrp((lar_prev[i] >> 1) + (lar [i] >> 1));
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
202 for (i = 13; i < 27; i++)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
203 dst[i] = filter_value(src[i], rrp, ctx->v);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
204
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
205 for (i = 0; i < 8; i++)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
206 rrp[i] = get_rrp((lar_prev[i] >> 2) + (lar [i] >> 1) + (lar[i] >> 2));
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
207 for (i = 27; i < 40; i++)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
208 dst[i] = filter_value(src[i], rrp, ctx->v);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
209
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
210 for (i = 0; i < 8; i++)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
211 rrp[i] = get_rrp(lar[i]);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
212 for (i = 40; i < 160; i++)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
213 dst[i] = filter_value(src[i], rrp, ctx->v);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
214
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
215 ctx->lar_idx ^= 1;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
216 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
217
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
218 static int postprocess(int16_t *data, int msr)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
219 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
220 int i;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
221 for (i = 0; i < 160; i++) {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
222 msr = av_clip_int16(data[i] + gsm_mult(msr, 28180));
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
223 data[i] = av_clip_int16(msr << 1) & ~7;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
224 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
225 return msr;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
226 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
227
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
228 static int gsm_decode_block(AVCodecContext *avctx, int16_t *samples,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
229 GetBitContext *gb)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
230 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
231 GSMContext *ctx = avctx->priv_data;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
232 int i;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
233 int16_t *ref_dst = ctx->ref_buf + 120;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
234 int *lar = ctx->lar[ctx->lar_idx];
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
235 lar[0] = decode_log_area(get_bits(gb, 6), 13107, 1 << 15);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
236 lar[1] = decode_log_area(get_bits(gb, 6), 13107, 1 << 15);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
237 lar[2] = decode_log_area(get_bits(gb, 5), 13107, (1 << 14) + 2048*2);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
238 lar[3] = decode_log_area(get_bits(gb, 5), 13107, (1 << 14) - 2560*2);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
239 lar[4] = decode_log_area(get_bits(gb, 4), 19223, (1 << 13) + 94*2);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
240 lar[5] = decode_log_area(get_bits(gb, 4), 17476, (1 << 13) - 1792*2);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
241 lar[6] = decode_log_area(get_bits(gb, 3), 31454, (1 << 12) - 341*2);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
242 lar[7] = decode_log_area(get_bits(gb, 3), 29708, (1 << 12) - 1144*2);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
243
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
244 for (i = 0; i < 4; i++) {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
245 int lag = get_bits(gb, 7);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
246 int gain_idx = get_bits(gb, 2);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
247 int offset = get_bits(gb, 2);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
248 lag = av_clip(lag, 40, 120);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
249 long_term_synth(ref_dst, lag, gain_idx);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
250 apcm_dequant_add(gb, ref_dst + offset);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
251 ref_dst += 40;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
252 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
253 memcpy(ctx->ref_buf, ctx->ref_buf + 160, 120 * sizeof(*ctx->ref_buf));
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
254 short_term_synth(ctx, samples, ctx->ref_buf + 120);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
255 // for optimal speed this could be merged with short_term_synth,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
256 // not done yet because it is a bit ugly
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
257 ctx->msr = postprocess(samples, ctx->msr);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
258 return 0;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
259 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
260
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
261 static int gsm_decode_frame(AVCodecContext *avctx, void *data,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
262 int *data_size, AVPacket *avpkt)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
263 {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
264 int res;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
265 GetBitContext gb;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
266 const uint8_t *buf = avpkt->data;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
267 int buf_size = avpkt->size;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
268 int16_t *samples = data;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
269 int frame_bytes = 2 * avctx->frame_size;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
270
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
271 if (*data_size < frame_bytes)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
272 return -1;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
273 *data_size = 0;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
274 if(buf_size < avctx->block_align)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
275 return AVERROR_INVALIDDATA;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
276 init_get_bits(&gb, buf, buf_size * 8);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
277
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
278 switch (avctx->codec_id) {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
279 case CODEC_ID_GSM:
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
280 if (get_bits(&gb, 4) != 0xd)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
281 av_log(avctx, AV_LOG_WARNING, "Missing GSM magic!\n");
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
282 res = gsm_decode_block(avctx, samples, &gb);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
283 if (res < 0)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
284 return res;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
285 break;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
286 case CODEC_ID_GSM_MS:
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
287 res = gsm_decode_block(avctx, samples, &gb);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
288 if (res < 0)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
289 return res;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
290 res = gsm_decode_block(avctx, samples + GSM_FRAME_SIZE, &gb);
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
291 if (res < 0)
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
292 return res;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
293 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
294 *data_size = frame_bytes;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
295 return avctx->block_align;
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
296 }
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
297
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
298 AVCodec gsm_decoder = {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
299 "gsm",
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
300 AVMEDIA_TYPE_AUDIO,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
301 CODEC_ID_GSM,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
302 sizeof(GSMContext),
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
303 gsm_init,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
304 NULL,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
305 NULL,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
306 gsm_decode_frame,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
307 .long_name = NULL_IF_CONFIG_SMALL("GSM"),
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
308 };
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
309
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
310 AVCodec gsm_ms_decoder = {
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
311 "gsm_ms",
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
312 AVMEDIA_TYPE_AUDIO,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
313 CODEC_ID_GSM_MS,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
314 sizeof(GSMContext),
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
315 gsm_init,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
316 NULL,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
317 NULL,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
318 gsm_decode_frame,
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
319 .long_name = NULL_IF_CONFIG_SMALL("GSM Microsoft variant"),
11b27985b3d0 Add native GSM 06.10 audio decoder.
reimar
parents:
diff changeset
320 };