e262ebd719f531c1cdeedb4dba91760284a899e7
[asterisk/asterisk.git] / codecs / codec_g722.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2008, Digium, Inc.
5  *
6  * Matthew Fredrickson <creslin@digium.com>
7  * Russell Bryant <russell@digium.com>
8  *
9  * Special thanks to Steve Underwood for the implementation
10  * and for doing the 8khz<->g.722 direct translation code.
11  *
12  * See http://www.asterisk.org for more information about
13  * the Asterisk project. Please do not directly contact
14  * any of the maintainers of this project for assistance;
15  * the project provides a web site, mailing lists and IRC
16  * channels for your use.
17  *
18  * This program is free software, distributed under the terms of
19  * the GNU General Public License Version 2. See the LICENSE file
20  * at the top of the source tree.
21  */
22
23 /*! \file
24  *
25  * \brief codec_g722.c - translate between signed linear and ITU G.722-64kbps
26  *
27  * \author Matthew Fredrickson <creslin@digium.com>
28  * \author Russell Bryant <russell@digium.com>
29  *
30  * \arg http://soft-switch.org/downloads/non-gpl-bits.tgz
31  * \arg http://lists.digium.com/pipermail/asterisk-dev/2006-September/022866.html
32  *
33  * \ingroup codecs
34  */
35
36 /*** MODULEINFO
37         <support_level>core</support_level>
38  ***/
39
40 #include "asterisk.h"
41
42 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
43
44 #include "asterisk/linkedlists.h"
45 #include "asterisk/module.h"
46 #include "asterisk/config.h"
47 #include "asterisk/translate.h"
48 #include "asterisk/utils.h"
49
50 #define BUFFER_SAMPLES   8096   /* size for the translation buffers */
51 #define BUF_SHIFT       5
52
53 #include "g722/g722.h"
54
55 /* Sample frame data */
56 #include "asterisk/slin.h"
57 #include "ex_g722.h"
58
59 struct g722_encoder_pvt {
60         g722_encode_state_t g722;
61 };
62
63 struct g722_decoder_pvt {
64         g722_decode_state_t g722;
65 };
66
67 /*! \brief init a new instance of g722_encoder_pvt. */
68 static int lintog722_new(struct ast_trans_pvt *pvt)
69 {
70         struct g722_encoder_pvt *tmp = pvt->pvt;
71
72         g722_encode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
73
74         return 0;
75 }
76
77 static int lin16tog722_new(struct ast_trans_pvt *pvt)
78 {
79         struct g722_encoder_pvt *tmp = pvt->pvt;
80
81         g722_encode_init(&tmp->g722, 64000, 0);
82
83         return 0;
84 }
85
86 /*! \brief init a new instance of g722_encoder_pvt. */
87 static int g722tolin_new(struct ast_trans_pvt *pvt)
88 {
89         struct g722_decoder_pvt *tmp = pvt->pvt;
90
91         g722_decode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
92
93         return 0;
94 }
95
96 static int g722tolin16_new(struct ast_trans_pvt *pvt)
97 {
98         struct g722_decoder_pvt *tmp = pvt->pvt;
99
100         g722_decode_init(&tmp->g722, 64000, 0);
101
102         return 0;
103 }
104
105 static int g722tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
106 {
107         struct g722_decoder_pvt *tmp = pvt->pvt;
108         int out_samples;
109         int in_samples;
110
111         /* g722_decode expects the samples to be in the invalid samples / 2 format */
112         in_samples = f->samples / 2;
113
114         out_samples = g722_decode(&tmp->g722, &pvt->outbuf.i16[pvt->samples * sizeof(int16_t)], 
115                 (uint8_t *) f->data.ptr, in_samples);
116
117         pvt->samples += out_samples;
118
119         pvt->datalen += (out_samples * sizeof(int16_t));
120
121         return 0;
122 }
123
124 static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
125 {
126         struct g722_encoder_pvt *tmp = pvt->pvt;
127         int outlen;
128
129         outlen = g722_encode(&tmp->g722, (&pvt->outbuf.ui8[pvt->datalen]), 
130                 (int16_t *) f->data.ptr, f->samples);
131
132         pvt->samples += outlen * 2;
133
134         pvt->datalen += outlen;
135
136         return 0;
137 }
138
139 static struct ast_translator g722tolin = {
140         .name = "g722tolin",
141         .src_codec = {
142                 .name = "g722",
143                 .type = AST_MEDIA_TYPE_AUDIO,
144                 .sample_rate = 16000,
145         },
146         .dst_codec = {
147                 .name = "slin",
148                 .type = AST_MEDIA_TYPE_AUDIO,
149                 .sample_rate = 8000,
150         },
151         .format = "slin",
152         .newpvt = g722tolin_new,        /* same for both directions */
153         .framein = g722tolin_framein,
154         .sample = g722_sample,
155         .desc_size = sizeof(struct g722_decoder_pvt),
156         .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t),
157         .buf_size = BUFFER_SAMPLES,
158 };
159
160 static struct ast_translator lintog722 = {
161         .name = "lintog722",
162         .src_codec = {
163                 .name = "slin",
164                 .type = AST_MEDIA_TYPE_AUDIO,
165                 .sample_rate = 8000,
166         },
167         .dst_codec = {
168                 .name = "g722",
169                 .type = AST_MEDIA_TYPE_AUDIO,
170                 .sample_rate = 16000,
171         },
172         .format = "g722",
173         .newpvt = lintog722_new,        /* same for both directions */
174         .framein = lintog722_framein,
175         .sample = slin8_sample,
176         .desc_size = sizeof(struct g722_encoder_pvt),
177         .buffer_samples = BUFFER_SAMPLES * 2,
178         .buf_size = BUFFER_SAMPLES,
179 };
180
181 static struct ast_translator g722tolin16 = {
182         .name = "g722tolin16",
183         .src_codec = {
184                 .name = "g722",
185                 .type = AST_MEDIA_TYPE_AUDIO,
186                 .sample_rate = 16000,
187         },
188         .dst_codec = {
189                 .name = "slin",
190                 .type = AST_MEDIA_TYPE_AUDIO,
191                 .sample_rate = 16000,
192         },
193         .format = "slin16",
194         .newpvt = g722tolin16_new,      /* same for both directions */
195         .framein = g722tolin_framein,
196         .sample = g722_sample,
197         .desc_size = sizeof(struct g722_decoder_pvt),
198         .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t),
199         .buf_size = BUFFER_SAMPLES,
200 };
201
202 static struct ast_translator lin16tog722 = {
203         .name = "lin16tog722",
204         .src_codec = {
205                 .name = "slin",
206                 .type = AST_MEDIA_TYPE_AUDIO,
207                 .sample_rate = 16000,
208         },
209         .dst_codec = {
210                 .name = "g722",
211                 .type = AST_MEDIA_TYPE_AUDIO,
212                 .sample_rate = 16000,
213         },
214         .format = "g722",
215         .newpvt = lin16tog722_new,      /* same for both directions */
216         .framein = lintog722_framein,
217         .sample = slin16_sample,
218         .desc_size = sizeof(struct g722_encoder_pvt),
219         .buffer_samples = BUFFER_SAMPLES * 2,
220         .buf_size = BUFFER_SAMPLES,
221 };
222
223 static int unload_module(void)
224 {
225         int res = 0;
226
227         res |= ast_unregister_translator(&g722tolin);
228         res |= ast_unregister_translator(&lintog722);
229         res |= ast_unregister_translator(&g722tolin16);
230         res |= ast_unregister_translator(&lin16tog722);
231
232         return res;
233 }
234
235 static int load_module(void)
236 {
237         int res = 0;
238
239         res |= ast_register_translator(&g722tolin);
240         res |= ast_register_translator(&lintog722);
241         res |= ast_register_translator(&g722tolin16);
242         res |= ast_register_translator(&lin16tog722);
243
244         if (res) {
245                 unload_module();
246                 return AST_MODULE_LOAD_FAILURE;
247         }       
248
249         return AST_MODULE_LOAD_SUCCESS;
250 }
251
252 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder",
253                 .support_level = AST_MODULE_SUPPORT_CORE,
254                 .load = load_module,
255                 .unload = unload_module,
256                );