annotate g726.c @ 1795:920e6381e1fe libavcodec

2 byte shorter userdata for mpeg4 in the past it was startcode,string,00,7F,startcode now it is startcode,string,stratcode both are mpeg4 compliant, as according to the standard the userdata lasts until the next 00 00 01 (startcode prefix) but some very primitive decoders which simply skip until the first 00 byte and then expect the next valid startcode might fail with the old variant, just a theory though (didnt test if quicktime can decode it now)
author michael
date Sun, 08 Feb 2004 22:52:35 +0000
parents 7da4bdafe42e
children fac680cf3008
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1791
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
1 /*
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
2 * G.726 ADPCM audio codec
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
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
6 * Section 4 "Computational Details".
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
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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"
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
25
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
26 /*
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
27 * G.726 Standard uses rather odd 11bit floating point arithmentic for
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
28 * 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
29 * instead of simply using 32bit integer arithmetic.
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
30 */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
31 typedef struct Float11 {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
32 int sign; /* 1bit sign */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
33 int exp; /* 4bit exponent */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
34 int mant; /* 6bit mantissa */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
35 } Float11;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
36
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
37 static inline Float11* i2f(int16_t i, Float11* f)
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 f->sign = (i < 0);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
40 if (f->sign)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
41 i = -i;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
42 f->exp = av_log2_16bit(i) + !!i;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
43 f->mant = i? (i<<6) >> f->exp :
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
44 1<<5;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
45 return f;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
46 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
47
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
48 static inline int16_t mult(Float11* f1, Float11* f2)
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 int res, exp;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
51
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
52 exp = f1->exp + f2->exp;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
53 res = (((f1->mant * f2->mant) + 0x30) >> 4) << 7;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
54 res = exp > 26 ? res << (exp - 26) : res >> (26 - exp);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
55 return (f1->sign ^ f2->sign) ? -res : res;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
56 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
57
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
58 static inline int sgn(int value)
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 return (value < 0) ? -1 : 1;
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
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
63 typedef struct G726Tables {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
64 int bits; /* bits per sample */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
65 int* quant; /* quantization table */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
66 int* iquant; /* inverse quantization table */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
67 int* W; /* special table #1 ;-) */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
68 int* F; /* special table #2 */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
69 } G726Tables;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
70
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
71 typedef struct G726Context {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
72 G726Tables* tbls; /* static tables needed for computation */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
73
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
74 Float11 sr[2]; /* prev. reconstructed samples */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
75 Float11 dq[6]; /* prev. difference */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
76 int a[2]; /* second order predictor coeffs */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
77 int b[6]; /* sixth order predictor coeffs */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
78 int pk[2]; /* signs of prev. 2 sez + dq */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
79
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
80 int ap; /* scale factor control */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
81 int yu; /* fast scale factor */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
82 int yl; /* slow scale factor */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
83 int dms; /* short average magnitude of F[i] */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
84 int dml; /* long average magnitude of F[i] */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
85 int td; /* tone detect */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
86
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
87 int se; /* estimated signal for the next iteration */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
88 int sez; /* estimated second order prediction */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
89 int y; /* quantizer scaling factor for the next iteration */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
90 } G726Context;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
91
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
92 static int quant_tbl16[] = /* 16kbit/s 2bits per sample */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
93 { 260, INT_MAX };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
94 static int iquant_tbl16[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
95 { 116, 365, 365, 116 };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
96 static int W_tbl16[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
97 { -22, 439, 439, -22 };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
98 static int F_tbl16[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
99 { 0, 7, 7, 0 };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
100
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
101 static int quant_tbl24[] = /* 24kbit/s 3bits per sample */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
102 { 7, 217, 330, INT_MAX };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
103 static int iquant_tbl24[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
104 { INT_MIN, 135, 273, 373, 373, 273, 135, INT_MIN };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
105 static int W_tbl24[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
106 { -4, 30, 137, 582, 582, 137, 30, -4 };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
107 static int F_tbl24[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
108 { 0, 1, 2, 7, 7, 2, 1, 0 };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
109
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
110 static int quant_tbl32[] = /* 32kbit/s 4bits per sample */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
111 { -125, 79, 177, 245, 299, 348, 399, INT_MAX };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
112 static int iquant_tbl32[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
113 { INT_MIN, 4, 135, 213, 273, 323, 373, 425,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
114 425, 373, 323, 273, 213, 135, 4, INT_MIN };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
115 static int W_tbl32[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
116 { -12, 18, 41, 64, 112, 198, 355, 1122,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
117 1122, 355, 198, 112, 64, 41, 18, -12};
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
118 static int F_tbl32[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
119 { 0, 0, 0, 1, 1, 1, 3, 7, 7, 3, 1, 1, 1, 0, 0, 0 };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
120
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
121 static int quant_tbl40[] = /* 40kbit/s 5bits per sample */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
122 { -122, -16, 67, 138, 197, 249, 297, 338,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
123 377, 412, 444, 474, 501, 527, 552, INT_MAX };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
124 static int iquant_tbl40[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
125 { INT_MIN, -66, 28, 104, 169, 224, 274, 318,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
126 358, 395, 429, 459, 488, 514, 539, 566,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
127 566, 539, 514, 488, 459, 429, 395, 358,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
128 318, 274, 224, 169, 104, 28, -66, INT_MIN };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
129 static int W_tbl40[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
130 { 14, 14, 24, 39, 40, 41, 58, 100,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
131 141, 179, 219, 280, 358, 440, 529, 696,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
132 696, 529, 440, 358, 280, 219, 179, 141,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
133 100, 58, 41, 40, 39, 24, 14, 14 };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
134 static int F_tbl40[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
135 { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 6,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
136 6, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
137
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
138 static G726Tables G726Tables_pool[] =
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
139 {{ 2, quant_tbl16, iquant_tbl16, W_tbl16, F_tbl16 },
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
140 { 3, quant_tbl24, iquant_tbl24, W_tbl24, F_tbl24 },
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
141 { 4, quant_tbl32, iquant_tbl32, W_tbl32, F_tbl32 },
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
142 { 5, quant_tbl40, iquant_tbl40, W_tbl40, F_tbl40 }};
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
143
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
144
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
145 /*
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
146 * Para 4.2.2 page 18: Adaptive quantizer.
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
147 */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
148 static inline uint8_t quant(G726Context* c, int d)
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 int sign, exp, i, dln;
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 sign = i = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
153 if (d < 0) {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
154 sign = 1;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
155 d = -d;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
156 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
157 exp = av_log2_16bit(d);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
158 dln = ((exp<<7) + (((d<<7)>>exp)&0x7f)) - (c->y>>2);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
159
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
160 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
161 ++i;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
162
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
163 if (sign)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
164 i = ~i;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
165 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
166 i = 0xff;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
167
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
168 return i;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
169 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
170
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 * Para 4.2.3 page 22: Inverse adaptive quantizer.
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
173 */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
174 static inline int16_t inverse_quant(G726Context* c, int i)
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 int dql, dex, dqt;
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 dql = c->tbls->iquant[i] + (c->y >> 2);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
179 dex = (dql>>7) & 0xf; /* 4bit exponent */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
180 dqt = (1<<7) + (dql & 0x7f); /* log2 -> linear */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
181 return (dql < 0) ? 0 : ((dqt<<7) >> (14-dex));
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
182 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
183
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
184 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
185 {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
186 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
187 Float11 f;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
188
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
189 dq = inverse_quant(c, I);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
190 if (I >> (c->tbls->bits - 1)) /* get the sign */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
191 dq = -dq;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
192 re_signal = c->se + dq;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
193
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
194 /* Transition detect */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
195 ylint = (c->yl >> 15);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
196 ylfrac = (c->yl >> 10) & 0x1f;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
197 thr2 = (ylint > 9) ? 0x1f << 10 : (0x20 + ylfrac) << ylint;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
198 if (c->td == 1 && abs(dq) > ((thr2+(thr2>>1))>>1))
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
199 tr = 1;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
200 else
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
201 tr = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
202
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
203 /* Update second order predictor coefficient A2 and A1 */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
204 pk0 = (c->sez + dq) ? sgn(c->sez + dq) : 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
205 dq0 = dq ? sgn(dq) : 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
206 if (tr) {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
207 c->a[0] = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
208 c->a[1] = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
209 for (i=0; i<6; i++)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
210 c->b[i] = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
211 } else {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
212 /* This is a bit crazy, but it really is +255 not +256 */
1792
7da4bdafe42e use clip() from common.h
michael
parents: 1791
diff changeset
213 fa1 = clip((-c->a[0]*c->pk[0]*pk0)>>5, -256, 255);
1791
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
214
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
215 c->a[1] += 128*pk0*c->pk[1] + fa1 - (c->a[1]>>7);
1792
7da4bdafe42e use clip() from common.h
michael
parents: 1791
diff changeset
216 c->a[1] = clip(c->a[1], -12288, 12288);
1791
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
217 c->a[0] += 64*3*pk0*c->pk[0] - (c->a[0] >> 8);
1792
7da4bdafe42e use clip() from common.h
michael
parents: 1791
diff changeset
218 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
219
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
220 for (i=0; i<6; i++)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
221 c->b[i] += 128*dq0*sgn(-c->dq[i].sign) - (c->b[i]>>8);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
222 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
223
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
224 /* Update Dq and Sr and Pk */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
225 c->pk[1] = c->pk[0];
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
226 c->pk[0] = pk0 ? pk0 : 1;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
227 c->sr[1] = c->sr[0];
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
228 i2f(re_signal, &c->sr[0]);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
229 for (i=5; i>0; i--)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
230 c->dq[i] = c->dq[i-1];
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
231 i2f(dq, &c->dq[0]);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
232 c->dq[0].sign = I >> (c->tbls->bits - 1); /* Isn't it crazy ?!?! */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
233
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
234 /* Update tone detect [I'm not sure 'tr == 0' is really needed] */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
235 c->td = (tr == 0 && c->a[1] < -11776);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
236
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
237 /* Update Ap */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
238 c->dms += ((c->tbls->F[I]<<9) - c->dms) >> 5;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
239 c->dml += ((c->tbls->F[I]<<11) - c->dml) >> 7;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
240 if (tr)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
241 c->ap = 256;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
242 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
243 c->ap += (-c->ap) >> 4;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
244 else
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
245 c->ap += (0x200 - c->ap) >> 4;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
246
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
247 /* Update Yu and Yl */
1792
7da4bdafe42e use clip() from common.h
michael
parents: 1791
diff changeset
248 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
249 c->yl += c->yu + ((-c->yl)>>6);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
250
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
251 /* Next iteration for Y */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
252 al = (c->ap >= 256) ? 1<<6 : c->ap >> 2;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
253 c->y = (c->yl + (c->yu - (c->yl>>6))*al) >> 6;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
254
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
255 /* Next iteration for SE and SEZ */
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
256 c->se = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
257 for (i=0; i<6; i++)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
258 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
259 c->sez = c->se >> 1;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
260 for (i=0; i<2; i++)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
261 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
262 c->se >>= 1;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
263
1792
7da4bdafe42e use clip() from common.h
michael
parents: 1791
diff changeset
264 return clip(re_signal << 2, -0xffff, 0xffff);
1791
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
265 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
266
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
267 static int g726_reset(G726Context* c, int bit_rate)
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 int i;
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 c->tbls = &G726Tables_pool[bit_rate/8000 - 2];
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
272 for (i=0; i<2; i++) {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
273 i2f(0, &c->sr[i]);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
274 c->a[i] = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
275 c->pk[i] = 1;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
276 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
277 for (i=0; i<6; i++) {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
278 i2f(0, &c->dq[i]);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
279 c->b[i] = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
280 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
281 c->ap = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
282 c->dms = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
283 c->dml = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
284 c->yu = 544;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
285 c->yl = 34816;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
286 c->td = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
287
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
288 c->se = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
289 c->sez = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
290 c->y = 544;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
291
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
292 return 0;
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
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
295 static int16_t g726_decode(G726Context* c, int16_t i)
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 return g726_iterate(c, 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
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
300 static int16_t g726_encode(G726Context* c, int16_t sig)
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 uint8_t i;
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 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
305 g726_iterate(c, i);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
306 return i;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
307 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
308
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
309 /* Interfacing to the libavcodec */
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 typedef struct AVG726Context {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
312 G726Context c;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
313 int bits_left;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
314 int bit_buffer;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
315 int code_size;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
316 } AVG726Context;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
317
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
318 static int g726_init(AVCodecContext * avctx)
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 AVG726Context* c = (AVG726Context*)avctx->priv_data;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
321
1792
7da4bdafe42e use clip() from common.h
michael
parents: 1791
diff changeset
322 if (avctx->channels != 1 ||
1791
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
323 (avctx->bit_rate != 16000 && avctx->bit_rate != 24000 &&
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
324 avctx->bit_rate != 32000 && avctx->bit_rate != 40000)) {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
325 av_log(avctx, AV_LOG_ERROR, "G726: unsupported audio format\n");
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
326 return -1;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
327 }
1792
7da4bdafe42e use clip() from common.h
michael
parents: 1791
diff changeset
328 if (avctx->sample_rate != 8000 && avctx->strict_std_compliance>=0) {
7da4bdafe42e use clip() from common.h
michael
parents: 1791
diff changeset
329 av_log(avctx, AV_LOG_ERROR, "G726: unsupported audio format\n");
7da4bdafe42e use clip() from common.h
michael
parents: 1791
diff changeset
330 return -1;
7da4bdafe42e use clip() from common.h
michael
parents: 1791
diff changeset
331 }
1791
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
332 g726_reset(&c->c, avctx->bit_rate);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
333 c->code_size = c->c.tbls->bits;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
334 c->bit_buffer = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
335 c->bits_left = 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
336
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
337 return 0;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
338 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
339
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
340 static int g726_encode_frame(AVCodecContext *avctx,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
341 uint8_t *dst, int buf_size, void *data)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
342 {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
343 AVG726Context *c = avctx->priv_data;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
344 short *samples = data;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
345 PutBitContext pb;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
346
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
347 init_put_bits(&pb, dst, 1024*1024);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
348
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
349 for (; buf_size; buf_size--)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
350 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
351
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
352 flush_put_bits(&pb);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
353
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
354 return put_bits_count(&pb)>>3;
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
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
357 static int g726_decode_frame(AVCodecContext *avctx,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
358 void *data, int *data_size,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
359 uint8_t *buf, int buf_size)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
360 {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
361 AVG726Context *c = avctx->priv_data;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
362 short *samples = data;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
363 uint8_t code;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
364 uint8_t mask;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
365 GetBitContext gb;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
366
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
367 if (!buf_size)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
368 goto out;
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 mask = (1<<c->code_size) - 1;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
371 init_get_bits(&gb, buf, buf_size * 8);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
372 if (c->bits_left) {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
373 int s = c->code_size - c->bits_left;;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
374 code = (c->bit_buffer << s) | get_bits(&gb, s);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
375 *samples++ = g726_decode(&c->c, code & mask);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
376 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
377
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
378 while (get_bits_count(&gb) + c->code_size <= buf_size*8)
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
379 *samples++ = g726_decode(&c->c, get_bits(&gb, c->code_size) & mask);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
380
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
381 c->bits_left = buf_size*8 - get_bits_count(&gb);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
382 c->bit_buffer = get_bits(&gb, c->bits_left);
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
383
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
384 out:
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
385 *data_size = (uint8_t*)samples - (uint8_t*)data;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
386 return buf_size;
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
387 }
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
388
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
389 #ifdef CONFIG_ENCODERS
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
390 AVCodec adpcm_g726_encoder = {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
391 "g726",
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
392 CODEC_TYPE_AUDIO,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
393 CODEC_ID_ADPCM_G726,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
394 sizeof(AVG726Context),
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
395 g726_init,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
396 g726_encode_frame,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
397 NULL,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
398 NULL,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
399 };
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
400 #endif //CONFIG_ENCODERS
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 AVCodec adpcm_g726_decoder = {
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
403 "g726",
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
404 CODEC_TYPE_AUDIO,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
405 CODEC_ID_ADPCM_G726,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
406 sizeof(AVG726Context),
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
407 g726_init,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
408 NULL,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
409 NULL,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
410 g726_decode_frame,
5e5c3d4a1e82 * Initial implementation of the G.726 ADPCM audio codec.
romansh
parents:
diff changeset
411 };