Asterisk - The Open Source Telephony Project  GIT-master-0190e70
codec_lpc10.c
Go to the documentation of this file.
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  * The lpc10 code is from a library used by nautilus, modified to be a bit
9  * nicer to the compiler.
10  * See http://www.arl.wustl.edu/~jaf/
11  *
12  * See http://www.asterisk.org for more information about
13  * the Asterisk project. Please do not directly contact
14  * any of the maintainers of this project for assistance;
15  * the project provides a web site, mailing lists and IRC
16  * channels for your use.
17  *
18  * This program is free software, distributed under the terms of
19  * the GNU General Public License Version 2. See the LICENSE file
20  * at the top of the source tree.
21  */
22 
23 /*! \file
24  *
25  * \brief Translate between signed linear and LPC10 (Linear Predictor Code)
26  *
27  * \ingroup codecs
28  */
29 
30 /*** MODULEINFO
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"
40 #include "asterisk/linkedlists.h"
41 
42 #include "lpc10/lpc10.h"
43 
44 /* Sample frame data */
45 #include "asterisk/slin.h"
46 #include "ex_lpc10.h"
47 
48 /* We use a very strange format here... I have no idea why... The frames are 180
49  samples long, which isn't even an even number of milliseconds... Not only that
50  but we hvae to waste two bits of each frame to keep them ending on a byte boundary
51  because the frames are 54 bits long */
52 
53 #define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
54 
55 #define BUFFER_SAMPLES 8000
56 
58  union {
61  } lpc10;
62  /* Enough to store a full second */
64  int longer;
65 };
66 
67 static int lpc10_enc_new(struct ast_trans_pvt *pvt)
68 {
69  struct lpc10_coder_pvt *tmp = pvt->pvt;
70 
71  return (tmp->lpc10.enc = create_lpc10_encoder_state()) ? 0 : -1;
72 }
73 
74 static int lpc10_dec_new(struct ast_trans_pvt *pvt)
75 {
76  struct lpc10_coder_pvt *tmp = pvt->pvt;
77 
78  return (tmp->lpc10.dec = create_lpc10_decoder_state()) ? 0 : -1;
79 }
80 
81 static void extract_bits(INT32 *bits, unsigned char *c)
82 {
83  int x;
84  for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
85  if (*c & (0x80 >> (x & 7)))
86  bits[x] = 1;
87  else
88  bits[x] = 0;
89  if ((x & 7) == 7)
90  c++;
91  }
92 }
93 
94 /* XXX note lpc10_encode() produces one bit per word in bits[] */
95 static void build_bits(unsigned char *c, INT32 *bits)
96 {
97  unsigned char mask=0x80;
98  int x;
99  *c = 0;
100  for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
101  if (bits[x])
102  *c |= mask;
103  mask = mask >> 1;
104  if ((x % 8)==7) {
105  c++;
106  *c = 0;
107  mask = 0x80;
108  }
109  }
110 }
111 
112 static int lpc10tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
113 {
114  struct lpc10_coder_pvt *tmp = pvt->pvt;
115  int16_t *dst = pvt->outbuf.i16;
116  int len = 0;
117 
118  while (len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
119  int x;
120  float tmpbuf[LPC10_SAMPLES_PER_FRAME];
121  INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; /* XXX see note */
123  ast_log(LOG_WARNING, "Out of buffer space\n");
124  return -1;
125  }
126  extract_bits(bits, f->data.ptr + len);
127  if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
128  ast_log(LOG_WARNING, "Invalid lpc10 data\n");
129  return -1;
130  }
131  for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
132  /* Convert to a short between -1.0 and 1.0 */
133  dst[pvt->samples + x] = (int16_t)(32768.0 * tmpbuf[x]);
134  }
135 
139  }
140  if (len != f->datalen)
141  printf("Decoded %d, expected %d\n", len, f->datalen);
142  return 0;
143 }
144 
145 static int lintolpc10_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
146 {
147  struct lpc10_coder_pvt *tmp = pvt->pvt;
148 
149  /* Just add the frames to our stream */
150  if (pvt->samples + f->samples > BUFFER_SAMPLES) {
151  ast_log(LOG_WARNING, "Out of buffer space\n");
152  return -1;
153  }
154  memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
155  pvt->samples += f->samples;
156  return 0;
157 }
158 
159 static struct ast_frame *lintolpc10_frameout(struct ast_trans_pvt *pvt)
160 {
161  struct lpc10_coder_pvt *tmp = pvt->pvt;
162  struct ast_frame *result = NULL;
163  struct ast_frame *last = NULL;
164  int samples = 0; /* output samples */
165 
166  while (pvt->samples >= LPC10_SAMPLES_PER_FRAME) {
167  struct ast_frame *current;
168  float tmpbuf[LPC10_SAMPLES_PER_FRAME];
169  INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; /* XXX what ??? */
170  int x;
171 
172  /* Encode a frame of data */
173  for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++)
174  tmpbuf[x] = (float)tmp->buf[x + samples] / 32768.0;
175  lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
176  build_bits(pvt->outbuf.uc, bits);
177 
178  samples += LPC10_SAMPLES_PER_FRAME;
180  /* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
181  important for IAX use */
182  tmp->longer = 1 - tmp->longer;
183 
184  current = ast_trans_frameout(pvt, LPC10_BYTES_IN_COMPRESSED_FRAME, LPC10_SAMPLES_PER_FRAME);
185  if (!current) {
186  continue;
187  } else if (last) {
188  AST_LIST_NEXT(last, frame_list) = current;
189  } else {
190  result = current;
191  }
192  last = current;
193  }
194 
195  /* Move the data at the end of the buffer to the front */
196  if (samples) {
197  memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
198  }
199 
200  return result;
201 }
202 
203 
204 static void lpc10_destroy(struct ast_trans_pvt *arg)
205 {
206  struct lpc10_coder_pvt *pvt = arg->pvt;
207  /* Enc and DEC are both just allocated, so they can be freed */
208  ast_free(pvt->lpc10.enc);
209 }
210 
211 static struct ast_translator lpc10tolin = {
212  .name = "lpc10tolin",
213  .src_codec = {
214  .name = "lpc10",
215  .type = AST_MEDIA_TYPE_AUDIO,
216  .sample_rate = 8000,
217  },
218  .dst_codec = {
219  .name = "slin",
220  .type = AST_MEDIA_TYPE_AUDIO,
221  .sample_rate = 8000,
222  },
223  .format = "slin",
224  .newpvt = lpc10_dec_new,
225  .framein = lpc10tolin_framein,
226  .destroy = lpc10_destroy,
227  .sample = lpc10_sample,
228  .desc_size = sizeof(struct lpc10_coder_pvt),
229  .buffer_samples = BUFFER_SAMPLES,
230  .buf_size = BUFFER_SAMPLES * 2,
231 };
232 
233 static struct ast_translator lintolpc10 = {
234  .name = "lintolpc10",
235  .src_codec = {
236  .name = "slin",
237  .type = AST_MEDIA_TYPE_AUDIO,
238  .sample_rate = 8000,
239  },
240  .dst_codec = {
241  .name = "lpc10",
242  .type = AST_MEDIA_TYPE_AUDIO,
243  .sample_rate = 8000,
244  },
245  .format = "lpc10",
246  .newpvt = lpc10_enc_new,
247  .framein = lintolpc10_framein,
248  .frameout = lintolpc10_frameout,
249  .destroy = lpc10_destroy,
250  .sample = slin8_sample,
251  .desc_size = sizeof(struct lpc10_coder_pvt),
252  .buffer_samples = BUFFER_SAMPLES,
254 };
255 
256 static int unload_module(void)
257 {
258  int res;
259 
260  res = ast_unregister_translator(&lintolpc10);
261  res |= ast_unregister_translator(&lpc10tolin);
262 
263  return res;
264 }
265 
266 static int load_module(void)
267 {
268  int res;
269 
270  res = ast_register_translator(&lpc10tolin);
271  res |= ast_register_translator(&lintolpc10);
272 
273  if (res) {
274  unload_module();
276  }
277 
279 }
280 
281 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "LPC10 2.4kbps Coder/Decoder",
282  .support_level = AST_MODULE_SUPPORT_CORE,
283  .load = load_module,
284  .unload = unload_module,
285 );
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout function
Definition: translate.c:432
int datalen
actual space used in outbuf
Definition: translate.h:218
#define LPC10_BYTES_IN_COMPRESSED_FRAME
Definition: codec_lpc10.c:53
Asterisk main include file. File version handling, generic pbx functions.
static int lpc10tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
Definition: codec_lpc10.c:112
Descriptor of a translator.
Definition: translate.h:137
short int16_t
Definition: db.h:59
union ast_trans_pvt::@321 outbuf
Support for translation of data formats. translate.c.
union lpc10_coder_pvt::@180 lpc10
int lpc10_encode(real *speech, INT32 *bits, struct lpc10_encoder_state *st)
Definition: lpcenc.c:108
#define LOG_WARNING
Definition: logger.h:274
union ast_frame::@257 data
static int lpc10_enc_new(struct ast_trans_pvt *pvt)
Definition: codec_lpc10.c:67
static int tmp()
Definition: bt_open.c:389
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
static struct ast_translator lpc10tolin
Definition: codec_lpc10.c:211
#define LPC10_BITS_IN_COMPRESSED_FRAME
Definition: lpc10.h:37
unsigned char * uc
Definition: translate.h:222
static struct test_val c
static struct ast_frame * slin8_sample(void)
Definition: slin.h:64
static int lintolpc10_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
Definition: codec_lpc10.c:145
#define NULL
Definition: resample.c:96
void * pvt
Definition: translate.h:219
#define LPC10_SAMPLES_PER_FRAME
Definition: lpc10.h:36
int16_t * i16
Definition: translate.h:223
Utility functions.
struct lpc10_decoder_state * create_lpc10_decoder_state(void)
Definition: lpcini.c:369
Configuration File Parser.
short buf[BUFFER_SAMPLES]
Definition: codec_lpc10.c:63
#define ast_log
Definition: astobj2.c:42
static struct ast_translator lintolpc10
Definition: codec_lpc10.c:233
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:257
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given tranlator.
Definition: translate.c:1327
struct lpc10_encoder_state * enc
Definition: codec_lpc10.c:59
static struct ast_frame * lintolpc10_frameout(struct ast_trans_pvt *pvt)
Definition: codec_lpc10.c:159
A set of macros to manage forward-linked lists.
static void lpc10_destroy(struct ast_trans_pvt *arg)
Definition: codec_lpc10.c:204
int lpc10_decode(INT32 *bits, real *speech, struct lpc10_decoder_state *st)
Definition: lpcdec.c:113
static void extract_bits(INT32 *bits, unsigned char *c)
Definition: codec_lpc10.c:81
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static struct ast_frame * lpc10_sample(void)
Definition: ex_lpc10.h:14
#define ast_free(a)
Definition: astmm.h:182
static int lpc10_dec_new(struct ast_trans_pvt *pvt)
Definition: codec_lpc10.c:74
struct lpc10_encoder_state * create_lpc10_encoder_state(void)
Definition: lpcini.c:258
Copyright (C) 2008, Digium, Inc.
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int unload_module(void)
Definition: codec_lpc10.c:256
static void build_bits(unsigned char *c, INT32 *bits)
Definition: codec_lpc10.c:95
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
#define BUFFER_SAMPLES
Definition: codec_lpc10.c:55
static PGresult * result
Definition: cel_pgsql.c:88
Data structure associated with a single frame of data.
struct lpc10_decoder_state * dec
Definition: codec_lpc10.c:60
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
char name[80]
Definition: translate.h:138
static int load_module(void)
Definition: codec_lpc10.c:266