d654e21e4838cd78b95fe836d68c486c3723ab96
[asterisk/asterisk.git] / codecs / codec_alaw.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief codec_alaw.c - translate between signed linear and alaw
22  * 
23  * \ingroup codecs
24  */
25
26 #include <fcntl.h>
27 #include <netinet/in.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 #include "asterisk.h"
34
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36
37 #include "asterisk/lock.h"
38 #include "asterisk/logger.h"
39 #include "asterisk/module.h"
40 #include "asterisk/config.h"
41 #include "asterisk/options.h"
42 #include "asterisk/translate.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/alaw.h"
45 #include "asterisk/utils.h"
46
47 #define BUFFER_SAMPLES   8096   /* size for the translation buffers */
48
49 /* Sample frame data (Mu data is okay) */
50
51 #include "slin_ulaw_ex.h"
52 #include "ulaw_slin_ex.h"
53
54 /*! \brief decode frame into lin and fill output buffer. */
55 static int alawtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
56 {
57         int i;
58         unsigned char *src = f->data;
59         int16_t *dst = (int16_t *)pvt->outbuf;
60
61         for ( i = 0; i < f->samples; i++)
62                 dst[pvt->samples + i] = AST_ALAW(src[i]);
63         pvt->samples += f->samples;
64         pvt->datalen += 2*f->samples;   /* 2 bytes/sample */
65         return 0;
66 }
67
68 /*! \brief convert and store input samples in output buffer */
69 static int lintoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
70 {
71         int x;
72         char *dst = pvt->outbuf + pvt->samples;
73         int16_t *src = f->data;
74
75         for ( x = 0; x < f->samples; x++) 
76                 *dst++ = AST_LIN2A(src[x]);
77         pvt->samples += f->samples;
78         pvt->datalen += f->samples;     /* 1 byte/sample */
79         return 0;
80 }
81
82 /*! \brief alawToLin_Sample */
83 static struct ast_frame *alawtolin_sample(void)
84 {
85         static struct ast_frame f;
86         f.frametype = AST_FRAME_VOICE;
87         f.subclass = AST_FORMAT_ALAW;
88         f.datalen = sizeof(ulaw_slin_ex);
89         f.samples = sizeof(ulaw_slin_ex);
90         f.mallocd = 0;
91         f.offset = 0;
92         f.src = __PRETTY_FUNCTION__;
93         f.data = ulaw_slin_ex;
94         return &f;
95 }
96
97 /*! \brief LinToalaw_Sample */
98 static struct ast_frame *lintoalaw_sample(void)
99 {
100         static struct ast_frame f;
101         f.frametype = AST_FRAME_VOICE;
102         f.subclass = AST_FORMAT_SLINEAR;
103         f.datalen = sizeof(slin_ulaw_ex);
104         f.samples = sizeof(slin_ulaw_ex) / 2;
105         f.mallocd = 0;
106         f.offset = 0;
107         f.src = __PRETTY_FUNCTION__;
108         f.data = slin_ulaw_ex;
109         return &f;
110 }
111
112 static struct ast_translator alawtolin = {
113         .name = "alawtolin",
114         .srcfmt = AST_FORMAT_ALAW,
115         .dstfmt = AST_FORMAT_SLINEAR,
116         .framein = alawtolin_framein,
117         .sample = alawtolin_sample,
118         .buffer_samples = BUFFER_SAMPLES,
119         .buf_size = BUFFER_SAMPLES * 2,
120         .plc_samples = 160,
121 };
122
123 static struct ast_translator lintoalaw = {
124         "lintoalaw",
125         .srcfmt = AST_FORMAT_SLINEAR,
126         .dstfmt = AST_FORMAT_ALAW,
127         .framein = lintoalaw_framein,
128         .sample = lintoalaw_sample,
129         .buffer_samples = BUFFER_SAMPLES,
130         .buf_size = BUFFER_SAMPLES,
131 };
132
133 static void parse_config(void)
134 {
135         struct ast_variable *var;
136         struct ast_config *cfg = ast_config_load("codecs.conf");
137         if (!cfg)
138                 return;
139         for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
140                 if (!strcasecmp(var->name, "genericplc")) {
141                         alawtolin.useplc = ast_true(var->value) ? 1 : 0;
142                         if (option_verbose > 2)
143                                 ast_verbose(VERBOSE_PREFIX_3 "codec_alaw: %susing generic PLC\n", alawtolin.useplc ? "" : "not ");
144                 }
145         }
146         ast_config_destroy(cfg);
147 }
148
149 /*! \brief standard module stuff */
150
151 static int reload(void *mod)
152 {
153         parse_config();
154         return 0;
155 }
156
157 static int unload_module(void *mod)
158 {
159         int res;
160         res = ast_unregister_translator(&lintoalaw);
161         res |= ast_unregister_translator(&alawtolin);
162         return res;
163 }
164
165 static int load_module(void *mod)
166 {
167         int res;
168         parse_config();
169         res = ast_register_translator(&alawtolin, mod);
170         if (!res)
171                 res = ast_register_translator(&lintoalaw, mod);
172         else
173                 ast_unregister_translator(&alawtolin);
174         return res;
175 }
176
177 static const char *description(void)
178 {
179         return "A-law Coder/Decoder";
180 }
181
182 static const char *key(void)
183 {
184         return ASTERISK_GPL_KEY;
185 }
186
187 STD_MOD(MOD_1, reload, NULL, NULL);