Asterisk - The Open Source Telephony Project GIT-master-a358458
codec_gsm.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * The GSM code is from TOAST. Copyright information for that package is available
5 * in the GSM directory.
6 *
7 * Copyright (C) 1999 - 2005, Digium, Inc.
8 *
9 * Mark Spencer <markster@digium.com>
10 *
11 * See http://www.asterisk.org for more information about
12 * the Asterisk project. Please do not directly contact
13 * any of the maintainers of this project for assistance;
14 * the project provides a web site, mailing lists and IRC
15 * channels for your use.
16 *
17 * This program is free software, distributed under the terms of
18 * the GNU General Public License Version 2. See the LICENSE file
19 * at the top of the source tree.
20 */
21
22/*! \file
23 *
24 * \brief Translate between signed linear and Global System for Mobile Communications (GSM)
25 *
26 * \ingroup codecs
27 */
28
29/*** MODULEINFO
30 <depend>gsm</depend>
31 <support_level>core</support_level>
32 ***/
33
34#include "asterisk.h"
35
36#include "asterisk/translate.h"
37#include "asterisk/config.h"
38#include "asterisk/module.h"
39#include "asterisk/utils.h"
41
42#ifdef HAVE_GSM_HEADER
43#include "gsm.h"
44#elif defined(HAVE_GSM_GSM_HEADER)
45#include <gsm/gsm.h>
46#endif
47
48#include "../formats/msgsm.h"
49
50#define BUFFER_SAMPLES 8000
51#define GSM_SAMPLES 160
52#define GSM_FRAME_LEN 33
53#define MSGSM_FRAME_LEN 65
54
55/* Sample frame data */
56#include "asterisk/slin.h"
57#include "ex_gsm.h"
58
59struct gsm_translator_pvt { /* both gsm2lin and lin2gsm */
61 int16_t buf[BUFFER_SAMPLES]; /* lin2gsm, temporary storage */
62};
63
64static int gsm_new(struct ast_trans_pvt *pvt)
65{
66 struct gsm_translator_pvt *tmp = pvt->pvt;
67
68 return (tmp->gsm = gsm_create()) ? 0 : -1;
69}
70
71/*! \brief decode and store in outbuf. */
72static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
73{
74 struct gsm_translator_pvt *tmp = pvt->pvt;
75 int x;
76 int16_t *dst = pvt->outbuf.i16;
77 /* guess format from frame len. 65 for MSGSM, 33 for regular GSM */
78 int flen = (f->datalen % MSGSM_FRAME_LEN == 0) ?
80
81 for (x=0; x < f->datalen; x += flen) {
82 unsigned char data[2 * GSM_FRAME_LEN];
83 unsigned char *src;
84 int len;
85 if (flen == MSGSM_FRAME_LEN) {
86 len = 2*GSM_SAMPLES;
87 src = data;
88 /* Translate MSGSM format to Real GSM format before feeding in */
89 /* XXX what's the point here! we should just work
90 * on the full format.
91 */
92 conv65(f->data.ptr + x, data);
93 } else {
95 src = f->data.ptr + x;
96 }
97 /* XXX maybe we don't need to check */
98 if (pvt->samples + len > BUFFER_SAMPLES) {
99 ast_log(LOG_WARNING, "Out of buffer space\n");
100 return -1;
101 }
102 if (gsm_decode(tmp->gsm, src, dst + pvt->samples)) {
103 ast_log(LOG_WARNING, "Invalid GSM data (1)\n");
104 return -1;
105 }
106 pvt->samples += GSM_SAMPLES;
107 pvt->datalen += 2 * GSM_SAMPLES;
108 if (flen == MSGSM_FRAME_LEN) {
109 if (gsm_decode(tmp->gsm, data + GSM_FRAME_LEN, dst + pvt->samples)) {
110 ast_log(LOG_WARNING, "Invalid GSM data (2)\n");
111 return -1;
112 }
113 pvt->samples += GSM_SAMPLES;
114 pvt->datalen += 2 * GSM_SAMPLES;
115 }
116 }
117 return 0;
118}
119
120/*! \brief store samples into working buffer for later decode */
121static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
122{
123 struct gsm_translator_pvt *tmp = pvt->pvt;
124
125 /* XXX We should look at how old the rest of our stream is, and if it
126 is too old, then we should overwrite it entirely, otherwise we can
127 get artifacts of earlier talk that do not belong */
128 if (pvt->samples + f->samples > BUFFER_SAMPLES) {
129 ast_log(LOG_WARNING, "Out of buffer space\n");
130 return -1;
131 }
132 memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
133 pvt->samples += f->samples;
134 return 0;
135}
136
137/*! \brief encode and produce a frame */
138static struct ast_frame *lintogsm_frameout(struct ast_trans_pvt *pvt)
139{
140 struct gsm_translator_pvt *tmp = pvt->pvt;
141 struct ast_frame *result = NULL;
142 struct ast_frame *last = NULL;
143 int samples = 0; /* output samples */
144
145 while (pvt->samples >= GSM_SAMPLES) {
146 struct ast_frame *current;
147
148 /* Encode a frame of data */
149 gsm_encode(tmp->gsm, tmp->buf + samples, (gsm_byte *) pvt->outbuf.c);
151 pvt->samples -= GSM_SAMPLES;
152
154 if (!current) {
155 continue;
156 } else if (last) {
158 } else {
159 result = current;
160 }
161 last = current;
162 }
163
164 /* Move the data at the end of the buffer to the front */
165 if (samples) {
166 memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
167 }
168
169 return result;
170}
171
172static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
173{
174 struct gsm_translator_pvt *tmp = pvt->pvt;
175 if (tmp->gsm)
176 gsm_destroy(tmp->gsm);
177}
178
179static struct ast_translator gsmtolin = {
180 .name = "gsmtolin",
181 .src_codec = {
182 .name = "gsm",
183 .type = AST_MEDIA_TYPE_AUDIO,
184 .sample_rate = 8000,
185 },
186 .dst_codec = {
187 .name = "slin",
188 .type = AST_MEDIA_TYPE_AUDIO,
189 .sample_rate = 8000,
190 },
191 .format = "slin",
192 .newpvt = gsm_new,
193 .framein = gsmtolin_framein,
194 .destroy = gsm_destroy_stuff,
195 .sample = gsm_sample,
196 .buffer_samples = BUFFER_SAMPLES,
197 .buf_size = BUFFER_SAMPLES * 2,
198 .desc_size = sizeof (struct gsm_translator_pvt ),
199};
200
201static struct ast_translator lintogsm = {
202 .name = "lintogsm",
203 .src_codec = {
204 .name = "slin",
205 .type = AST_MEDIA_TYPE_AUDIO,
206 .sample_rate = 8000,
207 },
208 .dst_codec = {
209 .name = "gsm",
210 .type = AST_MEDIA_TYPE_AUDIO,
211 .sample_rate = 8000,
212 },
213 .format = "gsm",
214 .newpvt = gsm_new,
215 .framein = lintogsm_framein,
216 .frameout = lintogsm_frameout,
217 .destroy = gsm_destroy_stuff,
218 .sample = slin8_sample,
219 .desc_size = sizeof (struct gsm_translator_pvt ),
221};
222
223static int unload_module(void)
224{
225 int res;
226
229
230 return res;
231}
232
233static int load_module(void)
234{
235 int res;
236
239
240 if (res) {
243 }
244
246}
247
249 .support_level = AST_MODULE_SUPPORT_CORE,
250 .load = load_module,
251 .unload = unload_module,
struct sla_ringing_trunk * last
Definition: app_sla.c:332
Asterisk main include file. File version handling, generic pbx functions.
#define ast_log
Definition: astobj2.c:42
static int tmp()
Definition: bt_open.c:389
static PGresult * result
Definition: cel_pgsql.c:84
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
static int gsm_new(struct ast_trans_pvt *pvt)
Definition: codec_gsm.c:64
#define BUFFER_SAMPLES
Definition: codec_gsm.c:50
static struct ast_translator lintogsm
Definition: codec_gsm.c:201
static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
store samples into working buffer for later decode
Definition: codec_gsm.c:121
#define GSM_SAMPLES
Definition: codec_gsm.c:51
#define MSGSM_FRAME_LEN
Definition: codec_gsm.c:53
static struct ast_translator gsmtolin
Definition: codec_gsm.c:179
static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
decode and store in outbuf.
Definition: codec_gsm.c:72
static int load_module(void)
Definition: codec_gsm.c:233
static int unload_module(void)
Definition: codec_gsm.c:223
#define GSM_FRAME_LEN
Definition: codec_gsm.c:52
static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
Definition: codec_gsm.c:172
static struct ast_frame * lintogsm_frameout(struct ast_trans_pvt *pvt)
encode and produce a frame
Definition: codec_gsm.c:138
short int16_t
Definition: db.h:59
8-bit raw data
static struct ast_frame * gsm_sample(void)
Definition: ex_gsm.h:17
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
unsigned char gsm_byte
Definition: gsm.h:41
Configuration File Parser.
#define LOG_WARNING
A set of macros to manage forward-linked lists.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
size_t current
Definition: main/cli.c:113
Asterisk module definitions.
@ AST_MODFLAG_DEFAULT
Definition: module.h:315
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static void conv65(wav_byte *c, gsm_byte *d)
Definition: msgsm.h:457
#define NULL
Definition: resample.c:96
static struct ast_frame * slin8_sample(void)
Definition: slin.h:64
Data structure associated with a single frame of data.
union ast_frame::@226 data
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
void * pvt
Definition: translate.h:219
int datalen
actual space used in outbuf
Definition: translate.h:218
union ast_trans_pvt::@287 outbuf
int16_t * i16
Definition: translate.h:223
Descriptor of a translator.
Definition: translate.h:137
char name[80]
Definition: translate.h:138
int16_t buf[BUFFER_SAMPLES]
Definition: codec_gsm.c:61
Support for translation of data formats. translate.c.
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:258
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given translator.
Definition: translate.c:1350
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout function
Definition: translate.c:439
Utility functions.