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, Adtran Inc. and Linux Support Services, LLC
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())) {
72 static struct ast_frame *lintogsm_sample()
74 static struct ast_frame f;
75 f.frametype = AST_FRAME_VOICE;
76 f.subclass = AST_FORMAT_SLINEAR;
77 f.datalen = sizeof(slin_gsm_ex);
79 f.timelen = sizeof(slin_gsm_ex)/16;
82 f.src = __PRETTY_FUNCTION__;
87 static struct ast_frame *gsmtolin_sample()
89 static struct ast_frame f;
90 f.frametype = AST_FRAME_VOICE;
91 f.subclass = AST_FORMAT_GSM;
92 f.datalen = sizeof(gsm_slin_ex);
93 /* All frames are 30 ms long */
97 f.src = __PRETTY_FUNCTION__;
102 static struct ast_frame *gsmtolin_frameout(struct ast_translator_pvt *tmp)
106 /* Signed linear is no particular frame size, so just send whatever
107 we have in the buffer in one lump sum */
108 tmp->f.frametype = AST_FRAME_VOICE;
109 tmp->f.subclass = AST_FORMAT_SLINEAR;
110 tmp->f.datalen = tmp->tail * 2;
112 tmp->f.timelen = tmp->tail / 8;
114 tmp->f.offset = AST_FRIENDLY_OFFSET;
115 tmp->f.src = __PRETTY_FUNCTION__;
116 tmp->f.data = tmp->buf;
117 /* Reset tail pointer */
121 /* Save a sample frame */
122 { static int samplefr = 0;
123 if (samplefr == 80) {
125 fd = open("gsm.example", O_WRONLY | O_CREAT, 0644);
126 write(fd, tmp->f.data, tmp->f.datalen);
135 static int gsmtolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
137 /* Assuming there's space left, decode into the current buffer at
139 if (tmp->tail + 160 < sizeof(tmp->buf)/2) {
140 if (gsm_decode(tmp->gsm, f->data, tmp->buf + tmp->tail)) {
141 ast_log(LOG_WARNING, "Invalid GSM data\n");
146 ast_log(LOG_WARNING, "Out of buffer space\n");
152 static int lintogsm_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
154 /* Just add the frames to our stream */
155 /* XXX We should look at how old the rest of our stream is, and if it
156 is too old, then we should overwrite it entirely, otherwise we can
157 get artifacts of earlier talk that do not belong */
158 if (tmp->tail + f->datalen < sizeof(tmp->buf) / 2) {
159 memcpy(tmp->buf + tmp->tail, f->data, f->datalen);
160 tmp->tail += f->datalen/2;
162 ast_log(LOG_WARNING, "Out of buffer space\n");
168 static struct ast_frame *lintogsm_frameout(struct ast_translator_pvt *tmp)
170 /* We can't work on anything less than a frame in size */
173 /* Encode a frame of data */
174 gsm_encode(tmp->gsm, tmp->buf, tmp->outbuf);
175 tmp->f.frametype = AST_FRAME_VOICE;
176 tmp->f.subclass = AST_FORMAT_GSM;
178 /* Assume 8000 Hz -- 20 ms */
181 tmp->f.offset = AST_FRIENDLY_OFFSET;
182 tmp->f.src = __PRETTY_FUNCTION__;
183 tmp->f.data = tmp->outbuf;
185 /* Move the data at the end of the buffer to the front */
187 memmove(tmp->buf, tmp->buf + 160 * 2, tmp->tail * 2);
189 /* Save a sample frame */
190 { static int samplefr = 0;
193 fd = open("gsm.example", O_WRONLY | O_CREAT, 0644);
194 write(fd, tmp->f.data, tmp->f.datalen);
203 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);