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/2 < 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 the frames */
194 fd2 = open("gsm.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
196 write(fd2, tmp->f.data, tmp->f.datalen);
202 static void gsm_destroy_stuff(struct ast_translator_pvt *pvt)
208 static struct ast_translator gsmtolin =
210 AST_FORMAT_GSM, AST_FORMAT_SLINEAR,
218 static struct ast_translator lintogsm =
220 AST_FORMAT_SLINEAR, AST_FORMAT_GSM,
228 int unload_module(void)
231 pthread_mutex_lock(&localuser_lock);
232 res = ast_unregister_translator(&lintogsm);
234 res = ast_unregister_translator(&gsmtolin);
237 pthread_mutex_unlock(&localuser_lock);
241 int load_module(void)
244 res=ast_register_translator(&gsmtolin);
246 res=ast_register_translator(&lintogsm);
248 ast_unregister_translator(&gsmtolin);
252 char *description(void)
260 STANDARD_USECOUNT(res);