00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 150729 $")
00033
00034 #include "asterisk/translate.h"
00035 #include "asterisk/config.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/utils.h"
00038
00039 #include "lpc10/lpc10.h"
00040
00041
00042 #include "asterisk/slin.h"
00043 #include "ex_lpc10.h"
00044
00045
00046
00047
00048
00049
00050 #define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
00051
00052 #define BUFFER_SAMPLES 8000
00053
00054 struct lpc10_coder_pvt {
00055 union {
00056 struct lpc10_encoder_state *enc;
00057 struct lpc10_decoder_state *dec;
00058 } lpc10;
00059
00060 short buf[BUFFER_SAMPLES];
00061 int longer;
00062 };
00063
00064 static int lpc10_enc_new(struct ast_trans_pvt *pvt)
00065 {
00066 struct lpc10_coder_pvt *tmp = pvt->pvt;
00067
00068 return (tmp->lpc10.enc = create_lpc10_encoder_state()) ? 0 : -1;
00069 }
00070
00071 static int lpc10_dec_new(struct ast_trans_pvt *pvt)
00072 {
00073 struct lpc10_coder_pvt *tmp = pvt->pvt;
00074
00075 return (tmp->lpc10.dec = create_lpc10_decoder_state()) ? 0 : -1;
00076 }
00077
00078 static void extract_bits(INT32 *bits, unsigned char *c)
00079 {
00080 int x;
00081 for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
00082 if (*c & (0x80 >> (x & 7)))
00083 bits[x] = 1;
00084 else
00085 bits[x] = 0;
00086 if ((x & 7) == 7)
00087 c++;
00088 }
00089 }
00090
00091
00092 static void build_bits(unsigned char *c, INT32 *bits)
00093 {
00094 unsigned char mask=0x80;
00095 int x;
00096 *c = 0;
00097 for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
00098 if (bits[x])
00099 *c |= mask;
00100 mask = mask >> 1;
00101 if ((x % 8)==7) {
00102 c++;
00103 *c = 0;
00104 mask = 0x80;
00105 }
00106 }
00107 }
00108
00109 static int lpc10tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00110 {
00111 struct lpc10_coder_pvt *tmp = pvt->pvt;
00112 int16_t *dst = pvt->outbuf.i16;
00113 int len = 0;
00114
00115 while (len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
00116 int x;
00117 float tmpbuf[LPC10_SAMPLES_PER_FRAME];
00118 INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
00119 if (pvt->samples + LPC10_SAMPLES_PER_FRAME > BUFFER_SAMPLES) {
00120 ast_log(LOG_WARNING, "Out of buffer space\n");
00121 return -1;
00122 }
00123 extract_bits(bits, f->data.ptr + len);
00124 if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
00125 ast_log(LOG_WARNING, "Invalid lpc10 data\n");
00126 return -1;
00127 }
00128 for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
00129
00130 dst[pvt->samples + x] = (int16_t)(32768.0 * tmpbuf[x]);
00131 }
00132
00133 pvt->samples += LPC10_SAMPLES_PER_FRAME;
00134 pvt->datalen += 2*LPC10_SAMPLES_PER_FRAME;
00135 len += LPC10_BYTES_IN_COMPRESSED_FRAME;
00136 }
00137 if (len != f->datalen)
00138 printf("Decoded %d, expected %d\n", len, f->datalen);
00139 return 0;
00140 }
00141
00142 static int lintolpc10_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00143 {
00144 struct lpc10_coder_pvt *tmp = pvt->pvt;
00145
00146
00147 if (pvt->samples + f->samples > BUFFER_SAMPLES) {
00148 ast_log(LOG_WARNING, "Out of buffer space\n");
00149 return -1;
00150 }
00151 memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
00152 pvt->samples += f->samples;
00153 return 0;
00154 }
00155
00156 static struct ast_frame *lintolpc10_frameout(struct ast_trans_pvt *pvt)
00157 {
00158 struct lpc10_coder_pvt *tmp = pvt->pvt;
00159 int x;
00160 int datalen = 0;
00161 int samples = 0;
00162 float tmpbuf[LPC10_SAMPLES_PER_FRAME];
00163 INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
00164
00165 if (pvt->samples < LPC10_SAMPLES_PER_FRAME)
00166 return NULL;
00167 while (pvt->samples >= LPC10_SAMPLES_PER_FRAME) {
00168
00169 for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++)
00170 tmpbuf[x] = (float)tmp->buf[x + samples] / 32768.0;
00171 lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
00172 build_bits(pvt->outbuf.uc + datalen, bits);
00173 datalen += LPC10_BYTES_IN_COMPRESSED_FRAME;
00174 samples += LPC10_SAMPLES_PER_FRAME;
00175 pvt->samples -= LPC10_SAMPLES_PER_FRAME;
00176
00177
00178 tmp->longer = 1 - tmp->longer;
00179 }
00180
00181 if (pvt->samples)
00182 memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
00183 return ast_trans_frameout(pvt, datalen, samples);
00184 }
00185
00186
00187 static void lpc10_destroy(struct ast_trans_pvt *arg)
00188 {
00189 struct lpc10_coder_pvt *pvt = arg->pvt;
00190
00191 ast_free(pvt->lpc10.enc);
00192 }
00193
00194 static struct ast_translator lpc10tolin = {
00195 .name = "lpc10tolin",
00196 .srcfmt = AST_FORMAT_LPC10,
00197 .dstfmt = AST_FORMAT_SLINEAR,
00198 .newpvt = lpc10_dec_new,
00199 .framein = lpc10tolin_framein,
00200 .destroy = lpc10_destroy,
00201 .sample = lpc10_sample,
00202 .desc_size = sizeof(struct lpc10_coder_pvt),
00203 .buffer_samples = BUFFER_SAMPLES,
00204 .plc_samples = LPC10_SAMPLES_PER_FRAME,
00205 .buf_size = BUFFER_SAMPLES * 2,
00206 };
00207
00208 static struct ast_translator lintolpc10 = {
00209 .name = "lintolpc10",
00210 .srcfmt = AST_FORMAT_SLINEAR,
00211 .dstfmt = AST_FORMAT_LPC10,
00212 .newpvt = lpc10_enc_new,
00213 .framein = lintolpc10_framein,
00214 .frameout = lintolpc10_frameout,
00215 .destroy = lpc10_destroy,
00216 .sample = slin8_sample,
00217 .desc_size = sizeof(struct lpc10_coder_pvt),
00218 .buffer_samples = BUFFER_SAMPLES,
00219 .buf_size = LPC10_BYTES_IN_COMPRESSED_FRAME * (1 + BUFFER_SAMPLES / LPC10_SAMPLES_PER_FRAME),
00220 };
00221
00222 static int parse_config(int reload)
00223 {
00224 struct ast_variable *var;
00225 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00226 struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
00227 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID)
00228 return 0;
00229 for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
00230 if (!strcasecmp(var->name, "genericplc")) {
00231 lpc10tolin.useplc = ast_true(var->value) ? 1 : 0;
00232 ast_verb(3, "codec_lpc10: %susing generic PLC\n",
00233 lpc10tolin.useplc ? "" : "not ");
00234 }
00235 }
00236 ast_config_destroy(cfg);
00237 return 0;
00238 }
00239
00240 static int reload(void)
00241 {
00242 if (parse_config(1))
00243 return AST_MODULE_LOAD_DECLINE;
00244 return AST_MODULE_LOAD_SUCCESS;
00245 }
00246
00247
00248 static int unload_module(void)
00249 {
00250 int res;
00251
00252 res = ast_unregister_translator(&lintolpc10);
00253 res |= ast_unregister_translator(&lpc10tolin);
00254
00255 return res;
00256 }
00257
00258 static int load_module(void)
00259 {
00260 int res;
00261
00262 if (parse_config(0))
00263 return AST_MODULE_LOAD_DECLINE;
00264 res = ast_register_translator(&lpc10tolin);
00265 if (!res)
00266 res = ast_register_translator(&lintolpc10);
00267 else
00268 ast_unregister_translator(&lpc10tolin);
00269 if (res)
00270 return AST_MODULE_LOAD_FAILURE;
00271 return AST_MODULE_LOAD_SUCCESS;
00272 }
00273
00274 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "LPC10 2.4kbps Coder/Decoder",
00275 .load = load_module,
00276 .unload = unload_module,
00277 .reload = reload,
00278 );