From 9416148d39a6404d8ebba064b027e5e7ff399372 Mon Sep 17 00:00:00 2001 From: markster Date: Wed, 5 Jan 2000 17:22:42 +0000 Subject: Version 0.1.2 from FTP git-svn-id: http://svn.digium.com/svn/asterisk/trunk@191 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_modem.c | 16 +- channels/chan_modem_aopen.c | 13 +- codecs/Makefile | 12 +- codecs/codec_lpc10.c | 348 ++++++++++++++++++++++++++++++++++++++++++++ codecs/lpc10_slin_ex.h | 13 ++ codecs/slin_lpc10_ex.h | 21 +++ 6 files changed, 412 insertions(+), 11 deletions(-) create mode 100755 codecs/codec_lpc10.c create mode 100755 codecs/lpc10_slin_ex.h create mode 100755 codecs/slin_lpc10_ex.h diff --git a/channels/chan_modem.c b/channels/chan_modem.c index 7c6fedbf2..bf4a89c60 100755 --- a/channels/chan_modem.c +++ b/channels/chan_modem.c @@ -419,7 +419,6 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state) snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5); tmp->type = type; tmp->fd = i->fd; - /* XXX Switching formats silently causes kernel panics XXX */ tmp->format = i->mc->formats; tmp->state = state; if (state == AST_STATE_RING) @@ -433,7 +432,7 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state) tmp->pvt->write = modem_write; strncpy(tmp->context, i->context, sizeof(tmp->context)); if (strlen(i->cid)) - strncpy(tmp->callerid, i->cid, sizeof(tmp->callerid)); + tmp->callerid = strdup(i->cid); i->owner = tmp; pthread_mutex_lock(&usecnt_lock); usecnt++; @@ -443,6 +442,7 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state) if (ast_pbx_start(tmp)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); ast_hangup(tmp); + tmp = NULL; } } } else @@ -454,6 +454,12 @@ static void modem_mini_packet(struct ast_modem_pvt *i) { struct ast_frame *fr; fr = i->mc->read(i); + if (fr->frametype == AST_FRAME_CONTROL) { + if (fr->subclass == AST_CONTROL_RING) { + ast_modem_new(i, AST_STATE_RING); + restart_monitor(); + } + } } static void *do_monitor(void *data) @@ -701,10 +707,10 @@ int load_module() ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver); if (ast_load_resource(driver)) { - ast_log(LOG_ERROR, "Failed to laod driver %s\n", driver); + ast_log(LOG_ERROR, "Failed to load driver %s\n", driver); ast_destroy(cfg); - unload_module(); pthread_mutex_unlock(&iflock); + unload_module(); return -1; } } else if (!strcasecmp(v->name, "mode")) { @@ -742,8 +748,6 @@ int load_module() return 0; } - - int unload_module() { struct ast_modem_pvt *p, *pl; diff --git a/channels/chan_modem_aopen.c b/channels/chan_modem_aopen.c index ae2b7e41a..f344cb149 100755 --- a/channels/chan_modem_aopen.c +++ b/channels/chan_modem_aopen.c @@ -194,9 +194,13 @@ static struct ast_frame *aopen_handle_escape(struct ast_modem_pvt *p, char esc) ast_log(LOG_DEBUG, "Escaped character '%c'\n", esc); switch(esc) { + case 'R': /* Pseudo ring */ + p->fr.frametype = AST_FRAME_CONTROL; + p->fr.subclass = AST_CONTROL_RING; + return &p->fr; case 'X': /* Pseudo connect */ p->fr.frametype = AST_FRAME_CONTROL; - p->fr.subclass = AST_CONTROL_ANSWER; + p->fr.subclass = AST_CONTROL_RING; if (p->owner) p->owner->state = AST_STATE_UP; if (aopen_startrec(p)) @@ -255,11 +259,14 @@ static struct ast_frame *aopen_read(struct ast_modem_pvt *p) /* If we're in immediate mode, reply now */ if (p->mode == MODEM_MODE_IMMEDIATE) return aopen_handle_escape(p, 'X'); - } + } else if (!strcasecmp(result, "BUSY")) { /* Same as a busy signal */ return aopen_handle_escape(p, 'b'); - } + } else + if (!strcasecmp(result, "RING")) { + return aopen_handle_escape(p, 'R'); + } else if (!strcasecmp(result, "NO DIALTONE")) { /* There's no dialtone, so the line isn't working */ ast_log(LOG_WARNING, "Device '%s' lacking dialtone\n", p->dev); diff --git a/codecs/Makefile b/codecs/Makefile index 0e015cf92..baec412a5 100755 --- a/codecs/Makefile +++ b/codecs/Makefile @@ -26,8 +26,9 @@ LIBG723=g723.1/libg723.a LIBG723B=g723.1b/libg723b.a LIBGSM=gsm/lib/libgsm.a LIBMP3=mp3/libmp3.a +LIBLPC10=lpc10/liblpc10.a -CODECS+=$(MODG723) codec_gsm.so codec_mp3_d.so +CODECS+=$(MODG723) codec_gsm.so codec_mp3_d.so codec_lpc10.so all: $(CODECS) @@ -37,6 +38,7 @@ clean: ! [ -d g723.1b ] || make -C g723.1b clean make -C gsm clean make -C mp3 clean + make -C lpc10 clean $(LIBG723): make -C g723.1 all @@ -50,11 +52,14 @@ $(LIBG723B): $(LIBMP3): make -C mp3 all +$(LIBLPC10): + make -C lpc10 all + codec_g723_1.so : codec_g723_1.o $(LIBG723) $(CC) -shared -Xlinker -x -o $@ $< $(LIBG723) codec_g723_1b.o : codec_g723_1.c - $(CC) -c -o $@ $(CFLAGS) -DANNEX_B $< + $(CC) -c -o $@ $(CFLAGS) -DANNEX_B -Dsingle $< codec_g723_1b.so : codec_g723_1b.o $(LIBG723B) $(CC) -shared -Xlinker -x -o $@ $< $(LIBG723B) -lm @@ -62,6 +67,9 @@ codec_g723_1b.so : codec_g723_1b.o $(LIBG723B) codec_gsm.so: codec_gsm.o $(LIBGSM) $(CC) -shared -Xlinker -x -o $@ $< $(LIBGSM) +codec_lpc10.so: codec_lpc10.o $(LIBLPC10) + $(CC) -shared -Xlinker -x -o $@ $< $(LIBLPC10) -lm + codec_mp3_d.so: codec_mp3_d.o $(LIBMP3) $(CC) -shared -Xlinker -x -o $@ $< $(LIBMP3) diff --git a/codecs/codec_lpc10.c b/codecs/codec_lpc10.c new file mode 100755 index 000000000..6316241dd --- /dev/null +++ b/codecs/codec_lpc10.c @@ -0,0 +1,348 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Translate between signed linear and LPC10 (Linear Predictor Code) + * + * The lpc10 code is from a library used by nautilus, modified to be a bit + * nicer to the compiler. + * + * See http://www.arl.wustl.edu/~jaf/ + * + * Copyright (C) 1999, Mark Spencer + * + * Mark Spencer + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lpc10/lpc10.h" + +/* Sample frame data */ +#include "slin_lpc10_ex.h" +#include "lpc10_slin_ex.h" + +/* We use a very strange format here... I have no idea why... The frames are 180 + samples long, which isn't even an even number of milliseconds... Not only that + but we hvae to waste two bits of each frame to keep them ending on a byte boundary + because the frames are 54 bits long */ + +#define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8 + +static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER; +static int localusecnt=0; + +static char *tdesc = "LPC10 2.4kbps (signed linear) Voice Coder"; + +struct ast_translator_pvt { + union { + struct lpc10_encoder_state *enc; + struct lpc10_decoder_state *dec; + } lpc10; + struct ast_frame f; + /* Space to build offset */ + char offset[AST_FRIENDLY_OFFSET]; + /* Buffer for our outgoing frame */ + short outbuf[LPC10_SAMPLES_PER_FRAME]; + /* Enough to store a full second */ + short buf[8000]; + int tail; + int longer; +}; + +#define lpc10_coder_pvt ast_translator_pvt + +static struct ast_translator_pvt *lpc10_enc_new() +{ + struct lpc10_coder_pvt *tmp; + tmp = malloc(sizeof(struct lpc10_coder_pvt)); + if (tmp) { + if (!(tmp->lpc10.enc = create_lpc10_encoder_state())) { + free(tmp); + tmp = NULL; + } + tmp->tail = 0; + tmp->longer = 0; + localusecnt++; + } + return tmp; +} + +static struct ast_translator_pvt *lpc10_dec_new() +{ + struct lpc10_coder_pvt *tmp; + tmp = malloc(sizeof(struct lpc10_coder_pvt)); + if (tmp) { + if (!(tmp->lpc10.dec = create_lpc10_decoder_state())) { + free(tmp); + tmp = NULL; + } + tmp->tail = 0; + tmp->longer = 0; + localusecnt++; + } + return tmp; +} +static struct ast_frame *lintolpc10_sample() +{ + static struct ast_frame f; + static int longer = 0; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_SLINEAR; + f.datalen = sizeof(slin_lpc10_ex); + /* Assume 8000 Hz */ + f.timelen = LPC10_SAMPLES_PER_FRAME/8; + f.timelen += longer; + longer = 1- longer; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = slin_lpc10_ex; + return &f; +} + +static struct ast_frame *lpc10tolin_sample() +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_LPC10; + f.datalen = sizeof(lpc10_slin_ex); + /* All frames are 22 ms long (maybe a little more -- why did he choose + LPC10_SAMPLES_PER_FRAME sample frames anyway?? */ + f.timelen = LPC10_SAMPLES_PER_FRAME/8; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = lpc10_slin_ex; + return &f; +} + +static struct ast_frame *lpc10tolin_frameout(struct ast_translator_pvt *tmp) +{ + if (!tmp->tail) + return NULL; + /* Signed linear is no particular frame size, so just send whatever + we have in the buffer in one lump sum */ + tmp->f.frametype = AST_FRAME_VOICE; + tmp->f.subclass = AST_FORMAT_SLINEAR; + tmp->f.datalen = tmp->tail * 2; + /* Assume 8000 Hz */ + tmp->f.timelen = tmp->tail / 8; + tmp->f.mallocd = 0; + tmp->f.offset = AST_FRIENDLY_OFFSET; + tmp->f.src = __PRETTY_FUNCTION__; + tmp->f.data = tmp->buf; + /* Reset tail pointer */ + tmp->tail = 0; + +#if 0 + /* Save a sample frame */ + { static int samplefr = 0; + if (samplefr == 80) { + int fd; + fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644); + write(fd, tmp->f.data, tmp->f.datalen); + close(fd); + } + samplefr++; + } +#endif + return &tmp->f; +} + +static void extract_bits(INT32 *bits, unsigned char *c) +{ + int x; + for (x=0;x> (x & 7))) + bits[x] = 1; + else + bits[x] = 0; + if ((x & 7) == 7) + c++; + } +} + +static void build_bits(unsigned char *c, INT32 *bits) +{ + unsigned char mask=0x80; + int x; + *c = 0; + for (x=0;x> 1; + if ((x % 8)==7) { + c++; + *c = 0; + mask = 0x80; + } + } +} + +static int lpc10tolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f) +{ + /* Assuming there's space left, decode into the current buffer at + the tail location */ + int x; + float tmpbuf[LPC10_SAMPLES_PER_FRAME]; + short *sd; + INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; + if (tmp->tail + LPC10_SAMPLES_PER_FRAME < sizeof(tmp->buf)/2) { + sd = tmp->buf + tmp->tail; + extract_bits(bits, f->data); + if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) { + ast_log(LOG_WARNING, "Invalid lpc10 data\n"); + return -1; + } + for (x=0;xtail+=LPC10_SAMPLES_PER_FRAME; + } else { + ast_log(LOG_WARNING, "Out of buffer space\n"); + return -1; + } + return 0; +} + +static int lintolpc10_framein(struct ast_translator_pvt *tmp, struct ast_frame *f) +{ + /* Just add the frames to our stream */ + /* XXX We should look at how old the rest of our stream is, and if it + is too old, then we should overwrite it entirely, otherwise we can + get artifacts of earlier talk that do not belong */ + if (tmp->tail + f->datalen < sizeof(tmp->buf) / 2) { + memcpy((tmp->buf + tmp->tail), f->data, f->datalen); + tmp->tail += f->datalen/2; + } else { + ast_log(LOG_WARNING, "Out of buffer space\n"); + return -1; + } + return 0; +} + +static struct ast_frame *lintolpc10_frameout(struct ast_translator_pvt *tmp) +{ + int x; + float tmpbuf[LPC10_SAMPLES_PER_FRAME]; + INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; + /* We can't work on anything less than a frame in size */ + if (tmp->tail < LPC10_SAMPLES_PER_FRAME) + return NULL; + /* Encode a frame of data */ + for (x=0;xbuf[x] / 32768.0; + } + lpc10_encode(tmpbuf, bits, tmp->lpc10.enc); + build_bits((unsigned char *)tmp->outbuf, bits); + tmp->f.frametype = AST_FRAME_VOICE; + tmp->f.subclass = AST_FORMAT_LPC10; + tmp->f.datalen = LPC10_BYTES_IN_COMPRESSED_FRAME; + tmp->f.timelen = 22; + /* We alternate between 22 and 23 ms to simulate 22.5 ms */ + tmp->f.timelen += tmp->longer; + /* Use one of the two left over bits to record if this is a 22 or 23 ms frame... + important for IAX use */ + tmp->longer = 1 - tmp->longer; + tmp->f.mallocd = 0; + tmp->f.offset = AST_FRIENDLY_OFFSET; + tmp->f.src = __PRETTY_FUNCTION__; + tmp->f.data = tmp->outbuf; + ((char *)(tmp->f.data))[LPC10_BYTES_IN_COMPRESSED_FRAME - 1] |= tmp->longer; + tmp->tail -= LPC10_SAMPLES_PER_FRAME; + /* Move the data at the end of the buffer to the front */ + if (tmp->tail) + memmove(tmp->buf, tmp->buf + LPC10_SAMPLES_PER_FRAME, tmp->tail * 2); +#if 0 + /* Save a sample frame */ + { static int samplefr = 0; + if (samplefr == 0) { + int fd; + fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644); + write(fd, tmp->f.data, tmp->f.datalen); + close(fd); + } + samplefr++; + } +#endif + return &tmp->f; +} + +static void lpc10_destroy(struct ast_translator_pvt *pvt) +{ + /* Enc and DEC are both just allocated, so they can be freed */ + free(pvt->lpc10.enc); + free(pvt); + localusecnt--; +} + +static struct ast_translator lpc10tolin = + { "lpc10tolin", + AST_FORMAT_LPC10, AST_FORMAT_SLINEAR, + lpc10_dec_new, + lpc10tolin_framein, + lpc10tolin_frameout, + lpc10_destroy, + lpc10tolin_sample + }; + +static struct ast_translator lintolpc10 = + { "lintolpc10", + AST_FORMAT_SLINEAR, AST_FORMAT_LPC10, + lpc10_enc_new, + lintolpc10_framein, + lintolpc10_frameout, + lpc10_destroy, + lintolpc10_sample + }; + +int unload_module(void) +{ + int res; + pthread_mutex_lock(&localuser_lock); + res = ast_unregister_translator(&lintolpc10); + if (!res) + res = ast_unregister_translator(&lpc10tolin); + if (localusecnt) + res = -1; + pthread_mutex_unlock(&localuser_lock); + return res; +} + +int load_module(void) +{ + int res; + res=ast_register_translator(&lpc10tolin); + if (!res) + res=ast_register_translator(&lintolpc10); + else + ast_unregister_translator(&lpc10tolin); + return res; +} + +char *description(void) +{ + return tdesc; +} + +int usecount(void) +{ + int res; + STANDARD_USECOUNT(res); + return res; +} diff --git a/codecs/lpc10_slin_ex.h b/codecs/lpc10_slin_ex.h new file mode 100755 index 000000000..802c3f785 --- /dev/null +++ b/codecs/lpc10_slin_ex.h @@ -0,0 +1,13 @@ +/* + * 8-bit raw data + * + * Source: example.lpc10 + * + * Copyright (C) 1999, Mark Spencer and Linux Support Services + * + * Distributed under the terms of the GNU General Public License + * + */ + +static unsigned char lpc10_slin_ex[] = { +0x1, 0x8, 0x31, 0x8, 0x31, 0x80, 0x30 }; diff --git a/codecs/slin_lpc10_ex.h b/codecs/slin_lpc10_ex.h new file mode 100755 index 000000000..d738ae41e --- /dev/null +++ b/codecs/slin_lpc10_ex.h @@ -0,0 +1,21 @@ +/* + * Signed 16-bit audio data + * + * Source: example.slin + * + * Copyright (C) 1999, Mark Spencer and Linux Support Services + * + * Distributed under the terms of the GNU General Public License + * + */ + +static signed short slin_lpc10_ex[] = { +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000 }; -- cgit v1.2.3