Asterisk - The Open Source Telephony Project  21.4.1
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 /*** MODULEINFO
30  <depend>lpc10</depend>
31  ***/
32 
33 /*** MODULEINFO
34  <support_level>core</support_level>
35  ***/
36 
37 #include "asterisk.h"
38 
39 #include "asterisk/translate.h"
40 #include "asterisk/config.h"
41 #include "asterisk/module.h"
42 #include "asterisk/utils.h"
43 #include "asterisk/linkedlists.h"
44 
45 #include <lpc10.h>
46 
47 /* Sample frame data */
48 #include "asterisk/slin.h"
49 #include "ex_lpc10.h"
50 
51 /* We use a very strange format here... I have no idea why... The frames are 180
52  samples long, which isn't even an even number of milliseconds... Not only that
53  but we hvae to waste two bits of each frame to keep them ending on a byte boundary
54  because the frames are 54 bits long */
55 
56 #define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
57 
58 #define BUFFER_SAMPLES 8000
59 
61  union {
62  struct lpc10_encoder_state *enc;
63  struct lpc10_decoder_state *dec;
64  } lpc10;
65  /* Enough to store a full second */
66  short buf[BUFFER_SAMPLES];
67  int longer;
68 };
69 
70 static int lpc10_enc_new(struct ast_trans_pvt *pvt)
71 {
72  struct lpc10_coder_pvt *tmp = pvt->pvt;
73 
74  return (tmp->lpc10.enc = create_lpc10_encoder_state()) ? 0 : -1;
75 }
76 
77 static int lpc10_dec_new(struct ast_trans_pvt *pvt)
78 {
79  struct lpc10_coder_pvt *tmp = pvt->pvt;
80 
81  return (tmp->lpc10.dec = create_lpc10_decoder_state()) ? 0 : -1;
82 }
83 
84 static void extract_bits(INT32 *bits, unsigned char *c)
85 {
86  int x;
87  for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
88  if (*c & (0x80 >> (x & 7)))
89  bits[x] = 1;
90  else
91  bits[x] = 0;
92  if ((x & 7) == 7)
93  c++;
94  }
95 }
96 
97 /* XXX note lpc10_encode() produces one bit per word in bits[] */
98 static void build_bits(unsigned char *c, INT32 *bits)
99 {
100  unsigned char mask=0x80;
101  int x;
102  *c = 0;
103  for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
104  if (bits[x])
105  *c |= mask;
106  mask = mask >> 1;
107  if ((x % 8)==7) {
108  c++;
109  *c = 0;
110  mask = 0x80;
111  }
112  }
113 }
114 
115 static int lpc10tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
116 {
117  struct lpc10_coder_pvt *tmp = pvt->pvt;
118  int16_t *dst = pvt->outbuf.i16;
119  int len = 0;
120 
121  while (len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
122  int x;
123  float tmpbuf[LPC10_SAMPLES_PER_FRAME];
124  INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; /* XXX see note */
125  if (pvt->samples + LPC10_SAMPLES_PER_FRAME > BUFFER_SAMPLES) {
126  ast_log(LOG_WARNING, "Out of buffer space\n");
127  return -1;
128  }
129  extract_bits(bits, f->data.ptr + len);
130  if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
131  ast_log(LOG_WARNING, "Invalid lpc10 data\n");
132  return -1;
133  }
134  for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
135  /* Convert to a short between -1.0 and 1.0 */
136  dst[pvt->samples + x] = (int16_t)(32768.0 * tmpbuf[x]);
137  }
138 
139  pvt->samples += LPC10_SAMPLES_PER_FRAME;
140  pvt->datalen += 2*LPC10_SAMPLES_PER_FRAME;
141  len += LPC10_BYTES_IN_COMPRESSED_FRAME;
142  }
143  if (len != f->datalen)
144  printf("Decoded %d, expected %d\n", len, f->datalen);
145  return 0;
146 }
147 
148 static int lintolpc10_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
149 {
150  struct lpc10_coder_pvt *tmp = pvt->pvt;
151 
152  /* Just add the frames to our stream */
153  if (pvt->samples + f->samples > BUFFER_SAMPLES) {
154  ast_log(LOG_WARNING, "Out of buffer space\n");
155  return -1;
156  }
157  memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
158  pvt->samples += f->samples;
159  return 0;
160 }
161 
162 static struct ast_frame *lintolpc10_frameout(struct ast_trans_pvt *pvt)
163 {
164  struct lpc10_coder_pvt *tmp = pvt->pvt;
165  struct ast_frame *result = NULL;
166  struct ast_frame *last = NULL;
167  int samples = 0; /* output samples */
168 
169  while (pvt->samples >= LPC10_SAMPLES_PER_FRAME) {
170  struct ast_frame *current;
171  float tmpbuf[LPC10_SAMPLES_PER_FRAME];
172  INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; /* XXX what ??? */
173  int x;
174 
175  /* Encode a frame of data */
176  for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++)
177  tmpbuf[x] = (float)tmp->buf[x + samples] / 32768.0;
178  lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
179  build_bits(pvt->outbuf.uc, bits);
180 
181  samples += LPC10_SAMPLES_PER_FRAME;
182  pvt->samples -= LPC10_SAMPLES_PER_FRAME;
183  /* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
184  important for IAX use */
185  tmp->longer = 1 - tmp->longer;
186 
187  current = ast_trans_frameout(pvt, LPC10_BYTES_IN_COMPRESSED_FRAME, LPC10_SAMPLES_PER_FRAME);
188  if (!current) {
189  continue;
190  } else if (last) {
191  AST_LIST_NEXT(last, frame_list) = current;
192  } else {
193  result = current;
194  }
195  last = current;
196  }
197 
198  /* Move the data at the end of the buffer to the front */
199  if (samples) {
200  memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
201  }
202 
203  return result;
204 }
205 
206 
207 static void lpc10_destroy(struct ast_trans_pvt *arg)
208 {
209  struct lpc10_coder_pvt *pvt = arg->pvt;
210  /* Enc and DEC are both just allocated, so they can be freed */
211  ast_free(pvt->lpc10.enc);
212 }
213 
214 static struct ast_translator lpc10tolin = {
215  .name = "lpc10tolin",
216  .src_codec = {
217  .name = "lpc10",
218  .type = AST_MEDIA_TYPE_AUDIO,
219  .sample_rate = 8000,
220  },
221  .dst_codec = {
222  .name = "slin",
223  .type = AST_MEDIA_TYPE_AUDIO,
224  .sample_rate = 8000,
225  },
226  .format = "slin",
227  .newpvt = lpc10_dec_new,
228  .framein = lpc10tolin_framein,
229  .destroy = lpc10_destroy,
230  .sample = lpc10_sample,
231  .desc_size = sizeof(struct lpc10_coder_pvt),
232  .buffer_samples = BUFFER_SAMPLES,
233  .buf_size = BUFFER_SAMPLES * 2,
234 };
235 
236 static struct ast_translator lintolpc10 = {
237  .name = "lintolpc10",
238  .src_codec = {
239  .name = "slin",
240  .type = AST_MEDIA_TYPE_AUDIO,
241  .sample_rate = 8000,
242  },
243  .dst_codec = {
244  .name = "lpc10",
245  .type = AST_MEDIA_TYPE_AUDIO,
246  .sample_rate = 8000,
247  },
248  .format = "lpc10",
249  .newpvt = lpc10_enc_new,
250  .framein = lintolpc10_framein,
251  .frameout = lintolpc10_frameout,
252  .destroy = lpc10_destroy,
253  .sample = slin8_sample,
254  .desc_size = sizeof(struct lpc10_coder_pvt),
255  .buffer_samples = BUFFER_SAMPLES,
256  .buf_size = LPC10_BYTES_IN_COMPRESSED_FRAME * (1 + BUFFER_SAMPLES / LPC10_SAMPLES_PER_FRAME),
257 };
258 
259 static int unload_module(void)
260 {
261  int res;
262 
263  res = ast_unregister_translator(&lintolpc10);
264  res |= ast_unregister_translator(&lpc10tolin);
265 
266  return res;
267 }
268 
269 static int load_module(void)
270 {
271  int res;
272 
273  res = ast_register_translator(&lpc10tolin);
274  res |= ast_register_translator(&lintolpc10);
275 
276  if (res) {
277  unload_module();
279  }
280 
282 }
283 
284 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "LPC10 2.4kbps Coder/Decoder",
285  .support_level = AST_MODULE_SUPPORT_CORE,
286  .load = load_module,
287  .unload = unload_module,
288 );
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout function
Definition: translate.c:439
int datalen
actual space used in outbuf
Definition: translate.h:218
Asterisk main include file. File version handling, generic pbx functions.
Descriptor of a translator.
Definition: translate.h:137
Support for translation of data formats. translate.c.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
unsigned char * uc
Definition: translate.h:222
void * pvt
Definition: translate.h:219
Utility functions.
Configuration File Parser.
#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
A set of macros to manage forward-linked lists.
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
union ast_frame::@224 data
Copyright (C) 2008, Digium, Inc.
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
Data structure associated with a single frame of data.
#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