From 509765aef52f3ce306a114832ab885ad85522d2e Mon Sep 17 00:00:00 2001 From: markster Date: Thu, 16 Dec 1999 13:44:30 +0000 Subject: Version 0.1.1 from FTP git-svn-id: http://svn.digium.com/svn/asterisk/trunk@139 f38db490-d61c-443f-a65b-d21fe96a405b --- BUGS | 6 +- channels/chan_ixj.c | 52 +++- channels/chan_vofr.c | 27 +- codecs/mp3/Makefile | 37 +++ formats/format_g723.c | 4 +- formats/format_gsm.c | 298 ++++++++++++++++++ formats/format_mp3.c | 103 ++++--- formats/format_wav.c | 4 +- formats/format_wav_gsm.c | 586 +++++++++++++++++++++++++++++++++++ formats/msgsm.h | 685 +++++++++++++++++++++++++++++++++++++++++ include/asterisk/channel_pvt.h | 6 +- include/asterisk/io.h | 6 +- io.c | 4 +- 13 files changed, 1750 insertions(+), 68 deletions(-) create mode 100755 codecs/mp3/Makefile create mode 100755 formats/format_gsm.c create mode 100755 formats/format_wav_gsm.c create mode 100755 formats/msgsm.h diff --git a/BUGS b/BUGS index 04fbe3e48..495e20da1 100755 --- a/BUGS +++ b/BUGS @@ -2,8 +2,10 @@ these bugs are in asterisk, and sometimes they relate to the products that asterisk uses. -* The MP3 decoder is completely broken - * The translator API may introduce warble in the case of going in both directions, but I haven't verified that. The trouble should only enter in the case of mismatched frame lengths. + +* In general Asterisk is a very new program, and there are liable to be + many bugs yet to be discovered, so if you think you've found one, please + be sure to report it. diff --git a/channels/chan_ixj.c b/channels/chan_ixj.c index 5f476cdf6..c8cdb91dd 100755 --- a/channels/chan_ixj.c +++ b/channels/chan_ixj.c @@ -3,7 +3,7 @@ * * QuickNet Internet Phone Jack Channel * - * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * Copyright (C) 1999, Mark Spencer * * Mark Spencer * @@ -60,7 +60,7 @@ static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER; which are not currently in use. */ static pthread_t monitor_thread = -1; -static int restart_monitor(); +static int restart_monitor(void); /* The private structures of the Phone Jack channels are linked for selecting outgoing channels */ @@ -129,7 +129,8 @@ static int ixj_call(struct ast_channel *ast, char *dest, int timeout) } /* When we call, it just works, really, there's no destination... Just ring the phone and wait for someone to answer */ - ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fd); + if (option_debug) + ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fd); ioctl(p->fd, IXJCTL_RING_START); ast->state = AST_STATE_RINGING; return 0; @@ -139,7 +140,8 @@ static int ixj_hangup(struct ast_channel *ast) { struct ixj_pvt *p; p = ast->pvt->pvt; - ast_log(LOG_DEBUG, "ixj_hangup(%s)\n", ast->name); + if (option_debug) + ast_log(LOG_DEBUG, "ixj_hangup(%s)\n", ast->name); if (!ast->pvt->pvt) { ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); return 0; @@ -217,7 +219,8 @@ static int ixj_setup(struct ast_channel *ast) static int ixj_answer(struct ast_channel *ast) { ixj_setup(ast); - ast_log(LOG_DEBUG, "ixj_answer(%s)\n", ast->name); + if (option_debug) + ast_log(LOG_DEBUG, "ixj_answer(%s)\n", ast->name); ast->rings = 0; ast->state = AST_STATE_UP; return 0; @@ -287,6 +290,14 @@ static struct ast_frame *ixj_read(struct ast_channel *ast) res = read(p->fd, p->buf, IXJ_MAX_BUF); ast->blocking = 0; if (res < 0) { +#if 0 + if (errno == EAGAIN) { + ast_log(LOG_WARNING, "Null frame received\n"); + p->fr.frametype = AST_FRAME_NULL; + p->fr.subclass = 0; + return &p->fr; + } +#endif ast_log(LOG_WARNING, "Error reading: %s\n", strerror(errno)); return NULL; } @@ -486,6 +497,10 @@ static void ixj_check_exception(struct ixj_pvt *i) ixj_new(i, AST_STATE_UP); /* No need to restart monitor, we are the monitor */ if (i->owner) { + pthread_mutex_lock(&usecnt_lock); + usecnt--; + pthread_mutex_unlock(&usecnt_lock); + ast_update_use_count(); ixj_setup(i->owner); } } else if (ast_exists_extension(NULL, "default", i->ext, 1)) { @@ -494,10 +509,16 @@ static void ixj_check_exception(struct ixj_pvt *i) strncpy(i->context, "default", sizeof(i->context)); ixj_new(i, AST_STATE_UP); if (i->owner) { + pthread_mutex_lock(&usecnt_lock); + usecnt--; + pthread_mutex_unlock(&usecnt_lock); + ast_update_use_count(); ixj_setup(i->owner); } } else if ((strlen(i->ext) >= ast_pbx_longest_extension(i->context)) && (strlen(i->ext) >= ast_pbx_longest_extension("default"))) { + if (option_debug) + ast_log(LOG_DEBUG, "%s is too long\n", i->ext); /* It's not a valid extension, give a busy signal */ ioctl(i->fd, IXJCTL_BUSY); } @@ -512,18 +533,23 @@ static void ixj_check_exception(struct ixj_pvt *i) if (i->mode == MODE_IMMEDIATE) { ixj_new(i, AST_STATE_RING); } else if (i->mode == MODE_DIALTONE) { -#if 0 - /* XXX Bug in the Phone jack, you can't detect DTMF when playing a tone XXX */ - ioctl(i->fd, IXJCTL_DIALTONE); -#else + pthread_mutex_lock(&usecnt_lock); + usecnt++; + pthread_mutex_unlock(&usecnt_lock); + ast_update_use_count(); /* Play the dialtone */ i->dialtone++; ioctl(i->fd, IXJCTL_PLAY_STOP); ioctl(i->fd, IXJCTL_PLAY_CODEC, ULAW); ioctl(i->fd, IXJCTL_PLAY_START); -#endif } } else { + if (i->dialtone) { + pthread_mutex_lock(&usecnt_lock); + usecnt--; + pthread_mutex_unlock(&usecnt_lock); + ast_update_use_count(); + } memset(i->ext, 0, sizeof(i->ext)); ioctl(i->fd, IXJCTL_CPT_STOP); ioctl(i->fd, IXJCTL_PLAY_STOP); @@ -690,11 +716,13 @@ static int restart_monitor() return 0; } -struct ixj_pvt *mkif(char *iface, int mode) +static struct ixj_pvt *mkif(char *iface, int mode) { /* Make a ixj_pvt structure for this interface */ struct ixj_pvt *tmp; +#if 0 int flags; +#endif tmp = malloc(sizeof(struct ixj_pvt)); if (tmp) { @@ -709,8 +737,10 @@ struct ixj_pvt *mkif(char *iface, int mode) ioctl(tmp->fd, IXJCTL_RING_STOP); ioctl(tmp->fd, IXJCTL_CPT_STOP); tmp->mode = mode; +#if 0 flags = fcntl(tmp->fd, F_GETFL); fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK); +#endif tmp->owner = NULL; tmp->lastformat = -1; tmp->lastinput = -1; diff --git a/channels/chan_vofr.c b/channels/chan_vofr.c index ea17df951..aee44ff2e 100755 --- a/channels/chan_vofr.c +++ b/channels/chan_vofr.c @@ -3,7 +3,7 @@ * * Implementation of Voice over Frame Relay, Adtran Style * - * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * Copyright (C) 1999, Mark Spencer * * Mark Spencer * @@ -55,7 +55,7 @@ static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER; which are not currently in use. */ static pthread_t monitor_thread = -1; -static int restart_monitor(); +static int restart_monitor(void); /* The private structures of the Adtran VoFR channels are linked for selecting outgoing channels */ @@ -558,6 +558,9 @@ static struct ast_frame *vofr_read(struct ast_channel *ast) fr->subclass = 0; break; } + case VOFR_SIGNAL_RING: + ast->rings++; + break; case VOFR_SIGNAL_UNKNOWN: switch(vh->data[1]) { case 0x1: @@ -783,7 +786,21 @@ static int vofr_mini_packet(struct vofr_pvt *i, struct vofr_hdr *pkt, int len) switch(pkt->data[0]) { case VOFR_SIGNAL_RING: /* If we get a RING, we definitely want to start a new thread */ - vofr_new(i, AST_STATE_RING); + if (!i->owner) + vofr_new(i, AST_STATE_RING); + else + ast_log(LOG_WARNING, "Got a ring, but there's an owner?\n"); + break; + case VOFR_SIGNAL_OFF_HOOK: + /* Network termination, go off hook */ +#if 0 + ast_log(LOG_DEBUG, "Off hook\n"); +#endif + vofr_xmit_signal(i, 0x10, 2); + if (!i->owner) + vofr_new(i, AST_STATE_UP); + else + ast_log(LOG_WARNING, "Got an offhook, but there's an owner?\n"); break; case VOFR_SIGNAL_ON_HOOK: break; @@ -896,7 +913,7 @@ static void *do_monitor(void *data) } -static int restart_monitor() +static int restart_monitor(void) { /* If we're supposed to be stopped -- stay stopped */ if (monitor_thread == -2) @@ -926,7 +943,7 @@ static int restart_monitor() return 0; } -struct vofr_pvt *mkif(char *type, char *iface) +static struct vofr_pvt *mkif(char *type, char *iface) { /* Make a vofr_pvt structure for this interface */ struct vofr_pvt *tmp; diff --git a/codecs/mp3/Makefile b/codecs/mp3/Makefile new file mode 100755 index 000000000..44ebc39d1 --- /dev/null +++ b/codecs/mp3/Makefile @@ -0,0 +1,37 @@ +# +# LMC section + +CFLAGS+= -I../include -Iinclude -O6 -funroll-loops -finline-functions -Wall -Wno-missing-prototypes -Wno-missing-declarations -g +RANLIB=ranlib + +# the XING decoder objs and dependencies: +# This is kinda nasty, since there's C, C++, and asm, oh my! +# of course, each needs different compilation methods. grr. +XINGOBJX86 = src/x86gas.o + +XINGOBJS = src/cdct.o src/cupl3.o \ + src/hwin.o src/iup.o src/l3init.o \ + src/msis.o src/wavep.o src/csbt.o \ + src/cwinm.o src/icdct.o src/mdct.o \ + src/uph.o src/cup.o src/dec8.o \ + src/isbt.o src/l3dq.o src/mhead.o \ + src/upsf.o src/iwinm.o + +LIBMP3=libmp3.a +ARFLAGS=cr + +XINGLMCOBJC += $(shell if uname -m | grep -q i.86; then echo src/x86gas.o; fi) + +#assembly lang code, if we need it + +XINGLMCOBJ = $(XINGOBJS) + +all: $(LIBMP3) + +$(LIBMP3): $(XINGOBJS) + $(AR) $(ARFLAGS) $(LIBMP3) $(XINGLMCOBJ) + $(RANLIB) $(LIBMP3) + +clean: + rm -f $(XINGOBJS) + rm -f $(LIBMP3) diff --git a/formats/format_g723.c b/formats/format_g723.c index 827987049..3824e04e7 100755 --- a/formats/format_g723.c +++ b/formats/format_g723.c @@ -3,7 +3,7 @@ * * Old-style G.723 frame/timestamp format. * - * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * Copyright (C) 1999, Mark Spencer * * Mark Spencer * @@ -285,7 +285,7 @@ static int g723_write(struct ast_filestream *fs, struct ast_frame *f) return 0; } -char *g723_getcomment(struct ast_filestream *s) +static char *g723_getcomment(struct ast_filestream *s) { return NULL; } diff --git a/formats/format_gsm.c b/formats/format_gsm.c new file mode 100755 index 000000000..6a06627fb --- /dev/null +++ b/formats/format_gsm.c @@ -0,0 +1,298 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Save to raw, headerless GSM data. + * + * 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 +#include +#include +#include + +/* Some Ideas for this code came from makegsme.c by Jeffery Chilton */ + +/* Portions of the conversion code are by guido@sienanet.it */ + +struct ast_filestream { + void *reserved[AST_RESERVED_POINTERS]; + /* Believe it or not, we must decode/recode to account for the + weird MS format */ + /* This is what a filestream means to us */ + int fd; /* Descriptor */ + struct ast_channel *owner; + struct ast_frame fr; /* Frame information */ + char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */ + char empty; /* Empty character */ + unsigned char gsm[33]; /* Two Real GSM Frames */ + int lasttimeout; + struct timeval last; + int adj; + struct ast_filestream *next; +}; + + +static struct ast_filestream *glist = NULL; +static pthread_mutex_t gsm_lock = PTHREAD_MUTEX_INITIALIZER; +static int glistcnt = 0; + +static char *name = "gsm"; +static char *desc = "Raw GSM data"; +static char *exts = "gsm"; + +static struct ast_filestream *gsm_open(int fd) +{ + /* We don't have any header to read or anything really, but + if we did, it would go here. We also might want to check + and be sure it's a valid file. */ + struct ast_filestream *tmp; + if ((tmp = malloc(sizeof(struct ast_filestream)))) { + memset(tmp, 0, sizeof(struct ast_filestream)); + if (pthread_mutex_lock(&gsm_lock)) { + ast_log(LOG_WARNING, "Unable to lock gsm list\n"); + free(tmp); + return NULL; + } + tmp->next = glist; + glist = tmp; + tmp->fd = fd; + tmp->owner = NULL; + tmp->fr.data = tmp->gsm; + tmp->fr.frametype = AST_FRAME_VOICE; + tmp->fr.subclass = AST_FORMAT_GSM; + /* datalen will vary for each frame */ + tmp->fr.src = name; + tmp->fr.mallocd = 0; + tmp->lasttimeout = -1; + glistcnt++; + pthread_mutex_unlock(&gsm_lock); + ast_update_use_count(); + } + return tmp; +} + +static struct ast_filestream *gsm_rewrite(int fd, char *comment) +{ + /* We don't have any header to read or anything really, but + if we did, it would go here. We also might want to check + and be sure it's a valid file. */ + struct ast_filestream *tmp; + if ((tmp = malloc(sizeof(struct ast_filestream)))) { + memset(tmp, 0, sizeof(struct ast_filestream)); + if (pthread_mutex_lock(&gsm_lock)) { + ast_log(LOG_WARNING, "Unable to lock gsm list\n"); + free(tmp); + return NULL; + } + tmp->next = glist; + glist = tmp; + tmp->fd = fd; + tmp->owner = NULL; + tmp->lasttimeout = -1; + glistcnt++; + pthread_mutex_unlock(&gsm_lock); + ast_update_use_count(); + } else + ast_log(LOG_WARNING, "Out of memory\n"); + return tmp; +} + +static struct ast_frame *gsm_read(struct ast_filestream *s) +{ + return NULL; +} + +static void gsm_close(struct ast_filestream *s) +{ + struct ast_filestream *tmp, *tmpl = NULL; + if (pthread_mutex_lock(&gsm_lock)) { + ast_log(LOG_WARNING, "Unable to lock gsm list\n"); + return; + } + tmp = glist; + while(tmp) { + if (tmp == s) { + if (tmpl) + tmpl->next = tmp->next; + else + glist = tmp->next; + break; + } + tmpl = tmp; + tmp = tmp->next; + } + glistcnt--; + if (s->owner) { + s->owner->stream = NULL; + if (s->owner->streamid > -1) + ast_sched_del(s->owner->sched, s->owner->streamid); + s->owner->streamid = -1; + } + pthread_mutex_unlock(&gsm_lock); + ast_update_use_count(); + if (!tmp) + ast_log(LOG_WARNING, "Freeing a filestream we don't seem to own\n"); + close(s->fd); + free(s); +} + +static int ast_read_callback(void *data) +{ + int retval = 0; + int res; + int delay = 20; + struct ast_filestream *s = data; + struct timeval tv; + /* Send a frame from the file to the appropriate channel */ + + s->fr.frametype = AST_FRAME_VOICE; + s->fr.subclass = AST_FORMAT_GSM; + s->fr.offset = AST_FRIENDLY_OFFSET; + s->fr.timelen = 20; + s->fr.datalen = 33; + s->fr.mallocd = 0; + s->fr.data = s->gsm; + if ((res = read(s->fd, s->gsm, 33)) != 33) { + if (res) + ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); + s->owner->streamid = -1; + return 0; + } + /* Lastly, process the frame */ + if (ast_write(s->owner, &s->fr)) { + ast_log(LOG_WARNING, "Failed to write frame\n"); + s->owner->streamid = -1; + return 0; + } + if (s->last.tv_usec || s->last.tv_usec) { + int ms; + gettimeofday(&tv, NULL); + ms = 1000 * (tv.tv_sec - s->last.tv_sec) + + (tv.tv_usec - s->last.tv_usec) / 1000; + s->last.tv_sec = tv.tv_sec; + s->last.tv_usec = tv.tv_usec; + if ((ms - delay) * (ms - delay) > 4) { + /* Compensate if we're more than 2 ms off */ + s->adj -= (ms - delay); + } +#if 0 + fprintf(stdout, "Delay is %d, adjustment is %d, last was %d\n", delay, s->adj, ms); +#endif + delay += s->adj; + if (delay < 1) + delay = 1; + } else + gettimeofday(&s->last, NULL); + if (s->lasttimeout != delay) { + /* We'll install the next timeout now. */ + s->owner->streamid = ast_sched_add(s->owner->sched, + delay, ast_read_callback, s); + s->lasttimeout = delay; + } else { + /* Just come back again at the same time */ + retval = -1; + } + return retval; +} + +static int gsm_apply(struct ast_channel *c, struct ast_filestream *s) +{ + /* Select our owner for this stream, and get the ball rolling. */ + s->owner = c; + ast_read_callback(s); + return 0; +} + +static int gsm_write(struct ast_filestream *fs, struct ast_frame *f) +{ + int res; + if (f->frametype != AST_FRAME_VOICE) { + ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); + return -1; + } + if (f->subclass != AST_FORMAT_GSM) { + ast_log(LOG_WARNING, "Asked to write non-GSM frame (%d)!\n", f->subclass); + return -1; + } + if (f->datalen != 33) { + ast_log(LOG_WARNING, "Invalid data length, %d, should be 33\n", f->datalen); + return -1; + } + if ((res = write(fs->fd, f->data, f->datalen)) != f->datalen) { + ast_log(LOG_WARNING, "Bad write (%d/33): %s\n", res, strerror(errno)); + return -1; + } + return 0; +} + +static char *gsm_getcomment(struct ast_filestream *s) +{ + return NULL; +} + +int load_module() +{ + return ast_format_register(name, exts, AST_FORMAT_GSM, + gsm_open, + gsm_rewrite, + gsm_apply, + gsm_write, + gsm_read, + gsm_close, + gsm_getcomment); + + +} + +int unload_module() +{ + struct ast_filestream *tmp, *tmpl; + if (pthread_mutex_lock(&gsm_lock)) { + ast_log(LOG_WARNING, "Unable to lock gsm list\n"); + return -1; + } + tmp = glist; + while(tmp) { + if (tmp->owner) + ast_softhangup(tmp->owner); + tmpl = tmp; + tmp = tmp->next; + free(tmpl); + } + pthread_mutex_unlock(&gsm_lock); + return ast_format_unregister(name); +} + +int usecount() +{ + int res; + if (pthread_mutex_lock(&gsm_lock)) { + ast_log(LOG_WARNING, "Unable to lock gsm list\n"); + return -1; + } + res = glistcnt; + pthread_mutex_unlock(&gsm_lock); + return res; +} + +char *description() +{ + return desc; +} + diff --git a/formats/format_mp3.c b/formats/format_mp3.c index 811acbe14..85abdbc1b 100755 --- a/formats/format_mp3.c +++ b/formats/format_mp3.c @@ -3,7 +3,7 @@ * * Everybody's favorite format: MP3 Files! Yay! * - * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * Copyright (C) 1999, Mark Spencer * * Mark Spencer * @@ -26,8 +26,7 @@ #include #include "../channels/adtranvofr.h" - -#define MP3_MAX_SIZE 1400 +#define MAX_FRAME_SIZE 1441 struct ast_filestream { /* First entry MUST be reserved for the channel type */ @@ -36,9 +35,13 @@ struct ast_filestream { int fd; /* Descriptor */ struct ast_channel *owner; struct ast_filestream *next; - struct ast_frame *fr; /* Frame representation of buf */ - char buf[sizeof(struct ast_frame) + MP3_MAX_SIZE + AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */ + struct ast_frame fr; /* Frame representation of buf */ + char offset[AST_FRIENDLY_OFFSET]; + unsigned char buf[MAX_FRAME_SIZE * 2]; + int lasttimeout; int pos; + int adj; + struct timeval last; }; @@ -47,16 +50,10 @@ static pthread_mutex_t mp3_lock = PTHREAD_MUTEX_INITIALIZER; static int glistcnt = 0; static char *name = "mp3"; -static char *desc = "MPEG-2 Layer 3 File Format Support"; +static char *desc = "MPEG-1,2 Layer 3 File Format Support"; static char *exts = "mp3|mpeg3"; -#if 0 -#define MP3_FRAMELEN 417 -#else -#define MP3_FRAMELEN 400 -#endif -#define MP3_OUTPUTLEN 2304 /* Bytes */ -#define MP3_TIMELEN ((MP3_OUTPUTLEN * 1000 / 16000) ) +#include "../codecs/mp3anal.h" static struct ast_filestream *mp3_open(int fd) { @@ -74,13 +71,10 @@ static struct ast_filestream *mp3_open(int fd) glist = tmp; tmp->fd = fd; tmp->owner = NULL; - tmp->fr = (struct ast_frame *)tmp->buf; - tmp->fr->data = tmp->buf + sizeof(struct ast_frame); - tmp->fr->frametype = AST_FRAME_VOICE; - tmp->fr->subclass = AST_FORMAT_MP3; - /* datalen will vary for each frame */ - tmp->fr->src = name; - tmp->fr->mallocd = 0; + tmp->lasttimeout = -1; + tmp->last.tv_usec = 0; + tmp->last.tv_sec = 0; + tmp->adj = 0; glistcnt++; pthread_mutex_unlock(&mp3_lock); ast_update_use_count(); @@ -104,7 +98,6 @@ static struct ast_filestream *mp3_rewrite(int fd, char *comment) glist = tmp; tmp->fd = fd; tmp->owner = NULL; - tmp->fr = NULL; glistcnt++; pthread_mutex_unlock(&mp3_lock); ast_update_use_count(); @@ -155,28 +148,67 @@ static void mp3_close(struct ast_filestream *s) static int ast_read_callback(void *data) { /* XXX Don't assume frames are this size XXX */ - u_int16_t size=MP3_FRAMELEN; u_int32_t delay = -1; int res; struct ast_filestream *s = data; - /* Send a frame from the file to the appropriate channel */ - /* Read the data into the buffer */ - s->fr->offset = AST_FRIENDLY_OFFSET; - s->fr->datalen = size; - s->fr->data = s->buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET; - if ((res = read(s->fd, s->fr->data , size)) != size) { - ast_log(LOG_WARNING, "Short read (%d of %d bytes) (%s)!\n", res, size, strerror(errno)); + int size; + int ms=0; + struct timeval tv; + if ((res = read(s->fd, s->buf , 4)) != 4) { + ast_log(LOG_WARNING, "Short read (%d of 4 bytes) (%s)!\n", res, strerror(errno)); s->owner->streamid = -1; return 0; } - delay = MP3_TIMELEN; - s->fr->timelen = delay; + if (mp3_badheader(s->buf)) { + ast_log(LOG_WARNING, "Bad mp3 header\n"); + return 0; + } + if ((size = mp3_framelen(s->buf)) < 0) { + ast_log(LOG_WARNING, "Unable to calculate frame size\n"); + return 0; + } + if ((res = read(s->fd, s->buf + 4 , size - 4)) != size - 4) { + ast_log(LOG_WARNING, "Short read (%d of %d bytes) (%s)!\n", res, size - 4, strerror(errno)); + s->owner->streamid = -1; + return 0; + } + /* Send a frame from the file to the appropriate channel */ + /* Read the data into the buffer */ + s->fr.offset = AST_FRIENDLY_OFFSET; + s->fr.frametype = AST_FRAME_VOICE; + s->fr.subclass = AST_FORMAT_MP3; + s->fr.mallocd = 0; + s->fr.src = name; + s->fr.datalen = size; + s->fr.data = s->buf; + delay = mp3_samples(s->buf) * 1000 / mp3_samplerate(s->buf); + if (s->last.tv_sec || s->last.tv_usec) { + /* To keep things running smoothly, we watch how close we're coming */ + gettimeofday(&tv, NULL); + ms = ((tv.tv_usec - s->last.tv_usec) / 1000 + (tv.tv_sec - s->last.tv_sec) * 1000); + /* If we're within 2 milliseconds, that's close enough */ + if ((ms - delay) * (ms - delay) > 4) + s->adj -= (ms - delay); + } + s->fr.timelen = delay; +#if 0 + ast_log(LOG_DEBUG, "delay is %d, adjusting by %d, as last was %d\n", delay, s->adj, ms); +#endif + delay += s->adj; + if (delay < 1) + delay = 1; /* Lastly, process the frame */ - if (ast_write(s->owner, s->fr)) { + if (ast_write(s->owner, &s->fr)) { ast_log(LOG_WARNING, "Failed to write frame\n"); s->owner->streamid = -1; return 0; } + gettimeofday(&s->last, NULL); + if (s->lasttimeout != delay) { + s->owner->streamid = ast_sched_add(s->owner->sched, delay, ast_read_callback, s); + s->lasttimeout = delay; + return 0; + } return -1; } @@ -184,7 +216,6 @@ static int mp3_apply(struct ast_channel *c, struct ast_filestream *s) { /* Select our owner for this stream, and get the ball rolling. */ s->owner = c; - s->owner->streamid = ast_sched_add(s->owner->sched, MP3_TIMELEN, ast_read_callback, s); ast_read_callback(s); return 0; } @@ -192,10 +223,6 @@ static int mp3_apply(struct ast_channel *c, struct ast_filestream *s) static int mp3_write(struct ast_filestream *fs, struct ast_frame *f) { int res; - if (fs->fr) { - ast_log(LOG_WARNING, "Asked to write on a read stream??\n"); - return -1; - } if (f->frametype != AST_FRAME_VOICE) { ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; @@ -211,7 +238,7 @@ static int mp3_write(struct ast_filestream *fs, struct ast_frame *f) return 0; } -char *mp3_getcomment(struct ast_filestream *s) +static char *mp3_getcomment(struct ast_filestream *s) { return NULL; } diff --git a/formats/format_wav.c b/formats/format_wav.c index e3265d379..9ba4fdc22 100755 --- a/formats/format_wav.c +++ b/formats/format_wav.c @@ -3,7 +3,7 @@ * * Microsoft WAV File Format using libaudiofile * - * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * Copyright (C) 1999, Mark Spencer * * Mark Spencer * @@ -298,7 +298,7 @@ static int wav_write(struct ast_filestream *fs, struct ast_frame *f) return 0; } -char *wav_getcomment(struct ast_filestream *s) +static char *wav_getcomment(struct ast_filestream *s) { return NULL; } diff --git a/formats/format_wav_gsm.c b/formats/format_wav_gsm.c new file mode 100755 index 000000000..b901a4028 --- /dev/null +++ b/formats/format_wav_gsm.c @@ -0,0 +1,586 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Save GSM in the proprietary Microsoft format. + * + * 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 +#include +#include +#include +#include "msgsm.h" + +/* Some Ideas for this code came from makewave.c by Jeffery Chilton */ + +/* Portions of the conversion code are by guido@sienanet.it */ + +struct ast_filestream { + void *reserved[AST_RESERVED_POINTERS]; + /* Believe it or not, we must decode/recode to account for the + weird MS format */ + /* This is what a filestream means to us */ + int fd; /* Descriptor */ + int bytes; + struct ast_channel *owner; + struct ast_frame fr; /* Frame information */ + char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */ + char empty; /* Empty character */ + unsigned char gsm[66]; /* Two Real GSM Frames */ + int foffset; + int secondhalf; /* Are we on the second half */ + int lasttimeout; + struct timeval last; + int adj; + struct ast_filestream *next; +}; + + +static struct ast_filestream *glist = NULL; +static pthread_mutex_t wav_lock = PTHREAD_MUTEX_INITIALIZER; +static int glistcnt = 0; + +static char *name = "wav49"; +static char *desc = "Microsoft WAV format (Proprietary GSM)"; +static char *exts = "WAV"; + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define htoll(b) (b) +#define htols(b) (b) +#define ltohl(b) (b) +#define ltohs(b) (b) +#else +#if __BYTE_ORDER == __BIG_ENDIAN +#define htoll(b) \ + (((((b) ) & 0xFF) << 24) | \ + ((((b) >> 8) & 0xFF) << 16) | \ + ((((b) >> 16) & 0xFF) << 8) | \ + ((((b) >> 24) & 0xFF) )) +#define htols(b) \ + (((((b) ) & 0xFF) << 8) | \ + ((((b) >> 8) & 0xFF) )) +#define ltohl(b) htoll(b) +#define ltohs(b) htols(b) +#else +#error "Endianess not defined" +#endif +#endif + + +static int check_header(int fd) +{ + int type, size, formtype; + int fmt, hsize, fact; + short format, chans; + int freq; + int data; + if (read(fd, &type, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (type)\n"); + return -1; + } + if (read(fd, &size, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (size)\n"); + return -1; + } + size = ltohl(size); + if (read(fd, &formtype, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (formtype)\n"); + return -1; + } + if (memcmp(&type, "RIFF", 4)) { + ast_log(LOG_WARNING, "Does not begin with RIFF\n"); + return -1; + } + if (memcmp(&formtype, "WAVE", 4)) { + ast_log(LOG_WARNING, "Does not contain WAVE\n"); + return -1; + } + if (read(fd, &fmt, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (fmt)\n"); + return -1; + } + if (memcmp(&fmt, "fmt ", 4)) { + ast_log(LOG_WARNING, "Does not say fmt\n"); + return -1; + } + if (read(fd, &hsize, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (formtype)\n"); + return -1; + } + if (ltohl(hsize) != 20) { + ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize)); + return -1; + } + if (read(fd, &format, 2) != 2) { + ast_log(LOG_WARNING, "Read failed (format)\n"); + return -1; + } + if (ltohs(format) != 49) { + ast_log(LOG_WARNING, "Not a GSM file %d\n", ltohs(format)); + return -1; + } + if (read(fd, &chans, 2) != 2) { + ast_log(LOG_WARNING, "Read failed (format)\n"); + return -1; + } + if (ltohs(chans) != 1) { + ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans)); + return -1; + } + if (read(fd, &freq, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (freq)\n"); + return -1; + } + if (ltohl(freq) != 8000) { + ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq)); + return -1; + } + /* Ignore the byte frequency */ + if (read(fd, &freq, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (X_1)\n"); + return -1; + } + /* Ignore the two weird fields */ + if (read(fd, &freq, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (X_2/X_3)\n"); + return -1; + } + /* Ignore the byte frequency */ + if (read(fd, &freq, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (Y_1)\n"); + return -1; + } + /* Check for the word fact */ + if (read(fd, &fact, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (fact)\n"); + return -1; + } + if (memcmp(&fact, "fact", 4)) { + ast_log(LOG_WARNING, "Does not say fact\n"); + return -1; + } + /* Ignore the "fact value" */ + if (read(fd, &fact, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (fact header)\n"); + return -1; + } + if (read(fd, &fact, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (fact value)\n"); + return -1; + } + /* Check for the word data */ + if (read(fd, &data, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (data)\n"); + return -1; + } + if (memcmp(&data, "data", 4)) { + ast_log(LOG_WARNING, "Does not say data\n"); + return -1; + } + /* Ignore the data length */ + if (read(fd, &data, 4) != 4) { + ast_log(LOG_WARNING, "Read failed (data)\n"); + return -1; + } + return 0; +} + +static int update_header(int fd, int bytes) +{ + int cur; + int datalen = htoll(bytes); + int filelen = htoll(52 + ((bytes + 1) & ~0x1)); + cur = lseek(fd, 0, SEEK_CUR); + if (cur < 0) { + ast_log(LOG_WARNING, "Unable to find our position\n"); + return -1; + } + if (lseek(fd, 4, SEEK_SET) != 4) { + ast_log(LOG_WARNING, "Unable to set our position\n"); + return -1; + } + if (write(fd, &filelen, 4) != 4) { + ast_log(LOG_WARNING, "Unable to set write file size\n"); + return -1; + } + if (lseek(fd, 56, SEEK_SET) != 56) { + ast_log(LOG_WARNING, "Unable to set our position\n"); + return -1; + } + if (write(fd, &datalen, 4) != 4) { + ast_log(LOG_WARNING, "Unable to set write datalen\n"); + return -1; + } + if (lseek(fd, cur, SEEK_SET) != cur) { + ast_log(LOG_WARNING, "Unable to return to position\n"); + return -1; + } + return 0; +} + +static int write_header(int fd) +{ + unsigned int hz=htoll(8000); + unsigned int bhz = htoll(1625); + unsigned int hs = htoll(20); + unsigned short fmt = htols(49); + unsigned short chans = htols(1); + unsigned int fhs = htoll(4); + unsigned int x_1 = htoll(65); + unsigned short x_2 = htols(2); + unsigned short x_3 = htols(320); + unsigned int y_1 = htoll(20160); + unsigned int size = htoll(0); + /* Write a GSM header, ignoring sizes which will be filled in later */ + if (write(fd, "RIFF", 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &size, 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, "WAVEfmt ", 8) != 8) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &hs, 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &fmt, 2) != 2) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &chans, 2) != 2) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &hz, 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &bhz, 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &x_1, 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &x_2, 2) != 2) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &x_3, 2) != 2) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, "fact", 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &fhs, 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &y_1, 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, "data", 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + if (write(fd, &size, 4) != 4) { + ast_log(LOG_WARNING, "Unable to write header\n"); + return -1; + } + return 0; +} + +static struct ast_filestream *wav_open(int fd) +{ + /* We don't have any header to read or anything really, but + if we did, it would go here. We also might want to check + and be sure it's a valid file. */ + struct ast_filestream *tmp; + if ((tmp = malloc(sizeof(struct ast_filestream)))) { + memset(tmp, 0, sizeof(struct ast_filestream)); + if (check_header(fd)) { + free(tmp); + return NULL; + } + if (pthread_mutex_lock(&wav_lock)) { + ast_log(LOG_WARNING, "Unable to lock wav list\n"); + free(tmp); + return NULL; + } + tmp->next = glist; + glist = tmp; + tmp->fd = fd; + tmp->owner = NULL; + tmp->fr.data = tmp->gsm; + tmp->fr.frametype = AST_FRAME_VOICE; + tmp->fr.subclass = AST_FORMAT_GSM; + /* datalen will vary for each frame */ + tmp->fr.src = name; + tmp->fr.mallocd = 0; + tmp->secondhalf = 0; + tmp->lasttimeout = -1; + glistcnt++; + pthread_mutex_unlock(&wav_lock); + ast_update_use_count(); + } + return tmp; +} + +static struct ast_filestream *wav_rewrite(int fd, char *comment) +{ + /* We don't have any header to read or anything really, but + if we did, it would go here. We also might want to check + and be sure it's a valid file. */ + struct ast_filestream *tmp; + if ((tmp = malloc(sizeof(struct ast_filestream)))) { + memset(tmp, 0, sizeof(struct ast_filestream)); + if (write_header(fd)) { + free(tmp); + return NULL; + } + if (pthread_mutex_lock(&wav_lock)) { + ast_log(LOG_WARNING, "Unable to lock wav list\n"); + free(tmp); + return NULL; + } + tmp->next = glist; + glist = tmp; + tmp->fd = fd; + tmp->owner = NULL; + tmp->lasttimeout = -1; + glistcnt++; + pthread_mutex_unlock(&wav_lock); + ast_update_use_count(); + } else + ast_log(LOG_WARNING, "Out of memory\n"); + return tmp; +} + +static struct ast_frame *wav_read(struct ast_filestream *s) +{ + return NULL; +} + +static void wav_close(struct ast_filestream *s) +{ + struct ast_filestream *tmp, *tmpl = NULL; + char zero = 0; + if (pthread_mutex_lock(&wav_lock)) { + ast_log(LOG_WARNING, "Unable to lock wav list\n"); + return; + } + tmp = glist; + while(tmp) { + if (tmp == s) { + if (tmpl) + tmpl->next = tmp->next; + else + glist = tmp->next; + break; + } + tmpl = tmp; + tmp = tmp->next; + } + glistcnt--; + if (s->owner) { + s->owner->stream = NULL; + if (s->owner->streamid > -1) + ast_sched_del(s->owner->sched, s->owner->streamid); + s->owner->streamid = -1; + } + pthread_mutex_unlock(&wav_lock); + ast_update_use_count(); + if (!tmp) + ast_log(LOG_WARNING, "Freeing a filestream we don't seem to own\n"); + /* Pad to even length */ + if (s->bytes & 0x1) + write(s->fd, &zero, 1); + close(s->fd); + free(s); +} + +static int ast_read_callback(void *data) +{ + int retval = 0; + int res; + int delay = 20; + struct ast_filestream *s = data; + char msdata[66]; + struct timeval tv; + /* Send a frame from the file to the appropriate channel */ + + s->fr.frametype = AST_FRAME_VOICE; + s->fr.subclass = AST_FORMAT_GSM; + s->fr.offset = AST_FRIENDLY_OFFSET; + s->fr.timelen = 20; + s->fr.datalen = 33; + s->fr.mallocd = 0; + if (s->secondhalf) { + /* Just return a frame based on the second GSM frame */ + s->fr.data = s->gsm + 33; + } else { + if ((res = read(s->fd, msdata, 65)) != 65) { + if (res && (res != 1)) + ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); + s->owner->streamid = -1; + return 0; + } + /* Convert from MS format to two real GSM frames */ + conv65(msdata, s->gsm); + s->fr.data = s->gsm; + } + s->secondhalf = !s->secondhalf; + /* Lastly, process the frame */ + if (ast_write(s->owner, &s->fr)) { + ast_log(LOG_WARNING, "Failed to write frame\n"); + s->owner->streamid = -1; + return 0; + } + if (s->last.tv_usec || s->last.tv_usec) { + int ms; + gettimeofday(&tv, NULL); + ms = 1000 * (tv.tv_sec - s->last.tv_sec) + + (tv.tv_usec - s->last.tv_usec) / 1000; + s->last.tv_sec = tv.tv_sec; + s->last.tv_usec = tv.tv_usec; + if ((ms - delay) * (ms - delay) > 4) { + /* Compensate if we're more than 2 ms off */ + s->adj -= (ms - delay); + } +#if 0 + fprintf(stdout, "Delay is %d, adjustment is %d, last was %d\n", delay, s->adj, ms); +#endif + delay += s->adj; + if (delay < 1) + delay = 1; + } else + gettimeofday(&s->last, NULL); + if (s->lasttimeout != delay) { + /* We'll install the next timeout now. */ + s->owner->streamid = ast_sched_add(s->owner->sched, + delay, ast_read_callback, s); + s->lasttimeout = delay; + } else { + /* Just come back again at the same time */ + retval = -1; + } + return retval; +} + +static int wav_apply(struct ast_channel *c, struct ast_filestream *s) +{ + /* Select our owner for this stream, and get the ball rolling. */ + s->owner = c; + ast_read_callback(s); + return 0; +} + +static int wav_write(struct ast_filestream *fs, struct ast_frame *f) +{ + int res; + char msdata[66]; + if (f->frametype != AST_FRAME_VOICE) { + ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); + return -1; + } + if (f->subclass != AST_FORMAT_GSM) { + ast_log(LOG_WARNING, "Asked to write non-GSM frame (%d)!\n", f->subclass); + return -1; + } + if (fs->secondhalf) { + memcpy(fs->gsm + 33, f->data, 33); + conv66(fs->gsm, msdata); + if ((res = write(fs->fd, msdata, 65)) != 65) { + ast_log(LOG_WARNING, "Bad write (%d/65): %s\n", res, strerror(errno)); + return -1; + } + fs->bytes += 65; + update_header(fs->fd, fs->bytes); + } else { + /* Copy the data and do nothing */ + memcpy(fs->gsm, f->data, 33); + } + fs->secondhalf = !fs->secondhalf; + return 0; +} + +static char *wav_getcomment(struct ast_filestream *s) +{ + return NULL; +} + +int load_module() +{ + return ast_format_register(name, exts, AST_FORMAT_GSM, + wav_open, + wav_rewrite, + wav_apply, + wav_write, + wav_read, + wav_close, + wav_getcomment); + + +} + +int unload_module() +{ + struct ast_filestream *tmp, *tmpl; + if (pthread_mutex_lock(&wav_lock)) { + ast_log(LOG_WARNING, "Unable to lock wav list\n"); + return -1; + } + tmp = glist; + while(tmp) { + if (tmp->owner) + ast_softhangup(tmp->owner); + tmpl = tmp; + tmp = tmp->next; + free(tmpl); + } + pthread_mutex_unlock(&wav_lock); + return ast_format_unregister(name); +} + +int usecount() +{ + int res; + if (pthread_mutex_lock(&wav_lock)) { + ast_log(LOG_WARNING, "Unable to lock wav list\n"); + return -1; + } + res = glistcnt; + pthread_mutex_unlock(&wav_lock); + return res; +} + +char *description() +{ + return desc; +} + diff --git a/formats/msgsm.h b/formats/msgsm.h new file mode 100755 index 000000000..2513e72b1 --- /dev/null +++ b/formats/msgsm.h @@ -0,0 +1,685 @@ +/* Conversion routines derived from code by guido@sienanet.it */ + +#define GSM_MAGIC 0xD + +typedef unsigned char gsm_byte; +typedef unsigned char wav_byte; +typedef unsigned int uword; + +#define readGSM_33(c1) { \ + gsm_byte *c = (c1); \ + LARc[0] = (*c++ & 0xF) << 2; /* 1 */ \ + LARc[0] |= (*c >> 6) & 0x3; \ + LARc[1] = *c++ & 0x3F; \ + LARc[2] = (*c >> 3) & 0x1F; \ + LARc[3] = (*c++ & 0x7) << 2; \ + LARc[3] |= (*c >> 6) & 0x3; \ + LARc[4] = (*c >> 2) & 0xF; \ + LARc[5] = (*c++ & 0x3) << 2; \ + LARc[5] |= (*c >> 6) & 0x3; \ + LARc[6] = (*c >> 3) & 0x7; \ + LARc[7] = *c++ & 0x7; \ + Nc[0] = (*c >> 1) & 0x7F; \ + bc[0] = (*c++ & 0x1) << 1; \ + bc[0] |= (*c >> 7) & 0x1; \ + Mc[0] = (*c >> 5) & 0x3; \ + xmaxc[0] = (*c++ & 0x1F) << 1; \ + xmaxc[0] |= (*c >> 7) & 0x1; \ + xmc[0] = (*c >> 4) & 0x7; \ + xmc[1] = (*c >> 1) & 0x7; \ + xmc[2] = (*c++ & 0x1) << 2; \ + xmc[2] |= (*c >> 6) & 0x3; \ + xmc[3] = (*c >> 3) & 0x7; \ + xmc[4] = *c++ & 0x7; \ + xmc[5] = (*c >> 5) & 0x7; \ + xmc[6] = (*c >> 2) & 0x7; \ + xmc[7] = (*c++ & 0x3) << 1; /* 10 */ \ + xmc[7] |= (*c >> 7) & 0x1; \ + xmc[8] = (*c >> 4) & 0x7; \ + xmc[9] = (*c >> 1) & 0x7; \ + xmc[10] = (*c++ & 0x1) << 2; \ + xmc[10] |= (*c >> 6) & 0x3; \ + xmc[11] = (*c >> 3) & 0x7; \ + xmc[12] = *c++ & 0x7; \ + Nc[1] = (*c >> 1) & 0x7F; \ + bc[1] = (*c++ & 0x1) << 1; \ + bc[1] |= (*c >> 7) & 0x1; \ + Mc[1] = (*c >> 5) & 0x3; \ + xmaxc[1] = (*c++ & 0x1F) << 1; \ + xmaxc[1] |= (*c >> 7) & 0x1; \ + xmc[13] = (*c >> 4) & 0x7; \ + xmc[14] = (*c >> 1) & 0x7; \ + xmc[15] = (*c++ & 0x1) << 2; \ + xmc[15] |= (*c >> 6) & 0x3; \ + xmc[16] = (*c >> 3) & 0x7; \ + xmc[17] = *c++ & 0x7; \ + xmc[18] = (*c >> 5) & 0x7; \ + xmc[19] = (*c >> 2) & 0x7; \ + xmc[20] = (*c++ & 0x3) << 1; \ + xmc[20] |= (*c >> 7) & 0x1; \ + xmc[21] = (*c >> 4) & 0x7; \ + xmc[22] = (*c >> 1) & 0x7; \ + xmc[23] = (*c++ & 0x1) << 2; \ + xmc[23] |= (*c >> 6) & 0x3; \ + xmc[24] = (*c >> 3) & 0x7; \ + xmc[25] = *c++ & 0x7; \ + Nc[2] = (*c >> 1) & 0x7F; \ + bc[2] = (*c++ & 0x1) << 1; /* 20 */ \ + bc[2] |= (*c >> 7) & 0x1; \ + Mc[2] = (*c >> 5) & 0x3; \ + xmaxc[2] = (*c++ & 0x1F) << 1; \ + xmaxc[2] |= (*c >> 7) & 0x1; \ + xmc[26] = (*c >> 4) & 0x7; \ + xmc[27] = (*c >> 1) & 0x7; \ + xmc[28] = (*c++ & 0x1) << 2; \ + xmc[28] |= (*c >> 6) & 0x3; \ + xmc[29] = (*c >> 3) & 0x7; \ + xmc[30] = *c++ & 0x7; \ + xmc[31] = (*c >> 5) & 0x7; \ + xmc[32] = (*c >> 2) & 0x7; \ + xmc[33] = (*c++ & 0x3) << 1; \ + xmc[33] |= (*c >> 7) & 0x1; \ + xmc[34] = (*c >> 4) & 0x7; \ + xmc[35] = (*c >> 1) & 0x7; \ + xmc[36] = (*c++ & 0x1) << 2; \ + xmc[36] |= (*c >> 6) & 0x3; \ + xmc[37] = (*c >> 3) & 0x7; \ + xmc[38] = *c++ & 0x7; \ + Nc[3] = (*c >> 1) & 0x7F; \ + bc[3] = (*c++ & 0x1) << 1; \ + bc[3] |= (*c >> 7) & 0x1; \ + Mc[3] = (*c >> 5) & 0x3; \ + xmaxc[3] = (*c++ & 0x1F) << 1; \ + xmaxc[3] |= (*c >> 7) & 0x1; \ + xmc[39] = (*c >> 4) & 0x7; \ + xmc[40] = (*c >> 1) & 0x7; \ + xmc[41] = (*c++ & 0x1) << 2; \ + xmc[41] |= (*c >> 6) & 0x3; \ + xmc[42] = (*c >> 3) & 0x7; \ + xmc[43] = *c++ & 0x7; /* 30 */ \ + xmc[44] = (*c >> 5) & 0x7; \ + xmc[45] = (*c >> 2) & 0x7; \ + xmc[46] = (*c++ & 0x3) << 1; \ + xmc[46] |= (*c >> 7) & 0x1; \ + xmc[47] = (*c >> 4) & 0x7; \ + xmc[48] = (*c >> 1) & 0x7; \ + xmc[49] = (*c++ & 0x1) << 2; \ + xmc[49] |= (*c >> 6) & 0x3; \ + xmc[50] = (*c >> 3) & 0x7; \ + xmc[51] = *c & 0x7; /* 33 */ \ +} + +static void conv66(gsm_byte * d, wav_byte * c) { + gsm_byte frame_chain; + unsigned int sr; + unsigned int LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + + readGSM_33(d); + sr = 0; + sr = (sr >> 6) | (LARc[0] << 10); + sr = (sr >> 6) | (LARc[1] << 10); + *c++ = sr >> 4; + sr = (sr >> 5) | (LARc[2] << 11); + *c++ = sr >> 7; + sr = (sr >> 5) | (LARc[3] << 11); + sr = (sr >> 4) | (LARc[4] << 12); + *c++ = sr >> 6; + sr = (sr >> 4) | (LARc[5] << 12); + sr = (sr >> 3) | (LARc[6] << 13); + *c++ = sr >> 7; + sr = (sr >> 3) | (LARc[7] << 13); + sr = (sr >> 7) | (Nc[0] << 9); + *c++ = sr >> 5; + sr = (sr >> 2) | (bc[0] << 14); + sr = (sr >> 2) | (Mc[0] << 14); + sr = (sr >> 6) | (xmaxc[0] << 10); + *c++ = sr >> 3; + sr = (sr >> 3 )|( xmc[0] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[1] << 13); + sr = (sr >> 3 )|( xmc[2] << 13); + sr = (sr >> 3 )|( xmc[3] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[4] << 13); + sr = (sr >> 3 )|( xmc[5] << 13); + sr = (sr >> 3 )|( xmc[6] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[7] << 13); + sr = (sr >> 3 )|( xmc[8] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[9] << 13); + sr = (sr >> 3 )|( xmc[10] << 13); + sr = (sr >> 3 )|( xmc[11] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[12] << 13); + sr = (sr >> 7 )|( Nc[1] << 9); + *c++ = sr >> 5; + sr = (sr >> 2 )|( bc[1] << 14); + sr = (sr >> 2 )|( Mc[1] << 14); + sr = (sr >> 6 )|( xmaxc[1] << 10); + *c++ = sr >> 3; + sr = (sr >> 3 )|( xmc[13] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[14] << 13); + sr = (sr >> 3 )|( xmc[15] << 13); + sr = (sr >> 3 )|( xmc[16] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[17] << 13); + sr = (sr >> 3 )|( xmc[18] << 13); + sr = (sr >> 3 )|( xmc[19] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[20] << 13); + sr = (sr >> 3 )|( xmc[21] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[22] << 13); + sr = (sr >> 3 )|( xmc[23] << 13); + sr = (sr >> 3 )|( xmc[24] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[25] << 13); + sr = (sr >> 7 )|( Nc[2] << 9); + *c++ = sr >> 5; + sr = (sr >> 2 )|( bc[2] << 14); + sr = (sr >> 2 )|( Mc[2] << 14); + sr = (sr >> 6 )|( xmaxc[2] << 10); + *c++ = sr >> 3; + sr = (sr >> 3 )|( xmc[26] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[27] << 13); + sr = (sr >> 3 )|( xmc[28] << 13); + sr = (sr >> 3 )|( xmc[29] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[30] << 13); + sr = (sr >> 3 )|( xmc[31] << 13); + sr = (sr >> 3 )|( xmc[32] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[33] << 13); + sr = (sr >> 3 )|( xmc[34] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[35] << 13); + sr = (sr >> 3 )|( xmc[36] << 13); + sr = (sr >> 3 )|( xmc[37] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[38] << 13); + sr = (sr >> 7 )|( Nc[3] << 9); + *c++ = sr >> 5; + sr = (sr >> 2 )|( bc[3] << 14); + sr = (sr >> 2 )|( Mc[3] << 14); + sr = (sr >> 6 )|( xmaxc[3] << 10); + *c++ = sr >> 3; + sr = (sr >> 3 )|( xmc[39] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[40] << 13); + sr = (sr >> 3 )|( xmc[41] << 13); + sr = (sr >> 3 )|( xmc[42] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[43] << 13); + sr = (sr >> 3 )|( xmc[44] << 13); + sr = (sr >> 3 )|( xmc[45] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[46] << 13); + sr = (sr >> 3 )|( xmc[47] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[48] << 13); + sr = (sr >> 3 )|( xmc[49] << 13); + sr = (sr >> 3 )|( xmc[50] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[51] << 13); + sr = sr >> 4; + *c = sr >> 8; + frame_chain = *c; + readGSM_33(d+33);// puts all the parameters into LARc etc. + + + sr = 0; +// sr = (sr >> 4 )|( s->frame_chain << 12); + sr = (sr >> 4 )|( frame_chain << 12); + + sr = (sr >> 6 )|( LARc[0] << 10); + *c++ = sr >> 6; + sr = (sr >> 6 )|( LARc[1] << 10); + *c++ = sr >> 8; + sr = (sr >> 5 )|( LARc[2] << 11); + sr = (sr >> 5 )|( LARc[3] << 11); + *c++ = sr >> 6; + sr = (sr >> 4 )|( LARc[4] << 12); + sr = (sr >> 4 )|( LARc[5] << 12); + *c++ = sr >> 6; + sr = (sr >> 3 )|( LARc[6] << 13); + sr = (sr >> 3 )|( LARc[7] << 13); + *c++ = sr >> 8; + sr = (sr >> 7 )|( Nc[0] << 9); + sr = (sr >> 2 )|( bc[0] << 14); + *c++ = sr >> 7; + sr = (sr >> 2 )|( Mc[0] << 14); + sr = (sr >> 6 )|( xmaxc[0] << 10); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[0] << 13); + sr = (sr >> 3 )|( xmc[1] << 13); + sr = (sr >> 3 )|( xmc[2] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[3] << 13); + sr = (sr >> 3 )|( xmc[4] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[5] << 13); + sr = (sr >> 3 )|( xmc[6] << 13); + sr = (sr >> 3 )|( xmc[7] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[8] << 13); + sr = (sr >> 3 )|( xmc[9] << 13); + sr = (sr >> 3 )|( xmc[10] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[11] << 13); + sr = (sr >> 3 )|( xmc[12] << 13); + *c++ = sr >> 8; + sr = (sr >> 7 )|( Nc[1] << 9); + sr = (sr >> 2 )|( bc[1] << 14); + *c++ = sr >> 7; + sr = (sr >> 2 )|( Mc[1] << 14); + sr = (sr >> 6 )|( xmaxc[1] << 10); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[13] << 13); + sr = (sr >> 3 )|( xmc[14] << 13); + sr = (sr >> 3 )|( xmc[15] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[16] << 13); + sr = (sr >> 3 )|( xmc[17] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[18] << 13); + sr = (sr >> 3 )|( xmc[19] << 13); + sr = (sr >> 3 )|( xmc[20] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[21] << 13); + sr = (sr >> 3 )|( xmc[22] << 13); + sr = (sr >> 3 )|( xmc[23] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[24] << 13); + sr = (sr >> 3 )|( xmc[25] << 13); + *c++ = sr >> 8; + sr = (sr >> 7 )|( Nc[2] << 9); + sr = (sr >> 2 )|( bc[2] << 14); + *c++ = sr >> 7; + sr = (sr >> 2 )|( Mc[2] << 14); + sr = (sr >> 6 )|( xmaxc[2] << 10); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[26] << 13); + sr = (sr >> 3 )|( xmc[27] << 13); + sr = (sr >> 3 )|( xmc[28] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[29] << 13); + sr = (sr >> 3 )|( xmc[30] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[31] << 13); + sr = (sr >> 3 )|( xmc[32] << 13); + sr = (sr >> 3 )|( xmc[33] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[34] << 13); + sr = (sr >> 3 )|( xmc[35] << 13); + sr = (sr >> 3 )|( xmc[36] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[37] << 13); + sr = (sr >> 3 )|( xmc[38] << 13); + *c++ = sr >> 8; + sr = (sr >> 7 )|( Nc[3] << 9); + sr = (sr >> 2 )|( bc[3] << 14); + *c++ = sr >> 7; + sr = (sr >> 2 )|( Mc[3] << 14); + sr = (sr >> 6 )|( xmaxc[3] << 10); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[39] << 13); + sr = (sr >> 3 )|( xmc[40] << 13); + sr = (sr >> 3 )|( xmc[41] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[42] << 13); + sr = (sr >> 3 )|( xmc[43] << 13); + *c++ = sr >> 8; + sr = (sr >> 3 )|( xmc[44] << 13); + sr = (sr >> 3 )|( xmc[45] << 13); + sr = (sr >> 3 )|( xmc[46] << 13); + *c++ = sr >> 7; + sr = (sr >> 3 )|( xmc[47] << 13); + sr = (sr >> 3 )|( xmc[48] << 13); + sr = (sr >> 3 )|( xmc[49] << 13); + *c++ = sr >> 6; + sr = (sr >> 3 )|( xmc[50] << 13); + sr = (sr >> 3 )|( xmc[51] << 13); + *c++ = sr >> 8; + +} + +#define writeGSM_33(c1) { \ + gsm_byte *c = (c1); \ + *c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */ \ + | ((LARc[0] >> 2) & 0xF); \ + *c++ = ((LARc[0] & 0x3) << 6) \ + | (LARc[1] & 0x3F); \ + *c++ = ((LARc[2] & 0x1F) << 3) \ + | ((LARc[3] >> 2) & 0x7); \ + *c++ = ((LARc[3] & 0x3) << 6) \ + | ((LARc[4] & 0xF) << 2) \ + | ((LARc[5] >> 2) & 0x3); \ + *c++ = ((LARc[5] & 0x3) << 6) \ + | ((LARc[6] & 0x7) << 3) \ + | (LARc[7] & 0x7); \ + *c++ = ((Nc[0] & 0x7F) << 1) \ + | ((bc[0] >> 1) & 0x1); \ + *c++ = ((bc[0] & 0x1) << 7) \ + | ((Mc[0] & 0x3) << 5) \ + | ((xmaxc[0] >> 1) & 0x1F); \ + *c++ = ((xmaxc[0] & 0x1) << 7) \ + | ((xmc[0] & 0x7) << 4) \ + | ((xmc[1] & 0x7) << 1) \ + | ((xmc[2] >> 2) & 0x1); \ + *c++ = ((xmc[2] & 0x3) << 6) \ + | ((xmc[3] & 0x7) << 3) \ + | (xmc[4] & 0x7); \ + *c++ = ((xmc[5] & 0x7) << 5) /* 10 */ \ + | ((xmc[6] & 0x7) << 2) \ + | ((xmc[7] >> 1) & 0x3); \ + *c++ = ((xmc[7] & 0x1) << 7) \ + | ((xmc[8] & 0x7) << 4) \ + | ((xmc[9] & 0x7) << 1) \ + | ((xmc[10] >> 2) & 0x1); \ + *c++ = ((xmc[10] & 0x3) << 6) \ + | ((xmc[11] & 0x7) << 3) \ + | (xmc[12] & 0x7); \ + *c++ = ((Nc[1] & 0x7F) << 1) \ + | ((bc[1] >> 1) & 0x1); \ + *c++ = ((bc[1] & 0x1) << 7) \ + | ((Mc[1] & 0x3) << 5) \ + | ((xmaxc[1] >> 1) & 0x1F); \ + *c++ = ((xmaxc[1] & 0x1) << 7) \ + | ((xmc[13] & 0x7) << 4) \ + | ((xmc[14] & 0x7) << 1) \ + | ((xmc[15] >> 2) & 0x1); \ + *c++ = ((xmc[15] & 0x3) << 6) \ + | ((xmc[16] & 0x7) << 3) \ + | (xmc[17] & 0x7); \ + *c++ = ((xmc[18] & 0x7) << 5) \ + | ((xmc[19] & 0x7) << 2) \ + | ((xmc[20] >> 1) & 0x3); \ + *c++ = ((xmc[20] & 0x1) << 7) \ + | ((xmc[21] & 0x7) << 4) \ + | ((xmc[22] & 0x7) << 1) \ + | ((xmc[23] >> 2) & 0x1); \ + *c++ = ((xmc[23] & 0x3) << 6) \ + | ((xmc[24] & 0x7) << 3) \ + | (xmc[25] & 0x7); \ + *c++ = ((Nc[2] & 0x7F) << 1) /* 20 */ \ + | ((bc[2] >> 1) & 0x1); \ + *c++ = ((bc[2] & 0x1) << 7) \ + | ((Mc[2] & 0x3) << 5) \ + | ((xmaxc[2] >> 1) & 0x1F); \ + *c++ = ((xmaxc[2] & 0x1) << 7) \ + | ((xmc[26] & 0x7) << 4) \ + | ((xmc[27] & 0x7) << 1) \ + | ((xmc[28] >> 2) & 0x1); \ + *c++ = ((xmc[28] & 0x3) << 6) \ + | ((xmc[29] & 0x7) << 3) \ + | (xmc[30] & 0x7); \ + *c++ = ((xmc[31] & 0x7) << 5) \ + | ((xmc[32] & 0x7) << 2) \ + | ((xmc[33] >> 1) & 0x3); \ + *c++ = ((xmc[33] & 0x1) << 7) \ + | ((xmc[34] & 0x7) << 4) \ + | ((xmc[35] & 0x7) << 1) \ + | ((xmc[36] >> 2) & 0x1); \ + *c++ = ((xmc[36] & 0x3) << 6) \ + | ((xmc[37] & 0x7) << 3) \ + | (xmc[38] & 0x7); \ + *c++ = ((Nc[3] & 0x7F) << 1) \ + | ((bc[3] >> 1) & 0x1); \ + *c++ = ((bc[3] & 0x1) << 7) \ + | ((Mc[3] & 0x3) << 5) \ + | ((xmaxc[3] >> 1) & 0x1F); \ + *c++ = ((xmaxc[3] & 0x1) << 7) \ + | ((xmc[39] & 0x7) << 4) \ + | ((xmc[40] & 0x7) << 1) \ + | ((xmc[41] >> 2) & 0x1); \ + *c++ = ((xmc[41] & 0x3) << 6) /* 30 */ \ + | ((xmc[42] & 0x7) << 3) \ + | (xmc[43] & 0x7); \ + *c++ = ((xmc[44] & 0x7) << 5) \ + | ((xmc[45] & 0x7) << 2) \ + | ((xmc[46] >> 1) & 0x3); \ + *c++ = ((xmc[46] & 0x1) << 7) \ + | ((xmc[47] & 0x7) << 4) \ + | ((xmc[48] & 0x7) << 1) \ + | ((xmc[49] >> 2) & 0x1); \ + *c++ = ((xmc[49] & 0x3) << 6) \ + | ((xmc[50] & 0x7) << 3) \ + | (xmc[51] & 0x7); \ +} + +static void conv65( wav_byte * c, gsm_byte * d){ + + unsigned int sr = 0; + unsigned int frame_chain; + unsigned int LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + + sr = *c++; + LARc[0] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 2; + LARc[1] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 4; + LARc[2] = sr & 0x1f; sr >>= 5; + LARc[3] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 2; + LARc[4] = sr & 0xf; sr >>= 4; + LARc[5] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; /* 5 */ + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[0] = sr & 0x7f; sr >>= 7; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[0] = sr & 0x3f; sr >>= 6; + xmc[0] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[1] = sr & 0x7; sr >>= 3; + xmc[2] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + xmc[5] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 10 */ + xmc[6] = sr & 0x7; sr >>= 3; + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[9] = sr & 0x7; sr >>= 3; + xmc[10] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[1] = sr & 0x7f; sr >>= 7; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[1] = sr & 0x3f; sr >>= 6; + xmc[13] = sr & 0x7; sr >>= 3; + sr = *c++; /* 15 */ + xmc[14] = sr & 0x7; sr >>= 3; + xmc[15] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + xmc[18] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[19] = sr & 0x7; sr >>= 3; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[22] = sr & 0x7; sr >>= 3; + xmc[23] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; /* 20 */ + Nc[2] = sr & 0x7f; sr >>= 7; + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[2] = sr & 0x3f; sr >>= 6; + xmc[26] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[27] = sr & 0x7; sr >>= 3; + xmc[28] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + xmc[31] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[32] = sr & 0x7; sr >>= 3; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + sr = *c++; /* 25 */ + xmc[35] = sr & 0x7; sr >>= 3; + xmc[36] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[3] = sr & 0x7f; sr >>= 7; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[3] = sr & 0x3f; sr >>= 6; + xmc[39] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[40] = sr & 0x7; sr >>= 3; + xmc[41] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 30 */ + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + xmc[44] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[45] = sr & 0x7; sr >>= 3; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + frame_chain = sr & 0xf; + + + writeGSM_33(d);// LARc etc. -> array of 33 GSM bytes + + + sr = frame_chain; + sr |= (uword)*c++ << 4; /* 1 */ + LARc[0] = sr & 0x3f; sr >>= 6; + LARc[1] = sr & 0x3f; sr >>= 6; + sr = *c++; + LARc[2] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 3; + LARc[3] = sr & 0x1f; sr >>= 5; + LARc[4] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; + LARc[5] = sr & 0xf; sr >>= 4; + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr = *c++; /* 5 */ + Nc[0] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[0] = sr & 0x3f; sr >>= 6; + xmc[0] = sr & 0x7; sr >>= 3; + xmc[1] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[2] = sr & 0x7; sr >>= 3; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[5] = sr & 0x7; sr >>= 3; + xmc[6] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 10 */ + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + xmc[9] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[10] = sr & 0x7; sr >>= 3; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[1] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[1] = sr & 0x3f; sr >>= 6; + xmc[13] = sr & 0x7; sr >>= 3; + xmc[14] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 15 */ + xmc[15] = sr & 0x7; sr >>= 3; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[18] = sr & 0x7; sr >>= 3; + xmc[19] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + xmc[22] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[23] = sr & 0x7; sr >>= 3; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[2] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; /* 20 */ + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[2] = sr & 0x3f; sr >>= 6; + xmc[26] = sr & 0x7; sr >>= 3; + xmc[27] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[28] = sr & 0x7; sr >>= 3; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[31] = sr & 0x7; sr >>= 3; + xmc[32] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + xmc[35] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 25 */ + xmc[36] = sr & 0x7; sr >>= 3; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[3] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[3] = sr & 0x3f; sr >>= 6; + xmc[39] = sr & 0x7; sr >>= 3; + xmc[40] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[41] = sr & 0x7; sr >>= 3; + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + sr = *c++; /* 30 */ + xmc[44] = sr & 0x7; sr >>= 3; + xmc[45] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + xmc[48] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[49] = sr & 0x7; sr >>= 3; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + writeGSM_33(d+33); + +} diff --git a/include/asterisk/channel_pvt.h b/include/asterisk/channel_pvt.h index 6628e9d5f..bd75102e5 100755 --- a/include/asterisk/channel_pvt.h +++ b/include/asterisk/channel_pvt.h @@ -3,7 +3,7 @@ * * Private channel definitions for channel implementations only. * - * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * Copyright (C) 1999, Mark Spencer * * Mark Spencer * @@ -40,8 +40,8 @@ struct ast_channel_pvt { }; /* Create a channel structure */ -struct ast_channel *ast_channel_alloc(); -#define ast_channel_free(a) free(a) +struct ast_channel *ast_channel_alloc(void); +void ast_channel_free(struct ast_channel *); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/asterisk/io.h b/include/asterisk/io.h index 64d039a51..82060c20d 100755 --- a/include/asterisk/io.h +++ b/include/asterisk/io.h @@ -3,7 +3,7 @@ * * Mark Spencer * - * Copyright(C) 1999, Adtran, Inc. + * Copyright(C) Mark Spencer * * Distributed under the terms of the GNU General Public License (GPL) Version 2 * @@ -38,10 +38,10 @@ extern "C" { struct io_context; /* Create a context for I/O operations */ -struct io_context *io_context_create(); +extern struct io_context *io_context_create(void); /* Destroy a context for I/O operations */ -void io_context_destroy(struct io_context *ioc); +extern void io_context_destroy(struct io_context *ioc); typedef int (*ast_io_cb)(int *id, int fd, short events, void *cbdata); #define AST_IO_CB(a) ((ast_io_cb)(a)) diff --git a/io.c b/io.c index 2ec5b0218..aef361c64 100755 --- a/io.c +++ b/io.c @@ -3,7 +3,7 @@ * * Mark Spencer * - * Copyright(C) 1999, Adtran, Inc. + * Copyright(C) Mark Spencer * * Distributed under the terms of the GNU General Public License (GPL) Version 2 * @@ -58,7 +58,7 @@ struct io_context { }; -struct io_context *io_context_create() +struct io_context *io_context_create(void) { /* Create an I/O context */ struct io_context *tmp; -- cgit v1.2.3