Mercurial > libavcodec.hg
annotate g726.c @ 3198:6b9f0c4fbdbe libavcodec
First part of a series of speed-enchancing patches.
This one sets up a snow.h and makes snow use the dsputil function pointer
framework to access the three functions that will be implemented in asm
in the other parts of the patchset.
Patch by Robert Edele < yartrebo AH earthlink POIS net>
Original thread:
Subject: [Ffmpeg-devel] [PATCH] Snow mmx+sse2 asm optimizations
Date: Sun, 05 Feb 2006 12:47:14 -0500
author | gpoirier |
---|---|
date | Thu, 16 Mar 2006 19:18:18 +0000 |
parents | 0b546eab515d |
children | 20545fbb6f7c |
rev | line source |
---|---|
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
1 /* |
2967 | 2 * G.726 ADPCM audio codec |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
3 * Copyright (c) 2004 Roman Shaposhnik. |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
4 * |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
5 * This is a very straightforward rendition of the G.726 |
2967 | 6 * Section 4 "Computational Details". |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
7 * |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
8 * This library is free software; you can redistribute it and/or |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
9 * modify it under the terms of the GNU Lesser General Public |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
10 * License as published by the Free Software Foundation; either |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
11 * version 2 of the License, or (at your option) any later version. |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
12 * |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
13 * This library is distributed in the hope that it will be useful, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
16 * Lesser General Public License for more details. |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
17 * |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
18 * You should have received a copy of the GNU Lesser General Public |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
19 * License along with this library; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2979
diff
changeset
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
21 */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
22 #include <limits.h> |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
23 #include "avcodec.h" |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
24 #include "common.h" |
2398
582e635cfa08
common.c -> bitstream.c (and the single non bitstream func -> utils.c)
michael
parents:
2135
diff
changeset
|
25 #include "bitstream.h" |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
26 |
2135 | 27 /** |
28 * G.726 11bit float. | |
2967 | 29 * G.726 Standard uses rather odd 11bit floating point arithmentic for |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
30 * numerous occasions. It's a mistery to me why they did it this way |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
31 * instead of simply using 32bit integer arithmetic. |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
32 */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
33 typedef struct Float11 { |
2979 | 34 int sign; /**< 1bit sign */ |
35 int exp; /**< 4bit exponent */ | |
36 int mant; /**< 6bit mantissa */ | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
37 } Float11; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
38 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
39 static inline Float11* i2f(int16_t i, Float11* f) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
40 { |
2979 | 41 f->sign = (i < 0); |
42 if (f->sign) | |
43 i = -i; | |
44 f->exp = av_log2_16bit(i) + !!i; | |
45 f->mant = i? (i<<6) >> f->exp : | |
46 1<<5; | |
47 return f; | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
48 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
49 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
50 static inline int16_t mult(Float11* f1, Float11* f2) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
51 { |
2979 | 52 int res, exp; |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
53 |
2979 | 54 exp = f1->exp + f2->exp; |
55 res = (((f1->mant * f2->mant) + 0x30) >> 4) << 7; | |
56 res = exp > 26 ? res << (exp - 26) : res >> (26 - exp); | |
57 return (f1->sign ^ f2->sign) ? -res : res; | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
58 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
59 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
60 static inline int sgn(int value) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
61 { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
62 return (value < 0) ? -1 : 1; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
63 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
64 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
65 typedef struct G726Tables { |
2979 | 66 int bits; /**< bits per sample */ |
67 int* quant; /**< quantization table */ | |
68 int* iquant; /**< inverse quantization table */ | |
69 int* W; /**< special table #1 ;-) */ | |
70 int* F; /**< special table #2 */ | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
71 } G726Tables; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
72 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
73 typedef struct G726Context { |
2979 | 74 G726Tables* tbls; /**< static tables needed for computation */ |
2967 | 75 |
2979 | 76 Float11 sr[2]; /**< prev. reconstructed samples */ |
77 Float11 dq[6]; /**< prev. difference */ | |
78 int a[2]; /**< second order predictor coeffs */ | |
79 int b[6]; /**< sixth order predictor coeffs */ | |
80 int pk[2]; /**< signs of prev. 2 sez + dq */ | |
2967 | 81 |
2979 | 82 int ap; /**< scale factor control */ |
83 int yu; /**< fast scale factor */ | |
84 int yl; /**< slow scale factor */ | |
85 int dms; /**< short average magnitude of F[i] */ | |
86 int dml; /**< long average magnitude of F[i] */ | |
87 int td; /**< tone detect */ | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
88 |
2979 | 89 int se; /**< estimated signal for the next iteration */ |
90 int sez; /**< estimated second order prediction */ | |
91 int y; /**< quantizer scaling factor for the next iteration */ | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
92 } G726Context; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
93 |
2135 | 94 static int quant_tbl16[] = /**< 16kbit/s 2bits per sample */ |
2967 | 95 { 260, INT_MAX }; |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
96 static int iquant_tbl16[] = |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
97 { 116, 365, 365, 116 }; |
2967 | 98 static int W_tbl16[] = |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
99 { -22, 439, 439, -22 }; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
100 static int F_tbl16[] = |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
101 { 0, 7, 7, 0 }; |
2967 | 102 |
2135 | 103 static int quant_tbl24[] = /**< 24kbit/s 3bits per sample */ |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
104 { 7, 217, 330, INT_MAX }; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
105 static int iquant_tbl24[] = |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
106 { INT_MIN, 135, 273, 373, 373, 273, 135, INT_MIN }; |
2967 | 107 static int W_tbl24[] = |
108 { -4, 30, 137, 582, 582, 137, 30, -4 }; | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
109 static int F_tbl24[] = |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
110 { 0, 1, 2, 7, 7, 2, 1, 0 }; |
2967 | 111 |
2135 | 112 static int quant_tbl32[] = /**< 32kbit/s 4bits per sample */ |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
113 { -125, 79, 177, 245, 299, 348, 399, INT_MAX }; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
114 static int iquant_tbl32[] = |
2967 | 115 { INT_MIN, 4, 135, 213, 273, 323, 373, 425, |
2979 | 116 425, 373, 323, 273, 213, 135, 4, INT_MIN }; |
2967 | 117 static int W_tbl32[] = |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
118 { -12, 18, 41, 64, 112, 198, 355, 1122, |
2979 | 119 1122, 355, 198, 112, 64, 41, 18, -12}; |
2967 | 120 static int F_tbl32[] = |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
121 { 0, 0, 0, 1, 1, 1, 3, 7, 7, 3, 1, 1, 1, 0, 0, 0 }; |
2967 | 122 |
2135 | 123 static int quant_tbl40[] = /**< 40kbit/s 5bits per sample */ |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
124 { -122, -16, 67, 138, 197, 249, 297, 338, |
2979 | 125 377, 412, 444, 474, 501, 527, 552, INT_MAX }; |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
126 static int iquant_tbl40[] = |
2967 | 127 { INT_MIN, -66, 28, 104, 169, 224, 274, 318, |
2979 | 128 358, 395, 429, 459, 488, 514, 539, 566, |
129 566, 539, 514, 488, 459, 429, 395, 358, | |
130 318, 274, 224, 169, 104, 28, -66, INT_MIN }; | |
2967 | 131 static int W_tbl40[] = |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
132 { 14, 14, 24, 39, 40, 41, 58, 100, |
2979 | 133 141, 179, 219, 280, 358, 440, 529, 696, |
134 696, 529, 440, 358, 280, 219, 179, 141, | |
135 100, 58, 41, 40, 39, 24, 14, 14 }; | |
2967 | 136 static int F_tbl40[] = |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
137 { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 6, |
2979 | 138 6, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
139 |
2967 | 140 static G726Tables G726Tables_pool[] = |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
141 {{ 2, quant_tbl16, iquant_tbl16, W_tbl16, F_tbl16 }, |
2979 | 142 { 3, quant_tbl24, iquant_tbl24, W_tbl24, F_tbl24 }, |
143 { 4, quant_tbl32, iquant_tbl32, W_tbl32, F_tbl32 }, | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
144 { 5, quant_tbl40, iquant_tbl40, W_tbl40, F_tbl40 }}; |
2967 | 145 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
146 |
2135 | 147 /** |
2967 | 148 * Para 4.2.2 page 18: Adaptive quantizer. |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
149 */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
150 static inline uint8_t quant(G726Context* c, int d) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
151 { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
152 int sign, exp, i, dln; |
2967 | 153 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
154 sign = i = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
155 if (d < 0) { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
156 sign = 1; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
157 d = -d; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
158 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
159 exp = av_log2_16bit(d); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
160 dln = ((exp<<7) + (((d<<7)>>exp)&0x7f)) - (c->y>>2); |
2967 | 161 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
162 while (c->tbls->quant[i] < INT_MAX && c->tbls->quant[i] < dln) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
163 ++i; |
2967 | 164 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
165 if (sign) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
166 i = ~i; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
167 if (c->tbls->bits != 2 && i == 0) /* I'm not sure this is a good idea */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
168 i = 0xff; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
169 |
2967 | 170 return i; |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
171 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
172 |
2135 | 173 /** |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
174 * Para 4.2.3 page 22: Inverse adaptive quantizer. |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
175 */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
176 static inline int16_t inverse_quant(G726Context* c, int i) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
177 { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
178 int dql, dex, dqt; |
2967 | 179 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
180 dql = c->tbls->iquant[i] + (c->y >> 2); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
181 dex = (dql>>7) & 0xf; /* 4bit exponent */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
182 dqt = (1<<7) + (dql & 0x7f); /* log2 -> linear */ |
2967 | 183 return (dql < 0) ? 0 : ((dqt<<7) >> (14-dex)); |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
184 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
185 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
186 static inline int16_t g726_iterate(G726Context* c, int16_t I) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
187 { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
188 int dq, re_signal, pk0, fa1, i, tr, ylint, ylfrac, thr2, al, dq0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
189 Float11 f; |
2967 | 190 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
191 dq = inverse_quant(c, I); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
192 if (I >> (c->tbls->bits - 1)) /* get the sign */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
193 dq = -dq; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
194 re_signal = c->se + dq; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
195 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
196 /* Transition detect */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
197 ylint = (c->yl >> 15); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
198 ylfrac = (c->yl >> 10) & 0x1f; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
199 thr2 = (ylint > 9) ? 0x1f << 10 : (0x20 + ylfrac) << ylint; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
200 if (c->td == 1 && abs(dq) > ((thr2+(thr2>>1))>>1)) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
201 tr = 1; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
202 else |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
203 tr = 0; |
2967 | 204 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
205 /* Update second order predictor coefficient A2 and A1 */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
206 pk0 = (c->sez + dq) ? sgn(c->sez + dq) : 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
207 dq0 = dq ? sgn(dq) : 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
208 if (tr) { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
209 c->a[0] = 0; |
2979 | 210 c->a[1] = 0; |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
211 for (i=0; i<6; i++) |
2979 | 212 c->b[i] = 0; |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
213 } else { |
2979 | 214 /* This is a bit crazy, but it really is +255 not +256 */ |
215 fa1 = clip((-c->a[0]*c->pk[0]*pk0)>>5, -256, 255); | |
2967 | 216 |
2979 | 217 c->a[1] += 128*pk0*c->pk[1] + fa1 - (c->a[1]>>7); |
218 c->a[1] = clip(c->a[1], -12288, 12288); | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
219 c->a[0] += 64*3*pk0*c->pk[0] - (c->a[0] >> 8); |
2979 | 220 c->a[0] = clip(c->a[0], -(15360 - c->a[1]), 15360 - c->a[1]); |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
221 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
222 for (i=0; i<6; i++) |
2979 | 223 c->b[i] += 128*dq0*sgn(-c->dq[i].sign) - (c->b[i]>>8); |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
224 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
225 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
226 /* Update Dq and Sr and Pk */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
227 c->pk[1] = c->pk[0]; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
228 c->pk[0] = pk0 ? pk0 : 1; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
229 c->sr[1] = c->sr[0]; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
230 i2f(re_signal, &c->sr[0]); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
231 for (i=5; i>0; i--) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
232 c->dq[i] = c->dq[i-1]; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
233 i2f(dq, &c->dq[0]); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
234 c->dq[0].sign = I >> (c->tbls->bits - 1); /* Isn't it crazy ?!?! */ |
2967 | 235 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
236 /* Update tone detect [I'm not sure 'tr == 0' is really needed] */ |
2967 | 237 c->td = (tr == 0 && c->a[1] < -11776); |
238 | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
239 /* Update Ap */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
240 c->dms += ((c->tbls->F[I]<<9) - c->dms) >> 5; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
241 c->dml += ((c->tbls->F[I]<<11) - c->dml) >> 7; |
2967 | 242 if (tr) |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
243 c->ap = 256; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
244 else if (c->y > 1535 && !c->td && (abs((c->dms << 2) - c->dml) < (c->dml >> 3))) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
245 c->ap += (-c->ap) >> 4; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
246 else |
2967 | 247 c->ap += (0x200 - c->ap) >> 4; |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
248 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
249 /* Update Yu and Yl */ |
1792 | 250 c->yu = clip(c->y + (((c->tbls->W[I] << 5) - c->y) >> 5), 544, 5120); |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
251 c->yl += c->yu + ((-c->yl)>>6); |
2967 | 252 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
253 /* Next iteration for Y */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
254 al = (c->ap >= 256) ? 1<<6 : c->ap >> 2; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
255 c->y = (c->yl + (c->yu - (c->yl>>6))*al) >> 6; |
2967 | 256 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
257 /* Next iteration for SE and SEZ */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
258 c->se = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
259 for (i=0; i<6; i++) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
260 c->se += mult(i2f(c->b[i] >> 2, &f), &c->dq[i]); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
261 c->sez = c->se >> 1; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
262 for (i=0; i<2; i++) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
263 c->se += mult(i2f(c->a[i] >> 2, &f), &c->sr[i]); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
264 c->se >>= 1; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
265 |
1792 | 266 return clip(re_signal << 2, -0xffff, 0xffff); |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
267 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
268 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
269 static int g726_reset(G726Context* c, int bit_rate) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
270 { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
271 int i; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
272 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
273 c->tbls = &G726Tables_pool[bit_rate/8000 - 2]; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
274 for (i=0; i<2; i++) { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
275 i2f(0, &c->sr[i]); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
276 c->a[i] = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
277 c->pk[i] = 1; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
278 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
279 for (i=0; i<6; i++) { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
280 i2f(0, &c->dq[i]); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
281 c->b[i] = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
282 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
283 c->ap = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
284 c->dms = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
285 c->dml = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
286 c->yu = 544; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
287 c->yl = 34816; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
288 c->td = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
289 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
290 c->se = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
291 c->sez = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
292 c->y = 544; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
293 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
294 return 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
295 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
296 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
297 static int16_t g726_decode(G726Context* c, int16_t i) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
298 { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
299 return g726_iterate(c, i); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
300 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
301 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
302 static int16_t g726_encode(G726Context* c, int16_t sig) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
303 { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
304 uint8_t i; |
2967 | 305 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
306 i = quant(c, sig/4 - c->se) & ((1<<c->tbls->bits) - 1); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
307 g726_iterate(c, i); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
308 return i; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
309 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
310 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
311 /* Interfacing to the libavcodec */ |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
312 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
313 typedef struct AVG726Context { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
314 G726Context c; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
315 int bits_left; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
316 int bit_buffer; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
317 int code_size; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
318 } AVG726Context; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
319 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
320 static int g726_init(AVCodecContext * avctx) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
321 { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
322 AVG726Context* c = (AVG726Context*)avctx->priv_data; |
2967 | 323 |
1792 | 324 if (avctx->channels != 1 || |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
325 (avctx->bit_rate != 16000 && avctx->bit_rate != 24000 && |
2979 | 326 avctx->bit_rate != 32000 && avctx->bit_rate != 40000)) { |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
327 av_log(avctx, AV_LOG_ERROR, "G726: unsupported audio format\n"); |
2979 | 328 return -1; |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
329 } |
2658
d1609cfeb1d0
#defines for strict_std_compliance and split between inofficial extensions and non standarized things
michael
parents:
2398
diff
changeset
|
330 if (avctx->sample_rate != 8000 && avctx->strict_std_compliance>FF_COMPLIANCE_INOFFICIAL) { |
1792 | 331 av_log(avctx, AV_LOG_ERROR, "G726: unsupported audio format\n"); |
2979 | 332 return -1; |
1792 | 333 } |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
334 g726_reset(&c->c, avctx->bit_rate); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
335 c->code_size = c->c.tbls->bits; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
336 c->bit_buffer = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
337 c->bits_left = 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
338 |
1797
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
339 avctx->coded_frame = avcodec_alloc_frame(); |
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
340 if (!avctx->coded_frame) |
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
341 return -ENOMEM; |
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
342 avctx->coded_frame->key_frame = 1; |
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
343 |
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
344 return 0; |
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
345 } |
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
346 |
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
347 static int g726_close(AVCodecContext *avctx) |
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
348 { |
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
349 av_freep(&avctx->coded_frame); |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
350 return 0; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
351 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
352 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
353 static int g726_encode_frame(AVCodecContext *avctx, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
354 uint8_t *dst, int buf_size, void *data) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
355 { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
356 AVG726Context *c = avctx->priv_data; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
357 short *samples = data; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
358 PutBitContext pb; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
359 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
360 init_put_bits(&pb, dst, 1024*1024); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
361 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
362 for (; buf_size; buf_size--) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
363 put_bits(&pb, c->code_size, g726_encode(&c->c, *samples++)); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
364 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
365 flush_put_bits(&pb); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
366 |
2967 | 367 return put_bits_count(&pb)>>3; |
368 } | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
369 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
370 static int g726_decode_frame(AVCodecContext *avctx, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
371 void *data, int *data_size, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
372 uint8_t *buf, int buf_size) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
373 { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
374 AVG726Context *c = avctx->priv_data; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
375 short *samples = data; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
376 uint8_t code; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
377 uint8_t mask; |
2967 | 378 GetBitContext gb; |
379 | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
380 if (!buf_size) |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
381 goto out; |
2967 | 382 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
383 mask = (1<<c->code_size) - 1; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
384 init_get_bits(&gb, buf, buf_size * 8); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
385 if (c->bits_left) { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
386 int s = c->code_size - c->bits_left;; |
2979 | 387 code = (c->bit_buffer << s) | get_bits(&gb, s); |
388 *samples++ = g726_decode(&c->c, code & mask); | |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
389 } |
2967 | 390 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
391 while (get_bits_count(&gb) + c->code_size <= buf_size*8) |
2979 | 392 *samples++ = g726_decode(&c->c, get_bits(&gb, c->code_size) & mask); |
2967 | 393 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
394 c->bits_left = buf_size*8 - get_bits_count(&gb); |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
395 c->bit_buffer = get_bits(&gb, c->bits_left); |
2967 | 396 |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
397 out: |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
398 *data_size = (uint8_t*)samples - (uint8_t*)data; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
399 return buf_size; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
400 } |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
401 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
402 #ifdef CONFIG_ENCODERS |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
403 AVCodec adpcm_g726_encoder = { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
404 "g726", |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
405 CODEC_TYPE_AUDIO, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
406 CODEC_ID_ADPCM_G726, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
407 sizeof(AVG726Context), |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
408 g726_init, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
409 g726_encode_frame, |
1797
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
410 g726_close, |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
411 NULL, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
412 }; |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
413 #endif //CONFIG_ENCODERS |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
414 |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
415 AVCodec adpcm_g726_decoder = { |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
416 "g726", |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
417 CODEC_TYPE_AUDIO, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
418 CODEC_ID_ADPCM_G726, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
419 sizeof(AVG726Context), |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
420 g726_init, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
421 NULL, |
1797
fac680cf3008
* gotta setup coded_frame for encoding. avcodec.h says that for decoding
romansh
parents:
1792
diff
changeset
|
422 g726_close, |
1791
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
423 g726_decode_frame, |
5e5c3d4a1e82
* Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff
changeset
|
424 }; |