2 * Asterisk -- A telephony toolkit for Linux.
4 * Translate between signed linear and Global System for Mobile Communications (GSM)
6 * The GSM code is from TOAST. Copyright information for that package is available
7 * in the GSM directory.
9 * Copyright (C) 1999, Mark Spencer
11 * Mark Spencer <markster@linux-support.net>
13 * This program is free software, distributed under the terms of
14 * the GNU General Public License
17 #define TYPE_SILENCE 0x2
22 #include <asterisk/translate.h>
23 #include <asterisk/module.h>
24 #include <asterisk/logger.h>
29 #include <netinet/in.h>
33 #include "gsm/inc/gsm.h"
35 /* Sample frame data */
36 #include "slin_gsm_ex.h"
37 #include "gsm_slin_ex.h"
39 static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
40 static int localusecnt=0;
42 static char *tdesc = "GSM/PCM16 (signed linear) Codec Translator";
44 struct ast_translator_pvt {
47 /* Space to build offset */
48 char offset[AST_FRIENDLY_OFFSET];
49 /* Buffer for our outgoing frame */
51 /* Enough to store a full second */
56 #define gsm_coder_pvt ast_translator_pvt
58 static struct ast_translator_pvt *gsm_new()
60 struct gsm_coder_pvt *tmp;
61 tmp = malloc(sizeof(struct gsm_coder_pvt));
63 if (!(tmp->gsm = gsm_create())) {
73 static struct ast_frame *lintogsm_sample()
75 static struct ast_frame f;
76 f.frametype = AST_FRAME_VOICE;
77 f.subclass = AST_FORMAT_SLINEAR;
78 f.datalen = sizeof(slin_gsm_ex);
80 f.timelen = sizeof(slin_gsm_ex)/16;
83 f.src = __PRETTY_FUNCTION__;
88 static struct ast_frame *gsmtolin_sample()
90 static struct ast_frame f;
91 f.frametype = AST_FRAME_VOICE;
92 f.subclass = AST_FORMAT_GSM;
93 f.datalen = sizeof(gsm_slin_ex);
94 /* All frames are 20 ms long */
98 f.src = __PRETTY_FUNCTION__;
103 static struct ast_frame *gsmtolin_frameout(struct ast_translator_pvt *tmp)
107 /* Signed linear is no particular frame size, so just send whatever
108 we have in the buffer in one lump sum */
109 tmp->f.frametype = AST_FRAME_VOICE;
110 tmp->f.subclass = AST_FORMAT_SLINEAR;
111 tmp->f.datalen = tmp->tail * 2;
113 tmp->f.timelen = tmp->tail / 8;
115 tmp->f.offset = AST_FRIENDLY_OFFSET;
116 tmp->f.src = __PRETTY_FUNCTION__;
117 tmp->f.data = tmp->buf;
118 /* Reset tail pointer */
122 /* Save a sample frame */
123 { static int samplefr = 0;
124 if (samplefr == 80) {
126 fd = open("gsm.example", O_WRONLY | O_CREAT, 0644);
127 write(fd, tmp->f.data, tmp->f.datalen);
136 static int gsmtolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
138 /* Assuming there's space left, decode into the current buffer at
140 if (tmp->tail + 160 < sizeof(tmp->buf)/2) {
141 if (gsm_decode(tmp->gsm, f->data, tmp->buf + tmp->tail)) {
142 ast_log(LOG_WARNING, "Invalid GSM data\n");
147 ast_log(LOG_WARNING, "Out of buffer space\n");
153 static int lintogsm_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
155 /* Just add the frames to our stream */
156 /* XXX We should look at how old the rest of our stream is, and if it
157 is too old, then we should overwrite it entirely, otherwise we can
158 get artifacts of earlier talk that do not belong */
159 if (tmp->tail + f->datalen < sizeof(tmp->buf) / 2) {
160 memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
161 tmp->tail += f->datalen/2;
163 ast_log(LOG_WARNING, "Out of buffer space\n");
169 static struct ast_frame *lintogsm_frameout(struct ast_translator_pvt *tmp)
171 /* We can't work on anything less than a frame in size */
174 /* Encode a frame of data */
175 gsm_encode(tmp->gsm, tmp->buf, tmp->outbuf);
176 tmp->f.frametype = AST_FRAME_VOICE;
177 tmp->f.subclass = AST_FORMAT_GSM;
179 /* Assume 8000 Hz -- 20 ms */
182 tmp->f.offset = AST_FRIENDLY_OFFSET;
183 tmp->f.src = __PRETTY_FUNCTION__;
184 tmp->f.data = tmp->outbuf;
186 /* Move the data at the end of the buffer to the front */
188 memmove(tmp->buf, tmp->buf + 160, tmp->tail * 2);
190 /* Save a sample frame */
191 { static int samplefr = 0;
194 fd = open("gsm.example", O_WRONLY | O_CREAT, 0644);
195 write(fd, tmp->f.data, tmp->f.datalen);
204 static void gsm_destroy_stuff(struct ast_translator_pvt *pvt)
210 static struct ast_translator gsmtolin =
212 AST_FORMAT_GSM, AST_FORMAT_SLINEAR,
220 static struct ast_translator lintogsm =
222 AST_FORMAT_SLINEAR, AST_FORMAT_GSM,
230 int unload_module(void)
233 pthread_mutex_lock(&localuser_lock);
234 res = ast_unregister_translator(&lintogsm);
236 res = ast_unregister_translator(&gsmtolin);
239 pthread_mutex_unlock(&localuser_lock);
243 int load_module(void)
246 res=ast_register_translator(&gsmtolin);
248 res=ast_register_translator(&lintogsm);
250 ast_unregister_translator(&gsmtolin);
254 char *description(void)
262 STANDARD_USECOUNT(res);