From f7f5b56b0aae87907abd20cfbb845b3e0ad7808e Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Thu, 2 Oct 2003 23:17:32 +0000 Subject: Minor ADPCM quality enhancements git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1603 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- codecs/codec_adpcm.c | 91 +++++++++++++++++++++++++++++++++++----------------- formats/format_vox.c | 69 ++++++++++++++++++++++++++++----------- 2 files changed, 112 insertions(+), 48 deletions(-) diff --git a/codecs/codec_adpcm.c b/codecs/codec_adpcm.c index 584538367..28e4a2794 100755 --- a/codecs/codec_adpcm.c +++ b/codecs/codec_adpcm.c @@ -27,6 +27,7 @@ #include #define BUFFER_SIZE 8096 /* size for the translation buffers */ +#define BUF_SHIFT 5 static ast_mutex_t localuser_lock = AST_MUTEX_INITIALIZER; static int localusecnt = 0; @@ -77,21 +78,48 @@ static short nbl2bit[16][4] = { * Sets the index to the step size table for the next encode. */ -static inline short -decode (unsigned char encoded, short *ssindex) +static inline void +decode (unsigned char encoded, short *ssindex, short *signal, unsigned char *rkey, unsigned char *next) { short diff, step; step = stpsz[*ssindex]; - diff = nbl2bit[encoded][0] * (step * nbl2bit[encoded][1] + - (step >> 1) * nbl2bit[encoded][2] + - (step >> 2) * nbl2bit[encoded][3] + - (step >> 3)); + + diff = step * nbl2bit[encoded][1] + + (step >> 1) * nbl2bit[encoded][2] + + (step >> 2) * nbl2bit[encoded][3] + + (step >> 3); + if (nbl2bit[encoded][2] && (step & 0x1)) + diff++; + diff *= nbl2bit[encoded][0]; + + if ( *next & 0x1 ) + *signal -= 8; + else if ( *next & 0x2 ) + *signal += 8; + + *signal += diff; + + if (*signal > 2047) + *signal = 2047; + else if (*signal < -2047) + *signal = -2047; + + *next = 0; + if( encoded & 0x7 ) + *rkey = 0; + else if ( ++(*rkey) == 24 ) { + *rkey = 0; + if (*signal > 0) + *next = 0x1; + else if (*signal < 0) + *next = 0x2; + } + *ssindex = *ssindex + indsft[(encoded & 7)]; if (*ssindex < 0) *ssindex = 0; else if (*ssindex > 48) *ssindex = 48; - return (diff); } /* @@ -107,7 +135,7 @@ decode (unsigned char encoded, short *ssindex) */ static inline unsigned char -adpcm (short csig, short *ssindex, short *signal) +adpcm (short csig, short *ssindex, short *signal, unsigned char *rkey, unsigned char *next) { short diff, step; unsigned char encoded; @@ -142,7 +170,7 @@ adpcm (short csig, short *ssindex, short *signal) if (diff >= step) encoded |= 1; - *signal += decode (encoded, ssindex); + decode (encoded, ssindex, signal, rkey, next); return (encoded); } @@ -158,6 +186,8 @@ struct adpcm_encoder_pvt unsigned char outbuf[BUFFER_SIZE]; /* Encoded ADPCM, two nibbles to a word */ short ssindex; short signal; + unsigned char zero_count; + unsigned char next_flag; int tail; }; @@ -245,13 +275,15 @@ adpcmtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f) short signal; short ssindex; unsigned char *b; + unsigned char zero_count; + unsigned char next_flag; - if (f->datalen < 3) { - ast_log(LOG_WARNING, "Didn't have at least three bytes of input\n"); + if (f->datalen < BUF_SHIFT) { + ast_log(LOG_WARNING, "Didn't have at least %d bytes of input\n", BUF_SHIFT); return -1; } - if ((f->datalen - 3) * 4 > sizeof(tmp->outbuf)) { + if ((f->datalen - BUF_SHIFT) * 4 > sizeof(tmp->outbuf)) { ast_log(LOG_WARNING, "Out of buffer space\n"); return -1; } @@ -265,20 +297,16 @@ adpcmtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f) ssindex = 48; signal = (b[1] << 8) | b[2]; - - for (x=3;xdatalen;x++) { - signal += decode(b[x] >> 4, &ssindex); - if (signal > 2047) - signal = 2047; - if (signal < -2048) - signal = -2048; - tmp->outbuf[tmp->tail++] = signal << 4; - signal += decode(b[x] & 0x0f, &ssindex); - if (signal > 2047) - signal = 2047; - if (signal < -2048) - signal = -2048; - tmp->outbuf[tmp->tail++] = signal << 4; + + zero_count = b[3]; + next_flag = b[4]; + + for (x=BUF_SHIFT;xdatalen;x++) { + decode((b[x] >> 4) & 0xf, &ssindex, &signal, &zero_count, &next_flag); + tmp->outbuf[tmp->tail++] = signal << 4; + + decode(b[x] & 0x0f, &ssindex, &signal, &zero_count, &next_flag); + tmp->outbuf[tmp->tail++] = signal << 4; } return 0; @@ -372,12 +400,15 @@ lintoadpcm_frameout (struct ast_translator_pvt *pvt) tmp->outbuf[0] = tmp->ssindex & 0xff; tmp->outbuf[1] = (tmp->signal >> 8) & 0xff; tmp->outbuf[2] = (tmp->signal & 0xff); + tmp->outbuf[3] = tmp->zero_count; + tmp->outbuf[4] = tmp->next_flag; for (i = 0; i < i_max; i+=2) { - adpcm0 = adpcm(tmp->inbuf[i], &tmp->ssindex, &tmp->signal); - adpcm1 = adpcm(tmp->inbuf[i+1], &tmp->ssindex, &tmp->signal); - tmp->outbuf[i/2 + 3] = (adpcm0 << 4) | adpcm1; + adpcm0 = adpcm (tmp->inbuf[i], &tmp->ssindex, &tmp->signal, &tmp->zero_count, &tmp->next_flag); + adpcm1 = adpcm (tmp->inbuf[i+1], &tmp->ssindex, &tmp->signal, &tmp->zero_count, &tmp->next_flag); + + tmp->outbuf[i/2 + BUF_SHIFT] = (adpcm0 << 4) | adpcm1; }; @@ -388,7 +419,7 @@ lintoadpcm_frameout (struct ast_translator_pvt *pvt) tmp->f.offset = AST_FRIENDLY_OFFSET; tmp->f.src = __PRETTY_FUNCTION__; tmp->f.data = tmp->outbuf; - tmp->f.datalen = i_max / 2 + 3; + tmp->f.datalen = i_max / 2 + BUF_SHIFT; /* * If there is a signal left over (there should be no more than diff --git a/formats/format_vox.c b/formats/format_vox.c index 45ba749fb..4fd7ffd94 100755 --- a/formats/format_vox.c +++ b/formats/format_vox.c @@ -33,6 +33,7 @@ #endif #define BUF_SIZE 80 /* 160 samples */ +#define BUF_SHIFT 5 struct ast_filestream { void *reserved[AST_RESERVED_POINTERS]; @@ -41,11 +42,13 @@ struct ast_filestream { struct ast_frame fr; /* Frame information */ char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */ char empty; /* Empty character */ - unsigned char buf[BUF_SIZE + 3]; /* Output Buffer */ + unsigned char buf[BUF_SIZE + BUF_SHIFT]; /* Output Buffer */ int lasttimeout; struct timeval last; short signal; /* Signal level (file side) */ short ssindex; /* Signal ssindex (file side) */ + unsigned char zero_count; /* counter of consecutive zero samples */ + unsigned char next_flag; }; @@ -95,21 +98,48 @@ static short nbl2bit[16][4] = { * Sets the index to the step size table for the next encode. */ -static inline short -decode (unsigned char encoded, short *ssindex) +static inline void +decode (unsigned char encoded, short *ssindex, short *signal, unsigned char *rkey, unsigned char *next) { short diff, step; step = stpsz[*ssindex]; - diff = nbl2bit[encoded][0] * (step * nbl2bit[encoded][1] + - (step >> 1) * nbl2bit[encoded][2] + - (step >> 2) * nbl2bit[encoded][3] + - (step >> 3)); + + diff = step * nbl2bit[encoded][1] + + (step >> 1) * nbl2bit[encoded][2] + + (step >> 2) * nbl2bit[encoded][3] + + (step >> 3); + if (nbl2bit[encoded][2] && (step & 0x1)) + diff++; + diff *= nbl2bit[encoded][0]; + + if ( *next & 0x1 ) + *signal -= 8; + else if ( *next & 0x2 ) + *signal += 8; + + *signal += diff; + + if (*signal > 2047) + *signal = 2047; + else if (*signal < -2047) + *signal = -2047; + + *next = 0; + if( encoded & 0x7 ) + *rkey = 0; + else if ( ++(*rkey) == 24 ) { + *rkey = 0; + if (*signal > 0) + *next = 0x1; + else if (*signal < 0) + *next = 0x2; + } + *ssindex = *ssindex + indsft[(encoded & 7)]; if (*ssindex < 0) *ssindex = 0; else if (*ssindex > 48) *ssindex = 48; - return (diff); } /* @@ -129,6 +159,7 @@ adpcm (short csig, short *ssindex, short *signal) { short diff, step; unsigned char encoded; + unsigned char zero_count, next_flag; step = stpsz[*ssindex]; /* * Clip csig if too large or too small @@ -160,7 +191,8 @@ adpcm (short csig, short *ssindex, short *signal) if (diff >= step) encoded |= 1; - *signal += decode (encoded, ssindex); + decode (encoded, ssindex, signal, &zero_count, &next_flag); + return (encoded); } @@ -233,13 +265,12 @@ static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext) int res; int x; /* Send a frame from the file to the appropriate channel */ - s->fr.frametype = AST_FRAME_VOICE; s->fr.subclass = AST_FORMAT_ADPCM; s->fr.offset = AST_FRIENDLY_OFFSET; s->fr.mallocd = 0; s->fr.data = s->buf; - if ((res = read(s->fd, s->buf + 3, BUF_SIZE)) < 1) { + if ((res = read(s->fd, s->buf + BUF_SHIFT, BUF_SIZE)) < 1) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; @@ -248,13 +279,15 @@ static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext) s->buf[0] = s->ssindex & 0xff; s->buf[1] = (s->signal >> 8) & 0xff; s->buf[2] = s->signal & 0xff; + s->buf[3] = s->zero_count; + s->buf[4] = s->next_flag; /* Do the decoder to be sure we get the right stuff in the signal and index fields. */ - for (x=3;xsignal += decode(s->buf[x] >> 4, &s->ssindex); - s->signal += decode(s->buf[x] & 0xf, &s->ssindex); + for (x=BUF_SHIFT;xbuf[x] >> 4, &s->ssindex, &s->signal, &s->zero_count, &s->next_flag); + decode (s->buf[x] & 0xf, &s->ssindex, &s->signal, &s->zero_count, &s->next_flag); } s->fr.samples = res * 2; - s->fr.datalen = res + 3; + s->fr.datalen = res + BUF_SHIFT; *whennext = s->fr.samples; return &s->fr; } @@ -270,11 +303,11 @@ static int vox_write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-ADPCM frame (%d)!\n", f->subclass); return -1; } - if (f->datalen < 3) { - ast_log(LOG_WARNING, "Invalid frame of data (< 3 bytes long) from %s\n", f->src); + if (f->datalen < BUF_SHIFT) { + ast_log(LOG_WARNING, "Invalid frame of data (< %d bytes long) from %s\n", BUF_SHIFT, f->src); return -1; } - if ((res = write(fs->fd, f->data + 3, f->datalen - 3)) != f->datalen - 3) { + if ((res = write(fs->fd, f->data + BUF_SHIFT, f->datalen - BUF_SHIFT)) != f->datalen - BUF_SHIFT) { ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno)); return -1; } -- cgit v1.2.3