diff options
Diffstat (limited to 'codecs')
95 files changed, 21682 insertions, 0 deletions
diff --git a/codecs/Makefile b/codecs/Makefile new file mode 100644 index 000000000..a32d157a8 --- /dev/null +++ b/codecs/Makefile @@ -0,0 +1,61 @@ +# +# Asterisk -- A telephony toolkit for Linux. +# +# Makefile for codec modules +# +# Copyright (C) 1999-2006, Digium, Inc. +# +# Mark Spencer <markster@digium.com> +# +# This program is free software, distributed under the terms of +# the GNU General Public License +# + +-include ../menuselect.makeopts ../menuselect.makedeps + +MENUSELECT_CATEGORY=CODECS +MENUSELECT_DESCRIPTION=Codec Translators + +ALL_C_MODS:=$(patsubst %.c,%,$(wildcard codec_*.c)) +ALL_CC_MODS:=$(patsubst %.cc,%,$(wildcard codec_*.cc)) + +C_MODS:=$(filter-out $(MENUSELECT_CODECS),$(ALL_C_MODS)) +CC_MODS:=$(filter-out $(MENUSELECT_CODECS),$(ALL_CC_MODS)) + +LOADABLE_MODS:=$(C_MODS) $(CC_MODS) + +ifneq ($(findstring codecs,$(MENUSELECT_EMBED)),) + EMBEDDED_MODS:=$(LOADABLE_MODS) + LOADABLE_MODS:= +endif + +LIBILBC:=ilbc/libilbc.a +LIBLPC10:=lpc10/liblpc10.a + +all: _all + +include $(ASTTOPDIR)/Makefile.moddir_rules + +ifneq ($(GSM_INTERNAL),no) +GSM_INCLUDE:=-Igsm/inc +$(if $(filter codec_gsm,$(EMBEDDED_MODS)),modules.link,codec_gsm.so): gsm/lib/libgsm.a +endif + +clean:: + $(MAKE) -C gsm clean + $(MAKE) -C lpc10 clean + $(MAKE) -C ilbc clean + +gsm/lib/libgsm.a: + @mkdir -p gsm/lib + @$(MAKE) -C gsm lib/libgsm.a + +$(LIBLPC10): + @$(MAKE) -C lpc10 all + +$(if $(filter codec_lpc10,$(EMBEDDED_MODS)),modules.link,codec_lpc10.so): $(LIBLPC10) + +$(LIBILBC): + @$(MAKE) -C ilbc all ASTCFLAGS="$(filter-out -Wmissing-prototypes -Wmissing-declarations,$(ASTCFLAGS)) $(AST_NO_STRICT_OVERFLOW)" + +$(if $(filter codec_ilbc,$(EMBEDDED_MODS)),modules.link,codec_ilbc.so): $(LIBILBC) diff --git a/codecs/adpcm_slin_ex.h b/codecs/adpcm_slin_ex.h new file mode 100644 index 000000000..c3f86c72d --- /dev/null +++ b/codecs/adpcm_slin_ex.h @@ -0,0 +1,25 @@ +/*! \file + * adpcm_slin_ex.h -- + * + * \brief 4-bit ADPCM data, 20 milliseconds worth at 8 kHz. + * + * Source: g723.example + * + * Copyright (C) 2001-2005, Digium, Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static unsigned char adpcm_slin_ex[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/codecs/codec_a_mu.c b/codecs/codec_a_mu.c new file mode 100644 index 000000000..b9c1c4938 --- /dev/null +++ b/codecs/codec_a_mu.c @@ -0,0 +1,168 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2005, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief codec_a_mu.c - translate between alaw and ulaw directly + * + * \ingroup codecs + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "asterisk/lock.h" +#include "asterisk/logger.h" +#include "asterisk/module.h" +#include "asterisk/translate.h" +#include "asterisk/channel.h" +#include "asterisk/alaw.h" +#include "asterisk/ulaw.h" +#include "asterisk/utils.h" + +#define BUFFER_SAMPLES 8000 /* size for the translation buffers */ + +static unsigned char mu2a[256]; +static unsigned char a2mu[256]; + +/* Sample frame data (Mu data is okay) */ + +#include "ulaw_slin_ex.h" + +/*! \brief convert frame data and store into the buffer */ +static int alawtoulaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + int x = f->samples; + unsigned char *src = f->data; + unsigned char *dst = (unsigned char *)pvt->outbuf + pvt->samples; + + pvt->samples += x; + pvt->datalen += x; + + while (x--) + *dst++ = a2mu[*src++]; + + return 0; +} + +/*! \brief convert frame data and store into the buffer */ +static int ulawtoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + int x = f->samples; + unsigned char *src = f->data; + unsigned char *dst = (unsigned char *)pvt->outbuf + pvt->samples; + + pvt->samples += x; + pvt->datalen += x; + + while (x--) + *dst++ = mu2a[*src++]; + + return 0; +} + +/* + * alawToLin_Sample. Just random data, somehow... + */ +static struct ast_frame *alawtoulaw_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_ALAW; + f.datalen = sizeof(ulaw_slin_ex); + f.samples = sizeof(ulaw_slin_ex); + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = ulaw_slin_ex; /* XXX what ? */ + return &f; +} + +static struct ast_frame *ulawtoalaw_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_ULAW; + f.datalen = sizeof(ulaw_slin_ex); + f.samples = sizeof(ulaw_slin_ex); + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = ulaw_slin_ex; + return &f; +} + +static struct ast_translator alawtoulaw = { + .name = "alawtoulaw", + .srcfmt = AST_FORMAT_ALAW, + .dstfmt = AST_FORMAT_ULAW, + .framein = alawtoulaw_framein, + .sample = alawtoulaw_sample, + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES, +}; + +static struct ast_translator ulawtoalaw = { + .name = "ulawtoalaw", + .srcfmt = AST_FORMAT_ULAW, + .dstfmt = AST_FORMAT_ALAW, + .framein = ulawtoalaw_framein, + .sample = ulawtoalaw_sample, + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES, +}; + +/*! \brief standard module glue */ + +static int unload_module(void) +{ + int res; + + res = ast_unregister_translator(&ulawtoalaw); + res |= ast_unregister_translator(&alawtoulaw); + + return res; +} + +static int load_module(void) +{ + int res; + int x; + + for (x=0;x<256;x++) { + mu2a[x] = AST_LIN2A(AST_MULAW(x)); + a2mu[x] = AST_LIN2MU(AST_ALAW(x)); + } + res = ast_register_translator(&alawtoulaw); + if (!res) + res = ast_register_translator(&ulawtoalaw); + else + ast_unregister_translator(&alawtoulaw); + + return res; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "A-law and Mulaw direct Coder/Decoder"); diff --git a/codecs/codec_adpcm.c b/codecs/codec_adpcm.c new file mode 100644 index 000000000..7469f056c --- /dev/null +++ b/codecs/codec_adpcm.c @@ -0,0 +1,404 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Based on frompcm.c and topcm.c from the Emiliano MIPL browser/ + * interpreter. See http://www.bsdtelephony.com.mx + * + * Copyright (c) 2001 - 2005 Digium, Inc. + * All rights reserved. + * + * Karl Sackett <krs@linux-support.net>, 2001-03-21 + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief codec_adpcm.c - translate between signed linear and Dialogic ADPCM + * + * \ingroup codecs + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "asterisk/lock.h" +#include "asterisk/logger.h" +#include "asterisk/linkedlists.h" +#include "asterisk/module.h" +#include "asterisk/config.h" +#include "asterisk/options.h" +#include "asterisk/translate.h" +#include "asterisk/channel.h" +#include "asterisk/utils.h" + +/* define NOT_BLI to use a faster but not bit-level identical version */ +/* #define NOT_BLI */ + +#define BUFFER_SAMPLES 8096 /* size for the translation buffers */ + +/* Sample frame data */ + +#include "slin_adpcm_ex.h" +#include "adpcm_slin_ex.h" + +/* + * Step size index shift table + */ + +static int indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; + +/* + * Step size table, where stpsz[i]=floor[16*(11/10)^i] + */ + +static int stpsz[49] = { + 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, + 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, + 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, + 1060, 1166, 1282, 1411, 1552 +}; + +/* + * Decoder/Encoder state + * States for both encoder and decoder are synchronized + */ +struct adpcm_state { + int ssindex; + int signal; + int zero_count; + int next_flag; +}; + +/* + * Decode(encoded) + * Decodes the encoded nibble from the adpcm file. + * + * Results: + * Returns the encoded difference. + * + * Side effects: + * Sets the index to the step size table for the next encode. + */ + +static inline short decode(int encoded, struct adpcm_state *state) +{ + int diff; + int step; + int sign; + + step = stpsz[state->ssindex]; + + sign = encoded & 0x08; + encoded &= 0x07; +#ifdef NOT_BLI + diff = (((encoded << 1) + 1) * step) >> 3; +#else /* BLI code */ + diff = step >> 3; + if (encoded & 4) + diff += step; + if (encoded & 2) + diff += step >> 1; + if (encoded & 1) + diff += step >> 2; + if ((encoded >> 1) & step & 0x1) + diff++; +#endif + if (sign) + diff = -diff; + + if (state->next_flag & 0x1) + state->signal -= 8; + else if (state->next_flag & 0x2) + state->signal += 8; + + state->signal += diff; + + if (state->signal > 2047) + state->signal = 2047; + else if (state->signal < -2047) + state->signal = -2047; + + state->next_flag = 0; + +#ifdef AUTO_RETURN + if (encoded) + state->zero_count = 0; + else if (++(state->zero_count) == 24) { + state->zero_count = 0; + if (state->signal > 0) + state->next_flag = 0x1; + else if (state->signal < 0) + state->next_flag = 0x2; + } +#endif + + state->ssindex += indsft[encoded]; + if (state->ssindex < 0) + state->ssindex = 0; + else if (state->ssindex > 48) + state->ssindex = 48; + + return state->signal << 4; +} + +/* + * Adpcm + * Takes a signed linear signal and encodes it as ADPCM + * For more information see http://support.dialogic.com/appnotes/adpcm.pdf + * + * Results: + * Foo. + * + * Side effects: + * signal gets updated with each pass. + */ + +static inline int adpcm(short csig, struct adpcm_state *state) +{ + int diff; + int step; + int encoded; + + /* + * Clip csig if too large or too small + */ + csig >>= 4; + + step = stpsz[state->ssindex]; + diff = csig - state->signal; + +#ifdef NOT_BLI + if (diff < 0) { + encoded = (-diff << 2) / step; + if (encoded > 7) + encoded = 7; + encoded |= 0x08; + } else { + encoded = (diff << 2) / step; + if (encoded > 7) + encoded = 7; + } +#else /* BLI code */ + if (diff < 0) { + encoded = 8; + diff = -diff; + } else + encoded = 0; + if (diff >= step) { + encoded |= 4; + diff -= step; + } + step >>= 1; + if (diff >= step) { + encoded |= 2; + diff -= step; + } + step >>= 1; + if (diff >= step) + encoded |= 1; +#endif /* NOT_BLI */ + + /* feedback to state */ + decode(encoded, state); + + return encoded; +} + +/*----------------- Asterisk-codec glue ------------*/ + +/*! \brief Workspace for translating signed linear signals to ADPCM. */ +struct adpcm_encoder_pvt { + struct adpcm_state state; + int16_t inbuf[BUFFER_SAMPLES]; /* Unencoded signed linear values */ +}; + +/*! \brief Workspace for translating ADPCM signals to signed linear. */ +struct adpcm_decoder_pvt { + struct adpcm_state state; +}; + +/*! \brief decode 4-bit adpcm frame data and store in output buffer */ +static int adpcmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct adpcm_decoder_pvt *tmp = pvt->pvt; + int x = f->datalen; + unsigned char *src = f->data; + int16_t *dst = (int16_t *)pvt->outbuf + pvt->samples; + + while (x--) { + *dst++ = decode((*src >> 4) & 0xf, &tmp->state); + *dst++ = decode(*src++ & 0x0f, &tmp->state); + } + pvt->samples += f->samples; + pvt->datalen += 2*f->samples; + return 0; +} + +/*! \brief fill input buffer with 16-bit signed linear PCM values. */ +static int lintoadpcm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct adpcm_encoder_pvt *tmp = pvt->pvt; + + memcpy(&tmp->inbuf[pvt->samples], f->data, f->datalen); + pvt->samples += f->samples; + return 0; +} + +/*! \brief convert inbuf and store into frame */ +static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt) +{ + struct adpcm_encoder_pvt *tmp = pvt->pvt; + struct ast_frame *f; + int i; + int samples = pvt->samples; /* save original number */ + + if (samples < 2) + return NULL; + + pvt->samples &= ~1; /* atomic size is 2 samples */ + + for (i = 0; i < pvt->samples; i += 2) { + pvt->outbuf[i/2] = + (adpcm(tmp->inbuf[i ], &tmp->state) << 4) | + (adpcm(tmp->inbuf[i+1], &tmp->state) ); + }; + + f = ast_trans_frameout(pvt, pvt->samples/2, 0); + + /* + * If there is a left over sample, move it to the beginning + * of the input buffer. + */ + + if (samples & 1) { /* move the leftover sample at beginning */ + tmp->inbuf[0] = tmp->inbuf[samples - 1]; + pvt->samples = 1; + } + return f; +} + + +/*! \brief AdpcmToLin_Sample */ +static struct ast_frame *adpcmtolin_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_ADPCM; + f.datalen = sizeof(adpcm_slin_ex); + f.samples = sizeof(adpcm_slin_ex) * 2; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = adpcm_slin_ex; + return &f; +} + +/*! \brief LinToAdpcm_Sample */ +static struct ast_frame *lintoadpcm_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_SLINEAR; + f.datalen = sizeof(slin_adpcm_ex); + /* Assume 8000 Hz */ + f.samples = sizeof(slin_adpcm_ex) / 2; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = slin_adpcm_ex; + return &f; +} + +static struct ast_translator adpcmtolin = { + .name = "adpcmtolin", + .srcfmt = AST_FORMAT_ADPCM, + .dstfmt = AST_FORMAT_SLINEAR, + .framein = adpcmtolin_framein, + .sample = adpcmtolin_sample, + .desc_size = sizeof(struct adpcm_decoder_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES * 2, + .plc_samples = 160, +}; + +static struct ast_translator lintoadpcm = { + .name = "lintoadpcm", + .srcfmt = AST_FORMAT_SLINEAR, + .dstfmt = AST_FORMAT_ADPCM, + .framein = lintoadpcm_framein, + .frameout = lintoadpcm_frameout, + .sample = lintoadpcm_sample, + .desc_size = sizeof (struct adpcm_encoder_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES/ 2, /* 2 samples per byte */ +}; + +static void parse_config(void) +{ + struct ast_config *cfg = ast_config_load("codecs.conf"); + struct ast_variable *var; + if (cfg == NULL) + return; + for (var = ast_variable_browse(cfg, "plc"); var ; var = var->next) { + if (!strcasecmp(var->name, "genericplc")) { + adpcmtolin.useplc = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "codec_adpcm: %susing generic PLC\n", adpcmtolin.useplc ? "" : "not "); + } + } + ast_config_destroy(cfg); +} + +/*! \brief standard module glue */ +static int reload(void) +{ + parse_config(); + return 0; +} + +static int unload_module(void) +{ + int res; + + res = ast_unregister_translator(&lintoadpcm); + res |= ast_unregister_translator(&adpcmtolin); + + return res; +} + +static int load_module(void) +{ + int res; + + parse_config(); + res = ast_register_translator(&adpcmtolin); + if (!res) + res = ast_register_translator(&lintoadpcm); + else + ast_unregister_translator(&adpcmtolin); + + return res; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive Differential PCM Coder/Decoder", + .load = load_module, + .unload = unload_module, + .reload = reload, + ); diff --git a/codecs/codec_alaw.c b/codecs/codec_alaw.c new file mode 100644 index 000000000..de1061687 --- /dev/null +++ b/codecs/codec_alaw.c @@ -0,0 +1,189 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2005, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief codec_alaw.c - translate between signed linear and alaw + * + * \ingroup codecs + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "asterisk/lock.h" +#include "asterisk/logger.h" +#include "asterisk/module.h" +#include "asterisk/config.h" +#include "asterisk/options.h" +#include "asterisk/translate.h" +#include "asterisk/channel.h" +#include "asterisk/alaw.h" +#include "asterisk/utils.h" + +#define BUFFER_SAMPLES 8096 /* size for the translation buffers */ + +/* Sample frame data (Mu data is okay) */ + +#include "slin_ulaw_ex.h" +#include "ulaw_slin_ex.h" + +/*! \brief decode frame into lin and fill output buffer. */ +static int alawtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + int i = f->samples; + unsigned char *src = f->data; + int16_t *dst = (int16_t *)pvt->outbuf + pvt->samples; + + pvt->samples += i; + pvt->datalen += i * 2; /* 2 bytes/sample */ + + while (i--) + *dst++ = AST_ALAW(*src++); + + return 0; +} + +/*! \brief convert and store input samples in output buffer */ +static int lintoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + int i = f->samples; + char *dst = pvt->outbuf + pvt->samples; + int16_t *src = f->data; + + pvt->samples += i; + pvt->datalen += i; /* 1 byte/sample */ + + while (i--) + *dst++ = AST_LIN2A(*src++); + + return 0; +} + +/*! \brief alawToLin_Sample */ +static struct ast_frame *alawtolin_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_ALAW; + f.datalen = sizeof(ulaw_slin_ex); + f.samples = sizeof(ulaw_slin_ex); + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = ulaw_slin_ex; + return &f; +} + +/*! \brief LinToalaw_Sample */ +static struct ast_frame *lintoalaw_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_SLINEAR; + f.datalen = sizeof(slin_ulaw_ex); + f.samples = sizeof(slin_ulaw_ex) / 2; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = slin_ulaw_ex; + return &f; +} + +static struct ast_translator alawtolin = { + .name = "alawtolin", + .srcfmt = AST_FORMAT_ALAW, + .dstfmt = AST_FORMAT_SLINEAR, + .framein = alawtolin_framein, + .sample = alawtolin_sample, + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES * 2, + .plc_samples = 160, +}; + +static struct ast_translator lintoalaw = { + "lintoalaw", + .srcfmt = AST_FORMAT_SLINEAR, + .dstfmt = AST_FORMAT_ALAW, + .framein = lintoalaw_framein, + .sample = lintoalaw_sample, + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES, +}; + +static void parse_config(void) +{ + struct ast_variable *var; + struct ast_config *cfg = ast_config_load("codecs.conf"); + if (!cfg) + return; + for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { + if (!strcasecmp(var->name, "genericplc")) { + alawtolin.useplc = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "codec_alaw: %susing generic PLC\n", alawtolin.useplc ? "" : "not "); + } + } + ast_config_destroy(cfg); +} + +/*! \brief standard module stuff */ + +static int reload(void) +{ + parse_config(); + return 0; +} + +static int unload_module(void) +{ + int res; + + res = ast_unregister_translator(&lintoalaw); + res |= ast_unregister_translator(&alawtolin); + + return res; +} + +static int load_module(void) +{ + int res; + + parse_config(); + res = ast_register_translator(&alawtolin); + if (!res) + res = ast_register_translator(&lintoalaw); + else + ast_unregister_translator(&alawtolin); + + return res; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "A-law Coder/Decoder", + .load = load_module, + .unload = unload_module, + .reload = reload, + ); diff --git a/codecs/codec_dahdi.c b/codecs/codec_dahdi.c new file mode 100644 index 000000000..347fc8012 --- /dev/null +++ b/codecs/codec_dahdi.c @@ -0,0 +1,480 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * DAHDI native transcoding support + * + * Copyright (C) 1999 - 2008, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * Kevin P. Fleming <kpfleming@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Translate between various formats natively through DAHDI transcoding + * + * \ingroup codecs + */ + +/*** MODULEINFO + <depend>dahdi_transcode</depend> + <depend>dahdi</depend> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <netinet/in.h> +#include <string.h> +#include <stdio.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <sys/mman.h> + +#include "asterisk/lock.h" +#include "asterisk/translate.h" +#include "asterisk/config.h" +#include "asterisk/options.h" +#include "asterisk/module.h" +#include "asterisk/cli.h" +#include "asterisk/logger.h" +#include "asterisk/channel.h" +#include "asterisk/utils.h" +#include "asterisk/linkedlists.h" +#include "asterisk/dahdi_compat.h" + +#define BUFFER_SAMPLES 8000 + +static unsigned int global_useplc = 0; + +static struct channel_usage { + int total; + int encoders; + int decoders; +} channels; + +static char show_transcoder_usage[] = +"Usage: show transcoder\n" +" Displays channel utilization of DAHDI transcoder(s).\n"; + +static char transcoder_show_usage[] = +"Usage: transcoder show\n" +" Displays channel utilization of DAHDI transcoder(s).\n"; + +static int transcoder_show(int fd, int argc, char **argv); + +static struct ast_cli_entry cli_deprecated[] = { + { { "show", "transcoder", NULL }, + transcoder_show, + "Display DAHDI transcoder utilization.", + show_transcoder_usage} +}; + +static struct ast_cli_entry cli[] = { + { { "transcoder", "show", NULL }, + transcoder_show, + "Display DAHDI transcoder utilization.", + transcoder_show_usage, NULL, + &cli_deprecated[0]} +}; + +struct format_map { + unsigned int map[32][32]; +}; + +static struct format_map global_format_map = { { { 0 } } }; + +struct translator { + struct ast_translator t; + AST_LIST_ENTRY(translator) entry; +}; + +static AST_LIST_HEAD_STATIC(translators, translator); + +struct pvt { + int fd; + int fake; + int samples; + struct dahdi_transcoder_formats fmts; +}; + +static int transcoder_show(int fd, int argc, char **argv) +{ + struct channel_usage copy; + + copy = channels; + + if (copy.total == 0) + ast_cli(fd, "No DAHDI transcoders found.\n"); + else + ast_cli(fd, "%d/%d encoders/decoders of %d channels are in use.\n", copy.encoders, copy.decoders, copy.total); + + return RESULT_SUCCESS; +} + +static int zap_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + int res; + struct pvt *ztp = pvt->pvt; + + if (f->subclass) { + /* Give the frame to the hardware transcoder... */ + res = write(ztp->fd, f->data, f->datalen); + if (-1 == res) { + ast_log(LOG_ERROR, "Failed to write to transcoder: %s\n", strerror(errno)); + } + if (f->datalen != res) { + ast_log(LOG_ERROR, "Requested write of %d bytes, but only wrote %d bytes.\n", f->datalen, res); + } + res = -1; + pvt->samples += f->samples; + } else { + /* Fake a return frame for calculation purposes */ + ztp->fake = 2; + pvt->samples = f->samples; + res = 0; + } + return res; +} + +static struct ast_frame *zap_frameout(struct ast_trans_pvt *pvt) +{ + struct pvt *ztp = pvt->pvt; + + if (0 == ztp->fake) { + int res; + /* Let's check to see if there is a new frame for us.... */ + res = read(ztp->fd, pvt->outbuf + pvt->datalen, pvt->t->buf_size - pvt->datalen); + if (-1 == res) { + if (EWOULDBLOCK == errno) { + /* Nothing waiting... */ + return NULL; + } else { + ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno)); + return NULL; + } + } else { + pvt->f.samples = ztp->samples; + pvt->f.datalen = res; + pvt->datalen = 0; + pvt->f.frametype = AST_FRAME_VOICE; + pvt->f.subclass = 1 << (pvt->t->dstfmt); + pvt->f.mallocd = 0; + pvt->f.offset = AST_FRIENDLY_OFFSET; + pvt->f.src = pvt->t->name; + pvt->f.data = pvt->outbuf; + ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR); + + return &pvt->f; + } + + } else if (2 == ztp->fake) { + + ztp->fake = 1; + pvt->f.frametype = AST_FRAME_VOICE; + pvt->f.subclass = 0; + pvt->f.samples = 160; + pvt->f.data = NULL; + pvt->f.offset = 0; + pvt->f.datalen = 0; + pvt->f.mallocd = 0; + ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR); + pvt->samples = 0; + + return &pvt->f; + + } else if (1 == ztp->fake) { + + return NULL; + + } + /* Shouldn't get here... */ + return NULL; +} + +static void zap_destroy(struct ast_trans_pvt *pvt) +{ + struct pvt *ztp = pvt->pvt; + + switch (ztp->fmts.dstfmt) { + case AST_FORMAT_G729A: + case AST_FORMAT_G723_1: + ast_atomic_fetchadd_int(&channels.encoders, -1); + break; + default: + ast_atomic_fetchadd_int(&channels.decoders, -1); + break; + } + + close(ztp->fd); +} + +static int zap_translate(struct ast_trans_pvt *pvt, int dest, int source) +{ + /* Request translation through zap if possible */ + int fd; + struct pvt *ztp = pvt->pvt; + int flags; + + if ((fd = open(DAHDI_FILE_TRANSCODE, O_RDWR)) < 0) { + ast_log(LOG_ERROR, "Failed to open " DAHDI_FILE_TRANSCODE ": %s\n", strerror(errno)); + return -1; + } + + ztp->fmts.srcfmt = (1 << source); + ztp->fmts.dstfmt = (1 << dest); + + ast_log(LOG_VERBOSE, "Opening transcoder channel from %d to %d.\n", source, dest); + + if (ioctl(fd, DAHDI_TC_ALLOCATE, &ztp->fmts)) { + ast_log(LOG_ERROR, "Unable to attach to transcoder: %s\n", strerror(errno)); + close(fd); + + return -1; + } + + flags = fcntl(fd, F_GETFL); + if (flags > - 1) { + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) + ast_log(LOG_WARNING, "Could not set non-block mode!\n"); + } + + ztp->fd = fd; + + switch (ztp->fmts.dstfmt) { + case AST_FORMAT_G729A: + ztp->samples = 160; + break; + case AST_FORMAT_G723_1: + ztp->samples = 240; + break; + default: + ztp->samples = 160; + break; + }; + + switch (ztp->fmts.dstfmt) { + case AST_FORMAT_G729A: + ast_atomic_fetchadd_int(&channels.encoders, +1); + break; + case AST_FORMAT_G723_1: + ast_atomic_fetchadd_int(&channels.encoders, +1); + break; + default: + ast_atomic_fetchadd_int(&channels.decoders, +1); + break; + } + + return 0; +} + +static int zap_new(struct ast_trans_pvt *pvt) +{ + return zap_translate(pvt, pvt->t->dstfmt, pvt->t->srcfmt); +} + +static struct ast_frame *fakesrc_sample(void) +{ + /* Don't bother really trying to test hardware ones. */ + static struct ast_frame f = { + .frametype = AST_FRAME_VOICE, + .samples = 160, + .src = __PRETTY_FUNCTION__ + }; + + return &f; +} + +static int register_translator(int dst, int src) +{ + struct translator *zt; + int res; + + if (!(zt = ast_calloc(1, sizeof(*zt)))) + return -1; + + snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s", + ast_getformatname((1 << src)), ast_getformatname((1 << dst))); + zt->t.srcfmt = (1 << src); + zt->t.dstfmt = (1 << dst); + zt->t.newpvt = zap_new; + zt->t.framein = zap_framein; + zt->t.frameout = zap_frameout; + zt->t.destroy = zap_destroy; + zt->t.sample = fakesrc_sample; + zt->t.useplc = global_useplc; + zt->t.buf_size = BUFFER_SAMPLES * 2; + zt->t.desc_size = sizeof(struct pvt); + if ((res = ast_register_translator(&zt->t))) { + free(zt); + return -1; + } + + AST_LIST_LOCK(&translators); + AST_LIST_INSERT_HEAD(&translators, zt, entry); + AST_LIST_UNLOCK(&translators); + + global_format_map.map[dst][src] = 1; + + return res; +} + +static void drop_translator(int dst, int src) +{ + struct translator *cur; + + AST_LIST_LOCK(&translators); + AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, cur, entry) { + if (cur->t.srcfmt != src) + continue; + + if (cur->t.dstfmt != dst) + continue; + + AST_LIST_REMOVE_CURRENT(&translators, entry); + ast_unregister_translator(&cur->t); + free(cur); + global_format_map.map[dst][src] = 0; + break; + } + AST_LIST_TRAVERSE_SAFE_END; + AST_LIST_UNLOCK(&translators); +} + +static void unregister_translators(void) +{ + struct translator *cur; + + AST_LIST_LOCK(&translators); + while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) { + ast_unregister_translator(&cur->t); + free(cur); + } + AST_LIST_UNLOCK(&translators); +} + +static void parse_config(void) +{ + struct ast_variable *var; + struct ast_config *cfg = ast_config_load("codecs.conf"); + + if (!cfg) + return; + + for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { + if (!strcasecmp(var->name, "genericplc")) { + global_useplc = ast_true(var->value); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "codec_zap: %susing generic PLC\n", + global_useplc ? "" : "not "); + } + } + + ast_config_destroy(cfg); +} + +static void build_translators(struct format_map *map, unsigned int dstfmts, unsigned int srcfmts) +{ + unsigned int src, dst; + + for (src = 0; src < 32; src++) { + for (dst = 0; dst < 32; dst++) { + if (!(srcfmts & (1 << src))) + continue; + + if (!(dstfmts & (1 << dst))) + continue; + + if (global_format_map.map[dst][src]) + continue; + + if (!register_translator(dst, src)) + map->map[dst][src] = 1; + } + } +} + +static int find_transcoders(void) +{ + struct dahdi_transcoder_info info = { 0, }; + struct format_map map = { { { 0 } } }; + int fd, res; + unsigned int x, y; + + if ((fd = open(DAHDI_FILE_TRANSCODE, O_RDWR)) < 0) { + ast_log(LOG_ERROR, "Failed to open " DAHDI_FILE_TRANSCODE ": %s\n", strerror(errno)); + return 0; + } + + for (info.tcnum = 0; !(res = ioctl(fd, DAHDI_TC_GETINFO, &info)); info.tcnum++) { + if (option_verbose > 1) + ast_verbose(VERBOSE_PREFIX_2 "Found transcoder '%s'.\n", info.name); + build_translators(&map, info.dstfmts, info.srcfmts); + ast_atomic_fetchadd_int(&channels.total, info.numchannels / 2); + } + + close(fd); + + if (!info.tcnum && (option_verbose > 1)) + ast_verbose(VERBOSE_PREFIX_2 "No hardware transcoders found.\n"); + + for (x = 0; x < 32; x++) { + for (y = 0; y < 32; y++) { + if (!map.map[x][y] && global_format_map.map[x][y]) + drop_translator(x, y); + } + } + + return 0; +} + +static int reload(void) +{ + struct translator *cur; + + parse_config(); + + AST_LIST_LOCK(&translators); + AST_LIST_TRAVERSE(&translators, cur, entry) + cur->t.useplc = global_useplc; + AST_LIST_UNLOCK(&translators); + + return 0; +} + +static int unload_module(void) +{ + ast_cli_unregister_multiple(cli, sizeof(cli) / sizeof(cli[0])); + unregister_translators(); + + return 0; +} + +static int load_module(void) +{ + parse_config(); + find_transcoders(); + ast_cli_register_multiple(cli, sizeof(cli) / sizeof(cli[0])); + + return 0; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Generic DAHDI Transcoder Codec Translator", + .load = load_module, + .unload = unload_module, + .reload = reload, + ); diff --git a/codecs/codec_g726.c b/codecs/codec_g726.c new file mode 100644 index 000000000..bfc49ad9c --- /dev/null +++ b/codecs/codec_g726.c @@ -0,0 +1,964 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2006, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * Kevin P. Fleming <kpfleming@digium.com> + * + * Based on frompcm.c and topcm.c from the Emiliano MIPL browser/ + * interpreter. See http://www.bsdtelephony.com.mx + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief codec_g726.c - translate between signed linear and ITU G.726-32kbps (both RFC3551 and AAL2 codeword packing) + * + * \ingroup codecs + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "asterisk/lock.h" +#include "asterisk/logger.h" +#include "asterisk/linkedlists.h" +#include "asterisk/module.h" +#include "asterisk/config.h" +#include "asterisk/options.h" +#include "asterisk/translate.h" +#include "asterisk/channel.h" +#include "asterisk/utils.h" + +#define WANT_ASM +#include "log2comp.h" + +/* define NOT_BLI to use a faster but not bit-level identical version */ +/* #define NOT_BLI */ + +#if defined(NOT_BLI) +# if defined(_MSC_VER) +typedef __int64 sint64; +# elif defined(__GNUC__) +typedef long long sint64; +# else +# error 64-bit integer type is not defined for your compiler/platform +# endif +#endif + +#define BUFFER_SAMPLES 8096 /* size for the translation buffers */ +#define BUF_SHIFT 5 + +/* Sample frame data */ + +#include "slin_g726_ex.h" +#include "g726_slin_ex.h" + +/* + * The following is the definition of the state structure + * used by the G.726 encoder and decoder to preserve their internal + * state between successive calls. The meanings of the majority + * of the state structure fields are explained in detail in the + * CCITT Recommendation G.721. The field names are essentially identical + * to variable names in the bit level description of the coding algorithm + * included in this Recommendation. + */ +struct g726_state { + long yl; /* Locked or steady state step size multiplier. */ + int yu; /* Unlocked or non-steady state step size multiplier. */ + int dms; /* Short term energy estimate. */ + int dml; /* Long term energy estimate. */ + int ap; /* Linear weighting coefficient of 'yl' and 'yu'. */ + int a[2]; /* Coefficients of pole portion of prediction filter. + * stored as fixed-point 1==2^14 */ + int b[6]; /* Coefficients of zero portion of prediction filter. + * stored as fixed-point 1==2^14 */ + int pk[2]; /* Signs of previous two samples of a partially + * reconstructed signal. */ + int dq[6]; /* Previous 6 samples of the quantized difference signal + * stored as fixed point 1==2^12, + * or in internal floating point format */ + int sr[2]; /* Previous 2 samples of the quantized difference signal + * stored as fixed point 1==2^12, + * or in internal floating point format */ + int td; /* delayed tone detect, new in 1988 version */ +}; + +static int qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400}; +/* + * Maps G.721 code word to reconstructed scale factor normalized log + * magnitude values. + */ +static int _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425, + 425, 373, 323, 273, 213, 135, 4, -2048}; + +/* Maps G.721 code word to log of scale factor multiplier. */ +static int _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122, + 1122, 355, 198, 112, 64, 41, 18, -12}; +/* + * Maps G.721 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static int _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00, + 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0}; + + +/* + * g72x_init_state() + * + * This routine initializes and/or resets the g726_state structure + * pointed to by 'state_ptr'. + * All the initial state values are specified in the CCITT G.721 document. + */ +static void g726_init_state(struct g726_state *state_ptr) +{ + int cnta; + + state_ptr->yl = 34816; + state_ptr->yu = 544; + state_ptr->dms = 0; + state_ptr->dml = 0; + state_ptr->ap = 0; + for (cnta = 0; cnta < 2; cnta++) { + state_ptr->a[cnta] = 0; + state_ptr->pk[cnta] = 0; +#ifdef NOT_BLI + state_ptr->sr[cnta] = 1; +#else + state_ptr->sr[cnta] = 32; +#endif + } + for (cnta = 0; cnta < 6; cnta++) { + state_ptr->b[cnta] = 0; +#ifdef NOT_BLI + state_ptr->dq[cnta] = 1; +#else + state_ptr->dq[cnta] = 32; +#endif + } + state_ptr->td = 0; +} + +/* + * quan() + * + * quantizes the input val against the table of integers. + * It returns i if table[i - 1] <= val < table[i]. + * + * Using linear search for simple coding. + */ +static int quan(int val, int *table, int size) +{ + int i; + + for (i = 0; i < size && val >= *table; ++i, ++table) + ; + return (i); +} + +#ifdef NOT_BLI /* faster non-identical version */ + +/* + * predictor_zero() + * + * computes the estimated signal from 6-zero predictor. + * + */ +static int predictor_zero(struct g726_state *state_ptr) +{ /* divide by 2 is necessary here to handle negative numbers correctly */ + int i; + sint64 sezi; + for (sezi = 0, i = 0; i < 6; i++) /* ACCUM */ + sezi += (sint64)state_ptr->b[i] * state_ptr->dq[i]; + return (int)(sezi >> 13) / 2 /* 2^14 */; +} + +/* + * predictor_pole() + * + * computes the estimated signal from 2-pole predictor. + * + */ +static int predictor_pole(struct g726_state *state_ptr) +{ /* divide by 2 is necessary here to handle negative numbers correctly */ + return (int)(((sint64)state_ptr->a[1] * state_ptr->sr[1] + + (sint64)state_ptr->a[0] * state_ptr->sr[0]) >> 13) / 2 /* 2^14 */; +} + +#else /* NOT_BLI - identical version */ +/* + * fmult() + * + * returns the integer product of the fixed-point number "an" (1==2^12) and + * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn". + */ +static int fmult(int an, int srn) +{ + int anmag, anexp, anmant; + int wanexp, wanmant; + int retval; + + anmag = (an > 0) ? an : ((-an) & 0x1FFF); + anexp = ilog2(anmag) - 5; + anmant = (anmag == 0) ? 32 : + (anexp >= 0) ? anmag >> anexp : anmag << -anexp; + wanexp = anexp + ((srn >> 6) & 0xF) - 13; + + wanmant = (anmant * (srn & 077) + 0x30) >> 4; + retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) : + (wanmant >> -wanexp); + + return (((an ^ srn) < 0) ? -retval : retval); +} + +static int predictor_zero(struct g726_state *state_ptr) +{ + int i; + int sezi; + for (sezi = 0, i = 0; i < 6; i++) /* ACCUM */ + sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]); + return sezi; +} + +static int predictor_pole(struct g726_state *state_ptr) +{ + return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) + + fmult(state_ptr->a[0] >> 2, state_ptr->sr[0])); +} + +#endif /* NOT_BLI */ + +/* + * step_size() + * + * computes the quantization step size of the adaptive quantizer. + * + */ +static int step_size(struct g726_state *state_ptr) +{ + int y; + int dif; + int al; + + if (state_ptr->ap >= 256) + return (state_ptr->yu); + else { + y = state_ptr->yl >> 6; + dif = state_ptr->yu - y; + al = state_ptr->ap >> 2; + if (dif > 0) + y += (dif * al) >> 6; + else if (dif < 0) + y += (dif * al + 0x3F) >> 6; + return (y); + } +} + +/* + * quantize() + * + * Given a raw sample, 'd', of the difference signal and a + * quantization step size scale factor, 'y', this routine returns the + * ADPCM codeword to which that sample gets quantized. The step + * size scale factor division operation is done in the log base 2 domain + * as a subtraction. + */ +static int quantize( + int d, /* Raw difference signal sample */ + int y, /* Step size multiplier */ + int *table, /* quantization table */ + int size) /* table size of integers */ +{ + int dqm; /* Magnitude of 'd' */ + int exp; /* Integer part of base 2 log of 'd' */ + int mant; /* Fractional part of base 2 log */ + int dl; /* Log of magnitude of 'd' */ + int dln; /* Step size scale factor normalized log */ + int i; + + /* + * LOG + * + * Compute base 2 log of 'd', and store in 'dl'. + */ + dqm = abs(d); + exp = ilog2(dqm); + if (exp < 0) + exp = 0; + mant = ((dqm << 7) >> exp) & 0x7F; /* Fractional portion. */ + dl = (exp << 7) | mant; + + /* + * SUBTB + * + * "Divide" by step size multiplier. + */ + dln = dl - (y >> 2); + + /* + * QUAN + * + * Obtain codword i for 'd'. + */ + i = quan(dln, table, size); + if (d < 0) /* take 1's complement of i */ + return ((size << 1) + 1 - i); + else if (i == 0) /* take 1's complement of 0 */ + return ((size << 1) + 1); /* new in 1988 */ + else + return (i); +} + +/* + * reconstruct() + * + * Returns reconstructed difference signal 'dq' obtained from + * codeword 'i' and quantization step size scale factor 'y'. + * Multiplication is performed in log base 2 domain as addition. + */ +static int reconstruct( + int sign, /* 0 for non-negative value */ + int dqln, /* G.72x codeword */ + int y) /* Step size multiplier */ +{ + int dql; /* Log of 'dq' magnitude */ + int dex; /* Integer part of log */ + int dqt; + int dq; /* Reconstructed difference signal sample */ + + dql = dqln + (y >> 2); /* ADDA */ + + if (dql < 0) { +#ifdef NOT_BLI + return (sign) ? -1 : 1; +#else + return (sign) ? -0x8000 : 0; +#endif + } else { /* ANTILOG */ + dex = (dql >> 7) & 15; + dqt = 128 + (dql & 127); +#ifdef NOT_BLI + dq = ((dqt << 19) >> (14 - dex)); + return (sign) ? -dq : dq; +#else + dq = (dqt << 7) >> (14 - dex); + return (sign) ? (dq - 0x8000) : dq; +#endif + } +} + +/* + * update() + * + * updates the state variables for each output code + */ +static void update( + int code_size, /* distinguish 723_40 with others */ + int y, /* quantizer step size */ + int wi, /* scale factor multiplier */ + int fi, /* for long/short term energies */ + int dq, /* quantized prediction difference */ + int sr, /* reconstructed signal */ + int dqsez, /* difference from 2-pole predictor */ + struct g726_state *state_ptr) /* coder state pointer */ +{ + int cnt; + int mag; /* Adaptive predictor, FLOAT A */ +#ifndef NOT_BLI + int exp; +#endif + int a2p=0; /* LIMC */ + int a1ul; /* UPA1 */ + int pks1; /* UPA2 */ + int fa1; + int tr; /* tone/transition detector */ + int ylint, thr2, dqthr; + int ylfrac, thr1; + int pk0; + + pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */ + +#ifdef NOT_BLI + mag = abs(dq / 0x1000); /* prediction difference magnitude */ +#else + mag = dq & 0x7FFF; /* prediction difference magnitude */ +#endif + /* TRANS */ + ylint = state_ptr->yl >> 15; /* exponent part of yl */ + ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */ + thr1 = (32 + ylfrac) << ylint; /* threshold */ + thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */ + dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */ + if (state_ptr->td == 0) /* signal supposed voice */ + tr = 0; + else if (mag <= dqthr) /* supposed data, but small mag */ + tr = 0; /* treated as voice */ + else /* signal is data (modem) */ + tr = 1; + + /* + * Quantizer scale factor adaptation. + */ + + /* FUNCTW & FILTD & DELAY */ + /* update non-steady state step size multiplier */ + state_ptr->yu = y + ((wi - y) >> 5); + + /* LIMB */ + if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */ + state_ptr->yu = 544; + else if (state_ptr->yu > 5120) + state_ptr->yu = 5120; + + /* FILTE & DELAY */ + /* update steady state step size multiplier */ + state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6); + + /* + * Adaptive predictor coefficients. + */ + if (tr == 1) { /* reset a's and b's for modem signal */ + state_ptr->a[0] = 0; + state_ptr->a[1] = 0; + state_ptr->b[0] = 0; + state_ptr->b[1] = 0; + state_ptr->b[2] = 0; + state_ptr->b[3] = 0; + state_ptr->b[4] = 0; + state_ptr->b[5] = 0; + } else { /* update a's and b's */ + pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */ + + /* update predictor pole a[1] */ + a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7); + if (dqsez != 0) { + fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0]; + if (fa1 < -8191) /* a2p = function of fa1 */ + a2p -= 0x100; + else if (fa1 > 8191) + a2p += 0xFF; + else + a2p += fa1 >> 5; + + if (pk0 ^ state_ptr->pk[1]) + /* LIMC */ + if (a2p <= -12160) + a2p = -12288; + else if (a2p >= 12416) + a2p = 12288; + else + a2p -= 0x80; + else if (a2p <= -12416) + a2p = -12288; + else if (a2p >= 12160) + a2p = 12288; + else + a2p += 0x80; + } + + /* TRIGB & DELAY */ + state_ptr->a[1] = a2p; + + /* UPA1 */ + /* update predictor pole a[0] */ + state_ptr->a[0] -= state_ptr->a[0] >> 8; + if (dqsez != 0) { + if (pks1 == 0) + state_ptr->a[0] += 192; + else + state_ptr->a[0] -= 192; + } + /* LIMD */ + a1ul = 15360 - a2p; + if (state_ptr->a[0] < -a1ul) + state_ptr->a[0] = -a1ul; + else if (state_ptr->a[0] > a1ul) + state_ptr->a[0] = a1ul; + + /* UPB : update predictor zeros b[6] */ + for (cnt = 0; cnt < 6; cnt++) { + if (code_size == 5) /* for 40Kbps G.723 */ + state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9; + else /* for G.721 and 24Kbps G.723 */ + state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8; + if (mag) + { /* XOR */ + if ((dq ^ state_ptr->dq[cnt]) >= 0) + state_ptr->b[cnt] += 128; + else + state_ptr->b[cnt] -= 128; + } + } + } + + for (cnt = 5; cnt > 0; cnt--) + state_ptr->dq[cnt] = state_ptr->dq[cnt-1]; +#ifdef NOT_BLI + state_ptr->dq[0] = dq; +#else + /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */ + if (mag == 0) { + state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0x20 - 0x400; + } else { + exp = ilog2(mag) + 1; + state_ptr->dq[0] = (dq >= 0) ? + (exp << 6) + ((mag << 6) >> exp) : + (exp << 6) + ((mag << 6) >> exp) - 0x400; + } +#endif + + state_ptr->sr[1] = state_ptr->sr[0]; +#ifdef NOT_BLI + state_ptr->sr[0] = sr; +#else + /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */ + if (sr == 0) { + state_ptr->sr[0] = 0x20; + } else if (sr > 0) { + exp = ilog2(sr) + 1; + state_ptr->sr[0] = (exp << 6) + ((sr << 6) >> exp); + } else if (sr > -0x8000) { + mag = -sr; + exp = ilog2(mag) + 1; + state_ptr->sr[0] = (exp << 6) + ((mag << 6) >> exp) - 0x400; + } else + state_ptr->sr[0] = 0x20 - 0x400; +#endif + + /* DELAY A */ + state_ptr->pk[1] = state_ptr->pk[0]; + state_ptr->pk[0] = pk0; + + /* TONE */ + if (tr == 1) /* this sample has been treated as data */ + state_ptr->td = 0; /* next one will be treated as voice */ + else if (a2p < -11776) /* small sample-to-sample correlation */ + state_ptr->td = 1; /* signal may be data */ + else /* signal is voice */ + state_ptr->td = 0; + + /* + * Adaptation speed control. + */ + state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */ + state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */ + + if (tr == 1) + state_ptr->ap = 256; + else if (y < 1536) /* SUBTC */ + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else if (state_ptr->td == 1) + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else if (abs((state_ptr->dms << 2) - state_ptr->dml) >= + (state_ptr->dml >> 3)) + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else + state_ptr->ap += (-state_ptr->ap) >> 4; +} + +/* + * g726_decode() + * + * Description: + * + * Decodes a 4-bit code of G.726-32 encoded data of i and + * returns the resulting linear PCM, A-law or u-law value. + * return -1 for unknown out_coding value. + */ +static int g726_decode(int i, struct g726_state *state_ptr) +{ + int sezi, sez, se; /* ACCUM */ + int y; /* MIX */ + int sr; /* ADDB */ + int dq; + int dqsez; + + i &= 0x0f; /* mask to get proper bits */ +#ifdef NOT_BLI + sezi = predictor_zero(state_ptr); + sez = sezi; + se = sezi + predictor_pole(state_ptr); /* estimated signal */ +#else + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */ +#endif + + y = step_size(state_ptr); /* dynamic quantizer step size */ + + dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized diff. */ + +#ifdef NOT_BLI + sr = se + dq; /* reconst. signal */ + dqsez = dq + sez; /* pole prediction diff. */ +#else + sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */ + dqsez = sr - se + sez; /* pole prediction diff. */ +#endif + + update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); + +#ifdef NOT_BLI + return (sr >> 10); /* sr was 26-bit dynamic range */ +#else + return (sr << 2); /* sr was 14-bit dynamic range */ +#endif +} + +/* + * g726_encode() + * + * Encodes the input vale of linear PCM, A-law or u-law data sl and returns + * the resulting code. -1 is returned for unknown input coding value. + */ +static int g726_encode(int sl, struct g726_state *state_ptr) +{ + int sezi, se, sez; /* ACCUM */ + int d; /* SUBTA */ + int sr; /* ADDB */ + int y; /* MIX */ + int dqsez; /* ADDC */ + int dq, i; + +#ifdef NOT_BLI + sl <<= 10; /* 26-bit dynamic range */ + + sezi = predictor_zero(state_ptr); + sez = sezi; + se = sezi + predictor_pole(state_ptr); /* estimated signal */ +#else + sl >>= 2; /* 14-bit dynamic range */ + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */ +#endif + + d = sl - se; /* estimation difference */ + + /* quantize the prediction difference */ + y = step_size(state_ptr); /* quantizer step size */ +#ifdef NOT_BLI + d /= 0x1000; +#endif + i = quantize(d, y, qtab_721, 7); /* i = G726 code */ + + dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */ + +#ifdef NOT_BLI + sr = se + dq; /* reconst. signal */ + dqsez = dq + sez; /* pole prediction diff. */ +#else + sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */ + dqsez = sr - se + sez; /* pole prediction diff. */ +#endif + + update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * Private workspace for translating signed linear signals to G726. + * Don't bother to define two distinct structs. + */ + +struct g726_coder_pvt { + /* buffer any odd byte in input - 0x80 + (value & 0xf) if present */ + unsigned char next_flag; + struct g726_state g726; +}; + +/*! \brief init a new instance of g726_coder_pvt. */ +static int lintog726_new(struct ast_trans_pvt *pvt) +{ + struct g726_coder_pvt *tmp = pvt->pvt; + + g726_init_state(&tmp->g726); + + return 0; +} + +/*! \brief decode packed 4-bit G726 values (AAL2 packing) and store in buffer. */ +static int g726aal2tolin_framein (struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct g726_coder_pvt *tmp = pvt->pvt; + unsigned char *src = f->data; + int16_t *dst = (int16_t *) pvt->outbuf + pvt->samples; + unsigned int i; + + for (i = 0; i < f->datalen; i++) { + *dst++ = g726_decode((src[i] >> 4) & 0xf, &tmp->g726); + *dst++ = g726_decode(src[i] & 0x0f, &tmp->g726); + } + + pvt->samples += f->samples; + pvt->datalen += 2 * f->samples; /* 2 bytes/sample */ + + return 0; +} + +/*! \brief compress and store data (4-bit G726 samples, AAL2 packing) in outbuf */ +static int lintog726aal2_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct g726_coder_pvt *tmp = pvt->pvt; + int16_t *src = f->data; + unsigned int i; + + for (i = 0; i < f->samples; i++) { + unsigned char d = g726_encode(src[i], &tmp->g726); /* this sample */ + + if (tmp->next_flag & 0x80) { /* merge with leftover sample */ + pvt->outbuf[pvt->datalen++] = ((tmp->next_flag & 0xf)<< 4) | d; + pvt->samples += 2; /* 2 samples per byte */ + tmp->next_flag = 0; + } else { + tmp->next_flag = 0x80 | d; + } + } + + return 0; +} + +/*! \brief decode packed 4-bit G726 values (RFC3551 packing) and store in buffer. */ +static int g726tolin_framein (struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct g726_coder_pvt *tmp = pvt->pvt; + unsigned char *src = f->data; + int16_t *dst = (int16_t *) pvt->outbuf + pvt->samples; + unsigned int i; + + for (i = 0; i < f->datalen; i++) { + *dst++ = g726_decode(src[i] & 0x0f, &tmp->g726); + *dst++ = g726_decode((src[i] >> 4) & 0xf, &tmp->g726); + } + + pvt->samples += f->samples; + pvt->datalen += 2 * f->samples; /* 2 bytes/sample */ + + return 0; +} + +/*! \brief compress and store data (4-bit G726 samples, RFC3551 packing) in outbuf */ +static int lintog726_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct g726_coder_pvt *tmp = pvt->pvt; + int16_t *src = f->data; + unsigned int i; + + for (i = 0; i < f->samples; i++) { + unsigned char d = g726_encode(src[i], &tmp->g726); /* this sample */ + + if (tmp->next_flag & 0x80) { /* merge with leftover sample */ + pvt->outbuf[pvt->datalen++] = (d << 4) | (tmp->next_flag & 0xf); + pvt->samples += 2; /* 2 samples per byte */ + tmp->next_flag = 0; + } else { + tmp->next_flag = 0x80 | d; + } + } + + return 0; +} + +/*! \brief convert G726-32 RFC3551 packed data into AAL2 packed data (or vice-versa) */ +static int g726tog726aal2_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + unsigned char *src = f->data; + unsigned char *dst = (unsigned char *) pvt->outbuf + pvt->samples; + unsigned int i; + + for (i = 0; i < f->datalen; i++) + *dst++ = ((src[i] & 0xf) << 4) | (src[i] >> 4); + + pvt->samples += f->samples; + pvt->datalen += f->samples; /* 1 byte/sample */ + + return 0; +} + +static struct ast_frame *g726tolin_sample(void) +{ + static struct ast_frame f = { + .frametype = AST_FRAME_VOICE, + .subclass = AST_FORMAT_G726, + .datalen = sizeof(g726_slin_ex), + .samples = sizeof(g726_slin_ex) * 2, /* 2 samples per byte */ + .src = __PRETTY_FUNCTION__, + .data = g726_slin_ex, + }; + + return &f; +} + +static struct ast_frame *lintog726_sample (void) +{ + static struct ast_frame f = { + .frametype = AST_FRAME_VOICE, + .subclass = AST_FORMAT_SLINEAR, + .datalen = sizeof(slin_g726_ex), + .samples = sizeof(slin_g726_ex) / 2, /* 1 sample per 2 bytes */ + .src = __PRETTY_FUNCTION__, + .data = slin_g726_ex, + }; + + return &f; +} + +static struct ast_translator g726tolin = { + .name = "g726tolin", + .srcfmt = AST_FORMAT_G726, + .dstfmt = AST_FORMAT_SLINEAR, + .newpvt = lintog726_new, /* same for both directions */ + .framein = g726tolin_framein, + .sample = g726tolin_sample, + .desc_size = sizeof(struct g726_coder_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES * 2, + .plc_samples = 160, +}; + +static struct ast_translator lintog726 = { + .name = "lintog726", + .srcfmt = AST_FORMAT_SLINEAR, + .dstfmt = AST_FORMAT_G726, + .newpvt = lintog726_new, /* same for both directions */ + .framein = lintog726_framein, + .sample = lintog726_sample, + .desc_size = sizeof(struct g726_coder_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES/2, +}; + +static struct ast_translator g726aal2tolin = { + .name = "g726aal2tolin", + .srcfmt = AST_FORMAT_G726_AAL2, + .dstfmt = AST_FORMAT_SLINEAR, + .newpvt = lintog726_new, /* same for both directions */ + .framein = g726aal2tolin_framein, + .sample = g726tolin_sample, + .desc_size = sizeof(struct g726_coder_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES * 2, + .plc_samples = 160, +}; + +static struct ast_translator lintog726aal2 = { + .name = "lintog726aal2", + .srcfmt = AST_FORMAT_SLINEAR, + .dstfmt = AST_FORMAT_G726_AAL2, + .newpvt = lintog726_new, /* same for both directions */ + .framein = lintog726aal2_framein, + .sample = lintog726_sample, + .desc_size = sizeof(struct g726_coder_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES / 2, +}; + +static struct ast_translator g726tog726aal2 = { + .name = "g726tog726aal2", + .srcfmt = AST_FORMAT_G726, + .dstfmt = AST_FORMAT_G726_AAL2, + .framein = g726tog726aal2_framein, /* same for both directions */ + .sample = lintog726_sample, + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES, +}; + +static struct ast_translator g726aal2tog726 = { + .name = "g726aal2tog726", + .srcfmt = AST_FORMAT_G726_AAL2, + .dstfmt = AST_FORMAT_G726, + .framein = g726tog726aal2_framein, /* same for both directions */ + .sample = lintog726_sample, + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES, +}; + +static void parse_config(void) +{ + struct ast_variable *var; + struct ast_config *cfg = ast_config_load("codecs.conf"); + + if (!cfg) + return; + for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { + if (!strcasecmp(var->name, "genericplc")) { + g726tolin.useplc = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "codec_g726: %susing generic PLC\n", + g726tolin.useplc ? "" : "not "); + } + } + ast_config_destroy(cfg); +} + +static int reload(void) +{ + parse_config(); + + return 0; +} + +static int unload_module(void) +{ + int res = 0; + + res |= ast_unregister_translator(&g726tolin); + res |= ast_unregister_translator(&lintog726); + + res |= ast_unregister_translator(&g726aal2tolin); + res |= ast_unregister_translator(&lintog726aal2); + + res |= ast_unregister_translator(&g726aal2tog726); + res |= ast_unregister_translator(&g726tog726aal2); + + return res; +} + +static int load_module(void) +{ + int res = 0; + + + parse_config(); + + res |= ast_register_translator(&g726tolin); + res |= ast_register_translator(&lintog726); + + res |= ast_register_translator(&g726aal2tolin); + res |= ast_register_translator(&lintog726aal2); + + res |= ast_register_translator(&g726aal2tog726); + res |= ast_register_translator(&g726tog726aal2); + + if (res) + unload_module(); + + return res; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.726-32kbps G726 Transcoder", + .load = load_module, + .unload = unload_module, + .reload = reload, + ); diff --git a/codecs/codec_gsm.c b/codecs/codec_gsm.c new file mode 100644 index 000000000..8a3749319 --- /dev/null +++ b/codecs/codec_gsm.c @@ -0,0 +1,290 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * The GSM code is from TOAST. Copyright information for that package is available + * in the GSM directory. + * + * Copyright (C) 1999 - 2005, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Translate between signed linear and Global System for Mobile Communications (GSM) + * + * \ingroup codecs + */ + +/*** MODULEINFO + <depend>gsm</depend> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <netinet/in.h> +#include <string.h> +#include <stdio.h> + +#include "asterisk/lock.h" +#include "asterisk/translate.h" +#include "asterisk/config.h" +#include "asterisk/options.h" +#include "asterisk/module.h" +#include "asterisk/logger.h" +#include "asterisk/channel.h" +#include "asterisk/utils.h" + +#ifdef HAVE_GSM_HEADER +#include "gsm.h" +#elif defined(HAVE_GSM_GSM_HEADER) +#include <gsm/gsm.h> +#endif + +#include "../formats/msgsm.h" + +/* Sample frame data */ +#include "slin_gsm_ex.h" +#include "gsm_slin_ex.h" + +#define BUFFER_SAMPLES 8000 +#define GSM_SAMPLES 160 +#define GSM_FRAME_LEN 33 +#define MSGSM_FRAME_LEN 65 + +struct gsm_translator_pvt { /* both gsm2lin and lin2gsm */ + gsm gsm; + int16_t buf[BUFFER_SAMPLES]; /* lin2gsm, temporary storage */ +}; + +static int gsm_new(struct ast_trans_pvt *pvt) +{ + struct gsm_translator_pvt *tmp = pvt->pvt; + + return (tmp->gsm = gsm_create()) ? 0 : -1; +} + +static struct ast_frame *lintogsm_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_SLINEAR; + f.datalen = sizeof(slin_gsm_ex); + /* Assume 8000 Hz */ + f.samples = sizeof(slin_gsm_ex)/2; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = slin_gsm_ex; + return &f; +} + +static struct ast_frame *gsmtolin_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_GSM; + f.datalen = sizeof(gsm_slin_ex); + /* All frames are 20 ms long */ + f.samples = GSM_SAMPLES; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = gsm_slin_ex; + return &f; +} + +/*! \brief decode and store in outbuf. */ +static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct gsm_translator_pvt *tmp = pvt->pvt; + int x; + int16_t *dst = (int16_t *)pvt->outbuf; + /* guess format from frame len. 65 for MSGSM, 33 for regular GSM */ + int flen = (f->datalen % MSGSM_FRAME_LEN == 0) ? + MSGSM_FRAME_LEN : GSM_FRAME_LEN; + + for (x=0; x < f->datalen; x += flen) { + unsigned char data[2 * GSM_FRAME_LEN]; + unsigned char *src; + int len; + if (flen == MSGSM_FRAME_LEN) { + len = 2*GSM_SAMPLES; + src = data; + /* Translate MSGSM format to Real GSM format before feeding in */ + /* XXX what's the point here! we should just work + * on the full format. + */ + conv65(f->data + x, data); + } else { + len = GSM_SAMPLES; + src = f->data + x; + } + /* XXX maybe we don't need to check */ + if (pvt->samples + len > BUFFER_SAMPLES) { + ast_log(LOG_WARNING, "Out of buffer space\n"); + return -1; + } + if (gsm_decode(tmp->gsm, src, dst + pvt->samples)) { + ast_log(LOG_WARNING, "Invalid GSM data (1)\n"); + return -1; + } + pvt->samples += GSM_SAMPLES; + pvt->datalen += 2 * GSM_SAMPLES; + if (flen == MSGSM_FRAME_LEN) { + if (gsm_decode(tmp->gsm, data + GSM_FRAME_LEN, dst + pvt->samples)) { + ast_log(LOG_WARNING, "Invalid GSM data (2)\n"); + return -1; + } + pvt->samples += GSM_SAMPLES; + pvt->datalen += 2 * GSM_SAMPLES; + } + } + return 0; +} + +/*! \brief store samples into working buffer for later decode */ +static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct gsm_translator_pvt *tmp = pvt->pvt; + + /* 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 (pvt->samples + f->samples > BUFFER_SAMPLES) { + ast_log(LOG_WARNING, "Out of buffer space\n"); + return -1; + } + memcpy(tmp->buf + pvt->samples, f->data, f->datalen); + pvt->samples += f->samples; + return 0; +} + +/*! \brief encode and produce a frame */ +static struct ast_frame *lintogsm_frameout(struct ast_trans_pvt *pvt) +{ + struct gsm_translator_pvt *tmp = pvt->pvt; + int datalen = 0; + int samples = 0; + + /* We can't work on anything less than a frame in size */ + if (pvt->samples < GSM_SAMPLES) + return NULL; + while (pvt->samples >= GSM_SAMPLES) { + /* Encode a frame of data */ + gsm_encode(tmp->gsm, tmp->buf + samples, (gsm_byte *) pvt->outbuf + datalen); + datalen += GSM_FRAME_LEN; + samples += GSM_SAMPLES; + pvt->samples -= GSM_SAMPLES; + } + + /* Move the data at the end of the buffer to the front */ + if (pvt->samples) + memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); + + return ast_trans_frameout(pvt, datalen, samples); +} + +static void gsm_destroy_stuff(struct ast_trans_pvt *pvt) +{ + struct gsm_translator_pvt *tmp = pvt->pvt; + if (tmp->gsm) + gsm_destroy(tmp->gsm); +} + +static struct ast_translator gsmtolin = { + .name = "gsmtolin", + .srcfmt = AST_FORMAT_GSM, + .dstfmt = AST_FORMAT_SLINEAR, + .newpvt = gsm_new, + .framein = gsmtolin_framein, + .destroy = gsm_destroy_stuff, + .sample = gsmtolin_sample, + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES * 2, + .desc_size = sizeof (struct gsm_translator_pvt ), + .plc_samples = GSM_SAMPLES, +}; + +static struct ast_translator lintogsm = { + .name = "lintogsm", + .srcfmt = AST_FORMAT_SLINEAR, + .dstfmt = AST_FORMAT_GSM, + .newpvt = gsm_new, + .framein = lintogsm_framein, + .frameout = lintogsm_frameout, + .destroy = gsm_destroy_stuff, + .sample = lintogsm_sample, + .desc_size = sizeof (struct gsm_translator_pvt ), + .buf_size = (BUFFER_SAMPLES * GSM_FRAME_LEN + GSM_SAMPLES - 1)/GSM_SAMPLES, +}; + + +static void parse_config(void) +{ + struct ast_variable *var; + struct ast_config *cfg = ast_config_load("codecs.conf"); + if (!cfg) + return; + for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { + if (!strcasecmp(var->name, "genericplc")) { + gsmtolin.useplc = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "codec_gsm: %susing generic PLC\n", gsmtolin.useplc ? "" : "not "); + } + } + ast_config_destroy(cfg); +} + +/*! \brief standard module glue */ +static int reload(void) +{ + parse_config(); + return 0; +} + +static int unload_module(void) +{ + int res; + + res = ast_unregister_translator(&lintogsm); + if (!res) + res = ast_unregister_translator(&gsmtolin); + + return res; +} + +static int load_module(void) +{ + int res; + + parse_config(); + res = ast_register_translator(&gsmtolin); + if (!res) + res=ast_register_translator(&lintogsm); + else + ast_unregister_translator(&gsmtolin); + + return res; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "GSM Coder/Decoder", + .load = load_module, + .unload = unload_module, + .reload = reload, + ); diff --git a/codecs/codec_ilbc.c b/codecs/codec_ilbc.c new file mode 100644 index 000000000..b5fc9bf32 --- /dev/null +++ b/codecs/codec_ilbc.c @@ -0,0 +1,248 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * The iLBC code is from The IETF code base and is copyright The Internet Society (2004) + * + * Copyright (C) 1999 - 2005, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Translate between signed linear and Internet Low Bitrate Codec + * + * \ingroup codecs + */ + +/*** MODULEINFO + <defaultenabled>no</defaultenabled> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <netinet/in.h> +#include <string.h> +#include <stdio.h> + +#include "asterisk/lock.h" +#include "asterisk/translate.h" +#include "asterisk/module.h" +#include "asterisk/logger.h" +#include "asterisk/channel.h" +#include "asterisk/utils.h" + +#include "ilbc/iLBC_encode.h" +#include "ilbc/iLBC_decode.h" + +/* Sample frame data */ +#include "slin_ilbc_ex.h" +#include "ilbc_slin_ex.h" + +#define USE_ILBC_ENHANCER 0 +#define ILBC_MS 30 +/* #define ILBC_MS 20 */ + +#define ILBC_FRAME_LEN 50 /* apparently... */ +#define ILBC_SAMPLES 240 /* 30ms at 8000 hz */ +#define BUFFER_SAMPLES 8000 + +struct ilbc_coder_pvt { + iLBC_Enc_Inst_t enc; + iLBC_Dec_Inst_t dec; + /* Enough to store a full second */ + int16_t buf[BUFFER_SAMPLES]; +}; + +static int lintoilbc_new(struct ast_trans_pvt *pvt) +{ + struct ilbc_coder_pvt *tmp = pvt->pvt; + + initEncode(&tmp->enc, ILBC_MS); + + return 0; +} + +static int ilbctolin_new(struct ast_trans_pvt *pvt) +{ + struct ilbc_coder_pvt *tmp = pvt->pvt; + + initDecode(&tmp->dec, ILBC_MS, USE_ILBC_ENHANCER); + + return 0; +} + +static struct ast_frame *lintoilbc_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_SLINEAR; + f.datalen = sizeof(slin_ilbc_ex); + f.samples = sizeof(slin_ilbc_ex)/2; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = slin_ilbc_ex; + return &f; +} + +static struct ast_frame *ilbctolin_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_ILBC; + f.datalen = sizeof(ilbc_slin_ex); + /* All frames are 30 ms long */ + f.samples = ILBC_SAMPLES; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = ilbc_slin_ex; + return &f; +} + +/*! \brief decode a frame and store in outbuf */ +static int ilbctolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct ilbc_coder_pvt *tmp = pvt->pvt; + int plc_mode = 1; /* 1 = normal data, 0 = plc */ + /* Assuming there's space left, decode into the current buffer at + the tail location. Read in as many frames as there are */ + int x,i; + int16_t *dst = (int16_t *)pvt->outbuf; + float tmpf[ILBC_SAMPLES]; + + if (f->datalen == 0) { /* native PLC, set fake f->datalen and clear plc_mode */ + f->datalen = ILBC_FRAME_LEN; + f->samples = ILBC_SAMPLES; + plc_mode = 0; /* do native plc */ + pvt->samples += ILBC_SAMPLES; + } + + if (f->datalen % ILBC_FRAME_LEN) { + ast_log(LOG_WARNING, "Huh? An ilbc frame that isn't a multiple of 50 bytes long from %s (%d)?\n", f->src, f->datalen); + return -1; + } + + for (x=0; x < f->datalen ; x += ILBC_FRAME_LEN) { + if (pvt->samples + ILBC_SAMPLES > BUFFER_SAMPLES) { + ast_log(LOG_WARNING, "Out of buffer space\n"); + return -1; + } + iLBC_decode(tmpf, plc_mode ? f->data + x : NULL, &tmp->dec, plc_mode); + for ( i=0; i < ILBC_SAMPLES; i++) + dst[pvt->samples + i] = tmpf[i]; + pvt->samples += ILBC_SAMPLES; + pvt->datalen += 2*ILBC_SAMPLES; + } + return 0; +} + +/*! \brief store a frame into a temporary buffer, for later decoding */ +static int lintoilbc_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct ilbc_coder_pvt *tmp = pvt->pvt; + + /* 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 */ + memcpy(tmp->buf + pvt->samples, f->data, f->datalen); + pvt->samples += f->samples; + return 0; +} + +/*! \brief encode the temporary buffer and generate a frame */ +static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt) +{ + struct ilbc_coder_pvt *tmp = pvt->pvt; + int datalen = 0; + int samples = 0; + + /* We can't work on anything less than a frame in size */ + if (pvt->samples < ILBC_SAMPLES) + return NULL; + while (pvt->samples >= ILBC_SAMPLES) { + float tmpf[ILBC_SAMPLES]; + int i; + + /* Encode a frame of data */ + for (i = 0 ; i < ILBC_SAMPLES ; i++) + tmpf[i] = tmp->buf[samples + i]; + iLBC_encode((unsigned char *) pvt->outbuf + datalen, tmpf, &tmp->enc); + + datalen += ILBC_FRAME_LEN; + samples += ILBC_SAMPLES; + pvt->samples -= ILBC_SAMPLES; + } + + /* Move the data at the end of the buffer to the front */ + if (pvt->samples) + memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); + + return ast_trans_frameout(pvt, datalen, samples); +} + +static struct ast_translator ilbctolin = { + .name = "ilbctolin", + .srcfmt = AST_FORMAT_ILBC, + .dstfmt = AST_FORMAT_SLINEAR, + .newpvt = ilbctolin_new, + .framein = ilbctolin_framein, + .sample = ilbctolin_sample, + .desc_size = sizeof(struct ilbc_coder_pvt), + .buf_size = BUFFER_SAMPLES * 2, + .native_plc = 1, +}; + +static struct ast_translator lintoilbc = { + .name = "lintoilbc", + .srcfmt = AST_FORMAT_SLINEAR, + .dstfmt = AST_FORMAT_ILBC, + .newpvt = lintoilbc_new, + .framein = lintoilbc_framein, + .frameout = lintoilbc_frameout, + .sample = lintoilbc_sample, + .desc_size = sizeof(struct ilbc_coder_pvt), + .buf_size = (BUFFER_SAMPLES * ILBC_FRAME_LEN + ILBC_SAMPLES - 1) / ILBC_SAMPLES, +}; + +static int unload_module(void) +{ + int res; + + res = ast_unregister_translator(&lintoilbc); + res |= ast_unregister_translator(&ilbctolin); + + return res; +} + +static int load_module(void) +{ + int res; + + res = ast_register_translator(&ilbctolin); + if (!res) + res=ast_register_translator(&lintoilbc); + else + ast_unregister_translator(&ilbctolin); + + return res; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "iLBC Coder/Decoder"); diff --git a/codecs/codec_lpc10.c b/codecs/codec_lpc10.c new file mode 100644 index 000000000..3f46e0af8 --- /dev/null +++ b/codecs/codec_lpc10.c @@ -0,0 +1,317 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2005, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * 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/ + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Translate between signed linear and LPC10 (Linear Predictor Code) + * + * \ingroup codecs + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <netinet/in.h> +#include <string.h> +#include <stdio.h> + +#include "asterisk/lock.h" +#include "asterisk/translate.h" +#include "asterisk/config.h" +#include "asterisk/options.h" +#include "asterisk/module.h" +#include "asterisk/logger.h" +#include "asterisk/channel.h" +#include "asterisk/utils.h" + +#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 + +#define BUFFER_SAMPLES 8000 + +struct lpc10_coder_pvt { + union { + struct lpc10_encoder_state *enc; + struct lpc10_decoder_state *dec; + } lpc10; + /* Enough to store a full second */ + short buf[BUFFER_SAMPLES]; + int longer; +}; + +static int lpc10_enc_new(struct ast_trans_pvt *pvt) +{ + struct lpc10_coder_pvt *tmp = pvt->pvt; + + return (tmp->lpc10.enc = create_lpc10_encoder_state()) ? 0 : -1; +} + +static int lpc10_dec_new(struct ast_trans_pvt *pvt) +{ + struct lpc10_coder_pvt *tmp = pvt->pvt; + + return (tmp->lpc10.dec = create_lpc10_decoder_state()) ? 0 : -1; +} + +static struct ast_frame *lintolpc10_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_SLINEAR; + f.datalen = sizeof(slin_lpc10_ex); + /* Assume 8000 Hz */ + f.samples = LPC10_SAMPLES_PER_FRAME; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = slin_lpc10_ex; + return &f; +} + +static struct ast_frame *lpc10tolin_sample(void) +{ + 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.samples = LPC10_SAMPLES_PER_FRAME; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = lpc10_slin_ex; + return &f; +} + +static void extract_bits(INT32 *bits, unsigned char *c) +{ + int x; + for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) { + if (*c & (0x80 >> (x & 7))) + bits[x] = 1; + else + bits[x] = 0; + if ((x & 7) == 7) + c++; + } +} + +/* XXX note lpc10_encode() produces one bit per word in bits[] */ +static void build_bits(unsigned char *c, INT32 *bits) +{ + unsigned char mask=0x80; + int x; + *c = 0; + for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) { + if (bits[x]) + *c |= mask; + mask = mask >> 1; + if ((x % 8)==7) { + c++; + *c = 0; + mask = 0x80; + } + } +} + +static int lpc10tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct lpc10_coder_pvt *tmp = pvt->pvt; + int16_t *dst = (int16_t *)pvt->outbuf; + int len = 0; + + while (len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) { + int x; + float tmpbuf[LPC10_SAMPLES_PER_FRAME]; + INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; /* XXX see note */ + if (pvt->samples + LPC10_SAMPLES_PER_FRAME > BUFFER_SAMPLES) { + ast_log(LOG_WARNING, "Out of buffer space\n"); + return -1; + } + extract_bits(bits, f->data + len); + if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) { + ast_log(LOG_WARNING, "Invalid lpc10 data\n"); + return -1; + } + for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) { + /* Convert to a short between -1.0 and 1.0 */ + dst[pvt->samples + x] = (int16_t)(32768.0 * tmpbuf[x]); + } + + pvt->samples += LPC10_SAMPLES_PER_FRAME; + pvt->datalen += 2*LPC10_SAMPLES_PER_FRAME; + len += LPC10_BYTES_IN_COMPRESSED_FRAME; + } + if (len != f->datalen) + printf("Decoded %d, expected %d\n", len, f->datalen); + return 0; +} + +static int lintolpc10_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct lpc10_coder_pvt *tmp = pvt->pvt; + + /* Just add the frames to our stream */ + if (pvt->samples + f->samples > BUFFER_SAMPLES) { + ast_log(LOG_WARNING, "Out of buffer space\n"); + return -1; + } + memcpy(tmp->buf + pvt->samples, f->data, f->datalen); + pvt->samples += f->samples; + return 0; +} + +static struct ast_frame *lintolpc10_frameout(struct ast_trans_pvt *pvt) +{ + struct lpc10_coder_pvt *tmp = pvt->pvt; + int x; + int datalen = 0; /* output frame */ + int samples = 0; /* output samples */ + float tmpbuf[LPC10_SAMPLES_PER_FRAME]; + INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; /* XXX what ??? */ + /* We can't work on anything less than a frame in size */ + if (pvt->samples < LPC10_SAMPLES_PER_FRAME) + return NULL; + while (pvt->samples >= LPC10_SAMPLES_PER_FRAME) { + /* Encode a frame of data */ + for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) + tmpbuf[x] = (float)tmp->buf[x + samples] / 32768.0; + lpc10_encode(tmpbuf, bits, tmp->lpc10.enc); + build_bits((unsigned char *) pvt->outbuf + datalen, bits); + datalen += LPC10_BYTES_IN_COMPRESSED_FRAME; + samples += LPC10_SAMPLES_PER_FRAME; + pvt->samples -= LPC10_SAMPLES_PER_FRAME; + /* 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; + } + /* Move the data at the end of the buffer to the front */ + if (pvt->samples) + memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); + return ast_trans_frameout(pvt, datalen, samples); +} + + +static void lpc10_destroy(struct ast_trans_pvt *arg) +{ + struct lpc10_coder_pvt *pvt = arg->pvt; + /* Enc and DEC are both just allocated, so they can be freed */ + free(pvt->lpc10.enc); +} + +static struct ast_translator lpc10tolin = { + .name = "lpc10tolin", + .srcfmt = AST_FORMAT_LPC10, + .dstfmt = AST_FORMAT_SLINEAR, + .newpvt = lpc10_dec_new, + .framein = lpc10tolin_framein, + .destroy = lpc10_destroy, + .sample = lpc10tolin_sample, + .desc_size = sizeof(struct lpc10_coder_pvt), + .buffer_samples = BUFFER_SAMPLES, + .plc_samples = LPC10_SAMPLES_PER_FRAME, + .buf_size = BUFFER_SAMPLES * 2, +}; + +static struct ast_translator lintolpc10 = { + .name = "lintolpc10", + .srcfmt = AST_FORMAT_SLINEAR, + .dstfmt = AST_FORMAT_LPC10, + .newpvt = lpc10_enc_new, + .framein = lintolpc10_framein, + .frameout = lintolpc10_frameout, + .destroy = lpc10_destroy, + .sample = lintolpc10_sample, + .desc_size = sizeof(struct lpc10_coder_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = LPC10_BYTES_IN_COMPRESSED_FRAME * (1 + BUFFER_SAMPLES / LPC10_SAMPLES_PER_FRAME), +}; + +static void parse_config(void) +{ + struct ast_variable *var; + struct ast_config *cfg = ast_config_load("codecs.conf"); + if (!cfg) + return; + for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { + if (!strcasecmp(var->name, "genericplc")) { + lpc10tolin.useplc = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "codec_lpc10: %susing generic PLC\n", + lpc10tolin.useplc ? "" : "not "); + } + } + ast_config_destroy(cfg); +} + +static int reload(void) +{ + parse_config(); + + return 0; +} + + +static int unload_module(void) +{ + int res; + + res = ast_unregister_translator(&lintolpc10); + res |= ast_unregister_translator(&lpc10tolin); + + return res; +} + +static int load_module(void) +{ + int res; + + parse_config(); + res=ast_register_translator(&lpc10tolin); + if (!res) + res=ast_register_translator(&lintolpc10); + else + ast_unregister_translator(&lpc10tolin); + + return res; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "LPC10 2.4kbps Coder/Decoder", + .load = load_module, + .unload = unload_module, + .reload = reload, + ); diff --git a/codecs/codec_speex.c b/codecs/codec_speex.c new file mode 100644 index 000000000..6eff087d3 --- /dev/null +++ b/codecs/codec_speex.c @@ -0,0 +1,522 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2005, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Translate between signed linear and Speex (Open Codec) + * + * http://www.speex.org + * \note This work was motivated by Jeremy McNamara + * hacked to be configurable by anthm and bkw 9/28/2004 + * \ingroup codecs + */ + +/*** MODULEINFO + <depend>speex</depend> + <depend>speex_preprocess</depend> + <use>speexdsp</use> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <netinet/in.h> +#include <string.h> +#include <stdio.h> +#include <speex/speex.h> + +/* We require a post 1.1.8 version of Speex to enable preprocessing + and better type handling */ +#ifdef _SPEEX_TYPES_H +#include <speex/speex_preprocess.h> +#endif + +#include "asterisk/lock.h" +#include "asterisk/translate.h" +#include "asterisk/module.h" +#include "asterisk/config.h" +#include "asterisk/options.h" +#include "asterisk/logger.h" +#include "asterisk/channel.h" +#include "asterisk/utils.h" + +/* Sample frame data */ +#include "slin_speex_ex.h" +#include "speex_slin_ex.h" + +/* codec variables */ +static int quality = 3; +static int complexity = 2; +static int enhancement = 0; +static int vad = 0; +static int vbr = 0; +static float vbr_quality = 4; +static int abr = 0; +static int dtx = 0; /* set to 1 to enable silence detection */ + +static int preproc = 0; +static int pp_vad = 0; +static int pp_agc = 0; +static float pp_agc_level = 8000; /* XXX what is this 8000 ? */ +static int pp_denoise = 0; +static int pp_dereverb = 0; +static float pp_dereverb_decay = 0.4; +static float pp_dereverb_level = 0.3; + +#define TYPE_SILENCE 0x2 +#define TYPE_HIGH 0x0 +#define TYPE_LOW 0x1 +#define TYPE_MASK 0x3 + +#define BUFFER_SAMPLES 8000 +#define SPEEX_SAMPLES 160 + +struct speex_coder_pvt { + void *speex; + SpeexBits bits; + int framesize; + int silent_state; +#ifdef _SPEEX_TYPES_H + SpeexPreprocessState *pp; + spx_int16_t buf[BUFFER_SAMPLES]; +#else + int16_t buf[BUFFER_SAMPLES]; /* input, waiting to be compressed */ +#endif +}; + + +static int lintospeex_new(struct ast_trans_pvt *pvt) +{ + struct speex_coder_pvt *tmp = pvt->pvt; + + if (!(tmp->speex = speex_encoder_init(&speex_nb_mode))) + return -1; + + speex_bits_init(&tmp->bits); + speex_bits_reset(&tmp->bits); + speex_encoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize); + speex_encoder_ctl(tmp->speex, SPEEX_SET_COMPLEXITY, &complexity); +#ifdef _SPEEX_TYPES_H + if (preproc) { + tmp->pp = speex_preprocess_state_init(tmp->framesize, 8000); /* XXX what is this 8000 ? */ + speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_VAD, &pp_vad); + speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC, &pp_agc); + speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &pp_agc_level); + speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DENOISE, &pp_denoise); + speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB, &pp_dereverb); + speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &pp_dereverb_decay); + speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &pp_dereverb_level); + } +#endif + if (!abr && !vbr) { + speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &quality); + if (vad) + speex_encoder_ctl(tmp->speex, SPEEX_SET_VAD, &vad); + } + if (vbr) { + speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR, &vbr); + speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_quality); + } + if (abr) + speex_encoder_ctl(tmp->speex, SPEEX_SET_ABR, &abr); + if (dtx) + speex_encoder_ctl(tmp->speex, SPEEX_SET_DTX, &dtx); + tmp->silent_state = 0; + + return 0; +} + +static int speextolin_new(struct ast_trans_pvt *pvt) +{ + struct speex_coder_pvt *tmp = pvt->pvt; + + if (!(tmp->speex = speex_decoder_init(&speex_nb_mode))) + return -1; + + speex_bits_init(&tmp->bits); + speex_decoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize); + if (enhancement) + speex_decoder_ctl(tmp->speex, SPEEX_SET_ENH, &enhancement); + + return 0; +} + +static struct ast_frame *lintospeex_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_SLINEAR; + f.datalen = sizeof(slin_speex_ex); + /* Assume 8000 Hz */ + f.samples = sizeof(slin_speex_ex)/2; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = slin_speex_ex; + return &f; +} + +static struct ast_frame *speextolin_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_SPEEX; + f.datalen = sizeof(speex_slin_ex); + /* All frames are 20 ms long */ + f.samples = SPEEX_SAMPLES; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = speex_slin_ex; + return &f; +} + +/*! \brief convert and store into outbuf */ +static int speextolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct speex_coder_pvt *tmp = pvt->pvt; + + /* Assuming there's space left, decode into the current buffer at + the tail location. Read in as many frames as there are */ + int x; + int res; + int16_t *dst = (int16_t *)pvt->outbuf; + /* XXX fout is a temporary buffer, may have different types */ +#ifdef _SPEEX_TYPES_H + spx_int16_t fout[1024]; +#else + float fout[1024]; +#endif + + if (f->datalen == 0) { /* Native PLC interpolation */ + if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) { + ast_log(LOG_WARNING, "Out of buffer space\n"); + return -1; + } +#ifdef _SPEEX_TYPES_H + speex_decode_int(tmp->speex, NULL, dst + pvt->samples); +#else + speex_decode(tmp->speex, NULL, fout); + for (x=0;x<tmp->framesize;x++) { + dst[pvt->samples + x] = (int16_t)fout[x]; + } +#endif + pvt->samples += tmp->framesize; + pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */ + return 0; + } + + /* Read in bits */ + speex_bits_read_from(&tmp->bits, f->data, f->datalen); + for (;;) { +#ifdef _SPEEX_TYPES_H + res = speex_decode_int(tmp->speex, &tmp->bits, fout); +#else + res = speex_decode(tmp->speex, &tmp->bits, fout); +#endif + if (res < 0) + break; + if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) { + ast_log(LOG_WARNING, "Out of buffer space\n"); + return -1; + } + for (x = 0 ; x < tmp->framesize; x++) + dst[pvt->samples + x] = (int16_t)fout[x]; + pvt->samples += tmp->framesize; + pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */ + } + return 0; +} + +/*! \brief store input frame in work buffer */ +static int lintospeex_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct speex_coder_pvt *tmp = pvt->pvt; + + /* 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 */ + memcpy(tmp->buf + pvt->samples, f->data, f->datalen); + pvt->samples += f->samples; + return 0; +} + +/*! \brief convert work buffer and produce output frame */ +static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt) +{ + struct speex_coder_pvt *tmp = pvt->pvt; + int is_speech=1; + int datalen = 0; /* output bytes */ + int samples = 0; /* output samples */ + + /* We can't work on anything less than a frame in size */ + if (pvt->samples < tmp->framesize) + return NULL; + speex_bits_reset(&tmp->bits); + while (pvt->samples >= tmp->framesize) { +#ifdef _SPEEX_TYPES_H + /* Preprocess audio */ + if (preproc) + is_speech = speex_preprocess(tmp->pp, tmp->buf + samples, NULL); + /* Encode a frame of data */ + if (is_speech) { + /* If DTX enabled speex_encode returns 0 during silence */ + is_speech = speex_encode_int(tmp->speex, tmp->buf + samples, &tmp->bits) || !dtx; + } else { + /* 5 zeros interpreted by Speex as silence (submode 0) */ + speex_bits_pack(&tmp->bits, 0, 5); + } +#else + { + float fbuf[1024]; + int x; + /* Convert to floating point */ + for (x = 0; x < tmp->framesize; x++) + fbuf[x] = tmp->buf[samples + x]; + /* Encode a frame of data */ + is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx; + } +#endif + samples += tmp->framesize; + pvt->samples -= tmp->framesize; + } + + /* Move the data at the end of the buffer to the front */ + if (pvt->samples) + memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); + + /* Use AST_FRAME_CNG to signify the start of any silence period */ + if (is_speech) { + tmp->silent_state = 0; + } else { + if (tmp->silent_state) { + return NULL; + } else { + tmp->silent_state = 1; + speex_bits_reset(&tmp->bits); + memset(&pvt->f, 0, sizeof(pvt->f)); + pvt->f.frametype = AST_FRAME_CNG; + pvt->f.samples = samples; + /* XXX what now ? format etc... */ + } + } + + /* Terminate bit stream */ + speex_bits_pack(&tmp->bits, 15, 5); + datalen = speex_bits_write(&tmp->bits, pvt->outbuf, pvt->t->buf_size); + return ast_trans_frameout(pvt, datalen, samples); +} + +static void speextolin_destroy(struct ast_trans_pvt *arg) +{ + struct speex_coder_pvt *pvt = arg->pvt; + + speex_decoder_destroy(pvt->speex); + speex_bits_destroy(&pvt->bits); +} + +static void lintospeex_destroy(struct ast_trans_pvt *arg) +{ + struct speex_coder_pvt *pvt = arg->pvt; +#ifdef _SPEEX_TYPES_H + if (preproc) + speex_preprocess_state_destroy(pvt->pp); +#endif + speex_encoder_destroy(pvt->speex); + speex_bits_destroy(&pvt->bits); +} + +static struct ast_translator speextolin = { + .name = "speextolin", + .srcfmt = AST_FORMAT_SPEEX, + .dstfmt = AST_FORMAT_SLINEAR, + .newpvt = speextolin_new, + .framein = speextolin_framein, + .destroy = speextolin_destroy, + .sample = speextolin_sample, + .desc_size = sizeof(struct speex_coder_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES * 2, + .native_plc = 1, +}; + +static struct ast_translator lintospeex = { + .name = "lintospeex", + .srcfmt = AST_FORMAT_SLINEAR, + .dstfmt = AST_FORMAT_SPEEX, + .newpvt = lintospeex_new, + .framein = lintospeex_framein, + .frameout = lintospeex_frameout, + .destroy = lintospeex_destroy, + .sample = lintospeex_sample, + .desc_size = sizeof(struct speex_coder_pvt), + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */ +}; + +static void parse_config(void) +{ + struct ast_config *cfg = ast_config_load("codecs.conf"); + struct ast_variable *var; + int res; + float res_f; + + if (cfg == NULL) + return; + + for (var = ast_variable_browse(cfg, "speex"); var; var = var->next) { + if (!strcasecmp(var->name, "quality")) { + res = abs(atoi(var->value)); + if (res > -1 && res < 11) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Quality to %d\n",res); + quality = res; + } else + ast_log(LOG_ERROR,"Error Quality must be 0-10\n"); + } else if (!strcasecmp(var->name, "complexity")) { + res = abs(atoi(var->value)); + if (res > -1 && res < 11) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Complexity to %d\n",res); + complexity = res; + } else + ast_log(LOG_ERROR,"Error! Complexity must be 0-10\n"); + } else if (!strcasecmp(var->name, "vbr_quality")) { + if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0 && res_f <= 10) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting VBR Quality to %f\n",res_f); + vbr_quality = res_f; + } else + ast_log(LOG_ERROR,"Error! VBR Quality must be 0-10\n"); + } else if (!strcasecmp(var->name, "abr_quality")) { + ast_log(LOG_ERROR,"Error! ABR Quality setting obsolete, set ABR to desired bitrate\n"); + } else if (!strcasecmp(var->name, "enhancement")) { + enhancement = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Perceptual Enhancement Mode. [%s]\n",enhancement ? "on" : "off"); + } else if (!strcasecmp(var->name, "vbr")) { + vbr = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VBR Mode. [%s]\n",vbr ? "on" : "off"); + } else if (!strcasecmp(var->name, "abr")) { + res = abs(atoi(var->value)); + if (res >= 0) { + if (option_verbose > 2) { + if (res > 0) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting ABR target bitrate to %d\n",res); + else + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Disabling ABR\n"); + } + abr = res; + } else + ast_log(LOG_ERROR,"Error! ABR target bitrate must be >= 0\n"); + } else if (!strcasecmp(var->name, "vad")) { + vad = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VAD Mode. [%s]\n",vad ? "on" : "off"); + } else if (!strcasecmp(var->name, "dtx")) { + dtx = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: DTX Mode. [%s]\n",dtx ? "on" : "off"); + } else if (!strcasecmp(var->name, "preprocess")) { + preproc = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessing. [%s]\n",preproc ? "on" : "off"); + } else if (!strcasecmp(var->name, "pp_vad")) { + pp_vad = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor VAD. [%s]\n",pp_vad ? "on" : "off"); + } else if (!strcasecmp(var->name, "pp_agc")) { + pp_agc = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor AGC. [%s]\n",pp_agc ? "on" : "off"); + } else if (!strcasecmp(var->name, "pp_agc_level")) { + if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor AGC Level to %f\n",res_f); + pp_agc_level = res_f; + } else + ast_log(LOG_ERROR,"Error! Preprocessor AGC Level must be >= 0\n"); + } else if (!strcasecmp(var->name, "pp_denoise")) { + pp_denoise = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Denoise. [%s]\n",pp_denoise ? "on" : "off"); + } else if (!strcasecmp(var->name, "pp_dereverb")) { + pp_dereverb = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Dereverb. [%s]\n",pp_dereverb ? "on" : "off"); + } else if (!strcasecmp(var->name, "pp_dereverb_decay")) { + if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Decay to %f\n",res_f); + pp_dereverb_decay = res_f; + } else + ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Decay must be >= 0\n"); + } else if (!strcasecmp(var->name, "pp_dereverb_level")) { + if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Level to %f\n",res_f); + pp_dereverb_level = res_f; + } else + ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Level must be >= 0\n"); + } + } + ast_config_destroy(cfg); +} + +static int reload(void) +{ + parse_config(); + + return 0; +} + +static int unload_module(void) +{ + int res; + + res = ast_unregister_translator(&lintospeex); + res |= ast_unregister_translator(&speextolin); + + return res; +} + +static int load_module(void) +{ + int res; + + parse_config(); + res=ast_register_translator(&speextolin); + if (!res) + res=ast_register_translator(&lintospeex); + else + ast_unregister_translator(&speextolin); + + return res; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Speex Coder/Decoder", + .load = load_module, + .unload = unload_module, + .reload = reload, + ); diff --git a/codecs/codec_ulaw.c b/codecs/codec_ulaw.c new file mode 100644 index 000000000..334f8d9ad --- /dev/null +++ b/codecs/codec_ulaw.c @@ -0,0 +1,201 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2005, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief codec_ulaw.c - translate between signed linear and ulaw + * + * \ingroup codecs + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "asterisk/lock.h" +#include "asterisk/logger.h" +#include "asterisk/module.h" +#include "asterisk/config.h" +#include "asterisk/options.h" +#include "asterisk/translate.h" +#include "asterisk/channel.h" +#include "asterisk/ulaw.h" +#include "asterisk/utils.h" + +#define BUFFER_SAMPLES 8096 /* size for the translation buffers */ + +/* Sample frame data */ + +#include "slin_ulaw_ex.h" +#include "ulaw_slin_ex.h" + +/*! \brief convert and store samples in outbuf */ +static int ulawtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + int i = f->samples; + unsigned char *src = f->data; + int16_t *dst = (int16_t *)pvt->outbuf + pvt->samples; + + pvt->samples += i; + pvt->datalen += i * 2; /* 2 bytes/sample */ + + /* convert and copy in outbuf */ + while (i--) + *dst++ = AST_MULAW(*src++); + + return 0; +} + +/*! \brief convert and store samples in outbuf */ +static int lintoulaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + int i = f->samples; + char *dst = pvt->outbuf + pvt->samples; + int16_t *src = f->data; + + pvt->samples += i; + pvt->datalen += i; /* 1 byte/sample */ + + while (i--) + *dst++ = AST_LIN2MU(*src++); + + return 0; +} + +/*! * \brief ulawToLin_Sample */ +static struct ast_frame *ulawtolin_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_ULAW; + f.datalen = sizeof(ulaw_slin_ex); + f.samples = sizeof(ulaw_slin_ex); + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = ulaw_slin_ex; + return &f; +} + +/*! + * \brief LinToulaw_Sample + */ + +static struct ast_frame *lintoulaw_sample(void) +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_SLINEAR; + f.datalen = sizeof(slin_ulaw_ex); + /* Assume 8000 Hz */ + f.samples = sizeof(slin_ulaw_ex) / 2; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = slin_ulaw_ex; + return &f; +} + +/*! + * \brief The complete translator for ulawToLin. + */ + +static struct ast_translator ulawtolin = { + .name = "ulawtolin", + .srcfmt = AST_FORMAT_ULAW, + .dstfmt = AST_FORMAT_SLINEAR, + .framein = ulawtolin_framein, + .sample = ulawtolin_sample, + .buffer_samples = BUFFER_SAMPLES, + .buf_size = BUFFER_SAMPLES * 2, + .plc_samples = 160, +}; + +/*! + * \brief The complete translator for LinToulaw. + */ + +static struct ast_translator lintoulaw = { + .name = "lintoulaw", + .srcfmt = AST_FORMAT_SLINEAR, + .dstfmt = AST_FORMAT_ULAW, + .framein = lintoulaw_framein, + .sample = lintoulaw_sample, + .buf_size = BUFFER_SAMPLES, + .buffer_samples = BUFFER_SAMPLES, +}; + +static void parse_config(void) +{ + struct ast_variable *var; + struct ast_config *cfg = ast_config_load("codecs.conf"); + if (!cfg) + return; + for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { + if (!strcasecmp(var->name, "genericplc")) { + ulawtolin.useplc = ast_true(var->value) ? 1 : 0; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "codec_ulaw: %susing generic PLC\n", ulawtolin.useplc ? "" : "not "); + } + } + ast_config_destroy(cfg); +} + +static int reload(void) +{ + parse_config(); + + return 0; +} + +static int unload_module(void) +{ + int res; + + res = ast_unregister_translator(&lintoulaw); + res |= ast_unregister_translator(&ulawtolin); + + return res; +} + +static int load_module(void) +{ + int res; + + parse_config(); + res = ast_register_translator(&ulawtolin); + if (!res) + res = ast_register_translator(&lintoulaw); + else + ast_unregister_translator(&ulawtolin); + + return res; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "mu-Law Coder/Decoder", + .load = load_module, + .unload = unload_module, + .reload = reload, + ); diff --git a/codecs/g726_slin_ex.h b/codecs/g726_slin_ex.h new file mode 100644 index 000000000..80cbf00f4 --- /dev/null +++ b/codecs/g726_slin_ex.h @@ -0,0 +1,25 @@ +/*! \file + * adpcm_slin_ex.h -- + * + * \brief 4-bit G.726 data, 20 milliseconds worth at 8 kHz. + * + * Source: g726.example + * + * Copyright (C) 2001-2005, Digium, Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static unsigned char g726_slin_ex[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/codecs/gsm/COPYRIGHT b/codecs/gsm/COPYRIGHT new file mode 100644 index 000000000..eba0e523b --- /dev/null +++ b/codecs/gsm/COPYRIGHT @@ -0,0 +1,16 @@ +Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann, +Technische Universitaet Berlin + +Any use of this software is permitted provided that this notice is not +removed and that neither the authors nor the Technische Universitaet Berlin +are deemed to have made any representations as to the suitability of this +software for any purpose nor are held responsible for any defects of +this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + +As a matter of courtesy, the authors request to be informed about uses +this software has found, about bugs in this software, and about any +improvements that may be of general interest. + +Berlin, 28.11.1994 +Jutta Degener +Carsten Bormann diff --git a/codecs/gsm/Makefile b/codecs/gsm/Makefile new file mode 100644 index 000000000..8121b05a6 --- /dev/null +++ b/codecs/gsm/Makefile @@ -0,0 +1,543 @@ +# Copyright 1992-1996 by Jutta Degener and Carsten Bormann, Technische +# Universitaet Berlin. See the accompanying file "COPYRIGHT" for +# details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + +# Machine- or installation dependent flags you should configure to port + +SASR = -DSASR +######### Define SASR if >> is a signed arithmetic shift (-1 >> 1 == -1) + +#MULHACK = -DUSE_FLOAT_MUL +######### Define this if your host multiplies floats faster than integers, +######### e.g. on a SPARCstation. + +#FAST = -DFAST +######### Define together with USE_FLOAT_MUL to enable the GSM library's +######### approximation option for incorrect, but good-enough results. + +# LTP_CUT = -DLTP_CUT +LTP_CUT = +######### Define to enable the GSM library's long-term correlation +######### approximation option---faster, but worse; works for +######### both integer and floating point multiplications. +######### This flag is still in the experimental stage. + +WAV49 = -DWAV49 +#WAV49 = +######### Define to enable the GSM library's option to pack GSM frames +######### in the style used by the WAV #49 format. If you want to write +######### a tool that produces .WAV files which contain GSM-encoded data, +######### define this, and read about the GSM_OPT_WAV49 option in the +######### manual page on gsm_option(3). + +#K6OPT = -DK6OPT +#K6OPT = +######### Define to enable MMXTM optimizations for x86 architecture CPU's +######### which support MMX instructions. This should be newer pentiums, +######### ppro's, etc, as well as the AMD K6 and K7. The compile will +######### probably require gcc. + +ifeq (, $(findstring $(OSARCH) , Darwin SunOS )) +ifeq (, $(findstring $(PROC) , x86_64 amd64 ultrasparc sparc64 arm armv5b armeb hppa2.0 ppc powerpc ppc64 ia64 s390 bfin mipsel mips)) +ifeq (, $(findstring $(shell uname -m) , ppc ppc64 alpha armv4l s390 )) +OPTIMIZE+=-march=$(PROC) +endif +endif +endif + +#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only. +#This works for even old (2.96) versions of gcc and provides a small boost either way. +#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn't support it. +#So we go lowest common available by gcc and go a step down, still a step up from +#the default as we now have a better instruction set to work with. - Belgarath +ifeq ($(PROC),ultrasparc) +OPTIMIZE+=-mcpu=v8 -mtune=$(PROC) -O3 +endif + +PG = +#PG = -g -pg +######### Profiling flags. If you don't know what that means, leave it blank. + +# Choose a compiler. The code works both with ANSI and K&R-C. +# Use -DNeedFunctionPrototypes to compile with, -UNeedFunctionPrototypes to +# compile without, function prototypes in the header files. +# +# You can use the -DSTUPID_COMPILER to circumvent some compilers' +# static limits regarding the number of subexpressions in a statement. + +# CC = cc +# CCFLAGS = -c -DSTUPID_COMPILER + +# CC = /usr/lang/acc +# CCFLAGS = -c -O + +CCFLAGS += -c -DNeedFunctionPrototypes=1 -funroll-loops $(OPTIMIZE) + +# LD = gcc +# LDFLAGS = + + +# If your compiler needs additional flags/libraries, regardless of +# the source compiled, configure them here. + +# CCINC = -I/usr/gnu/lib/gcc-2.1/gcc-lib/sparc-sun-sunos4.1.2/2.1/include +######### Includes needed by $(CC) + +# LDINC = -L/usr/gnu/lib/gcc-2.1/gcc-lib/sparc-sun-sunos4.1.2/2.1 +######### Library paths needed by $(LD) + +# LDLIB = -lgcc +######### Additional libraries needed by $(LD) + + +# Where do you want to install libraries, binaries, a header file +# and the manual pages? +# +# Leave INSTALL_ROOT empty (or just don't execute "make install") to +# not install gsm and toast outside of this directory. + +INSTALL_ROOT = + +# Where do you want to install the gsm library, header file, and manpages? +# +# Leave GSM_INSTALL_ROOT empty to not install the GSM library outside of +# this directory. + +GSM_INSTALL_ROOT = $(INSTALL_ROOT) +GSM_INSTALL_LIB = $(GSM_INSTALL_ROOT)/lib +GSM_INSTALL_INC = $(GSM_INSTALL_ROOT)/inc +GSM_INSTALL_MAN = $(GSM_INSTALL_ROOT)/man/man3 + + +# Where do you want to install the toast binaries and their manpage? +# +# Leave TOAST_INSTALL_ROOT empty to not install the toast binaries outside +# of this directory. + +TOAST_INSTALL_ROOT = $(INSTALL_ROOT) +TOAST_INSTALL_BIN = $(TOAST_INSTALL_ROOT)/bin +TOAST_INSTALL_MAN = $(TOAST_INSTALL_ROOT)/man/man1 + +# Other tools + +SHELL = /bin/sh +LN = ln +BASENAME = basename +AR = ar +ARFLAGS = cr +RMFLAGS = -f +FIND = find +COMPRESS = compress +COMPRESSFLAGS = +# RANLIB = true +RANLIB = ranlib + +# +# You shouldn't have to configure below this line if you're porting. +# + + +# Local Directories + +ROOT = . +ADDTST = $(ROOT)/add-test +TST = $(ROOT)/tst +MAN = $(ROOT)/man +BIN = $(ROOT)/bin +SRC = $(ROOT)/src +LIB = $(ROOT)/lib +TLS = $(ROOT)/tls +INC = $(ROOT)/inc + +# Flags + +DEBUG = -DNDEBUG +######### Remove -DNDEBUG to enable assertions. + +ASTCFLAGS += $(PG) $(CCFLAGS) $(SASR) $(DEBUG) $(MULHACK) $(FAST) \ + $(LTP_CUT) $(WAV49) $(K6OPT) $(CCINC) -I$(INC) +######### It's $(CC) $(CFLAGS) + +LFLAGS = $(PG) $(LDFLAGS) $(LDINC) +######### It's $(LD) $(LFLAGS) + + +# Targets + +LIBGSM = $(LIB)/libgsm.a +LIBGSMSO= $(LIB)/libgsm.so + +TOAST = $(BIN)/toast +UNTOAST = $(BIN)/untoast +TCAT = $(BIN)/tcat + +# Headers + +GSM_HEADERS = $(INC)/gsm.h + +HEADERS = $(INC)/proto.h \ + $(INC)/unproto.h \ + $(INC)/config.h \ + $(INC)/private.h \ + $(INC)/gsm.h \ + $(INC)/toast.h \ + $(TLS)/taste.h + +# Sources + +GSM_SOURCES = $(SRC)/add.c \ + $(SRC)/code.c \ + $(SRC)/debug.c \ + $(SRC)/decode.c \ + $(SRC)/long_term.c \ + $(SRC)/lpc.c \ + $(SRC)/preprocess.c \ + $(SRC)/rpe.c \ + $(SRC)/gsm_destroy.c \ + $(SRC)/gsm_decode.c \ + $(SRC)/gsm_encode.c \ + $(SRC)/gsm_explode.c \ + $(SRC)/gsm_implode.c \ + $(SRC)/gsm_create.c \ + $(SRC)/gsm_print.c \ + $(SRC)/gsm_option.c \ + $(SRC)/short_term.c \ + $(SRC)/table.c + +# add k6-specific code only if not on a non-k6 hardware or proc. +# XXX Keep a space after each findstring argument +# XXX should merge with GSM_OBJECTS +ifeq ($(OSARCH),linux-gnu) +ifeq (,$(findstring $(shell uname -m) , x86_64 amd64 ppc ppc64 alpha armv4l sparc64 parisc s390 )) +ifeq (,$(findstring $(PROC) , arm armv5b armeb powerpc ia64 s390 bfin mipsel mips )) +GSM_SOURCES+= $(SRC)/k6opt.s +endif +endif +endif + +TOAST_SOURCES = $(SRC)/toast.c \ + $(SRC)/toast_lin.c \ + $(SRC)/toast_ulaw.c \ + $(SRC)/toast_alaw.c \ + $(SRC)/toast_audio.c + +SOURCES = $(GSM_SOURCES) \ + $(TOAST_SOURCES) \ + $(ADDTST)/add_test.c \ + $(TLS)/sour.c \ + $(TLS)/ginger.c \ + $(TLS)/sour1.dta \ + $(TLS)/sour2.dta \ + $(TLS)/bitter.c \ + $(TLS)/bitter.dta \ + $(TLS)/taste.c \ + $(TLS)/sweet.c \ + $(TST)/cod2lin.c \ + $(TST)/cod2txt.c \ + $(TST)/gsm2cod.c \ + $(TST)/lin2cod.c \ + $(TST)/lin2txt.c + +# Object files + +GSM_OBJECTS = $(SRC)/add.o \ + $(SRC)/code.o \ + $(SRC)/debug.o \ + $(SRC)/decode.o \ + $(SRC)/long_term.o \ + $(SRC)/lpc.o \ + $(SRC)/preprocess.o \ + $(SRC)/rpe.o \ + $(SRC)/gsm_destroy.o \ + $(SRC)/gsm_decode.o \ + $(SRC)/gsm_encode.o \ + $(SRC)/gsm_explode.o \ + $(SRC)/gsm_implode.o \ + $(SRC)/gsm_create.o \ + $(SRC)/gsm_print.o \ + $(SRC)/gsm_option.o \ + $(SRC)/short_term.o \ + $(SRC)/table.o + +ifeq ($(OSARCH),linux-gnu) +ifeq (,$(findstring $(shell uname -m) , x86_64 amd64 ppc ppc64 alpha armv4l sparc64 parisc )) +ifeq (,$(findstring $(PROC) , arm armv5b armeb powerpc ia64 bfin mipsel mips )) +GSM_OBJECTS+= $(SRC)/k6opt.o +endif +endif +endif + +TOAST_OBJECTS = $(SRC)/toast.o \ + $(SRC)/toast_lin.o \ + $(SRC)/toast_ulaw.o \ + $(SRC)/toast_alaw.o \ + $(SRC)/toast_audio.o + +OBJECTS = $(GSM_OBJECTS) $(TOAST_OBJECTS) + +# Manuals + +GSM_MANUALS = $(MAN)/gsm.3 \ + $(MAN)/gsm_explode.3 \ + $(MAN)/gsm_option.3 \ + $(MAN)/gsm_print.3 + +TOAST_MANUALS = $(MAN)/toast.1 + +MANUALS = $(GSM_MANUALS) $(TOAST_MANUALS) $(MAN)/bitter.1 + +# Other stuff in the distribution + +STUFF = ChangeLog \ + INSTALL \ + MACHINES \ + MANIFEST \ + Makefile \ + README \ + $(ADDTST)/add_test.dta \ + $(TLS)/bitter.dta \ + $(TST)/run + + +# Install targets + +GSM_INSTALL_TARGETS = \ + $(GSM_INSTALL_LIB)/libgsm.a \ + $(GSM_INSTALL_INC)/gsm.h \ + $(GSM_INSTALL_MAN)/gsm.3 \ + $(GSM_INSTALL_MAN)/gsm_explode.3 \ + $(GSM_INSTALL_MAN)/gsm_option.3 \ + $(GSM_INSTALL_MAN)/gsm_print.3 + +TOAST_INSTALL_TARGETS = \ + $(TOAST_INSTALL_BIN)/toast \ + $(TOAST_INSTALL_BIN)/tcat \ + $(TOAST_INSTALL_BIN)/untoast \ + $(TOAST_INSTALL_MAN)/toast.1 + + +# Default rules + +include $(ASTTOPDIR)/Makefile.rules + +# Target rules + +all: $(LIBGSM) $(LIBGSMSO) $(TOAST) $(TCAT) $(UNTOAST) + @-echo $(ROOT): Done. + +tst: $(TST)/lin2cod $(TST)/cod2lin $(TOAST) $(TST)/test-result + @-echo tst: Done. + +addtst: $(ADDTST)/add $(ADDTST)/add_test.dta + $(ADDTST)/add < $(ADDTST)/add_test.dta > /dev/null + @-echo addtst: Done. + +misc: $(TLS)/sweet $(TLS)/bitter $(TLS)/sour $(TLS)/ginger \ + $(TST)/lin2txt $(TST)/cod2txt $(TST)/gsm2cod + @-echo misc: Done. + +install: toastinstall gsminstall + @-echo install: Done. + + +# The basic API: libgsm + +$(LIBGSMSO): $(LIB) $(GSM_OBJECTS) + $(LD) -o $@.1.0.10 -shared -Xlinker -soname -Xlinker libgsm.so.1 $(GSM_OBJECTS) -lc + ln -fs libgsm.so.1.0.10 lib/libgsm.so.1 + ln -fs libgsm.so.1.0.10 lib/libgsm.so + +$(LIBGSM): $(GSM_OBJECTS) + $(ECHO_PREFIX) echo " [AR] $^ -> $@" + $(CMD_PREFIX) $(AR) cr $@ $^ + $(CMD_PREFIX) $(RANLIB) $@ + + +# Toast, Untoast and Tcat -- the compress-like frontends to gsm. + +$(TOAST): $(BIN) $(TOAST_OBJECTS) $(LIBGSM) + $(LD) $(LFLAGS) -o $(TOAST) $(TOAST_OBJECTS) $(LIBGSMSO) $(LDLIB) + +$(UNTOAST): $(BIN) $(TOAST) + -rm $(RMFLAGS) $(UNTOAST) + $(LN) toast $(UNTOAST) + +$(TCAT): $(BIN) $(TOAST) + -rm $(RMFLAGS) $(TCAT) + $(LN) toast $(TCAT) + + +# The local bin and lib directories + +$(BIN): + if [ ! -d $(BIN) ] ; then mkdir $(BIN) ; fi + +$(LIB): + if [ ! -d $(LIB) ] ; then mkdir $(LIB) ; fi + + +# Installation + +gsminstall: + -if [ x"$(GSM_INSTALL_ROOT)" != x ] ; then \ + $(MAKE) $(GSM_INSTALL_TARGETS) ; \ + fi + +toastinstall: + -if [ x"$(TOAST_INSTALL_ROOT)" != x ]; then \ + $(MAKE) $(TOAST_INSTALL_TARGETS); \ + fi + +gsmuninstall: + -if [ x"$(GSM_INSTALL_ROOT)" != x ] ; then \ + rm $(RMFLAGS) $(GSM_INSTALL_TARGETS) ; \ + fi + +toastuninstall: + -if [ x"$(TOAST_INSTALL_ROOT)" != x ] ; then \ + rm $(RMFLAGS) $(TOAST_INSTALL_TARGETS); \ + fi + +$(TOAST_INSTALL_BIN)/toast: $(TOAST) + -rm $@ + cp $(TOAST) $@ + chmod 755 $@ + +$(TOAST_INSTALL_BIN)/untoast: $(TOAST_INSTALL_BIN)/toast + -rm $@ + ln $? $@ + +$(TOAST_INSTALL_BIN)/tcat: $(TOAST_INSTALL_BIN)/toast + -rm $@ + ln $? $@ + +$(TOAST_INSTALL_MAN)/toast.1: $(MAN)/toast.1 + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_MAN)/gsm.3: $(MAN)/gsm.3 + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_MAN)/gsm_option.3: $(MAN)/gsm_option.3 + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_MAN)/gsm_explode.3: $(MAN)/gsm_explode.3 + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_MAN)/gsm_print.3: $(MAN)/gsm_print.3 + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_INC)/gsm.h: $(INC)/gsm.h + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_LIB)/libgsm.a: $(LIBGSM) + -rm $@ + cp $? $@ + chmod 444 $@ + + +# Distribution + +dist: gsm-1.0.tar.Z + @echo dist: Done. + +gsm-1.0.tar.Z: $(STUFF) $(SOURCES) $(HEADERS) $(MANUALS) + ( cd $(ROOT)/..; \ + tar cvf - `cat $(ROOT)/gsm-1.0/MANIFEST \ + | sed '/^#/d'` \ + ) | $(COMPRESS) $(COMPRESSFLAGS) > $(ROOT)/gsm-1.0.tar.Z + +# Clean + +uninstall: toastuninstall gsmuninstall + @-echo uninstall: Done. + +semi-clean: + -rm $(RMFLAGS) */*.o \ + $(TST)/lin2cod $(TST)/lin2txt \ + $(TST)/cod2lin $(TST)/cod2txt \ + $(TST)/gsm2cod \ + $(TST)/*.*.* + -$(FIND) . \( -name core -o -name foo \) \ + -print | xargs rm $(RMFLAGS) + +clean: semi-clean + -rm $(RMFLAGS) $(LIBGSM) $(ADDTST)/add \ + $(TOAST) $(TCAT) $(UNTOAST) \ + $(ROOT)/gsm-1.0.tar.Z + rm -rf lib + rm -f .*.d *.i */*.i + +# Two tools that helped me generate gsm_encode.c and gsm_decode.c, +# but aren't generally needed to port this. + +$(TLS)/sweet: $(TLS)/sweet.o $(TLS)/taste.o + $(LD) $(LFLAGS) -o $(TLS)/sweet \ + $(TLS)/sweet.o $(TLS)/taste.o $(LDLIB) + +$(TLS)/bitter: $(TLS)/bitter.o $(TLS)/taste.o + $(LD) $(LFLAGS) -o $(TLS)/bitter \ + $(TLS)/bitter.o $(TLS)/taste.o $(LDLIB) + +# A version of the same family that Jeff Chilton used to implement +# the WAV #49 GSM format. + +$(TLS)/ginger: $(TLS)/ginger.o $(TLS)/taste.o + $(LD) $(LFLAGS) -o $(TLS)/ginger \ + $(TLS)/ginger.o $(TLS)/taste.o $(LDLIB) + +$(TLS)/sour: $(TLS)/sour.o $(TLS)/taste.o + $(LD) $(LFLAGS) -o $(TLS)/sour \ + $(TLS)/sour.o $(TLS)/taste.o $(LDLIB) + +# Run $(ADDTST)/add < $(ADDTST)/add_test.dta to make sure the +# basic arithmetic functions work as intended. + +$(ADDTST)/add: $(ADDTST)/add_test.o + $(LD) $(LFLAGS) -o $(ADDTST)/add $(ADDTST)/add_test.o $(LDLIB) + + +# Various conversion programs between linear, text, .gsm and the code +# format used by the tests we ran (.cod). We paid for the test data, +# so I guess we can't just provide them with this package. Still, +# if you happen to have them lying around, here's the code. +# +# You can use gsm2cod | cod2txt independently to look at what's +# coded inside the compressed frames, although this shouldn't be +# hard to roll on your own using the gsm_print() function from +# the API. + + +$(TST)/test-result: $(TST)/lin2cod $(TST)/cod2lin $(TOAST) $(TST)/run + ( cd $(TST); ./run ) + +$(TST)/lin2txt: $(TST)/lin2txt.o $(LIBGSM) + $(LD) $(LFLAGS) -o $(TST)/lin2txt \ + $(TST)/lin2txt.o $(LIBGSM) $(LDLIB) + +$(TST)/lin2cod: $(TST)/lin2cod.o $(LIBGSM) + $(LD) $(LFLAGS) -o $(TST)/lin2cod \ + $(TST)/lin2cod.o $(LIBGSM) $(LDLIB) + +$(TST)/gsm2cod: $(TST)/gsm2cod.o $(LIBGSM) + $(LD) $(LFLAGS) -o $(TST)/gsm2cod \ + $(TST)/gsm2cod.o $(LIBGSM) $(LDLIB) + +$(TST)/cod2txt: $(TST)/cod2txt.o $(LIBGSM) + $(LD) $(LFLAGS) -o $(TST)/cod2txt \ + $(TST)/cod2txt.o $(LIBGSM) $(LDLIB) + +$(TST)/cod2lin: $(TST)/cod2lin.o $(LIBGSM) + $(LD) $(LFLAGS) -o $(TST)/cod2lin \ + $(TST)/cod2lin.o $(LIBGSM) $(LDLIB) diff --git a/codecs/gsm/README b/codecs/gsm/README new file mode 100644 index 000000000..cb6af85cf --- /dev/null +++ b/codecs/gsm/README @@ -0,0 +1,37 @@ + +GSM 06.10 13 kbit/s RPE/LTP speech compression available +-------------------------------------------------------- + +The Communications and Operating Systems Research Group (KBS) at the +Technische Universitaet Berlin is currently working on a set of +UNIX-based tools for computer-mediated telecooperation that will be +made freely available. + +As part of this effort we are publishing an implementation of the +European GSM 06.10 provisional standard for full-rate speech +transcoding, prI-ETS 300 036, which uses RPE/LTP (residual pulse +excitation/long term prediction) coding at 13 kbit/s. + +GSM 06.10 compresses frames of 160 13-bit samples (8 kHz sampling +rate, i.e. a frame rate of 50 Hz) into 260 bits; for compatibility +with typical UNIX applications, our implementation turns frames of 160 +16-bit linear samples into 33-byte frames (1650 Bytes/s). +The quality of the algorithm is good enough for reliable speaker +recognition; even music often survives transcoding in recognizable +form (given the bandwidth limitations of 8 kHz sampling rate). + +The interfaces offered are a front end modelled after compress(1), and +a library API. Compression and decompression run faster than realtime +on most SPARCstations. The implementation has been verified against the +ETSI standard test patterns. + +Jutta Degener (jutta@cs.tu-berlin.de) +Carsten Bormann (cabo@cs.tu-berlin.de) + +Communications and Operating Systems Research Group, TU Berlin +Fax: +49.30.31425156, Phone: +49.30.31424315 + +-- +Copyright 1992 by Jutta Degener and Carsten Bormann, Technische +Universitaet Berlin. See the accompanying file "COPYRIGHT" for +details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. diff --git a/codecs/gsm/inc/config.h b/codecs/gsm/inc/config.h new file mode 100644 index 000000000..e0b0632be --- /dev/null +++ b/codecs/gsm/inc/config.h @@ -0,0 +1,51 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#if 0 +efine SIGHANDLER_T int /* signal handlers are void */ +efine HAS_SYSV_SIGNAL 1 /* sigs not blocked/reset? */ +#endif + +#define HAS_STDLIB_H 1 /* /usr/include/stdlib.h */ +#if 0 +efine HAS_LIMITS_H 1 /* /usr/include/limits.h */ +#endif +#define HAS_FCNTL_H 1 /* /usr/include/fcntl.h */ +#if 0 +efine HAS_ERRNO_DECL 1 /* errno.h declares errno */ +#endif + +#define HAS_FSTAT 1 /* fstat syscall */ +#define HAS_FCHMOD 1 /* fchmod syscall */ +#define HAS_CHMOD 1 /* chmod syscall */ +#define HAS_FCHOWN 1 /* fchown syscall */ +#define HAS_CHOWN 1 /* chown syscall */ +#if 0 +efine HAS__FSETMODE 1 /* _fsetmode -- set file mode */ +#endif + +#define HAS_STRING_H 1 /* /usr/include/string.h */ +#if 0 +efine HAS_STRINGS_H 1 /* /usr/include/strings.h */ +#endif + +#define HAS_UNISTD_H 1 /* /usr/include/unistd.h */ +#define HAS_UTIME 1 /* POSIX utime(path, times) */ +#if 0 +efine HAS_UTIMES 1 /* use utimes() syscall instead */ +#endif +#define HAS_UTIME_H 1 /* UTIME header file */ +#if 0 +efine HAS_UTIMBUF 1 /* struct utimbuf */ +efine HAS_UTIMEUSEC 1 /* microseconds in utimbuf? */ +#endif + +#endif /* CONFIG_H */ diff --git a/codecs/gsm/inc/gsm.h b/codecs/gsm/inc/gsm.h new file mode 100644 index 000000000..81065e512 --- /dev/null +++ b/codecs/gsm/inc/gsm.h @@ -0,0 +1,71 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef GSM_H +#define GSM_H + +#ifdef __cplusplus +# define NeedFunctionPrototypes 1 +#endif + +#if __STDC__ +# define NeedFunctionPrototypes 1 +#endif + +#ifdef _NO_PROTO +# undef NeedFunctionPrototypes +#endif + +#ifdef NeedFunctionPrototypes +# include <stdio.h> /* for FILE * */ +#endif + +#undef GSM_P +#if NeedFunctionPrototypes +# define GSM_P( protos ) protos +#else +# define GSM_P( protos ) ( /* protos */ ) +#endif + +/* + * Interface + */ + +typedef struct gsm_state * gsm; +typedef short gsm_signal; /* signed 16 bit */ +typedef unsigned char gsm_byte; +typedef gsm_byte gsm_frame[33]; /* 33 * 8 bits */ + +#define GSM_MAGIC 0xD /* 13 kbit/s RPE-LTP */ + +#define GSM_PATCHLEVEL 10 +#define GSM_MINOR 0 +#define GSM_MAJOR 1 + +#define GSM_OPT_VERBOSE 1 +#define GSM_OPT_FAST 2 +#define GSM_OPT_LTP_CUT 3 +#define GSM_OPT_WAV49 4 +#define GSM_OPT_FRAME_INDEX 5 +#define GSM_OPT_FRAME_CHAIN 6 + +extern gsm gsm_create GSM_P((void)); +extern void gsm_destroy GSM_P((gsm)); + +extern int gsm_print GSM_P((FILE *, gsm, gsm_byte *)); +extern int gsm_option GSM_P((gsm, int, int *)); + +extern void gsm_encode GSM_P((gsm, gsm_signal *, gsm_byte *)); +extern int gsm_decode GSM_P((gsm, gsm_byte *, gsm_signal *)); + +extern int gsm_explode GSM_P((gsm, gsm_byte *, gsm_signal *)); +extern void gsm_implode GSM_P((gsm, gsm_signal *, gsm_byte *)); + +#undef GSM_P + +#endif /* GSM_H */ diff --git a/codecs/gsm/inc/private.h b/codecs/gsm/inc/private.h new file mode 100644 index 000000000..80ecbc59f --- /dev/null +++ b/codecs/gsm/inc/private.h @@ -0,0 +1,312 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef PRIVATE_H +#define PRIVATE_H + +typedef short word; /* 16 bit signed int */ +typedef long longword; /* 32 bit signed int */ + +typedef unsigned short uword; /* unsigned word */ +typedef unsigned long ulongword; /* unsigned longword */ + +struct gsm_state { + + word dp0[ 280 ]; + + word z1; /* preprocessing.c, Offset_com. */ + longword L_z2; /* Offset_com. */ + int mp; /* Preemphasis */ + + word u[8]; /* short_term_aly_filter.c */ + word LARpp[2][8]; /* */ + word j; /* */ + + word ltp_cut; /* long_term.c, LTP crosscorr. */ + word nrp; /* 40 */ /* long_term.c, synthesis */ + word v[9]; /* short_term.c, synthesis */ + word msr; /* decoder.c, Postprocessing */ + + char verbose; /* only used if !NDEBUG */ + char fast; /* only used if FAST */ + + char wav_fmt; /* only used if WAV49 defined */ + unsigned char frame_index; /* odd/even chaining */ + unsigned char frame_chain; /* half-byte to carry forward */ +}; + + +#define MIN_WORD (-32767 - 1) +#define MAX_WORD 32767 + +#define MIN_LONGWORD (-2147483647 - 1) +#define MAX_LONGWORD 2147483647 + +#ifdef SASR /* flag: >> is a signed arithmetic shift right */ +#undef SASR +#define SASR(x, by) ((x) >> (by)) +#else +#define SASR(x, by) ((x) >= 0 ? (x) >> (by) : (~(-((x) + 1) >> (by)))) +#endif /* SASR */ + +#include "proto.h" + +/* + * Prototypes from add.c + */ +extern word gsm_mult P((word a, word b)); +extern longword gsm_L_mult P((word a, word b)); +extern word gsm_mult_r P((word a, word b)); + +extern word gsm_div P((word num, word denum)); + +extern word gsm_add P(( word a, word b )); +extern longword gsm_L_add P(( longword a, longword b )); + +extern word gsm_sub P((word a, word b)); +extern longword gsm_L_sub P((longword a, longword b)); + +extern word gsm_abs P((word a)); + +extern word gsm_norm P(( longword a )); + +extern longword gsm_L_asl P((longword a, int n)); +extern word gsm_asl P((word a, int n)); + +extern longword gsm_L_asr P((longword a, int n)); +extern word gsm_asr P((word a, int n)); + +/* + * Inlined functions from add.h + */ + +/* + * #define GSM_MULT_R(a, b) (* word a, word b, !(a == b == MIN_WORD) *) \ + * (0x0FFFF & SASR(((longword)(a) * (longword)(b) + 16384), 15)) + */ +#define GSM_MULT_R(a, b) /* word a, word b, !(a == b == MIN_WORD) */ \ + (SASR( ((longword)(a) * (longword)(b) + 16384), 15 )) + +# define GSM_MULT(a,b) /* word a, word b, !(a == b == MIN_WORD) */ \ + (SASR( ((longword)(a) * (longword)(b)), 15 )) + +# define GSM_L_MULT(a, b) /* word a, word b */ \ + (((longword)(a) * (longword)(b)) << 1) + +#if defined(__GNUC__) && defined(__i386__) + +static __inline__ int GSM_L_ADD(int a, int b) +{ + __asm__ __volatile__( + + "addl %2,%0; jno 0f; movl $0x7fffffff,%0; adcl $0,%0; 0:" + : "=&r" (a) + : "0" (a), "ir" (b) + : "cc" + ); + return(a); +} + +static __inline__ short GSM_ADD(short a, short b) +{ + __asm__ __volatile__( + "addw %2,%0; jno 0f; movw $0x7fff,%0; adcw $0,%0; 0:" + : "=&r" (a) + : "0" (a), "ir" (b) + : "cc" + ); + return(a); +} + +static __inline__ short GSM_SUB(short a, short b) +{ + __asm__ __volatile__( + "subw %2,%0; jno 0f; movw $0x7fff,%0; adcw $0,%0; 0:" + : "=&r" (a) + : "0" (a), "ir" (b) + : "cc" + ); + return(a); +} + +#else + +#ifdef WIN32 +#define inline __inline +#define __inline__ __inline +#endif + +# define GSM_L_ADD(a, b) \ + ( (a) < 0 ? ( (b) >= 0 ? (a) + (b) \ + : (utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1)) \ + >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)utmp-2 ) \ + : ((b) <= 0 ? (a) + (b) \ + : (utmp = (ulongword)(a) + (ulongword)(b)) >= MAX_LONGWORD \ + ? MAX_LONGWORD : utmp)) + +static inline word GSM_ADD(longword a, longword b) +{ + register longword ltmp; + ltmp = a + b; + return (word)((ulongword) (ltmp - MIN_WORD) > MAX_WORD - MIN_WORD ? (ltmp > 0 ? MAX_WORD : MIN_WORD) : ltmp); +}; + +static inline word GSM_SUB(longword a, longword b) +{ + register longword ltmp; + ltmp = a - b; + return (word)(ltmp >= MAX_WORD ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp); +}; + +#endif + +# define GSM_ABS(a) ((a) < 0 ? ((a) == MIN_WORD ? MAX_WORD : -(a)) : (a)) + +/* Use these if necessary: + +# define GSM_MULT_R(a, b) gsm_mult_r(a, b) +# define GSM_MULT(a, b) gsm_mult(a, b) +# define GSM_L_MULT(a, b) gsm_L_mult(a, b) + +# define GSM_L_ADD(a, b) gsm_L_add(a, b) +# define GSM_ADD(a, b) gsm_add(a, b) +# define GSM_SUB(a, b) gsm_sub(a, b) + +# define GSM_ABS(a) gsm_abs(a) + +*/ + +/* + * More prototypes from implementations.. + */ +extern void Gsm_Coder P(( + struct gsm_state * S, + word * s, /* [0..159] samples IN */ + word * LARc, /* [0..7] LAR coefficients OUT */ + word * Nc, /* [0..3] LTP lag OUT */ + word * bc, /* [0..3] coded LTP gain OUT */ + word * Mc, /* [0..3] RPE grid selection OUT */ + word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ + word * xMc /* [13*4] normalized RPE samples OUT */)); + +extern void Gsm_Long_Term_Predictor P(( /* 4x for 160 samples */ + struct gsm_state * S, + word * d, /* [0..39] residual signal IN */ + word * dp, /* [-120..-1] d' IN */ + word * e, /* [0..40] OUT */ + word * dpp, /* [0..40] OUT */ + word * Nc, /* correlation lag OUT */ + word * bc /* gain factor OUT */)); + +extern void Gsm_LPC_Analysis P(( + struct gsm_state * S, + word * s, /* 0..159 signals IN/OUT */ + word * LARc)); /* 0..7 LARc's OUT */ + +extern void Gsm_Preprocess P(( + struct gsm_state * S, + word * s, word * so)); + +extern void Gsm_Encoding P(( + struct gsm_state * S, + word * e, + word * ep, + word * xmaxc, + word * Mc, + word * xMc)); + +extern void Gsm_Short_Term_Analysis_Filter P(( + struct gsm_state * S, + word * LARc, /* coded log area ratio [0..7] IN */ + word * d /* st res. signal [0..159] IN/OUT */)); + +extern void Gsm_Decoder P(( + struct gsm_state * S, + word * LARcr, /* [0..7] IN */ + word * Ncr, /* [0..3] IN */ + word * bcr, /* [0..3] IN */ + word * Mcr, /* [0..3] IN */ + word * xmaxcr, /* [0..3] IN */ + word * xMcr, /* [0..13*4] IN */ + word * s)); /* [0..159] OUT */ + +extern void Gsm_Decoding P(( + struct gsm_state * S, + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12] IN */ + word * erp)); /* [0..39] OUT */ + +extern void Gsm_Long_Term_Synthesis_Filtering P(( + struct gsm_state* S, + word Ncr, + word bcr, + word * erp, /* [0..39] IN */ + word * drp)); /* [-120..-1] IN, [0..40] OUT */ + +void Gsm_RPE_Decoding P(( + struct gsm_state *S, + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12], 3 bits IN */ + word * erp)); /* [0..39] OUT */ + +void Gsm_RPE_Encoding P(( + struct gsm_state * S, + word * e, /* -5..-1][0..39][40..44 IN/OUT */ + word * xmaxc, /* OUT */ + word * Mc, /* OUT */ + word * xMc)); /* [0..12] OUT */ + +extern void Gsm_Short_Term_Synthesis_Filter P(( + struct gsm_state * S, + word * LARcr, /* log area ratios [0..7] IN */ + word * drp, /* received d [0...39] IN */ + word * s)); /* signal s [0..159] OUT */ + +extern void Gsm_Update_of_reconstructed_short_time_residual_signal P(( + word * dpp, /* [0...39] IN */ + word * ep, /* [0...39] IN */ + word * dp)); /* [-120...-1] IN/OUT */ + +/* + * Tables from table.c + */ +#ifndef GSM_TABLE_C + +extern word gsm_A[8], gsm_B[8], gsm_MIC[8], gsm_MAC[8]; +extern word gsm_INVA[8]; +extern word gsm_DLB[4], gsm_QLB[4]; +extern word gsm_H[11]; +extern word gsm_NRFAC[8]; +extern word gsm_FAC[8]; + +#endif /* GSM_TABLE_C */ + +/* + * Debugging + */ +#ifdef NDEBUG + +# define gsm_debug_words(a, b, c, d) /* nil */ +# define gsm_debug_longwords(a, b, c, d) /* nil */ +# define gsm_debug_word(a, b) /* nil */ +# define gsm_debug_longword(a, b) /* nil */ + +#else /* !NDEBUG => DEBUG */ + + extern void gsm_debug_words P((char * name, int, int, word *)); + extern void gsm_debug_longwords P((char * name, int, int, longword *)); + extern void gsm_debug_longword P((char * name, longword)); + extern void gsm_debug_word P((char * name, word)); + +#endif /* !NDEBUG */ + +#include "unproto.h" + +#endif /* PRIVATE_H */ diff --git a/codecs/gsm/inc/proto.h b/codecs/gsm/inc/proto.h new file mode 100644 index 000000000..87cf05e8a --- /dev/null +++ b/codecs/gsm/inc/proto.h @@ -0,0 +1,65 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef PROTO_H +#define PROTO_H + +#if __cplusplus +# define NeedFunctionPrototypes 1 +#endif + +#if __STDC__ +# define NeedFunctionPrototypes 1 +#endif + +#ifdef _NO_PROTO +# undef NeedFunctionPrototypes +#endif + +#undef P /* gnu stdio.h actually defines this... */ +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef P4 +#undef P5 +#undef P6 +#undef P7 +#undef P8 + +#if NeedFunctionPrototypes + +# define P( protos ) protos + +# define P0() (void) +# define P1(x, a) (a) +# define P2(x, a, b) (a, b) +# define P3(x, a, b, c) (a, b, c) +# define P4(x, a, b, c, d) (a, b, c, d) +# define P5(x, a, b, c, d, e) (a, b, c, d, e) +# define P6(x, a, b, c, d, e, f) (a, b, c, d, e, f) +# define P7(x, a, b, c, d, e, f, g) (a, b, c, d, e, f, g) +# define P8(x, a, b, c, d, e, f, g, h) (a, b, c, d, e, f, g, h) + +#else /* !NeedFunctionPrototypes */ + +# define P( protos ) ( /* protos */ ) + +# define P0() () +# define P1(x, a) x a; +# define P2(x, a, b) x a; b; +# define P3(x, a, b, c) x a; b; c; +# define P4(x, a, b, c, d) x a; b; c; d; +# define P5(x, a, b, c, d, e) x a; b; c; d; e; +# define P6(x, a, b, c, d, e, f) x a; b; c; d; e; f; +# define P7(x, a, b, c, d, e, f, g) x a; b; c; d; e; f; g; +# define P8(x, a, b, c, d, e, f, g, h) x a; b; c; d; e; f; g; h; + +#endif /* !NeedFunctionPrototypes */ + +#endif /* PROTO_H */ diff --git a/codecs/gsm/inc/unproto.h b/codecs/gsm/inc/unproto.h new file mode 100644 index 000000000..ccd565109 --- /dev/null +++ b/codecs/gsm/inc/unproto.h @@ -0,0 +1,23 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifdef PROTO_H /* sic */ +#undef PROTO_H + +#undef P +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef P4 +#undef P5 +#undef P6 +#undef P7 +#undef P8 + +#endif /* PROTO_H */ diff --git a/codecs/gsm/libgsm.vcproj b/codecs/gsm/libgsm.vcproj new file mode 100644 index 000000000..f94b209d5 --- /dev/null +++ b/codecs/gsm/libgsm.vcproj @@ -0,0 +1,253 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="libgsm" + ProjectGUID="{8FD2E297-4096-47E5-9258-C48FF1841523}" + RootNamespace="libgsm" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(SolutionDir)$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="4" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="inc" + PreprocessorDefinitions="WIN32;_DEBUG;_LIB" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(SolutionDir)$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="4" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="inc" + PreprocessorDefinitions="WIN32;NDEBUG;_LIB" + RuntimeLibrary="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath=".\src\add.c" + > + </File> + <File + RelativePath=".\src\code.c" + > + </File> + <File + RelativePath=".\src\debug.c" + > + </File> + <File + RelativePath=".\src\decode.c" + > + </File> + <File + RelativePath=".\src\gsm_create.c" + > + </File> + <File + RelativePath=".\src\gsm_decode.c" + > + </File> + <File + RelativePath=".\src\gsm_destroy.c" + > + </File> + <File + RelativePath=".\src\gsm_encode.c" + > + </File> + <File + RelativePath=".\src\gsm_explode.c" + > + </File> + <File + RelativePath=".\src\gsm_implode.c" + > + </File> + <File + RelativePath=".\src\gsm_option.c" + > + </File> + <File + RelativePath=".\src\gsm_print.c" + > + </File> + <File + RelativePath=".\src\long_term.c" + > + </File> + <File + RelativePath=".\src\lpc.c" + > + </File> + <File + RelativePath=".\src\preprocess.c" + > + </File> + <File + RelativePath=".\src\rpe.c" + > + </File> + <File + RelativePath=".\src\short_term.c" + > + </File> + <File + RelativePath=".\src\table.c" + > + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath=".\inc\config.h" + > + </File> + <File + RelativePath=".\inc\gsm.h" + > + </File> + <File + RelativePath=".\inc\private.h" + > + </File> + <File + RelativePath=".\inc\proto.h" + > + </File> + <File + RelativePath=".\inc\unproto.h" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/codecs/gsm/src/add.c b/codecs/gsm/src/add.c new file mode 100644 index 000000000..f23d27f16 --- /dev/null +++ b/codecs/gsm/src/add.c @@ -0,0 +1,235 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +/* + * See private.h for the more commonly used macro versions. + */ + +#include <stdio.h> +#include <assert.h> + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +#define saturate(x) \ + ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) + +word gsm_add P2((a,b), word a, word b) +{ + longword sum = (longword)a + (longword)b; + return (word)saturate(sum); +} + +word gsm_sub P2((a,b), word a, word b) +{ + longword diff = (longword)a - (longword)b; + return (word)saturate(diff); +} + +word gsm_mult P2((a,b), word a, word b) +{ + if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD; + else return (word)SASR( (longword)a * (longword)b, 15 ); +} + +word gsm_mult_r P2((a,b), word a, word b) +{ + if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; + else { + longword prod = (longword)a * (longword)b + 16384; + prod >>= 15; + return (word)(prod & 0xFFFF); + } +} + +word gsm_abs P1((a), word a) +{ + return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a; +} + +longword gsm_L_mult P2((a,b),word a, word b) +{ + assert( a != MIN_WORD || b != MIN_WORD ); + return ((longword)a * (longword)b) << 1; +} + +longword gsm_L_add P2((a,b), longword a, longword b) +{ + if (a < 0) { + if (b >= 0) return a + b; + else { + ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1); + return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2; + } + } + else if (b <= 0) return a + b; + else { + ulongword A = (ulongword)a + (ulongword)b; + return A > MAX_LONGWORD ? MAX_LONGWORD : A; + } +} + +longword gsm_L_sub P2((a,b), longword a, longword b) +{ + if (a >= 0) { + if (b >= 0) return a - b; + else { + /* a>=0, b<0 */ + + ulongword A = (ulongword)a + -(b + 1); + return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1); + } + } + else if (b <= 0) return a - b; + else { + /* a<0, b>0 */ + + ulongword A = (ulongword)-(a + 1) + b; + return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1; + } +} + +static unsigned char const bitoff[ 256 ] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +word gsm_norm P1((a), longword a ) +/* + * the number of left shifts needed to normalize the 32 bit + * variable L_var1 for positive values on the interval + * + * with minimum of + * minimum of 1073741824 (01000000000000000000000000000000) and + * maximum of 2147483647 (01111111111111111111111111111111) + * + * + * and for negative values on the interval with + * minimum of -2147483648 (-10000000000000000000000000000000) and + * maximum of -1073741824 ( -1000000000000000000000000000000). + * + * in order to normalize the result, the following + * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); + * + * (That's 'ffs', only from the left, not the right..) + */ +{ + assert(a != 0); + + if (a < 0) { + if (a <= -1073741824) return 0; + a = ~a; + } + + return a & 0xffff0000 + ? ( a & 0xff000000 + ? -1 + bitoff[ 0xFF & (a >> 24) ] + : 7 + bitoff[ 0xFF & (a >> 16) ] ) + : ( a & 0xff00 + ? 15 + bitoff[ 0xFF & (a >> 8) ] + : 23 + bitoff[ 0xFF & a ] ); +} + +longword gsm_L_asl P2((a,n), longword a, int n) +{ + if (n >= 32) return 0; + if (n <= -32) return -(a < 0); + if (n < 0) return gsm_L_asr(a, -n); + return a << n; +} + +word gsm_asl P2((a,n), word a, int n) +{ + if (n >= 16) return 0; + if (n <= -16) return -(a < 0); + if (n < 0) return gsm_asr(a, -n); + return a << n; +} + +longword gsm_L_asr P2((a,n), longword a, int n) +{ + if (n >= 32) return -(a < 0); + if (n <= -32) return 0; + if (n < 0) return a << -n; + +# ifdef SASR + return a >> n; +# else + if (a >= 0) return a >> n; + else return -(longword)( -(ulongword)a >> n ); +# endif +} + +word gsm_asr P2((a,n), word a, int n) +{ + if (n >= 16) return -(a < 0); + if (n <= -16) return 0; + if (n < 0) return a << -n; + +# ifdef SASR + return a >> n; +# else + if (a >= 0) return a >> n; + else return -(word)( -(uword)a >> n ); +# endif +} + +/* + * (From p. 46, end of section 4.2.5) + * + * NOTE: The following lines gives [sic] one correct implementation + * of the div(num, denum) arithmetic operation. Compute div + * which is the integer division of num by denum: with denum + * >= num > 0 + */ + +word gsm_div P2((num,denum), word num, word denum) +{ + longword L_num = num; + longword L_denum = denum; + word div = 0; + int k = 15; + + /* The parameter num sometimes becomes zero. + * Although this is explicitly guarded against in 4.2.5, + * we assume that the result should then be zero as well. + */ + + /* assert(num != 0); */ + + assert(num >= 0 && denum >= num); + if (num == 0) + return 0; + + while (k--) { + div <<= 1; + L_num <<= 1; + + if (L_num >= L_denum) { + L_num -= L_denum; + div++; + } + } + + return div; +} diff --git a/codecs/gsm/src/code.c b/codecs/gsm/src/code.c new file mode 100644 index 000000000..4d195dfbd --- /dev/null +++ b/codecs/gsm/src/code.c @@ -0,0 +1,97 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "config.h" + +#ifdef HAS_STRING_H +#include <string.h> +#else +# include "proto.h" + extern char * memcpy P((char *, char *, int)); +#endif + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +/* + * 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER + */ + +void Gsm_Coder P8((S,s,LARc,Nc,bc,Mc,xmaxc,xMc), + + struct gsm_state * S, + + word * s, /* [0..159] samples IN */ + +/* + * The RPE-LTD coder works on a frame by frame basis. The length of + * the frame is equal to 160 samples. Some computations are done + * once per frame to produce at the output of the coder the + * LARc[1..8] parameters which are the coded LAR coefficients and + * also to realize the inverse filtering operation for the entire + * frame (160 samples of signal d[0..159]). These parts produce at + * the output of the coder: + */ + + word * LARc, /* [0..7] LAR coefficients OUT */ + +/* + * Procedure 4.2.11 to 4.2.18 are to be executed four times per + * frame. That means once for each sub-segment RPE-LTP analysis of + * 40 samples. These parts produce at the output of the coder: + */ + + word * Nc, /* [0..3] LTP lag OUT */ + word * bc, /* [0..3] coded LTP gain OUT */ + word * Mc, /* [0..3] RPE grid selection OUT */ + word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ + word * xMc /* [13*4] normalized RPE samples OUT */ +) +{ + int k; + word * dp = S->dp0 + 120; /* [ -120...-1 ] */ + word * dpp = dp; /* [ 0...39 ] */ + + static word e[50]; + + word so[160]; + + Gsm_Preprocess (S, s, so); + Gsm_LPC_Analysis (S, so, LARc); + Gsm_Short_Term_Analysis_Filter (S, LARc, so); + + for (k = 0; k <= 3; k++, xMc += 13) { + + Gsm_Long_Term_Predictor ( S, + so+k*40, /* d [0..39] IN */ + dp, /* dp [-120..-1] IN */ + e + 5, /* e [0..39] OUT */ + dpp, /* dpp [0..39] OUT */ + Nc++, + bc++); + + Gsm_RPE_Encoding ( S, + e + 5, /* e ][0..39][ IN/OUT */ + xmaxc++, Mc++, xMc ); + /* + * Gsm_Update_of_reconstructed_short_time_residual_signal + * ( dpp, e + 5, dp ); + */ + + { register int i; + for (i = 0; i <= 39; i++) + dp[ i ] = GSM_ADD( e[5 + i], dpp[i] ); + } + dp += 40; + dpp += 40; + + } + (void)memcpy( (char *)S->dp0, (char *)(S->dp0 + 160), + 120 * sizeof(*S->dp0) ); +} diff --git a/codecs/gsm/src/debug.c b/codecs/gsm/src/debug.c new file mode 100644 index 000000000..22dfa8082 --- /dev/null +++ b/codecs/gsm/src/debug.c @@ -0,0 +1,76 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#ifndef NDEBUG + +/* If NDEBUG _is_ defined and no debugging should be performed, + * calls to functions in this module are #defined to nothing + * in private.h. + */ + +#include <stdio.h> +#include "proto.h" + +void gsm_debug_words P4( (name, from, to, ptr), + char * name, + int from, + int to, + word * ptr) +{ + int nprinted = 0; + + fprintf( stderr, "%s [%d .. %d]: ", name, from, to ); + while (from <= to) { + fprintf(stderr, "%d ", ptr[ from ] ); + from++; + if (nprinted++ >= 7) { + nprinted = 0; + if (from < to) putc('\n', stderr); + } + } + putc('\n', stderr); +} + +void gsm_debug_longwords P4( (name, from, to, ptr), + char * name, + int from, + int to, + longword * ptr) +{ + int nprinted = 0; + + fprintf( stderr, "%s [%d .. %d]: ", name, from, to ); + while (from <= to) { + + fprintf(stderr, "%d ", ptr[ from ] ); + from++; + if (nprinted++ >= 7) { + nprinted = 0; + if (from < to) putc('\n', stderr); + } + } + putc('\n', stderr); +} + +void gsm_debug_longword P2( (name, value), + char * name, + longword value ) +{ + fprintf(stderr, "%s: %d\n", name, (long)value ); +} + +void gsm_debug_word P2( (name, value), + char * name, + word value ) +{ + fprintf(stderr, "%s: %d\n", name, (long)value); +} + +#endif diff --git a/codecs/gsm/src/decode.c b/codecs/gsm/src/decode.c new file mode 100644 index 000000000..093ac64df --- /dev/null +++ b/codecs/gsm/src/decode.c @@ -0,0 +1,62 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include <stdio.h> + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +/* + * 4.3 FIXED POINT IMPLEMENTATION OF THE RPE-LTP DECODER + */ + +static void Postprocessing P2((S,s), + struct gsm_state * S, + register word * s) +{ + register int k; + register word msr = S->msr; + register word tmp; + + for (k = 160; k--; s++) { + tmp = (word)GSM_MULT_R( msr, 28180 ); + msr = GSM_ADD(*s, tmp); /* Deemphasis */ + *s = GSM_ADD(msr, msr) & 0xFFF8; /* Truncation & Upscaling */ + } + S->msr = msr; +} + +void Gsm_Decoder P8((S,LARcr, Ncr,bcr,Mcr,xmaxcr,xMcr,s), + struct gsm_state * S, + + word * LARcr, /* [0..7] IN */ + + word * Ncr, /* [0..3] IN */ + word * bcr, /* [0..3] IN */ + word * Mcr, /* [0..3] IN */ + word * xmaxcr, /* [0..3] IN */ + word * xMcr, /* [0..13*4] IN */ + + word * s) /* [0..159] OUT */ +{ + int j, k; + word erp[40], wt[160]; + word * drp = S->dp0 + 120; + + for (j=0; j <= 3; j++, xmaxcr++, bcr++, Ncr++, Mcr++, xMcr += 13) { + + Gsm_RPE_Decoding( S, *xmaxcr, *Mcr, xMcr, erp ); + Gsm_Long_Term_Synthesis_Filtering( S, *Ncr, *bcr, erp, drp ); + + for (k = 0; k <= 39; k++) wt[ j * 40 + k ] = drp[ k ]; + } + + Gsm_Short_Term_Synthesis_Filter( S, LARcr, wt, s ); + Postprocessing(S, s); +} diff --git a/codecs/gsm/src/gsm_create.c b/codecs/gsm/src/gsm_create.c new file mode 100644 index 000000000..a59aa2f2a --- /dev/null +++ b/codecs/gsm/src/gsm_create.c @@ -0,0 +1,45 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +static char const ident[] = "$Header$"; + +#include "config.h" + +#ifdef HAS_STRING_H +#include <string.h> +#else +# include "proto.h" + extern char * memset P((char *, int, int)); +#endif + +#ifdef HAS_STDLIB_H +# include <stdlib.h> +#else +# ifdef HAS_MALLOC_H +# include <malloc.h> +# else + extern char * malloc(); +# endif +#endif + +#include <stdio.h> + +#include "gsm.h" +#include "private.h" +#include "proto.h" + +gsm gsm_create P0() +{ + gsm r; + + r = (gsm)malloc(sizeof(struct gsm_state)); + if (!r) return r; + + memset((char *)r, 0, sizeof(*r)); + r->nrp = 40; + + return r; +} diff --git a/codecs/gsm/src/gsm_decode.c b/codecs/gsm/src/gsm_decode.c new file mode 100644 index 000000000..7318ba2d4 --- /dev/null +++ b/codecs/gsm/src/gsm_decode.c @@ -0,0 +1,361 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +int gsm_decode P3((s, c, target), gsm s, gsm_byte * c, gsm_signal * target) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + +#ifdef WAV49 + if (s->wav_fmt) { + + uword sr = 0; + + s->frame_index = !s->frame_index; + if (s->frame_index) { + + 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[48] = sr & 0x7; sr >>= 3; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + s->frame_chain = sr & 0xf; + } + else { + sr = s->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; + } + } + else +#endif + { + /* GSM_MAGIC = (*c >> 4) & 0xF; */ + + if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; + + 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 */ + } + + Gsm_Decoder(s, LARc, Nc, bc, Mc, xmaxc, xmc, target); + + return 0; +} diff --git a/codecs/gsm/src/gsm_destroy.c b/codecs/gsm/src/gsm_destroy.c new file mode 100644 index 000000000..4807c0acd --- /dev/null +++ b/codecs/gsm/src/gsm_destroy.c @@ -0,0 +1,26 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "gsm.h" +#include "config.h" +#include "proto.h" + +#ifdef HAS_STDLIB_H +# include <stdlib.h> +#else +# ifdef HAS_MALLOC_H +# include <malloc.h> +# else + extern void free(); +# endif +#endif + +void gsm_destroy P1((S), gsm S) +{ + if (S) free((char *)S); +} diff --git a/codecs/gsm/src/gsm_encode.c b/codecs/gsm/src/gsm_encode.c new file mode 100644 index 000000000..62338300e --- /dev/null +++ b/codecs/gsm/src/gsm_encode.c @@ -0,0 +1,451 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +void gsm_encode P3((s, source, c), gsm s, gsm_signal * source, gsm_byte * c) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + + Gsm_Coder(s, source, LARc, Nc, bc, Mc, xmaxc, xmc); + + + /* variable size + + GSM_MAGIC 4 + + LARc[0] 6 + LARc[1] 6 + LARc[2] 5 + LARc[3] 5 + LARc[4] 4 + LARc[5] 4 + LARc[6] 3 + LARc[7] 3 + + Nc[0] 7 + bc[0] 2 + Mc[0] 2 + xmaxc[0] 6 + xmc[0] 3 + xmc[1] 3 + xmc[2] 3 + xmc[3] 3 + xmc[4] 3 + xmc[5] 3 + xmc[6] 3 + xmc[7] 3 + xmc[8] 3 + xmc[9] 3 + xmc[10] 3 + xmc[11] 3 + xmc[12] 3 + + Nc[1] 7 + bc[1] 2 + Mc[1] 2 + xmaxc[1] 6 + xmc[13] 3 + xmc[14] 3 + xmc[15] 3 + xmc[16] 3 + xmc[17] 3 + xmc[18] 3 + xmc[19] 3 + xmc[20] 3 + xmc[21] 3 + xmc[22] 3 + xmc[23] 3 + xmc[24] 3 + xmc[25] 3 + + Nc[2] 7 + bc[2] 2 + Mc[2] 2 + xmaxc[2] 6 + xmc[26] 3 + xmc[27] 3 + xmc[28] 3 + xmc[29] 3 + xmc[30] 3 + xmc[31] 3 + xmc[32] 3 + xmc[33] 3 + xmc[34] 3 + xmc[35] 3 + xmc[36] 3 + xmc[37] 3 + xmc[38] 3 + + Nc[3] 7 + bc[3] 2 + Mc[3] 2 + xmaxc[3] 6 + xmc[39] 3 + xmc[40] 3 + xmc[41] 3 + xmc[42] 3 + xmc[43] 3 + xmc[44] 3 + xmc[45] 3 + xmc[46] 3 + xmc[47] 3 + xmc[48] 3 + xmc[49] 3 + xmc[50] 3 + xmc[51] 3 + */ + +#ifdef WAV49 + + if (s->wav_fmt) { + s->frame_index = !s->frame_index; + if (s->frame_index) { + + uword sr; + + 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; + s->frame_chain = *c; + } + else { + uword sr; + + sr = 0; + sr = sr >> 4 | s->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; + } + } + + else + +#endif /* WAV49 */ + { + + *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); + + } +} diff --git a/codecs/gsm/src/gsm_explode.c b/codecs/gsm/src/gsm_explode.c new file mode 100644 index 000000000..a906fc2ed --- /dev/null +++ b/codecs/gsm/src/gsm_explode.c @@ -0,0 +1,417 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +int gsm_explode P3((s, c, target), gsm s, gsm_byte * c, gsm_signal * target) +{ +# define LARc target +# define Nc *((gsm_signal (*) [17])(target + 8)) +# define bc *((gsm_signal (*) [17])(target + 9)) +# define Mc *((gsm_signal (*) [17])(target + 10)) +# define xmaxc *((gsm_signal (*) [17])(target + 11)) + + +#ifdef WAV49 + if (s->wav_fmt) { + + uword sr = 0; + + if (s->frame_index == 1) { + + 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; +#undef xmc +#define xmc (target + 12) + 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; +#undef xmc +#define xmc (target + 29 - 13) + + 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; + +#undef xmc +#define xmc (target + 46 - 26) + + 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; +#undef xmc +#define xmc (target + 63 - 39) + + 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[48] = sr & 0x7; sr >>= 3; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + s->frame_chain = sr & 0xf; + } + else { + sr = s->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; +#undef xmc +#define xmc (target + 12) + 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; +#undef xmc +#define xmc (target + 29 - 13) + + 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; +#undef xmc +#define xmc (target + 46 - 26) + 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; + +#undef xmc +#define xmc (target + 63 - 39) + + 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; + } + } + else +#endif + { + /* GSM_MAGIC = (*c >> 4) & 0xF; */ + + if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; + + 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; + +#undef xmc +#define xmc (target + 12) + + 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; + +#undef xmc +#define xmc (target + 29 - 13) + + 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; + +#undef xmc +#define xmc (target + 46 - 26) + + 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; + +#undef xmc +#define xmc (target + 63 - 39) + + 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 */ + } + + return 0; +} diff --git a/codecs/gsm/src/gsm_implode.c b/codecs/gsm/src/gsm_implode.c new file mode 100644 index 000000000..453b8cf39 --- /dev/null +++ b/codecs/gsm/src/gsm_implode.c @@ -0,0 +1,515 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +void gsm_implode P3((s, source, c), gsm s, gsm_signal * source, gsm_byte * c) +{ + /* variable size index + + GSM_MAGIC 4 - + + LARc[0] 6 0 + LARc[1] 6 1 + LARc[2] 5 2 + LARc[3] 5 3 + LARc[4] 4 4 + LARc[5] 4 5 + LARc[6] 3 6 + LARc[7] 3 7 + + Nc[0] 7 8 + bc[0] 2 9 + Mc[0] 2 10 + xmaxc[0] 6 11 + xmc[0] 3 12 + xmc[1] 3 13 + xmc[2] 3 14 + xmc[3] 3 15 + xmc[4] 3 16 + xmc[5] 3 17 + xmc[6] 3 18 + xmc[7] 3 19 + xmc[8] 3 20 + xmc[9] 3 21 + xmc[10] 3 22 + xmc[11] 3 23 + xmc[12] 3 24 + + Nc[1] 7 25 + bc[1] 2 26 + Mc[1] 2 27 + xmaxc[1] 6 28 + xmc[13] 3 29 + xmc[14] 3 30 + xmc[15] 3 31 + xmc[16] 3 32 + xmc[17] 3 33 + xmc[18] 3 34 + xmc[19] 3 35 + xmc[20] 3 36 + xmc[21] 3 37 + xmc[22] 3 38 + xmc[23] 3 39 + xmc[24] 3 40 + xmc[25] 3 41 + + Nc[2] 7 42 + bc[2] 2 43 + Mc[2] 2 44 + xmaxc[2] 6 45 + xmc[26] 3 46 + xmc[27] 3 47 + xmc[28] 3 48 + xmc[29] 3 49 + xmc[30] 3 50 + xmc[31] 3 51 + xmc[32] 3 52 + xmc[33] 3 53 + xmc[34] 3 54 + xmc[35] 3 55 + xmc[36] 3 56 + xmc[37] 3 57 + xmc[38] 3 58 + + Nc[3] 7 59 + bc[3] 2 60 + Mc[3] 2 61 + xmaxc[3] 6 62 + xmc[39] 3 63 + xmc[40] 3 64 + xmc[41] 3 65 + xmc[42] 3 66 + xmc[43] 3 67 + xmc[44] 3 68 + xmc[45] 3 69 + xmc[46] 3 70 + xmc[47] 3 71 + xmc[48] 3 72 + xmc[49] 3 73 + xmc[50] 3 74 + xmc[51] 3 75 + */ + + /* There are 76 parameters per frame. The first eight are + * unique. The remaining 68 are four identical subframes of + * 17 parameters each. gsm_implode converts from a representation + * of these parameters as values in one array of signed words + * to the "packed" version of a GSM frame. + */ + +# define LARc source +# define Nc *((gsm_signal (*) [17])(source + 8)) +# define bc *((gsm_signal (*) [17])(source + 9)) +# define Mc *((gsm_signal (*) [17])(source + 10)) +# define xmaxc *((gsm_signal (*) [17])(source + 11)) + +#ifdef WAV49 + if (s->wav_fmt) { + + uword sr = 0; + if (s->frame_index == 0) { + + 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; +#undef xmc +#define xmc (source + 12) + 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; +#undef xmc +#define xmc (source + 29 - 13) + 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; +#undef xmc +#define xmc (source + 46 - 26) + 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; +#undef xmc +#define xmc (source + 63 - 39) + + 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[48] = sr & 0x7; sr >>= 3; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + s->frame_chain = sr & 0xf; + } + else { + sr = s->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; +#undef xmc +#define xmc (source + 12) + 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; +#undef xmc +#define xmc (source + 29 - 13) + 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; +#undef xmc +#define xmc (source + 46 - 26) + 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; +#undef xmc +#define xmc (source + 63 - 39) + + 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; + } + } + else +#endif + { + + *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) + +#undef xmc +#define xmc (source + 12) + + | ((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) + +#undef xmc +#define xmc (source + 29 - 13) + + | ((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) + +#undef xmc +#define xmc (source + 46 - 26) + + | ((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) + +#undef xmc +#define xmc (source + 63 - 39) + + | ((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); + } +} diff --git a/codecs/gsm/src/gsm_option.c b/codecs/gsm/src/gsm_option.c new file mode 100644 index 000000000..280780132 --- /dev/null +++ b/codecs/gsm/src/gsm_option.c @@ -0,0 +1,69 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +int gsm_option P3((r, opt, val), gsm r, int opt, int * val) +{ + int result = -1; + + switch (opt) { + case GSM_OPT_LTP_CUT: +#ifdef LTP_CUT + result = r->ltp_cut; + if (val) r->ltp_cut = *val; +#endif + break; + + case GSM_OPT_VERBOSE: +#ifndef NDEBUG + result = r->verbose; + if (val) r->verbose = *val; +#endif + break; + + case GSM_OPT_FAST: + +#if defined(FAST) && defined(USE_FLOAT_MUL) + result = r->fast; + if (val) r->fast = !!*val; +#endif + break; + + case GSM_OPT_FRAME_CHAIN: + +#ifdef WAV49 + result = r->frame_chain; + if (val) r->frame_chain = *val; +#endif + break; + + case GSM_OPT_FRAME_INDEX: + +#ifdef WAV49 + result = r->frame_index; + if (val) r->frame_index = *val; +#endif + break; + + case GSM_OPT_WAV49: + +#ifdef WAV49 + result = r->wav_fmt; + if (val) r->wav_fmt = !!*val; +#endif + break; + + default: + break; + } + return result; +} diff --git a/codecs/gsm/src/gsm_print.c b/codecs/gsm/src/gsm_print.c new file mode 100644 index 000000000..af745bc48 --- /dev/null +++ b/codecs/gsm/src/gsm_print.c @@ -0,0 +1,167 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include <stdio.h> + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +int gsm_print P3((f, s, c), FILE * f, gsm s, gsm_byte * c) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + + /* GSM_MAGIC = (*c >> 4) & 0xF; */ + + if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; + + 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 */ + + fprintf(f, + "LARc:\t%2.2d %2.2d %2.2d %2.2d %2.2d %2.2d %2.2d %2.2d\n", + LARc[0],LARc[1],LARc[2],LARc[3],LARc[4],LARc[5],LARc[6],LARc[7]); + + fprintf(f, "#1: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[0], bc[0], Mc[0], xmaxc[0]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[0],xmc[1],xmc[2],xmc[3],xmc[4],xmc[5],xmc[6], + xmc[7],xmc[8],xmc[9],xmc[10],xmc[11],xmc[12] ); + + fprintf(f, "#2: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[1], bc[1], Mc[1], xmaxc[1]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[13+0],xmc[13+1],xmc[13+2],xmc[13+3],xmc[13+4],xmc[13+5], + xmc[13+6], xmc[13+7],xmc[13+8],xmc[13+9],xmc[13+10],xmc[13+11], + xmc[13+12] ); + + fprintf(f, "#3: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[2], bc[2], Mc[2], xmaxc[2]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[26+0],xmc[26+1],xmc[26+2],xmc[26+3],xmc[26+4],xmc[26+5], + xmc[26+6], xmc[26+7],xmc[26+8],xmc[26+9],xmc[26+10],xmc[26+11], + xmc[26+12] ); + + fprintf(f, "#4: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[3], bc[3], Mc[3], xmaxc[3]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[39+0],xmc[39+1],xmc[39+2],xmc[39+3],xmc[39+4],xmc[39+5], + xmc[39+6], xmc[39+7],xmc[39+8],xmc[39+9],xmc[39+10],xmc[39+11], + xmc[39+12] ); + + return 0; +} diff --git a/codecs/gsm/src/k6opt.h b/codecs/gsm/src/k6opt.h new file mode 100644 index 000000000..16ea2ac8d --- /dev/null +++ b/codecs/gsm/src/k6opt.h @@ -0,0 +1,84 @@ +/* k6opt.h vector functions optimized for MMX extensions to x86 + * + * Copyright (C) 1999 by Stanley J. Brooks <stabro@megsinet.net> + * + * Any use of this software is permitted provided that this notice is not + * removed and that neither the authors nor the Technische Universitaet Berlin + * are deemed to have made any representations as to the suitability of this + * software for any purpose nor are held responsible for any defects of + * this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE; + * not even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. + * + * Chicago, 03.12.1999 + * Stanley J. Brooks + */ + +extern void Weighting_filter P2((e, x), + const word * e, /* signal [-5..0.39.44] IN */ + word * x /* signal [0..39] OUT */ +) +; + +extern longword k6maxcc P3((wt,dp,Nc_out), + const word *wt, + const word *dp, + word * Nc_out /* OUT */ +) +; +/* + * k6maxmin(p,n,out[]) + * input p[n] is array of shorts (require n>0) + * returns (long) maximum absolute value.. + * if out!=NULL, also returns out[0] the maximum and out[1] the minimum + */ +extern longword k6maxmin P3((p,n,out), + const word *p, + int n, + word *out /* out[0] is max, out[1] is min */ +) +; + +extern longword k6iprod P3((p,q,n), + const word *p, + const word *q, + int n +) +; + +/* + * k6vsraw(p,n,bits) + * input p[n] is array of shorts (require n>0) + * shift/round each to the right by bits>=0 bits. + */ +extern void k6vsraw P3((p,n,bits), + const word *p, + int n, + int bits +) +; + +/* + * k6vsllw(p,n,bits) + * input p[n] is array of shorts (require n>0) + * shift each to the left by bits>=0 bits. + */ +extern void k6vsllw P3((p,n,bits), + const word *p, + int n, + int bits +) +; + +#if 1 /* there isn't any significant speed gain from mmx here: */ +extern void Short_term_analysis_filteringx P4((u0,rp0,k_n,s), + register word * u0, + register word * rp0, /* [0..7] IN */ + register int k_n, /* k_end - k_start */ + register word * s /* [0..n-1] IN/OUT */ +) +; +/* +#define Short_term_analysis_filtering Short_term_analysis_filteringx +*/ +#endif diff --git a/codecs/gsm/src/k6opt.s b/codecs/gsm/src/k6opt.s new file mode 100644 index 000000000..d84d54cbf --- /dev/null +++ b/codecs/gsm/src/k6opt.s @@ -0,0 +1,739 @@ + .file "k6opt.s" + .version "01.01" +/* gcc2_compiled.: */ +.section .rodata + .align 4 + .type coefs,@object + .size coefs,24 +coefs: + .value -134 + .value -374 + .value 0 + .value 2054 + .value 5741 + .value 8192 + .value 5741 + .value 2054 + .value 0 + .value -374 + .value -134 + .value 0 +.text + .align 4 +/* void Weighting_filter (const short *e, short *x) */ +.globl Weighting_filter + .type Weighting_filter,@function +Weighting_filter: + pushl %ebp + movl %esp,%ebp + pushl %edi + pushl %esi + pushl %ebx + movl 12(%ebp),%edi + movl 8(%ebp),%ebx + addl $-10,%ebx + emms + movl $0x1000,%eax; movd %eax,%mm5 /* for rounding */ + movq coefs,%mm1 + movq coefs+8,%mm2 + movq coefs+16,%mm3 + xorl %esi,%esi + .p2align 2 +.L21: + movq (%ebx,%esi,2),%mm0 + pmaddwd %mm1,%mm0 + + movq 8(%ebx,%esi,2),%mm4 + pmaddwd %mm2,%mm4 + paddd %mm4,%mm0 + + movq 16(%ebx,%esi,2),%mm4 + pmaddwd %mm3,%mm4 + paddd %mm4,%mm0 + + movq %mm0,%mm4 + punpckhdq %mm0,%mm4 /* mm4 has high int32 of mm0 dup'd */ + paddd %mm4,%mm0; + + paddd %mm5,%mm0 /* add for roundoff */ + psrad $13,%mm0 + packssdw %mm0,%mm0 + movd %mm0,%eax /* ax has result */ + movw %ax,(%edi,%esi,2) + incl %esi + cmpl $39,%esi + jle .L21 + emms + popl %ebx + popl %esi + popl %edi + leave + ret +.Lfe1: + .size Weighting_filter,.Lfe1-Weighting_filter + +.macro ccstep n +.if \n + movq \n(%edi),%mm1 + movq \n(%esi),%mm2 +.else + movq (%edi),%mm1 + movq (%esi),%mm2 +.endif + pmaddwd %mm2,%mm1 + paddd %mm1,%mm0 +.endm + + .align 4 +/* long k6maxcc(const short *wt, const short *dp, short *Nc_out) */ +.globl k6maxcc + .type k6maxcc,@function +k6maxcc: + pushl %ebp + movl %esp,%ebp + pushl %edi + pushl %esi + pushl %ebx + emms + movl 8(%ebp),%edi + movl 12(%ebp),%esi + movl $0,%edx /* will be maximum inner-product */ + movl $40,%ebx + movl %ebx,%ecx /* will be index of max inner-product */ + subl $80,%esi + .p2align 2 +.L41: + movq (%edi),%mm0 + movq (%esi),%mm2 + pmaddwd %mm2,%mm0 + ccstep 8 + ccstep 16 + ccstep 24 + ccstep 32 + ccstep 40 + ccstep 48 + ccstep 56 + ccstep 64 + ccstep 72 + + movq %mm0,%mm1 + punpckhdq %mm0,%mm1 /* mm1 has high int32 of mm0 dup'd */ + paddd %mm1,%mm0; + movd %mm0,%eax /* eax has result */ + + cmpl %edx,%eax + jle .L40 + movl %eax,%edx + movl %ebx,%ecx + .p2align 2 +.L40: + subl $2,%esi + incl %ebx + cmpl $120,%ebx + jle .L41 + movl 16(%ebp),%eax + movw %cx,(%eax) + movl %edx,%eax + emms + popl %ebx + popl %esi + popl %edi + leave + ret +.Lfe2: + .size k6maxcc,.Lfe2-k6maxcc + + + .align 4 +/* long k6iprod (const short *p, const short *q, int n) */ +.globl k6iprod + .type k6iprod,@function +k6iprod: + pushl %ebp + movl %esp,%ebp + pushl %edi + pushl %esi + emms + pxor %mm0,%mm0 + movl 8(%ebp),%esi + movl 12(%ebp),%edi + movl 16(%ebp),%eax + leal -32(%esi,%eax,2),%edx /* edx = top - 32 */ + + cmpl %edx,%esi; ja .L202 + + .p2align 2 +.L201: + ccstep 0 + ccstep 8 + ccstep 16 + ccstep 24 + + addl $32,%esi + addl $32,%edi + cmpl %edx,%esi; jbe .L201 + + .p2align 2 +.L202: + addl $24,%edx /* now edx = top-8 */ + cmpl %edx,%esi; ja .L205 + + .p2align 2 +.L203: + ccstep 0 + + addl $8,%esi + addl $8,%edi + cmpl %edx,%esi; jbe .L203 + + .p2align 2 +.L205: + addl $4,%edx /* now edx = top-4 */ + cmpl %edx,%esi; ja .L207 + + movd (%edi),%mm1 + movd (%esi),%mm2 + pmaddwd %mm2,%mm1 + paddd %mm1,%mm0 + + addl $4,%esi + addl $4,%edi + + .p2align 2 +.L207: + addl $2,%edx /* now edx = top-2 */ + cmpl %edx,%esi; ja .L209 + + movswl (%edi),%eax + movd %eax,%mm1 + movswl (%esi),%eax + movd %eax,%mm2 + pmaddwd %mm2,%mm1 + paddd %mm1,%mm0 + + .p2align 2 +.L209: + movq %mm0,%mm1 + punpckhdq %mm0,%mm1 /* mm1 has high int32 of mm0 dup'd */ + paddd %mm1,%mm0; + movd %mm0,%eax /* eax has result */ + + emms + popl %esi + popl %edi + leave + ret +.Lfe3: + .size k6iprod,.Lfe3-k6iprod + + + .align 4 +/* void k6vsraw P3((short *p, int n, int bits) */ +.globl k6vsraw + .type k6vsraw,@function +k6vsraw: + pushl %ebp + movl %esp,%ebp + pushl %esi + movl 8(%ebp),%esi + movl 16(%ebp),%ecx + andl %ecx,%ecx; jle .L399 + movl 12(%ebp),%eax + leal -16(%esi,%eax,2),%edx /* edx = top - 16 */ + emms + movd %ecx,%mm3 + movq ones,%mm2 + psllw %mm3,%mm2; psrlw $1,%mm2 + cmpl %edx,%esi; ja .L306 + + .p2align 2 +.L302: /* 8 words per iteration */ + movq (%esi),%mm0 + movq 8(%esi),%mm1 + paddsw %mm2,%mm0 + psraw %mm3,%mm0; + paddsw %mm2,%mm1 + psraw %mm3,%mm1; + movq %mm0,(%esi) + movq %mm1,8(%esi) + addl $16,%esi + cmpl %edx,%esi + jbe .L302 + + .p2align 2 +.L306: + addl $12,%edx /* now edx = top-4 */ + cmpl %edx,%esi; ja .L310 + + .p2align 2 +.L308: /* do up to 6 words, two at a time */ + movd (%esi),%mm0 + paddsw %mm2,%mm0 + psraw %mm3,%mm0; + movd %mm0,(%esi) + addl $4,%esi + cmpl %edx,%esi + jbe .L308 + + .p2align 2 +.L310: + addl $2,%edx /* now edx = top-2 */ + cmpl %edx,%esi; ja .L315 + + movzwl (%esi),%eax + movd %eax,%mm0 + paddsw %mm2,%mm0 + psraw %mm3,%mm0; + movd %mm0,%eax + movw %ax,(%esi) + + .p2align 2 +.L315: + emms +.L399: + popl %esi + leave + ret +.Lfe4: + .size k6vsraw,.Lfe4-k6vsraw + + .align 4 +/* void k6vsllw P3((short *p, int n, int bits) */ +.globl k6vsllw + .type k6vsllw,@function +k6vsllw: + pushl %ebp + movl %esp,%ebp + pushl %esi + movl 8(%ebp),%esi + movl 16(%ebp),%ecx + andl %ecx,%ecx; jle .L499 + movl 12(%ebp),%eax + leal -16(%esi,%eax,2),%edx /* edx = top - 16 */ + emms + movd %ecx,%mm3 + cmpl %edx,%esi; ja .L406 + + .p2align 2 +.L402: /* 8 words per iteration */ + movq (%esi),%mm0 + movq 8(%esi),%mm1 + psllw %mm3,%mm0; + psllw %mm3,%mm1; + movq %mm0,(%esi) + movq %mm1,8(%esi) + addl $16,%esi + cmpl %edx,%esi + jbe .L402 + + .p2align 2 +.L406: + addl $12,%edx /* now edx = top-4 */ + cmpl %edx,%esi; ja .L410 + + .p2align 2 +.L408: /* do up to 6 words, two at a time */ + movd (%esi),%mm0 + psllw %mm3,%mm0; + movd %mm0,(%esi) + addl $4,%esi + cmpl %edx,%esi + jbe .L408 + + .p2align 2 +.L410: + addl $2,%edx /* now edx = top-2 */ + cmpl %edx,%esi; ja .L415 + + movzwl (%esi),%eax + movd %eax,%mm0 + psllw %mm3,%mm0; + movd %mm0,%eax + movw %ax,(%esi) + + .p2align 2 +.L415: + emms +.L499: + popl %esi + leave + ret +.Lfe5: + .size k6vsllw,.Lfe5-k6vsllw + + +.section .rodata + .align 4 + .type extremes,@object + .size extremes,8 +extremes: + .long 0x80008000 + .long 0x7fff7fff + .type ones,@object + .size ones,8 +ones: + .long 0x00010001 + .long 0x00010001 + +.text + .align 4 +/* long k6maxmin (const short *p, int n, short *out) */ +.globl k6maxmin + .type k6maxmin,@function +k6maxmin: + pushl %ebp + movl %esp,%ebp + pushl %esi + emms + movl 8(%ebp),%esi + movl 12(%ebp),%eax + leal -8(%esi,%eax,2),%edx + + cmpl %edx,%esi + jbe .L52 + movd extremes,%mm0 + movd extremes+4,%mm1 + jmp .L58 + + .p2align 2 +.L52: + movq (%esi),%mm0 /* mm0 will be max's */ + movq %mm0,%mm1 /* mm1 will be min's */ + addl $8,%esi + cmpl %edx,%esi + ja .L56 + + .p2align 2 +.L54: + movq (%esi),%mm2 + + movq %mm2,%mm3 + pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */ + movq %mm3,%mm4 + pand %mm2,%mm3 /* mm3 is mm2 masked to new max's */ + pandn %mm0,%mm4 /* mm4 is mm0 masked to its max's */ + por %mm3,%mm4 + movq %mm4,%mm0 /* now mm0 is updated max's */ + + movq %mm1,%mm3 + pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */ + pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */ + por %mm3,%mm2 + movq %mm2,%mm1 /* now mm1 is updated min's */ + + addl $8,%esi + cmpl %edx,%esi + jbe .L54 + + .p2align 2 +.L56: /* merge down the 4-word max/mins to lower 2 words */ + + movq %mm0,%mm2 + psrlq $32,%mm2 + movq %mm2,%mm3 + pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new max's */ + pandn %mm0,%mm3 /* mm3 is mm0 masked to its max's */ + por %mm3,%mm2 + movq %mm2,%mm0 /* now mm0 is updated max's */ + + movq %mm1,%mm2 + psrlq $32,%mm2 + movq %mm1,%mm3 + pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */ + pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */ + por %mm3,%mm2 + movq %mm2,%mm1 /* now mm1 is updated min's */ + + .p2align 2 +.L58: + addl $4,%edx /* now dx = top-4 */ + cmpl %edx,%esi + ja .L62 + /* here, there are >= 2 words of input remaining */ + movd (%esi),%mm2 + + movq %mm2,%mm3 + pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */ + movq %mm3,%mm4 + pand %mm2,%mm3 /* mm3 is mm2 masked to new max's */ + pandn %mm0,%mm4 /* mm4 is mm0 masked to its max's */ + por %mm3,%mm4 + movq %mm4,%mm0 /* now mm0 is updated max's */ + + movq %mm1,%mm3 + pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */ + pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */ + por %mm3,%mm2 + movq %mm2,%mm1 /* now mm1 is updated min's */ + + addl $4,%esi + + .p2align 2 +.L62: + /* merge down the 2-word max/mins to 1 word */ + + movq %mm0,%mm2 + psrlq $16,%mm2 + movq %mm2,%mm3 + pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new max's */ + pandn %mm0,%mm3 /* mm3 is mm0 masked to its max's */ + por %mm3,%mm2 + movd %mm2,%ecx /* cx is max so far */ + + movq %mm1,%mm2 + psrlq $16,%mm2 + movq %mm1,%mm3 + pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */ + pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */ + por %mm3,%mm2 + movd %mm2,%eax /* ax is min so far */ + + addl $2,%edx /* now dx = top-2 */ + cmpl %edx,%esi + ja .L65 + + /* here, there is one word of input left */ + cmpw (%esi),%cx + jge .L64 + movw (%esi),%cx + .p2align 2 +.L64: + cmpw (%esi),%ax + jle .L65 + movw (%esi),%ax + + .p2align 2 +.L65: /* (finally!) cx is the max, ax the min */ + movswl %cx,%ecx + movswl %ax,%eax + + movl 16(%ebp),%edx /* ptr to output max,min vals */ + andl %edx,%edx; jz .L77 + movw %cx,(%edx) /* max */ + movw %ax,2(%edx) /* min */ + .p2align 2 +.L77: + /* now calculate max absolute val */ + negl %eax + cmpl %ecx,%eax + jge .L81 + movl %ecx,%eax + .p2align 2 +.L81: + emms + popl %esi + leave + ret +.Lfe6: + .size k6maxmin,.Lfe6-k6maxmin + +/* void Short_term_analysis_filtering (short *u0, const short *rp0, int kn, short *s) */ + .equiv pm_u0,8 + .equiv pm_rp0,12 + .equiv pm_kn,16 + .equiv pm_s,20 + .equiv lv_u_top,-4 + .equiv lv_s_top,-8 + .equiv lv_rp,-40 /* local version of rp0 with each word twice */ + .align 4 +.globl Short_term_analysis_filteringx + .type Short_term_analysis_filteringx,@function +Short_term_analysis_filteringx: + pushl %ebp + movl %esp,%ebp + subl $40,%esp + pushl %edi + pushl %esi + + movl pm_rp0(%ebp),%esi; + leal lv_rp(%ebp),%edi; + cld + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + emms + movl $0x4000,%eax; + movd %eax,%mm4; + punpckldq %mm4,%mm4 /* (0x00004000,0x00004000) for rounding dword product pairs */ + + movl pm_u0(%ebp),%eax + addl $16,%eax + movl %eax,lv_u_top(%ebp) /* UTOP */ + movl pm_s(%ebp),%edx /* edx is local s ptr throughout below */ + movl pm_kn(%ebp),%eax + leal (%edx,%eax,2),%eax + movl %eax,lv_s_top(%ebp) + cmpl %eax,%edx + jae .L179 + .p2align 2 +.L181: + leal lv_rp(%ebp),%esi /* RP */ + movl pm_u0(%ebp),%edi /* U */ + movw (%edx),%ax /* (0,DI) */ + roll $16,%eax + movw (%edx),%ax /* (DI,DI) */ + .p2align 2 +.L185: /* RP is %esi */ + movl %eax,%ecx + movw (%edi),%ax /* (DI,U) */ + movd (%esi),%mm3 /* mm3 is (0,0,RP,RP) */ + movw %cx,(%edi) + + movd %eax,%mm2 /* mm2 is (0,0,DI,U) */ + rorl $16,%eax + movd %eax,%mm1 /* mm1 is (0,0,U,DI) */ + + movq %mm1,%mm0 + pmullw %mm3,%mm0 + pmulhw %mm3,%mm1 + punpcklwd %mm1,%mm0 /* mm0 is (RP*U,RP*DI) */ + paddd %mm4,%mm0 /* mm4 is 0x00004000,0x00004000 */ + psrad $15,%mm0 /* (RP*U,RP*DI) adjusted */ + packssdw %mm0,%mm0 /* (*,*,RP*U,RP*DI) adjusted and saturated to word */ + paddsw %mm2,%mm0 /* mm0 is (?,?, DI', U') */ + movd %mm0,%eax /* (DI,U') */ + + addl $2,%edi + addl $4,%esi + cmpl lv_u_top(%ebp),%edi + jb .L185 + + rorl $16,%eax + movw %ax,(%edx) /* last DI goes to *s */ + addl $2,%edx /* next s */ + cmpl lv_s_top(%ebp),%edx + jb .L181 + .p2align 2 +.L179: + emms + popl %esi + popl %edi + leave + ret +.Lfe7: + .size Short_term_analysis_filteringx,.Lfe7-Short_term_analysis_filteringx + +.end + +/* 'as' macro's seem to be case-insensitive */ +.macro STEP n +.if \n + movd \n(%esi),%mm3 /* mm3 is (0,0,RP,RP) */ +.else + movd (%esi),%mm3 /* mm3 is (0,0,RP,RP) */ +.endif + movq %mm5,%mm1; + movd %mm4,%ecx; movw %cx,%ax /* (DI,U) */ + psllq $48,%mm1; psrlq $16,%mm4; por %mm1,%mm4 + psllq $48,%mm0; psrlq $16,%mm5; por %mm0,%mm5 + + movd %eax,%mm2 /* mm2 is (0,0,DI,U) */ + rorl $16,%eax + movd %eax,%mm1 /* mm1 is (0,0,U,DI) */ + + movq %mm1,%mm0 + pmullw %mm3,%mm0 + pmulhw %mm3,%mm1 + punpcklwd %mm1,%mm0 /* mm0 is (RP*U,RP*DI) */ + paddd %mm6,%mm0 /* mm6 is 0x00004000,0x00004000 */ + psrad $15,%mm0 /* (RP*U,RP*DI) adjusted */ + packssdw %mm0,%mm0 /* (*,*,RP*U,RP*DI) adjusted and saturated to word */ + paddsw %mm2,%mm0 /* mm0 is (?,?, DI', U') */ + movd %mm0,%eax /* (DI,U') */ +.endm + +/* void Short_term_analysis_filtering (short *u0, const short *rp0, int kn, short *s) */ + .equiv pm_u0,8 + .equiv pm_rp0,12 + .equiv pm_kn,16 + .equiv pm_s,20 + .equiv lv_rp_top,-4 + .equiv lv_s_top,-8 + .equiv lv_rp,-40 /* local version of rp0 with each word twice */ + .align 4 +.globl Short_term_analysis_filteringx + .type Short_term_analysis_filteringx,@function +Short_term_analysis_filteringx: + pushl %ebp + movl %esp,%ebp + subl $56,%esp + pushl %edi + pushl %esi + pushl %ebx + + movl pm_rp0(%ebp),%esi; + leal lv_rp(%ebp),%edi; + cld + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + movl %edi,lv_rp_top(%ebp) + emms + + movl $0x4000,%eax; + movd %eax,%mm6; + punpckldq %mm6,%mm6 /* (0x00004000,0x00004000) for rounding dword product pairs */ + + movl pm_u0(%ebp),%ebx + movq (%ebx),%mm4; movq 8(%ebx),%mm5 /* the 8 u's */ + movl pm_s(%ebp),%edx /* edx is local s ptr throughout below */ + movl pm_kn(%ebp),%eax + leal (%edx,%eax,2),%eax + movl %eax,lv_s_top(%ebp) + cmpl %eax,%edx + jae .L179 + .p2align 2 +.L181: + leal lv_rp(%ebp),%esi /* RP */ + movw (%edx),%ax /* (0,DI) */ + roll $16,%eax + movw (%edx),%ax /* (DI,DI) */ + movd %eax,%mm0 + .p2align 2 +.L185: /* RP is %esi */ + step 0 + step 4 + step 8 + step 12 +/* + step 16 + step 20 + step 24 + step 28 +*/ + addl $16,%esi + cmpl lv_rp_top(%ebp),%esi + jb .L185 + + rorl $16,%eax + movw %ax,(%edx) /* last DI goes to *s */ + addl $2,%edx /* next s */ + cmpl lv_s_top(%ebp),%edx + jb .L181 +.L179: + movq %mm4,(%ebx); movq %mm5,8(%ebx) /* the 8 u's */ + emms + popl %ebx + popl %esi + popl %edi + leave + ret +.Lfe7: + .size Short_term_analysis_filteringx,.Lfe7-Short_term_analysis_filteringx + .ident "GCC: (GNU) 2.95.2 19991109 (Debian GNU/Linux)" diff --git a/codecs/gsm/src/long_term.c b/codecs/gsm/src/long_term.c new file mode 100644 index 000000000..83b6fdf85 --- /dev/null +++ b/codecs/gsm/src/long_term.c @@ -0,0 +1,955 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include <stdio.h> +#include <assert.h> + +#include "private.h" + +#include "gsm.h" +#include "proto.h" +#ifdef K6OPT +#include "k6opt.h" +#endif +/* + * 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION + */ + + +/* + * This module computes the LTP gain (bc) and the LTP lag (Nc) + * for the long term analysis filter. This is done by calculating a + * maximum of the cross-correlation function between the current + * sub-segment short term residual signal d[0..39] (output of + * the short term analysis filter; for simplification the index + * of this array begins at 0 and ends at 39 for each sub-segment of the + * RPE-LTP analysis) and the previous reconstructed short term + * residual signal dp[ -120 .. -1 ]. A dynamic scaling must be + * performed to avoid overflow. + */ + + /* The next procedure exists in six versions. First two integer + * version (if USE_FLOAT_MUL is not defined); then four floating + * point versions, twice with proper scaling (USE_FLOAT_MUL defined), + * once without (USE_FLOAT_MUL and FAST defined, and fast run-time + * option used). Every pair has first a Cut version (see the -C + * option to toast or the LTP_CUT option to gsm_option()), then the + * uncut one. (For a detailed explanation of why this is altogether + * a bad idea, see Henry Spencer and Geoff Collyer, ``#ifdef Considered + * Harmful''.) + */ + +#ifndef USE_FLOAT_MUL + +#ifdef LTP_CUT + +static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), + + struct gsm_state * st, + + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word wt[40]; + + longword L_result; + longword L_max, L_power; + word R, S, dmax, scal, best_k; + word ltp_cut; + + register word temp, wt_k; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) { + dmax = temp; + best_k = k; + } + } + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + if (temp > 6) scal = 0; + else scal = 6 - temp; + assert(scal >= 0); + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + wt_k = SASR(d[best_k], scal); + + for (lambda = 40; lambda <= 120; lambda++) { + L_result = (longword)wt_k * dp[best_k - lambda]; + if (L_result > L_max) { + Nc = lambda; + L_max = L_result; + } + } + *Nc_out = Nc; + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k; +#ifndef K6OPT + register int lambda; +#endif + word Nc, bc; + word wt[40]; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + + /* Initialization of a working array wt + */ + + for (k = 0; k <= 39; k++) wt[k] = SASR( d[k], scal ); + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ +# ifdef K6OPT + L_max = k6maxcc(wt,dp,&Nc); +# else + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda++) { + +# undef STEP +# define STEP(k) (longword)wt[k] * dp[k - lambda] + + register longword L_result; + + L_result = STEP(0) ; L_result += STEP(1) ; + L_result += STEP(2) ; L_result += STEP(3) ; + L_result += STEP(4) ; L_result += STEP(5) ; + L_result += STEP(6) ; L_result += STEP(7) ; + L_result += STEP(8) ; L_result += STEP(9) ; + L_result += STEP(10) ; L_result += STEP(11) ; + L_result += STEP(12) ; L_result += STEP(13) ; + L_result += STEP(14) ; L_result += STEP(15) ; + L_result += STEP(16) ; L_result += STEP(17) ; + L_result += STEP(18) ; L_result += STEP(19) ; + L_result += STEP(20) ; L_result += STEP(21) ; + L_result += STEP(22) ; L_result += STEP(23) ; + L_result += STEP(24) ; L_result += STEP(25) ; + L_result += STEP(26) ; L_result += STEP(27) ; + L_result += STEP(28) ; L_result += STEP(29) ; + L_result += STEP(30) ; L_result += STEP(31) ; + L_result += STEP(32) ; L_result += STEP(33) ; + L_result += STEP(34) ; L_result += STEP(35) ; + L_result += STEP(36) ; L_result += STEP(37) ; + L_result += STEP(38) ; L_result += STEP(39) ; + + if (L_result > L_max) { + + Nc = lambda; + L_max = L_result; + } + } +# endif + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = (word)SASR( L_max << temp, 16 ); + S = (word)SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#else /* USE_FLOAT_MUL */ + +#ifdef LTP_CUT + +static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), + struct gsm_state * st, /* IN */ + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word ltp_cut; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + ltp_cut = (longword)SASR(dmax, scal) * st->ltp_cut / 100; + + + /* Initialization of a working array wt + */ + + for (k = 0; k < 40; k++) { + register word w = SASR( d[k], scal ); + if (w < 0 ? w > -ltp_cut : w < ltp_cut) { + wt_float[k] = 0.0; + } + else { + wt_float[k] = w; + } + } + for (k = -120; k < 0; k++) dp_float[k] = dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + if ((W = wt_float[K]) != 0.0) { \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E; } else (a = lp[K]) + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + + } + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + + /* Initialization of a working array wt + */ + + for (k = 0; k < 40; k++) wt_float[k] = SASR( d[k], scal ); + for (k = -120; k < 0; k++) dp_float[k] = dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + W = wt_float[K]; \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + } + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#ifdef FAST +#ifdef LTP_CUT + +static void Cut_Fast_Calculation_of_the_LTP_parameters P5((st, + d,dp,bc_out,Nc_out), + struct gsm_state * st, /* IN */ + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + register float wt_float; + word Nc, bc; + word wt_max, best_k, ltp_cut; + + float dp_float_base[120], * dp_float = dp_float_base + 120; + + register float L_result, L_max, L_power; + + wt_max = 0; + + for (k = 0; k < 40; ++k) { + if ( d[k] > wt_max) wt_max = d[best_k = k]; + else if (-d[k] > wt_max) wt_max = -d[best_k = k]; + } + + assert(wt_max >= 0); + wt_float = (float)wt_max; + + for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda++) { + L_result = wt_float * dp_float[best_k - lambda]; + if (L_result > L_max) { + Nc = lambda; + L_max = L_result; + } + } + + *Nc_out = Nc; + if (L_max <= 0.) { + *bc_out = 0; + return; + } + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + dp_float -= Nc; + L_power = 0; + for (k = 0; k < 40; ++k) { + register float f = dp_float[k]; + L_power += f * f; + } + + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + /* Coding of the LTP gain + * Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + lambda = L_max / L_power * 32768.; + for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Fast_Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + register float L_max, L_power; + + for (k = 0; k < 40; ++k) wt_float[k] = (float)d[k]; + for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + W = wt_float[K]; \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + } + *Nc_out = Nc; + + if (L_max <= 0.) { + *bc_out = 0; + return; + } + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + dp_float -= Nc; + L_power = 0; + for (k = 0; k < 40; ++k) { + register float f = dp_float[k]; + L_power += f * f; + } + + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + /* Coding of the LTP gain + * Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + lambda = L_max / L_power * 32768.; + for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; + *bc_out = bc; +} + +#endif /* FAST */ +#endif /* USE_FLOAT_MUL */ + + +/* 4.2.12 */ + +static void Long_term_analysis_filtering P6((bc,Nc,dp,d,dpp,e), + word bc, /* IN */ + word Nc, /* IN */ + register word * dp, /* previous d [-120..-1] IN */ + register word * d, /* d [0..39] IN */ + register word * dpp, /* estimate [0..39] OUT */ + register word * e /* long term res. signal [0..39] OUT */ +) +/* + * In this part, we have to decode the bc parameter to compute + * the samples of the estimate dpp[0..39]. The decoding of bc needs the + * use of table 4.3b. The long term residual signal e[0..39] + * is then calculated to be fed to the RPE encoding section. + */ +{ + register int k; + +# undef STEP +# define STEP(BP) \ + for (k = 0; k <= 39; k++) { \ + dpp[k] = (word)GSM_MULT_R( BP, dp[k - Nc]); \ + e[k] = GSM_SUB( d[k], dpp[k] ); \ + } + + switch (bc) { + case 0: STEP( 3277 ); break; + case 1: STEP( 11469 ); break; + case 2: STEP( 21299 ); break; + case 3: STEP( 32767 ); break; + } +} + +void Gsm_Long_Term_Predictor P7((S,d,dp,e,dpp,Nc,bc), /* 4x for 160 samples */ + + struct gsm_state * S, + + word * d, /* [0..39] residual signal IN */ + word * dp, /* [-120..-1] d' IN */ + + word * e, /* [0..39] OUT */ + word * dpp, /* [0..39] OUT */ + word * Nc, /* correlation lag OUT */ + word * bc /* gain factor OUT */ +) +{ + assert( d ); assert( dp ); assert( e ); + assert( dpp); assert( Nc ); assert( bc ); + +#if defined(FAST) && defined(USE_FLOAT_MUL) + if (S->fast) +#if defined (LTP_CUT) + if (S->ltp_cut) + Cut_Fast_Calculation_of_the_LTP_parameters(S, + d, dp, bc, Nc); + else +#endif /* LTP_CUT */ + Fast_Calculation_of_the_LTP_parameters(d, dp, bc, Nc ); + else +#endif /* FAST & USE_FLOAT_MUL */ +#ifdef LTP_CUT + if (S->ltp_cut) + Cut_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc); + else +#endif + Calculation_of_the_LTP_parameters(d, dp, bc, Nc); + + Long_term_analysis_filtering( *bc, *Nc, dp, d, dpp, e ); +} + +/* 4.3.2 */ +void Gsm_Long_Term_Synthesis_Filtering P5((S,Ncr,bcr,erp,drp), + struct gsm_state * S, + + word Ncr, + word bcr, + register word * erp, /* [0..39] IN */ + register word * drp /* [-120..-1] IN, [-120..40] OUT */ +) +/* + * This procedure uses the bcr and Ncr parameter to realize the + * long term synthesis filtering. The decoding of bcr needs + * table 4.3b. + */ +{ + register int k; + word brp, drpp, Nr; + + /* Check the limits of Nr. + */ + Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr; + S->nrp = Nr; + assert(Nr >= 40 && Nr <= 120); + + /* Decoding of the LTP gain bcr + */ + brp = gsm_QLB[ bcr ]; + + /* Computation of the reconstructed short term residual + * signal drp[0..39] + */ + assert(brp != MIN_WORD); + + for (k = 0; k <= 39; k++) { + drpp = (word)GSM_MULT_R( brp, drp[ k - Nr ] ); + drp[k] = GSM_ADD( erp[k], drpp ); + } + + /* + * Update of the reconstructed short term residual signal + * drp[ -1..-120 ] + */ + + for (k = 0; k <= 119; k++) drp[ -120 + k ] = drp[ -80 + k ]; +} diff --git a/codecs/gsm/src/lpc.c b/codecs/gsm/src/lpc.c new file mode 100644 index 000000000..744149e02 --- /dev/null +++ b/codecs/gsm/src/lpc.c @@ -0,0 +1,372 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include <stdio.h> +#include <assert.h> + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +#ifdef K6OPT +#include "k6opt.h" +#endif + +#undef P + +/* + * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION + */ + +/* 4.2.4 */ + + +static void Autocorrelation P2((s, L_ACF), + word * s, /* [0..159] IN/OUT */ + longword * L_ACF) /* [0..8] OUT */ +/* + * The goal is to compute the array L_ACF[k]. The signal s[i] must + * be scaled in order to avoid an overflow situation. + */ +{ +#ifndef K6OPT + register int k, i; + word temp; +#endif + + word smax, scalauto; + +#ifdef USE_FLOAT_MUL + float float_s[160]; +#endif + + /* Dynamic scaling of the array s[0..159] + */ + + /* Search for the maximum. + */ +#ifndef K6OPT + smax = 0; + for (k = 0; k <= 159; k++) { + temp = GSM_ABS( s[k] ); + if (temp > smax) smax = temp; + } +#else + { + longword lmax; + lmax = k6maxmin(s,160,NULL); + smax = (lmax > MAX_WORD) ? MAX_WORD : lmax; + } +#endif + /* Computation of the scaling factor. + */ + if (smax == 0) scalauto = 0; + else { + assert(smax > 0); + scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */ + } + + /* Scaling of the array s[0...159] + */ + + if (scalauto > 0) { +# ifndef K6OPT + +# ifdef USE_FLOAT_MUL +# define SCALE(n) \ + case n: for (k = 0; k <= 159; k++) \ + float_s[k] = (float) \ + (s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\ + break; +# else +# define SCALE(n) \ + case n: for (k = 0; k <= 159; k++) \ + s[k] = (word)GSM_MULT_R( s[k], 16384 >> (n-1) );\ + break; +# endif /* USE_FLOAT_MUL */ + + switch (scalauto) { + SCALE(1) + SCALE(2) + SCALE(3) + SCALE(4) + } +# undef SCALE + +# else /* K6OPT */ + k6vsraw(s,160,scalauto); +# endif + } +# ifdef USE_FLOAT_MUL + else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k]; +# endif + + /* Compute the L_ACF[..]. + */ +#ifndef K6OPT + { +# ifdef USE_FLOAT_MUL + register float * sp = float_s; + register float sl = *sp; + +# define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]); +# else + word * sp = s; + word sl = *sp; + +# define STEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]); +# endif + +# define NEXTI sl = *++sp + + + for (k = 9; k--; L_ACF[k] = 0) ; + + STEP (0); + NEXTI; + STEP(0); STEP(1); + NEXTI; + STEP(0); STEP(1); STEP(2); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); + + for (i = 8; i <= 159; i++) { + + NEXTI; + + STEP(0); + STEP(1); STEP(2); STEP(3); STEP(4); + STEP(5); STEP(6); STEP(7); STEP(8); + } + + for (k = 9; k--; L_ACF[k] <<= 1) ; + + } + +#else + { + int k; + for (k=0; k<9; k++) { + L_ACF[k] = 2*k6iprod(s,s+k,160-k); + } + } +#endif + /* Rescaling of the array s[0..159] + */ + if (scalauto > 0) { + assert(scalauto <= 4); +#ifndef K6OPT + for (k = 160; k--; *s++ <<= scalauto) ; +# else /* K6OPT */ + k6vsllw(s,160,scalauto); +# endif + } +} + +#if defined(USE_FLOAT_MUL) && defined(FAST) + +static void Fast_Autocorrelation P2((s, L_ACF), + word * s, /* [0..159] IN/OUT */ + longword * L_ACF) /* [0..8] OUT */ +{ + register int k, i; + float f_L_ACF[9]; + float scale; + + float s_f[160]; + register float *sf = s_f; + + for (i = 0; i < 160; ++i) sf[i] = s[i]; + for (k = 0; k <= 8; k++) { + register float L_temp2 = 0; + register float *sfl = sf - k; + for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i]; + f_L_ACF[k] = L_temp2; + } + scale = MAX_LONGWORD / f_L_ACF[0]; + + for (k = 0; k <= 8; k++) { + L_ACF[k] = f_L_ACF[k] * scale; + } +} +#endif /* defined (USE_FLOAT_MUL) && defined (FAST) */ + +/* 4.2.5 */ + +static void Reflection_coefficients P2( (L_ACF, r), + longword * L_ACF, /* 0...8 IN */ + register word * r /* 0...7 OUT */ +) +{ + register int i, m, n; + register word temp; + word ACF[9]; /* 0..8 */ + word P[ 9]; /* 0..8 */ + word K[ 9]; /* 2..8 */ + + /* Schur recursion with 16 bits arithmetic. + */ + + if (L_ACF[0] == 0) { + for (i = 8; i--; *r++ = 0) ; + return; + } + + assert( L_ACF[0] != 0 ); + temp = gsm_norm( L_ACF[0] ); + + assert(temp >= 0 && temp < 32); + + /* ? overflow ? */ + for (i = 0; i <= 8; i++) ACF[i] = (word)SASR( L_ACF[i] << temp, 16 ); + + /* Initialize array P[..] and K[..] for the recursion. + */ + + for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ]; + for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ]; + + /* Compute reflection coefficients + */ + for (n = 1; n <= 8; n++, r++) { + + temp = P[1]; + temp = GSM_ABS(temp); + if (P[0] < temp) { + for (i = n; i <= 8; i++) *r++ = 0; + return; + } + + *r = gsm_div( temp, P[0] ); + + assert(*r >= 0); + if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */ + assert (*r != MIN_WORD); + if (n == 8) return; + + /* Schur recursion + */ + temp = (word)GSM_MULT_R( P[1], *r ); + P[0] = GSM_ADD( P[0], temp ); + + for (m = 1; m <= 8 - n; m++) { + temp = (word)GSM_MULT_R( K[ m ], *r ); + P[m] = GSM_ADD( P[ m+1 ], temp ); + + temp = (word)GSM_MULT_R( P[ m+1 ], *r ); + K[m] = GSM_ADD( K[ m ], temp ); + } + } +} + +/* 4.2.6 */ + +static void Transformation_to_Log_Area_Ratios P1((r), + register word * r /* 0..7 IN/OUT */ +) +/* + * The following scaling for r[..] and LAR[..] has been used: + * + * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1. + * LAR[..] = integer( real_LAR[..] * 16384 ); + * with -1.625 <= real_LAR <= 1.625 + */ +{ + register word temp; + register int i; + + + /* Computation of the LAR[0..7] from the r[0..7] + */ + for (i = 1; i <= 8; i++, r++) { + + temp = *r; + temp = GSM_ABS(temp); + assert(temp >= 0); + + if (temp < 22118) { + temp >>= 1; + } else if (temp < 31130) { + assert( temp >= 11059 ); + temp -= 11059; + } else { + assert( temp >= 26112 ); + temp -= 26112; + temp <<= 2; + } + + *r = *r < 0 ? -temp : temp; + assert( *r != MIN_WORD ); + } +} + +/* 4.2.7 */ + +static void Quantization_and_coding P1((LAR), + register word * LAR /* [0..7] IN/OUT */ +) +{ + register word temp; + + + /* This procedure needs four tables; the following equations + * give the optimum scaling for the constants: + * + * A[0..7] = integer( real_A[0..7] * 1024 ) + * B[0..7] = integer( real_B[0..7] * 512 ) + * MAC[0..7] = maximum of the LARc[0..7] + * MIC[0..7] = minimum of the LARc[0..7] + */ + +# undef STEP +# define STEP( A, B, MAC, MIC ) \ + temp = (word)GSM_MULT( A, *LAR ); \ + temp = GSM_ADD( temp, B ); \ + temp = GSM_ADD( temp, 256 ); \ + temp = (word)SASR( temp, 9 ); \ + *LAR = temp>MAC ? MAC - MIC : (temp<MIC ? 0 : temp - MIC); \ + LAR++; + + STEP( 20480, 0, 31, -32 ); + STEP( 20480, 0, 31, -32 ); + STEP( 20480, 2048, 15, -16 ); + STEP( 20480, -2560, 15, -16 ); + + STEP( 13964, 94, 7, -8 ); + STEP( 15360, -1792, 7, -8 ); + STEP( 8534, -341, 3, -4 ); + STEP( 9036, -1144, 3, -4 ); + +# undef STEP +} + +void Gsm_LPC_Analysis P3((S, s,LARc), + struct gsm_state *S, + word * s, /* 0..159 signals IN/OUT */ + word * LARc) /* 0..7 LARc's OUT */ +{ + longword L_ACF[9]; + +#if defined(USE_FLOAT_MUL) && defined(FAST) + if (S->fast) Fast_Autocorrelation (s, L_ACF ); + else +#endif + Autocorrelation (s, L_ACF ); + Reflection_coefficients (L_ACF, LARc ); + Transformation_to_Log_Area_Ratios (LARc); + Quantization_and_coding (LARc); +} diff --git a/codecs/gsm/src/preprocess.c b/codecs/gsm/src/preprocess.c new file mode 100644 index 000000000..eacdac851 --- /dev/null +++ b/codecs/gsm/src/preprocess.c @@ -0,0 +1,127 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include <stdio.h> +#include <assert.h> + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +/* 4.2.0 .. 4.2.3 PREPROCESSING SECTION + * + * After A-law to linear conversion (or directly from the + * Ato D converter) the following scaling is assumed for + * input to the RPE-LTP algorithm: + * + * in: 0.1.....................12 + * S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.* + * + * Where S is the sign bit, v a valid bit, and * a "don't care" bit. + * The original signal is called sop[..] + * + * out: 0.1................... 12 + * S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0 + */ + + +void Gsm_Preprocess P3((S, s, so), + struct gsm_state * S, + word * s, + word * so ) /* [0..159] IN/OUT */ +{ + word z1 = S->z1; + longword L_z2 = S->L_z2; + word mp = S->mp; + word s1; + word SO; + ulongword utmp; /* for L_ADD */ + register int k = 160; + + (void) utmp; + + while (k--) { + + /* 4.2.1 Downscaling of the input signal + */ + /* SO = SASR( *s, 3 ) << 2;*/ + SO = SASR( *s, 1 ) & ~3; + s++; + + assert (SO >= -0x4000); /* downscaled by */ + assert (SO <= 0x3FFC); /* previous routine. */ + + + /* 4.2.2 Offset compensation + * + * This part implements a high-pass filter and requires extended + * arithmetic precision for the recursive part of this filter. + * The input of this procedure is the array so[0...159] and the + * output the array sof[ 0...159 ]. + */ + /* Compute the non-recursive part + */ + + s1 = SO - z1; /* s1 = gsm_sub( *so, z1 ); */ + z1 = SO; + + assert(s1 != MIN_WORD); + + /* SJB Remark: float might be faster than the mess that follows */ + + /* Compute the recursive part + */ + + /* Execution of a 31 bv 16 bits multiplication + */ + { + word msp; +#ifndef __GNUC__ + word lsp; +#endif + longword L_s2; + longword L_temp; + + L_s2 = s1; + L_s2 <<= 15; +#ifndef __GNUC__ + msp = (word)SASR( L_z2, 15 ); + lsp = (word)(L_z2 & 0x7fff); /* gsm_L_sub(L_z2,(msp<<15)); */ + + L_s2 += GSM_MULT_R( lsp, 32735 ); + L_temp = (longword)msp * 32735; /* GSM_L_MULT(msp,32735) >> 1;*/ + L_z2 = GSM_L_ADD( L_temp, L_s2 ); + /* above does L_z2 = L_z2 * 0x7fd5/0x8000 + L_s2 */ +#else + L_z2 = ((long long)L_z2*32735 + 0x4000)>>15; + /* alternate (ansi) version of above line does slightly different rounding: + * L_temp = L_z2 >> 9; + * L_temp += L_temp >> 5; + * L_temp = (++L_temp) >> 1; + * L_z2 = L_z2 - L_temp; + */ + L_z2 = GSM_L_ADD(L_z2,L_s2); +#endif + /* Compute sof[k] with rounding + */ + L_temp = GSM_L_ADD( L_z2, 16384 ); + + /* 4.2.3 Preemphasis + */ + + msp = (word)GSM_MULT_R( mp, -28180 ); + mp = (word)SASR( L_temp, 15 ); + *so++ = GSM_ADD( mp, msp ); + } + } + + S->z1 = z1; + S->L_z2 = L_z2; + S->mp = mp; +} diff --git a/codecs/gsm/src/rpe.c b/codecs/gsm/src/rpe.c new file mode 100644 index 000000000..1c354795d --- /dev/null +++ b/codecs/gsm/src/rpe.c @@ -0,0 +1,490 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include <stdio.h> +#include <assert.h> + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +/* 4.2.13 .. 4.2.17 RPE ENCODING SECTION + */ + +/* 4.2.13 */ +#ifdef K6OPT +#include "k6opt.h" +#else +static void Weighting_filter P2((e, x), + register word * e, /* signal [-5..0.39.44] IN */ + word * x /* signal [0..39] OUT */ +) +/* + * The coefficients of the weighting filter are stored in a table + * (see table 4.4). The following scaling is used: + * + * H[0..10] = integer( real_H[ 0..10] * 8192 ); + */ +{ + /* word wt[ 50 ]; */ + + register longword L_result; + register int k /* , i */ ; + + /* Initialization of a temporary working array wt[0...49] + */ + + /* for (k = 0; k <= 4; k++) wt[k] = 0; + * for (k = 5; k <= 44; k++) wt[k] = *e++; + * for (k = 45; k <= 49; k++) wt[k] = 0; + * + * (e[-5..-1] and e[40..44] are allocated by the caller, + * are initially zero and are not written anywhere.) + */ + e -= 5; + + /* Compute the signal x[0..39] + */ + for (k = 0; k <= 39; k++) { + + L_result = 8192 >> 1; + + /* for (i = 0; i <= 10; i++) { + * L_temp = GSM_L_MULT( wt[k+i], gsm_H[i] ); + * L_result = GSM_L_ADD( L_result, L_temp ); + * } + */ + +#undef STEP +#define STEP( i, H ) (e[ k + i ] * (longword)H) + + /* Every one of these multiplications is done twice -- + * but I don't see an elegant way to optimize this. + * Do you? + */ + +#ifdef STUPID_COMPILER + L_result += STEP( 0, -134 ) ; + L_result += STEP( 1, -374 ) ; + /* + STEP( 2, 0 ) */ + L_result += STEP( 3, 2054 ) ; + L_result += STEP( 4, 5741 ) ; + L_result += STEP( 5, 8192 ) ; + L_result += STEP( 6, 5741 ) ; + L_result += STEP( 7, 2054 ) ; + /* + STEP( 8, 0 ) */ + L_result += STEP( 9, -374 ) ; + L_result += STEP( 10, -134 ) ; +#else + L_result += + STEP( 0, -134 ) + + STEP( 1, -374 ) + /* + STEP( 2, 0 ) */ + + STEP( 3, 2054 ) + + STEP( 4, 5741 ) + + STEP( 5, 8192 ) + + STEP( 6, 5741 ) + + STEP( 7, 2054 ) + /* + STEP( 8, 0 ) */ + + STEP( 9, -374 ) + + STEP(10, -134 ) + ; +#endif + + /* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x2) *) + * L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x4) *) + * + * x[k] = SASR( L_result, 16 ); + */ + + /* 2 adds vs. >>16 => 14, minus one shift to compensate for + * those we lost when replacing L_MULT by '*'. + */ + + L_result = SASR( L_result, 13 ); + x[k] = (word)( L_result < MIN_WORD ? MIN_WORD + : (L_result > MAX_WORD ? MAX_WORD : L_result )); + } +} +#endif /* K6OPT */ + +/* 4.2.14 */ + +static void RPE_grid_selection P3((x,xM,Mc_out), + word * x, /* [0..39] IN */ + word * xM, /* [0..12] OUT */ + word * Mc_out /* OUT */ +) +/* + * The signal x[0..39] is used to select the RPE grid which is + * represented by Mc. + */ +{ + /* register word temp1; */ + register int /* m, */ i; + register longword L_result, L_temp; + longword EM; /* xxx should be L_EM? */ + word Mc; + + longword L_common_0_3; + + EM = 0; + Mc = 0; + + /* for (m = 0; m <= 3; m++) { + * L_result = 0; + * + * + * for (i = 0; i <= 12; i++) { + * + * temp1 = SASR( x[m + 3*i], 2 ); + * + * assert(temp1 != MIN_WORD); + * + * L_temp = GSM_L_MULT( temp1, temp1 ); + * L_result = GSM_L_ADD( L_temp, L_result ); + * } + * + * if (L_result > EM) { + * Mc = m; + * EM = L_result; + * } + * } + */ + +#undef STEP +#define STEP( m, i ) L_temp = SASR( x[m + 3 * i], 2 ); \ + L_result += L_temp * L_temp; + + /* common part of 0 and 3 */ + + L_result = 0; + STEP( 0, 1 ); STEP( 0, 2 ); STEP( 0, 3 ); STEP( 0, 4 ); + STEP( 0, 5 ); STEP( 0, 6 ); STEP( 0, 7 ); STEP( 0, 8 ); + STEP( 0, 9 ); STEP( 0, 10); STEP( 0, 11); STEP( 0, 12); + L_common_0_3 = L_result; + + /* i = 0 */ + + STEP( 0, 0 ); + L_result <<= 1; /* implicit in L_MULT */ + EM = L_result; + + /* i = 1 */ + + L_result = 0; + STEP( 1, 0 ); + STEP( 1, 1 ); STEP( 1, 2 ); STEP( 1, 3 ); STEP( 1, 4 ); + STEP( 1, 5 ); STEP( 1, 6 ); STEP( 1, 7 ); STEP( 1, 8 ); + STEP( 1, 9 ); STEP( 1, 10); STEP( 1, 11); STEP( 1, 12); + L_result <<= 1; + if (L_result > EM) { + Mc = 1; + EM = L_result; + } + + /* i = 2 */ + + L_result = 0; + STEP( 2, 0 ); + STEP( 2, 1 ); STEP( 2, 2 ); STEP( 2, 3 ); STEP( 2, 4 ); + STEP( 2, 5 ); STEP( 2, 6 ); STEP( 2, 7 ); STEP( 2, 8 ); + STEP( 2, 9 ); STEP( 2, 10); STEP( 2, 11); STEP( 2, 12); + L_result <<= 1; + if (L_result > EM) { + Mc = 2; + EM = L_result; + } + + /* i = 3 */ + + L_result = L_common_0_3; + STEP( 3, 12 ); + L_result <<= 1; + if (L_result > EM) { + Mc = 3; + EM = L_result; + } + + /**/ + + /* Down-sampling by a factor 3 to get the selected xM[0..12] + * RPE sequence. + */ + for (i = 0; i <= 12; i ++) xM[i] = x[Mc + 3*i]; + *Mc_out = Mc; +} + +/* 4.12.15 */ + +static void APCM_quantization_xmaxc_to_exp_mant P3((xmaxc,exp_out,mant_out), + word xmaxc, /* IN */ + word * exp_out, /* OUT */ + word * mant_out ) /* OUT */ +{ + word exp, mant; + + /* Compute exponent and mantissa of the decoded version of xmaxc + */ + + exp = 0; + if (xmaxc > 15) exp = SASR(xmaxc, 3) - 1; + mant = xmaxc - (exp << 3); + + if (mant == 0) { + exp = -4; + mant = 7; + } + else { + while (mant <= 7) { + mant = mant << 1 | 1; + exp--; + } + mant -= 8; + } + + assert( exp >= -4 && exp <= 6 ); + assert( mant >= 0 && mant <= 7 ); + + *exp_out = exp; + *mant_out = mant; +} + +static void APCM_quantization P5((xM,xMc,mant_out,exp_out,xmaxc_out), + word * xM, /* [0..12] IN */ + + word * xMc, /* [0..12] OUT */ + word * mant_out, /* OUT */ + word * exp_out, /* OUT */ + word * xmaxc_out /* OUT */ +) +{ + int i, itest; + + word xmax, xmaxc, temp, temp1, temp2; + word exp, mant; + + + /* Find the maximum absolute value xmax of xM[0..12]. + */ + + xmax = 0; + for (i = 0; i <= 12; i++) { + temp = xM[i]; + temp = GSM_ABS(temp); + if (temp > xmax) xmax = temp; + } + + /* Qantizing and coding of xmax to get xmaxc. + */ + + exp = 0; + temp = SASR( xmax, 9 ); + itest = 0; + + for (i = 0; i <= 5; i++) { + + itest |= (temp <= 0); + temp = SASR( temp, 1 ); + + assert(exp <= 5); + if (itest == 0) exp++; /* exp = add (exp, 1) */ + } + + assert(exp <= 6 && exp >= 0); + temp = exp + 5; + + assert(temp <= 11 && temp >= 0); + xmaxc = gsm_add( SASR(xmax, temp), exp << 3 ); + + /* Quantizing and coding of the xM[0..12] RPE sequence + * to get the xMc[0..12] + */ + + APCM_quantization_xmaxc_to_exp_mant( xmaxc, &exp, &mant ); + + /* This computation uses the fact that the decoded version of xmaxc + * can be calculated by using the exponent and the mantissa part of + * xmaxc (logarithmic table). + * So, this method avoids any division and uses only a scaling + * of the RPE samples by a function of the exponent. A direct + * multiplication by the inverse of the mantissa (NRFAC[0..7] + * found in table 4.5) gives the 3 bit coded version xMc[0..12] + * of the RPE samples. + */ + + + /* Direct computation of xMc[0..12] using table 4.5 + */ + + assert( exp <= 4096 && exp >= -4096); + assert( mant >= 0 && mant <= 7 ); + + temp1 = 6 - exp; /* normalization by the exponent */ + temp2 = gsm_NRFAC[ mant ]; /* inverse mantissa */ + + for (i = 0; i <= 12; i++) { + + assert(temp1 >= 0 && temp1 < 16); + + temp = xM[i] << temp1; + temp = (word)GSM_MULT( temp, temp2 ); + temp = SASR(temp, 12); + xMc[i] = temp + 4; /* see note below */ + } + + /* NOTE: This equation is used to make all the xMc[i] positive. + */ + + *mant_out = mant; + *exp_out = exp; + *xmaxc_out = xmaxc; +} + +/* 4.2.16 */ + +static void APCM_inverse_quantization P4((xMc,mant,exp,xMp), + register word * xMc, /* [0..12] IN */ + word mant, + word exp, + register word * xMp) /* [0..12] OUT */ +/* + * This part is for decoding the RPE sequence of coded xMc[0..12] + * samples to obtain the xMp[0..12] array. Table 4.6 is used to get + * the mantissa of xmaxc (FAC[0..7]). + */ +{ + int i; + word temp, temp1, temp2, temp3; + + assert( mant >= 0 && mant <= 7 ); + + temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */ + temp2 = gsm_sub( 6, exp ); /* see 4.2-15 for exp */ + temp3 = gsm_asl( 1, gsm_sub( temp2, 1 )); + + for (i = 13; i--;) { + + assert( *xMc <= 7 && *xMc >= 0 ); /* 3 bit unsigned */ + + /* temp = gsm_sub( *xMc++ << 1, 7 ); */ + temp = (*xMc++ << 1) - 7; /* restore sign */ + assert( temp <= 7 && temp >= -7 ); /* 4 bit signed */ + + temp <<= 12; /* 16 bit signed */ + temp = (word)GSM_MULT_R( temp1, temp ); + temp = GSM_ADD( temp, temp3 ); + *xMp++ = gsm_asr( temp, temp2 ); + } +} + +/* 4.2.17 */ + +static void RPE_grid_positioning P3((Mc,xMp,ep), + word Mc, /* grid position IN */ + register word * xMp, /* [0..12] IN */ + register word * ep /* [0..39] OUT */ +) +/* + * This procedure computes the reconstructed long term residual signal + * ep[0..39] for the LTP analysis filter. The inputs are the Mc + * which is the grid position selection and the xMp[0..12] decoded + * RPE samples which are upsampled by a factor of 3 by inserting zero + * values. + */ +{ + int i = 13; + + assert(0 <= Mc && Mc <= 3); + + switch (Mc) { + case 3: *ep++ = 0; + case 2: do { + *ep++ = 0; + case 1: *ep++ = 0; + case 0: *ep++ = *xMp++; + } while (--i); + } + while (++Mc < 4) *ep++ = 0; + + /* + + int i, k; + for (k = 0; k <= 39; k++) ep[k] = 0; + for (i = 0; i <= 12; i++) { + ep[ Mc + (3*i) ] = xMp[i]; + } + */ +} + +/* 4.2.18 */ + +/* This procedure adds the reconstructed long term residual signal + * ep[0..39] to the estimated signal dpp[0..39] from the long term + * analysis filter to compute the reconstructed short term residual + * signal dp[-40..-1]; also the reconstructed short term residual + * array dp[-120..-41] is updated. + */ + +#if 0 /* Has been inlined in code.c */ +void Gsm_Update_of_reconstructed_short_time_residual_signal P3((dpp, ep, dp), + word * dpp, /* [0...39] IN */ + word * ep, /* [0...39] IN */ + word * dp) /* [-120...-1] IN/OUT */ +{ + int k; + + for (k = 0; k <= 79; k++) + dp[ -120 + k ] = dp[ -80 + k ]; + + for (k = 0; k <= 39; k++) + dp[ -40 + k ] = gsm_add( ep[k], dpp[k] ); +} +#endif /* Has been inlined in code.c */ + +void Gsm_RPE_Encoding P5((S,e,xmaxc,Mc,xMc), + + struct gsm_state * S, + + word * e, /* -5..-1][0..39][40..44 IN/OUT */ + word * xmaxc, /* OUT */ + word * Mc, /* OUT */ + word * xMc) /* [0..12] OUT */ +{ + word x[40]; + word xM[13], xMp[13]; + word mant, exp; + + Weighting_filter(e, x); + RPE_grid_selection(x, xM, Mc); + + APCM_quantization( xM, xMc, &mant, &exp, xmaxc); + APCM_inverse_quantization( xMc, mant, exp, xMp); + + RPE_grid_positioning( *Mc, xMp, e ); + +} + +void Gsm_RPE_Decoding P5((S, xmaxcr, Mcr, xMcr, erp), + struct gsm_state * S, + + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12], 3 bits IN */ + word * erp /* [0..39] OUT */ +) +{ + word exp, mant; + word xMp[ 13 ]; + + APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &exp, &mant ); + APCM_inverse_quantization( xMcr, mant, exp, xMp ); + RPE_grid_positioning( Mcr, xMp, erp ); + +} diff --git a/codecs/gsm/src/short_term.c b/codecs/gsm/src/short_term.c new file mode 100644 index 000000000..43c592c04 --- /dev/null +++ b/codecs/gsm/src/short_term.c @@ -0,0 +1,448 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include <stdio.h> +#include <assert.h> + +#include "private.h" + +#include "gsm.h" +#include "proto.h" +#ifdef K6OPT +#include "k6opt.h" + +#define Short_term_analysis_filtering Short_term_analysis_filteringx + +#endif +/* + * SHORT TERM ANALYSIS FILTERING SECTION + */ + +/* 4.2.8 */ + +static void Decoding_of_the_coded_Log_Area_Ratios P2((LARc,LARpp), + word * LARc, /* coded log area ratio [0..7] IN */ + word * LARpp) /* out: decoded .. */ +{ + register word temp1 /* , temp2 */; + + /* This procedure requires for efficient implementation + * two tables. + * + * INVA[1..8] = integer( (32768 * 8) / real_A[1..8]) + * MIC[1..8] = minimum value of the LARc[1..8] + */ + + /* Compute the LARpp[1..8] + */ + + /* for (i = 1; i <= 8; i++, B++, MIC++, INVA++, LARc++, LARpp++) { + * + * temp1 = GSM_ADD( *LARc, *MIC ) << 10; + * temp2 = *B << 1; + * temp1 = GSM_SUB( temp1, temp2 ); + * + * assert(*INVA != MIN_WORD); + * + * temp1 = GSM_MULT_R( *INVA, temp1 ); + * *LARpp = GSM_ADD( temp1, temp1 ); + * } + */ + +#undef STEP +#define STEP( B, MIC, INVA ) \ + temp1 = GSM_ADD( *LARc++, MIC ) << 10; \ + temp1 = GSM_SUB( temp1, B << 1 ); \ + temp1 = (word)GSM_MULT_R( INVA, temp1 ); \ + *LARpp++ = GSM_ADD( temp1, temp1 ); + + STEP( 0, -32, 13107 ); + STEP( 0, -32, 13107 ); + STEP( 2048, -16, 13107 ); + STEP( -2560, -16, 13107 ); + + STEP( 94, -8, 19223 ); + STEP( -1792, -8, 17476 ); + STEP( -341, -4, 31454 ); + STEP( -1144, -4, 29708 ); + + /* NOTE: the addition of *MIC is used to restore + * the sign of *LARc. + */ +} + +/* 4.2.9 */ +/* Computation of the quantized reflection coefficients + */ + +/* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8] + */ + +/* + * Within each frame of 160 analyzed speech samples the short term + * analysis and synthesis filters operate with four different sets of + * coefficients, derived from the previous set of decoded LARs(LARpp(j-1)) + * and the actual set of decoded LARs (LARpp(j)) + * + * (Initial value: LARpp(j-1)[1..8] = 0.) + */ + +static void Coefficients_0_12 P3((LARpp_j_1, LARpp_j, LARp), + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + + for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) { + *LARp = GSM_ADD( SASR( *LARpp_j_1, 2 ), SASR( *LARpp_j, 2 )); + *LARp = GSM_ADD( *LARp, SASR( *LARpp_j_1, 1)); + } +} + +static void Coefficients_13_26 P3((LARpp_j_1, LARpp_j, LARp), + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { + *LARp = GSM_ADD( SASR( *LARpp_j_1, 1), SASR( *LARpp_j, 1 )); + } +} + +static void Coefficients_27_39 P3((LARpp_j_1, LARpp_j, LARp), + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + + for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { + *LARp = GSM_ADD( SASR( *LARpp_j_1, 2 ), SASR( *LARpp_j, 2 )); + *LARp = GSM_ADD( *LARp, SASR( *LARpp_j, 1 )); + } +} + + +static void Coefficients_40_159 P2((LARpp_j, LARp), + register word * LARpp_j, + register word * LARp) +{ + register int i; + + for (i = 1; i <= 8; i++, LARp++, LARpp_j++) + *LARp = *LARpp_j; +} + +/* 4.2.9.2 */ + +static void LARp_to_rp P1((LARp), + register word * LARp) /* [0..7] IN/OUT */ +/* + * The input of this procedure is the interpolated LARp[0..7] array. + * The reflection coefficients, rp[i], are used in the analysis + * filter and in the synthesis filter. + */ +{ + register int i; + register word temp; + + for (i = 1; i <= 8; i++, LARp++) { + + /* temp = GSM_ABS( *LARp ); + * + * if (temp < 11059) temp <<= 1; + * else if (temp < 20070) temp += 11059; + * else temp = GSM_ADD( temp >> 2, 26112 ); + * + * *LARp = *LARp < 0 ? -temp : temp; + */ + + if (*LARp < 0) { + temp = *LARp == MIN_WORD ? MAX_WORD : -(*LARp); + *LARp = - ((temp < 11059) ? temp << 1 + : ((temp < 20070) ? temp + 11059 + : GSM_ADD( temp >> 2, 26112 ))); + } else { + temp = *LARp; + *LARp = (temp < 11059) ? temp << 1 + : ((temp < 20070) ? temp + 11059 + : GSM_ADD( temp >> 2, 26112 )); + } + } +} + + +/* 4.2.10 */ +#ifndef Short_term_analysis_filtering + +/* SJB Remark: + * I tried 2 MMX versions of this function, neither is significantly + * faster than the C version which follows. MMX might be useful if + * one were processing 2 input streams in parallel. + */ +static void Short_term_analysis_filtering P4((u0,rp0,k_n,s), + register word * u0, + register word * rp0, /* [0..7] IN */ + register int k_n, /* k_end - k_start */ + register word * s /* [0..n-1] IN/OUT */ +) +/* + * This procedure computes the short term residual signal d[..] to be fed + * to the RPE-LTP loop from the s[..] signal and from the local rp[..] + * array (quantized reflection coefficients). As the call of this + * procedure can be done in many ways (see the interpolation of the LAR + * coefficient), it is assumed that the computation begins with index + * k_start (for arrays d[..] and s[..]) and stops with index k_end + * (k_start and k_end are defined in 4.2.9.1). This procedure also + * needs to keep the array u0[0..7] in memory for each call. + */ +{ + register word * u_top = u0 + 8; + register word * s_top = s + k_n; + + while (s < s_top) { + register word *u, *rp ; + register longword di, u_out; + di = u_out = *s; + for (rp=rp0, u=u0; u<u_top;) { + register longword ui, rpi; + ui = *u; + *u++ = (word)u_out; + rpi = *rp++; + u_out = ui + (((rpi*di)+0x4000)>>15); + di = di + (((rpi*ui)+0x4000)>>15); + /* make the common case fastest: */ + if ((u_out == (word)u_out) && (di == (word)di)) continue; + /* otherwise do slower fixup (saturation) */ + if (u_out>MAX_WORD) u_out=MAX_WORD; + else if (u_out<MIN_WORD) u_out=MIN_WORD; + if (di>MAX_WORD) di=MAX_WORD; + else if (di<MIN_WORD) di=MIN_WORD; + } + *s++ = (word)di; + } +} +#endif + +#if defined(USE_FLOAT_MUL) && defined(FAST) + +static void Fast_Short_term_analysis_filtering P4((u,rp,k_n,s), + register word * u; + register word * rp, /* [0..7] IN */ + register int k_n, /* k_end - k_start */ + register word * s /* [0..n-1] IN/OUT */ +) +{ + register int i; + + float uf[8], + rpf[8]; + + register float scalef = 3.0517578125e-5; + register float sav, di, temp; + + for (i = 0; i < 8; ++i) { + uf[i] = u[i]; + rpf[i] = rp[i] * scalef; + } + for (; k_n--; s++) { + sav = di = *s; + for (i = 0; i < 8; ++i) { + register float rpfi = rpf[i]; + register float ufi = uf[i]; + + uf[i] = sav; + temp = rpfi * di + ufi; + di += rpfi * ufi; + sav = temp; + } + *s = di; + } + for (i = 0; i < 8; ++i) u[i] = uf[i]; +} +#endif /* ! (defined (USE_FLOAT_MUL) && defined (FAST)) */ + +/* + * SJB Remark: modified Short_term_synthesis_filtering() below + * for significant (abt 35%) speedup of decompression. + * (gcc-2.95, k6 cpu) + * Please don't change this without benchmarking decompression + * to see that you haven't harmed speed. + * This function burns most of CPU time for untoasting. + * Unfortunately, didn't see any good way to benefit from mmx. + */ +static void Short_term_synthesis_filtering P5((S,rrp,k,wt,sr), + struct gsm_state * S, + register word * rrp, /* [0..7] IN */ + register int k, /* k_end - k_start */ + register word * wt, /* [0..k-1] IN */ + register word * sr /* [0..k-1] OUT */ +) +{ + register word * v = S->v; + register int i; + register longword sri; + + while (k--) { + sri = *wt++; + for (i = 8; i--;) { + register longword tmp1, tmp2; + + /* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], v[i] ) ); + */ + tmp1 = rrp[i]; + tmp2 = v[i]; + + tmp2 = (( tmp1 * tmp2 + 16384) >> 15) ; + /* saturation done below */ + sri -= tmp2; + if (sri != (word)sri) { + sri = (sri<0)? MIN_WORD:MAX_WORD; + } + /* v[i+1] = GSM_ADD( v[i], gsm_mult_r( rrp[i], sri ) ); + */ + + tmp1 = (( tmp1 * sri + 16384) >> 15) ; + /* saturation done below */ + tmp1 += v[i]; + if (tmp1 != (word)tmp1) { + tmp1 = (tmp1<0)? MIN_WORD:MAX_WORD; + } + v[i+1] = (word)tmp1; + } + *sr++ = v[0] = (word)sri; + } +} + + +#if defined(FAST) && defined(USE_FLOAT_MUL) + +static void Fast_Short_term_synthesis_filtering P5((S,rrp,k,wt,sr), + struct gsm_state * S, + register word * rrp, /* [0..7] IN */ + register int k, /* k_end - k_start */ + register word * wt, /* [0..k-1] IN */ + register word * sr /* [0..k-1] OUT */ +) +{ + register word * v = S->v; + register int i; + + float va[9], rrpa[8]; + register float scalef = 3.0517578125e-5, temp; + + for (i = 0; i < 8; ++i) { + va[i] = v[i]; + rrpa[i] = (float)rrp[i] * scalef; + } + while (k--) { + register float sri = *wt++; + for (i = 8; i--;) { + sri -= rrpa[i] * va[i]; + if (sri < -32768.) sri = -32768.; + else if (sri > 32767.) sri = 32767.; + + temp = va[i] + rrpa[i] * sri; + if (temp < -32768.) temp = -32768.; + else if (temp > 32767.) temp = 32767.; + va[i+1] = temp; + } + *sr++ = va[0] = sri; + } + for (i = 0; i < 9; ++i) v[i] = va[i]; +} + +#endif /* defined(FAST) && defined(USE_FLOAT_MUL) */ + +void Gsm_Short_Term_Analysis_Filter P3((S,LARc,s), + + struct gsm_state * S, + + word * LARc, /* coded log area ratio [0..7] IN */ + word * s /* signal [0..159] IN/OUT */ +) +{ + word * LARpp_j = S->LARpp[ S->j ]; + word * LARpp_j_1 = S->LARpp[ S->j ^= 1 ]; + + word LARp[8]; + +#undef FILTER +#if defined(FAST) && defined(USE_FLOAT_MUL) +# define FILTER (* (S->fast \ + ? Fast_Short_term_analysis_filtering \ + : Short_term_analysis_filtering )) + +#else +# define FILTER Short_term_analysis_filtering +#endif + + Decoding_of_the_coded_Log_Area_Ratios( LARc, LARpp_j ); + + Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER( S->u, LARp, 13, s); + + Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S->u, LARp, 14, s + 13); + + Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S->u, LARp, 13, s + 27); + + Coefficients_40_159( LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S->u, LARp, 120, s + 40); + +} + +void Gsm_Short_Term_Synthesis_Filter P4((S, LARcr, wt, s), + struct gsm_state * S, + + word * LARcr, /* received log area ratios [0..7] IN */ + word * wt, /* received d [0..159] IN */ + + word * s /* signal s [0..159] OUT */ +) +{ + word * LARpp_j = S->LARpp[ S->j ]; + word * LARpp_j_1 = S->LARpp[ S->j ^=1 ]; + + word LARp[8]; + +#undef FILTER +#if defined(FAST) && defined(USE_FLOAT_MUL) + +# define FILTER (* (S->fast \ + ? Fast_Short_term_synthesis_filtering \ + : Short_term_synthesis_filtering )) +#else +# define FILTER Short_term_synthesis_filtering +#endif + + Decoding_of_the_coded_Log_Area_Ratios( LARcr, LARpp_j ); + + Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, wt, s ); + + Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 14, wt + 13, s + 13 ); + + Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, wt + 27, s + 27 ); + + Coefficients_40_159( LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER(S, LARp, 120, wt + 40, s + 40); +} diff --git a/codecs/gsm/src/table.c b/codecs/gsm/src/table.c new file mode 100644 index 000000000..16a04118c --- /dev/null +++ b/codecs/gsm/src/table.c @@ -0,0 +1,63 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +/* Most of these tables are inlined at their point of use. + */ + +/* 4.4 TABLES USED IN THE FIXED POINT IMPLEMENTATION OF THE RPE-LTP + * CODER AND DECODER + * + * (Most of them inlined, so watch out.) + */ + +#define GSM_TABLE_C +#include "private.h" +#include "gsm.h" + +/* Table 4.1 Quantization of the Log.-Area Ratios + */ +/* i 1 2 3 4 5 6 7 8 */ +word gsm_A[8] = {20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036}; +word gsm_B[8] = { 0, 0, 2048, -2560, 94, -1792, -341, -1144}; +word gsm_MIC[8] = { -32, -32, -16, -16, -8, -8, -4, -4 }; +word gsm_MAC[8] = { 31, 31, 15, 15, 7, 7, 3, 3 }; + + +/* Table 4.2 Tabulation of 1/A[1..8] + */ +word gsm_INVA[8]={ 13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708 }; + + +/* Table 4.3a Decision level of the LTP gain quantizer + */ +/* bc 0 1 2 3 */ +word gsm_DLB[4] = { 6554, 16384, 26214, 32767 }; + + +/* Table 4.3b Quantization levels of the LTP gain quantizer + */ +/* bc 0 1 2 3 */ +word gsm_QLB[4] = { 3277, 11469, 21299, 32767 }; + + +/* Table 4.4 Coefficients of the weighting filter + */ +/* i 0 1 2 3 4 5 6 7 8 9 10 */ +word gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 }; + + +/* Table 4.5 Normalized inverse mantissa used to compute xM/xmax + */ +/* i 0 1 2 3 4 5 6 7 */ +word gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 }; + + +/* Table 4.6 Normalized direct mantissa used to compute xM/xmax + */ +/* i 0 1 2 3 4 5 6 7 */ +word gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 }; diff --git a/codecs/gsm_slin_ex.h b/codecs/gsm_slin_ex.h new file mode 100644 index 000000000..2f001abec --- /dev/null +++ b/codecs/gsm_slin_ex.h @@ -0,0 +1,16 @@ +/*! \file + * \brief 8-bit raw data + * + * Source: gsm.example + * + * Copyright (C) 1999-2005, Digium Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static unsigned char gsm_slin_ex[] = { +0xda, 0xa6, 0xac, 0x2d, 0xa3, 0x50, 000, 0x49, 0x24, 0x92, +0x49, 0x24, 0x50, 0x40, 0x49, 0x24, 0x92, 0x37, 0x24, 0x52, +000, 0x49, 0x24, 0x92, 0x47, 0x24, 0x50, 0x80, 0x46, 0xe3, +0x6d, 0xb8, 0xdc }; diff --git a/codecs/ilbc/Makefile b/codecs/ilbc/Makefile new file mode 100644 index 000000000..51e2ae249 --- /dev/null +++ b/codecs/ilbc/Makefile @@ -0,0 +1,20 @@ +LIB=libilbc.a +CFLAGS+=-fPIC + +OBJS=anaFilter.o iCBSearch.o packing.o \ + constants.o gainquant.o iLBC_decode.o StateConstructW.o \ + createCB.o getCBvec.o iLBC_encode.o StateSearchW.o doCPLC.o \ + helpfun.o syntFilter.o enhancer.o hpInput.o LPCdecode.o \ + filter.o hpOutput.o LPCencode.o FrameClassify.o iCBConstruct.o lsf.o + +include $(ASTTOPDIR)/Makefile.rules + +all: $(LIB) + +$(LIB): $(OBJS) + $(ECHO_PREFIX) echo " [AR] $^ -> $@" + $(CMD_PREFIX) $(AR) cr $@ $^ + $(CMD_PREFIX) $(RANLIB) $@ + +clean: + rm -f $(LIB) *.o .*.d *.s *.i diff --git a/codecs/ilbc_slin_ex.h b/codecs/ilbc_slin_ex.h new file mode 100644 index 000000000..b9f4bd4e8 --- /dev/null +++ b/codecs/ilbc_slin_ex.h @@ -0,0 +1,17 @@ +/*! \file + * \brief Raw 8-bit data + * + * Source: ilbc.out + * + * Copyright (C) 1999-2005, Digium Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static unsigned char ilbc_slin_ex[] = { +0xff, 0xa0, 0xff, 0xfa, 0xf, 0x60, 0x12, 0x11, 0xa2, 0x47, +0x22, 0x8c, 00, 00, 0x1, 0x2, 0x80, 0x43, 0xa0, 0x40, +0x33, 0xff, 0xcf, 0xc0, 0xf3, 0xf3, 0x3f, 0x8f, 0x3f, 0xff, +0xff, 0xff, 0xff, 0xfc, 0xf9, 0xe5, 0x55, 0x78, 0xb, 0xca, +0xe1, 0x27, 0x94, 0x7b, 0xa8, 0x91, 0x2c, 0x36, 0x8, 0x56 }; diff --git a/codecs/log2comp.h b/codecs/log2comp.h new file mode 100644 index 000000000..aa397c858 --- /dev/null +++ b/codecs/log2comp.h @@ -0,0 +1,74 @@ +/*! \file + * \brief log2comp.h - various base 2 log computation versions + * + * Asterisk -- A telephony toolkit for Linux. + * + * \author Alex Volkov <codepro@usa.net> + * + * Copyright (c) 2004 - 2005, Digium Inc. + * + * This program is free software, distributed under the terms of + * the GNU General Public License + * + * Define WANT_ASM before including this file to use assembly + * whenever possible + */ + +#if defined(_MSC_VER) +# define inline __inline +#elif defined(__GNUC__) +# define inline __inline__ +#else +# define inline +#endif + +#if defined(WANT_ASM) && defined(_MSC_VER) && defined(_M_IX86) +/* MS C Inline Asm */ +# pragma warning( disable : 4035 ) +static inline int ilog2(int val) { __asm +{ + xor eax, eax + dec eax + bsr eax, val +}} +# pragma warning( default : 4035 ) +#elif defined(WANT_ASM) && defined(__GNUC__) && (defined(__i386__) || defined(i386)) +/* GNU Inline Asm */ +static inline int ilog2(int val) +{ + int a; + __asm__ + ("\ + xorl %0, %0 ;\ + decl %0 ;\ + bsrl %1, %0 ;\ + " + : "=&r" (a) + : "mr" (val) + : "cc" + ); + return a; +} +#elif defined(WANT_ASM) && defined(__GNUC__) && defined(__powerpc__) +static inline int ilog2(int val) +{ + int a; + __asm__ ("cntlzw %0,%1" + : "=r" (a) + : "r" (val) + ); + return 31-a; +} +#else +/* no ASM for this compiler and/or platform */ +/* rather slow base 2 log computation + * Using looped shift. + */ +static inline int ilog2(int val) +{ + int i; + for (i = -1; val; ++i, val >>= 1) + ; + return (i); +} +#endif diff --git a/codecs/lpc10/Makefile b/codecs/lpc10/Makefile new file mode 100644 index 000000000..bf6a6e08a --- /dev/null +++ b/codecs/lpc10/Makefile @@ -0,0 +1,77 @@ +# +# Makefile for LPC-10 speech coder library (unix) +# + +# default C compiler +CC?= gcc + +# +# These definitions for CFLAGS and LIB_TARGET_DIR are used when one +# runs make in the lpc10 directory, without environment variables that +# override them. When make is run in this directory from a makefile +# for an application that uses the LPC10 coder, there are environment +# variables set for CFLAGS and LIB_TARGET_DIR that override these +# definitions. +# + +LIB_TARGET_DIR = . + +# +# -I$(LIB_TARGET_DIR) option needed so that #include "machine.h" +# directives can find the machine.h file. +# + +CFLAGS+= -fPIC -Wno-comment + +# The code here generates lots of warnings, so compiling with -Werror +# fails miserably. Remove it for the time being. +ASTCFLAGS:= $(ASTCFLAGS:-Werror=) + +#fix for PPC processors and ALPHA, And UltraSparc too +ifneq ($(OSARCH),Darwin) + ifneq ($(findstring BSD,${OSARCH}),BSD) + ifneq ($(PROC),ppc) + ifneq ($(PROC),x86_64) + ifneq ($(PROC),alpha) +#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only. +#This works for even old (2.96) versions of gcc and provides a small boost either way. +#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn.t support it. +#So we go lowest common available by gcc and go a step down, still a step up from +#the default as we now have a better instruction set to work with. - Belgarath + ifeq ($(PROC),ultrasparc) + CFLAGS+= -mtune=$(PROC) -mcpu=v8 -O3 -fomit-frame-pointer + else + ifneq ($(OSARCH),SunOS) + ifneq ($(OSARCH),arm) +# CFLAGS+= -march=$(PROC) + endif + endif + endif + endif + endif + endif + endif +endif + +LIB = $(LIB_TARGET_DIR)/liblpc10.a + +.PHONY: all clean + +include $(ASTTOPDIR)/Makefile.rules + +all: $(LIB) + +OBJ=f2clib.o analys.o bsynz.o chanwr.o dcbias.o decode.o \ + deemp.o difmag.o dyptrk.o encode.o energy.o ham84.o \ + hp100.o invert.o irc2pc.o ivfilt.o lpcdec.o lpcenc.o \ + lpcini.o lpfilt.o median.o mload.o onset.o pitsyn.o \ + placea.o placev.o preemp.o prepro.o random.o rcchk.o \ + synths.o tbdm.o voicin.o vparms.o + +$(LIB): $(OBJ) + $(ECHO_PREFIX) echo " [AR] $^ -> $@" + $(CMD_PREFIX) $(AR) cr $@ $^ + $(CMD_PREFIX) $(RANLIB) $@ + +clean: + rm -f *.o $(LIB) .*.d *.s *.i diff --git a/codecs/lpc10/README b/codecs/lpc10/README new file mode 100644 index 000000000..30abe4c97 --- /dev/null +++ b/codecs/lpc10/README @@ -0,0 +1,89 @@ +Tue Aug 20 16:19:51 CDT 1996 +Andy Fingerhut (jaf@arl.wustl.edu) + +In release 1.4, there are quite a few hand modifications to the C code +that was automatically created from the Fortran code with f2c. They +are all summarized in change log comments at the beginning of the +changed files. All of the original files from f2c were checked in to +RCS before modification, so it is possible to see exactly what changes +were made, for the extremely curious. That precaution was also for my +benefit, in case I ever recompile the Fortran sources, and want to +make similar changes to that new C source code. + +Below is the README file for this directory included with the 1.3 +release of the LPC-10 package. A few parts of it are a little out of +date, but it is correct for the most part. + + +Sun Jul 7 15:30:31 CDT 1996 +Andy Fingerhut (jaf@arl.wustl.edu) + +To create the LPC-10 library, copy the appropriate makefile to the +proper name for easy use, e.g., for Unix, copy makefile.unx to the +file "Makefile". The file makefile.dos has been used with some +version of the 'nmake' utility that comes with the Microsoft C +compiler (the same one used for Nautilus v1.5a, which I believe +specifies Microsoft C version 7.0 or later). + +Then edit the file lpc10.h in the directory above. It should already +be set up to work properly on any Unix compiler for which "int" is 32 +bits and "short" is 16 bits, and under the Microsoft C compiler +configured so that "long" is 32 bits and "int" is 16 bits. There must +be a typedef for the two types INT32 and INT16 in that file. You +should choose types that compile to those sizes using your compiler, +because there are places in the LPC-10 code that expect INT16's to +have exactly 16 bits (at least, I *think* they must be no larger), and +INT32's to have exactly 32 bits. + + +A few notes on how these files were created +------------------------------------------- + +(This section is mostly for my benefit, so I can remember what I did. +You don't need to read it if you just want to use this package. It +might be useful to read it if you change the Fortran sources and want +to recreate a usable library of C sources. -- Andy) + +These C sources were created automatically from the Fortran sources +using f2c, for the most part. Listed below are the extra +modifications that were made after this automatic conversion. Many of +them were made so that it was not necessary to install f2c in order to +use this LPC-10 coder. + +1. + +Put all of those files that were necessary for only the coder, rather +than an application that uses the coder, into this subdirectory called +lpc10. + +2. + +Copied f2c.h from the f2c distribution into this subdirectory. Some +modifications were made to the "typedef" statements in this file, to +explicitly indicate the sizes (in bits) that different integer types +should be. The types INT32 and INT16 must be defined in a file called +lpc10.h in the directory above. Created the file f2clib.c, containing +only the functions pow_ii(), r_sign(), and i_nint() from the f2c +library. + +3. + +The f2c output originally had a file called contrl_com.c, that defined +a small structure containing a few variables that were used in many +different functions of the LPC10 code. Every file containing +functions that used it defined it as "extern", while contrl_com.c +actually allocated storage for the structure. Bill Dorsey, one of the +lead developers of Nautilus, said that the Microsoft C compiler had +problems either compiling this file, or linking it with all of the +other compiled files, so he just eliminated that file and removed the +"extern" keyword from the one of the files that declared it that way. +The file chosen (arbitrarily) was analys.c. + +4. + +Copied the makefiles for Unix and Microsoft C from the Nautilus v1.5a +distribution into the lpc10 directory. Modified them to take out +references to Nautilus. These makefiles don't create an executable, +but a library of compiled functions called liblpc10.a (Unix) or +LPC10.LIB (DOS). This library can be used when linking an executable +that calls the functions lpcini_(), lpcenc_(), and lpcdec_(). diff --git a/codecs/lpc10/analys.c b/codecs/lpc10/analys.c new file mode 100644 index 000000000..50e95703d --- /dev/null +++ b/codecs/lpc10/analys.c @@ -0,0 +1,649 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.2 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:16:01 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:29:08 jaf + * Initial revision + * + +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int analys_(real *speech, integer *voice, integer *pitch, real *rms, real *rc, struct lpc10_encoder_state *st); +/* comlen contrl_ 12 */ +/*:ref: preemp_ 14 5 6 6 4 6 6 */ +/*:ref: onset_ 14 7 6 4 4 4 4 4 4 */ +/*:ref: placev_ 14 11 4 4 4 4 4 4 4 4 4 4 4 */ +/*:ref: lpfilt_ 14 4 6 6 4 4 */ +/*:ref: ivfilt_ 14 5 6 6 4 4 6 */ +/*:ref: tbdm_ 14 8 6 4 4 4 6 4 4 4 */ +/*:ref: voicin_ 14 12 4 6 6 4 4 6 6 4 6 4 4 4 */ +/*:ref: dyptrk_ 14 6 6 4 4 4 4 4 */ +/*:ref: placea_ 14 9 4 4 4 4 4 4 4 4 4 */ +/*:ref: dcbias_ 14 3 4 6 6 */ +/*:ref: energy_ 14 3 4 6 6 */ +/*:ref: mload_ 14 6 4 4 4 6 6 6 */ +/*:ref: invert_ 14 4 4 6 6 6 */ +/*:ref: rcchk_ 14 3 4 6 6 */ +/*:ref: initonset_ 14 0 */ +/*:ref: initvoicin_ 14 0 */ +/*:ref: initdyptrk_ 14 0 */ +/* Rerunning f2c -P may change prototypes or declarations. */ +#endif + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* Table of constant values */ + +static integer c__10 = 10; +static integer c__181 = 181; +static integer c__720 = 720; +static integer c__3 = 3; +static integer c__90 = 90; +static integer c__156 = 156; +static integer c__307 = 307; +static integer c__462 = 462; +static integer c__312 = 312; +static integer c__60 = 60; +static integer c__1 = 1; + +/* ****************************************************************** */ + +/* ANALYS Version 55 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.2 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:16:01 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:29:08 jaf + * Initial revision + * */ +/* Revision 1.9 1996/05/23 19:41:07 jaf */ +/* Commented out some unnecessary lines that were reading uninitialized */ +/* values. */ + +/* Revision 1.8 1996/03/27 23:57:55 jaf */ +/* Added some comments about which indices of the local buffers INBUF, */ +/* LPBUF, etc., get read or modified by some of the subroutine calls. I */ +/* just did this while trying to figure out the discrepancy between the */ +/* embedded code compiled with all local variables implicitly saved, and */ +/* without. */ + +/* I added some debugging write statements in hopes of finding a problem. */ +/* None of them ever printed anything while running with the long input */ +/* speech file dam9.spd provided in the distribution. */ + +/* Revision 1.7 1996/03/27 18:06:20 jaf */ +/* Commented out access to MAXOSP, which is just a debugging variable */ +/* that was defined in the COMMON block CONTRL in contrl.fh. */ + +/* Revision 1.6 1996/03/26 19:31:33 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.5 1996/03/21 15:19:35 jaf */ +/* Added comments for ENTRY PITDEC. */ + +/* Revision 1.4 1996/03/19 20:54:27 jaf */ +/* Added a line to INITANALYS. See comments there. */ + +/* Revision 1.3 1996/03/19 20:52:49 jaf */ +/* Rearranged the order of the local variables quite a bit, to separate */ +/* them into groups of "constants", "locals that don't need to be saved */ +/* from one call to the next", and "local that do need to be saved from */ +/* one call to the next". */ + +/* Several locals in the last set should have been given initial values, */ +/* but weren't. I gave them all initial values of 0. */ + +/* Added a separate ENTRY INITANALYS that initializes all local state */ +/* that should be, and also calls the corresponding entries of the */ +/* subroutines called by ANALYS that also have local state. */ + +/* There used to be DATA statements in ANALYS. I got rid of most of */ +/* them, and added a local logical variable FIRST that calls the entry */ +/* INITANALYS on the first call to ANALYS. This is just so that one need */ +/* not remember to call INITANALYS first in order for the state to be */ +/* initialized. */ + +/* Revision 1.2 1996/03/11 23:29:32 jaf */ +/* Added several comments with my own personal questions about the */ +/* Fortran 77 meaning of the parameters passed to the subroutine PREEMP. */ + +/* Revision 1.1 1996/02/07 14:42:29 jaf */ +/* Initial revision */ + + +/* ****************************************************************** */ + +/* SUBROUTINE ANALYS */ + +/* Input: */ +/* SPEECH */ +/* Indices 1 through LFRAME read. */ +/* Output: */ +/* VOICE */ +/* Indices 1 through 2 written. */ +/* PITCH */ +/* Written in subroutine DYPTRK, and then perhaps read and written */ +/* some more. */ +/* RMS */ +/* Written. */ +/* RC */ +/* Indices 1 through ORDER written (ORDER defined in contrl.fh). */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITANALYS. */ + + +/* ENTRY PITDEC */ + +/* Input: */ +/* PITCH - Encoded pitch index */ +/* Output: */ +/* PTAU - Decoded pitch period */ + +/* This entry has no local state. It accesses a "constant" array */ +/* declared in ANALYS. */ + +/* Subroutine */ int analys_(real *speech, integer *voice, integer + *pitch, real *rms, real *rc, struct lpc10_encoder_state *st) +{ + /* Initialized data */ + + static integer tau[60] = { 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34, + 35,36,37,38,39,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72, + 74,76,78,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136, + 140,144,148,152,156 }; + static integer buflim[4] = { 181,720,25,720 }; + static real precoef = .9375f; + + /* System generated locals */ + integer i__1; + + /* Local variables */ + real amdf[60]; + integer half; + real abuf[156]; + real *bias; + extern /* Subroutine */ int tbdm_(real *, integer *, integer *, integer *, + real *, integer *, integer *, integer *); + integer *awin; + integer midx, ewin[6] /* was [2][3] */; + real ivrc[2], temp; + real *zpre; + integer *vwin; + integer i__, j, lanal; + extern /* Subroutine */ int rcchk_(integer *, real *, real *), mload_( + integer *, integer *, integer *, real *, real *, real *); + real *inbuf, *pebuf; + real *lpbuf, *ivbuf; + real *rcbuf; + integer *osbuf; + extern /* Subroutine */ int onset_(real *, integer *, integer *, integer * + , integer *, integer *, integer *, struct lpc10_encoder_state *); + integer *osptr; + extern int dcbias_(integer *, real *, real *); + integer ipitch; + integer *obound; + extern /* Subroutine */ int preemp_(real *, real *, integer *, real *, + real *), voicin_(integer *, real *, real *, integer *, integer *, + real *, real *, integer *, real *, integer *, integer *, integer *, + struct lpc10_encoder_state *); + integer *voibuf; + integer mintau; + real *rmsbuf; + extern /* Subroutine */ int lpfilt_(real *, real *, integer *, integer *), + ivfilt_(real *, real *, integer *, integer *, real *), energy_( + integer *, real *, real *), invert_(integer *, real *, real *, + real *); + integer minptr, maxptr; + extern /* Subroutine */ int dyptrk_(real *, integer *, integer *, integer + *, integer *, integer *, struct lpc10_encoder_state *); + real phi[100] /* was [10][10] */, psi[10]; + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.2 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:16:01 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:29:08 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments to ANALYS */ +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.2 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:16:01 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:29:08 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Arguments to entry PITDEC (below) */ +/* Parameters/constants */ +/* Constants */ +/* NF = Number of frames */ +/* AF = Frame in which analysis is done */ +/* OSLEN = Length of the onset buffer */ +/* LTAU = Number of pitch lags */ +/* SBUFL, SBUFH = Start and end index of speech buffers */ +/* LBUFL, LBUFH = Start and end index of LPF speech buffer */ +/* MINWIN, MAXWIN = Min and Max length of voicing (and analysis) windows +*/ +/* PWLEN, PWINH, PWINL = Length, upper and lower limits of pitch window + */ +/* DVWINL, DVWINH = Default lower and upper limits of voicing window */ +/* The tables TAU and BUFLIM, and the variable PRECOEF, are not */ +/* Fortran PARAMETER's, but they are initialized with DATA */ +/* statements, and never modified. Thus, they need not have SAVE */ +/* statements for them to keep their values from one invocation to +*/ +/* the next. */ +/* Local variables that need not be saved */ +/* Local state */ +/* Data Buffers */ +/* INBUF Raw speech (with DC bias removed each frame) */ +/* PEBUF Preemphasized speech */ +/* LPBUF Low pass speech buffer */ +/* IVBUF Inverse filtered speech */ +/* OSBUF Indexes of onsets in speech buffers */ +/* VWIN Voicing window indices */ +/* AWIN Analysis window indices */ +/* EWIN Energy window indices */ +/* VOIBUF Voicing decisions on windows in VWIN */ +/* RMSBUF RMS energy */ +/* RCBUF Reflection Coefficients */ + +/* Pitch is handled separately from the above parameters. */ +/* The following variables deal with pitch: */ +/* MIDX Encoded initial pitch estimate for analysis frame */ +/* IPITCH Initial pitch computed for frame AF (decoded from MIDX) */ +/* PITCH The encoded pitch value (index into TAU) for the present */ +/* frame (delayed and smoothed by Dyptrack) */ + /* Parameter adjustments */ + if (speech) { + --speech; + } + if (voice) { + --voice; + } + if (rc) { + --rc; + } + + /* Function Body */ + +/* Calculations are done on future frame due to requirements */ +/* of the pitch tracker. Delay RMS and RC's 2 frames to give */ +/* current frame parameters on return. */ +/* Update all buffers */ + + inbuf = &(st->inbuf[0]); + pebuf = &(st->pebuf[0]); + lpbuf = &(st->lpbuf[0]); + ivbuf = &(st->ivbuf[0]); + bias = &(st->bias); + osbuf = &(st->osbuf[0]); + osptr = &(st->osptr); + obound = &(st->obound[0]); + vwin = &(st->vwin[0]); + awin = &(st->awin[0]); + voibuf = &(st->voibuf[0]); + rmsbuf = &(st->rmsbuf[0]); + rcbuf = &(st->rcbuf[0]); + zpre = &(st->zpre); + + i__1 = 720 - contrl_1.lframe; + for (i__ = 181; i__ <= i__1; ++i__) { + inbuf[i__ - 181] = inbuf[contrl_1.lframe + i__ - 181]; + pebuf[i__ - 181] = pebuf[contrl_1.lframe + i__ - 181]; + } + i__1 = 540 - contrl_1.lframe; + for (i__ = 229; i__ <= i__1; ++i__) { + ivbuf[i__ - 229] = ivbuf[contrl_1.lframe + i__ - 229]; + } + i__1 = 720 - contrl_1.lframe; + for (i__ = 25; i__ <= i__1; ++i__) { + lpbuf[i__ - 25] = lpbuf[contrl_1.lframe + i__ - 25]; + } + j = 1; + i__1 = (*osptr) - 1; + for (i__ = 1; i__ <= i__1; ++i__) { + if (osbuf[i__ - 1] > contrl_1.lframe) { + osbuf[j - 1] = osbuf[i__ - 1] - contrl_1.lframe; + ++j; + } + } + *osptr = j; + voibuf[0] = voibuf[2]; + voibuf[1] = voibuf[3]; + for (i__ = 1; i__ <= 2; ++i__) { + vwin[(i__ << 1) - 2] = vwin[((i__ + 1) << 1) - 2] - contrl_1.lframe; + vwin[(i__ << 1) - 1] = vwin[((i__ + 1) << 1) - 1] - contrl_1.lframe; + awin[(i__ << 1) - 2] = awin[((i__ + 1) << 1) - 2] - contrl_1.lframe; + awin[(i__ << 1) - 1] = awin[((i__ + 1) << 1) - 1] - contrl_1.lframe; +/* EWIN(*,J) is unused for J .NE. AF, so the following shift is +*/ +/* unnecessary. It also causes error messages when the C versio +n */ +/* of the code created from this by f2c is run with Purify. It +*/ +/* correctly complains that uninitialized memory is being read. +*/ +/* EWIN(1,I) = EWIN(1,I+1) - LFRAME */ +/* EWIN(2,I) = EWIN(2,I+1) - LFRAME */ + obound[i__ - 1] = obound[i__]; + voibuf[i__ * 2] = voibuf[(i__ + 1) * 2]; + voibuf[(i__ << 1) + 1] = voibuf[((i__ + 1) << 1) + 1]; + rmsbuf[i__ - 1] = rmsbuf[i__]; + i__1 = contrl_1.order; + for (j = 1; j <= i__1; ++j) { + rcbuf[j + i__ * 10 - 11] = rcbuf[j + (i__ + 1) * 10 - 11]; + } + } +/* Copy input speech, scale to sign+12 bit integers */ +/* Remove long term DC bias. */ +/* If the average value in the frame was over 1/4096 (after current +*/ +/* BIAS correction), then subtract that much more from samples in */ +/* next frame. If the average value in the frame was under */ +/* -1/4096, add 1/4096 more to samples in next frame. In all other +*/ +/* cases, keep BIAS the same. */ + temp = 0.f; + i__1 = contrl_1.lframe; + for (i__ = 1; i__ <= i__1; ++i__) { + inbuf[720 - contrl_1.lframe + i__ - 181] = speech[i__] * 4096.f - + (*bias); + temp += inbuf[720 - contrl_1.lframe + i__ - 181]; + } + if (temp > (real) contrl_1.lframe) { + *bias += 1; + } + if (temp < (real) (-contrl_1.lframe)) { + *bias += -1; + } +/* Place Voicing Window */ + i__ = 721 - contrl_1.lframe; + preemp_(&inbuf[i__ - 181], &pebuf[i__ - 181], &contrl_1.lframe, &precoef, + zpre); + onset_(pebuf, osbuf, osptr, &c__10, &c__181, &c__720, &contrl_1.lframe, st); + +/* MAXOSP is just a debugging variable. */ + +/* MAXOSP = MAX( MAXOSP, OSPTR ) */ + + placev_(osbuf, osptr, &c__10, &obound[2], vwin, &c__3, &contrl_1.lframe, + &c__90, &c__156, &c__307, &c__462); +/* The Pitch Extraction algorithm estimates the pitch for a frame +*/ +/* of speech by locating the minimum of the average magnitude difference + */ +/* function (AMDF). The AMDF operates on low-pass, inverse filtered */ +/* speech. (The low-pass filter is an 800 Hz, 19 tap, equiripple, FIR +*/ +/* filter and the inverse filter is a 2nd-order LPC filter.) The pitch +*/ +/* estimate is later refined by dynamic programming (DYPTRK). However, +*/ +/* since some of DYPTRK's parameters are a function of the voicing */ +/* decisions, a voicing decision must precede the final pitch estimation. +*/ +/* See subroutines LPFILT, IVFILT, and TBDM. */ +/* LPFILT reads indices LBUFH-LFRAME-29 = 511 through LBUFH = 720 */ +/* of INBUF, and writes indices LBUFH+1-LFRAME = 541 through LBUFH +*/ +/* = 720 of LPBUF. */ + lpfilt_(&inbuf[228], &lpbuf[384], &c__312, &contrl_1.lframe); +/* IVFILT reads indices (PWINH-LFRAME-7) = 353 through PWINH = 540 +*/ +/* of LPBUF, and writes indices (PWINH-LFRAME+1) = 361 through */ +/* PWINH = 540 of IVBUF. */ + ivfilt_(&lpbuf[204], ivbuf, &c__312, &contrl_1.lframe, ivrc); +/* TBDM reads indices PWINL = 229 through */ +/* (PWINL-1)+MAXWIN+(TAU(LTAU)-TAU(1))/2 = 452 of IVBUF, and writes +*/ +/* indices 1 through LTAU = 60 of AMDF. */ + tbdm_(ivbuf, &c__156, tau, &c__60, amdf, &minptr, &maxptr, &mintau); +/* Voicing decisions are made for each half frame of input speech. +*/ +/* An initial voicing classification is made for each half of the */ +/* analysis frame, and the voicing decisions for the present frame */ +/* are finalized. See subroutine VOICIN. */ +/* The voicing detector (VOICIN) classifies the input signal as */ +/* unvoiced (including silence) or voiced using the AMDF windowed */ +/* maximum-to-minimum ratio, the zero crossing rate, energy measures, */ +/* reflection coefficients, and prediction gains. */ +/* The pitch and voicing rules apply smoothing and isolated */ +/* corrections to the pitch and voicing estimates and, in the process, +*/ +/* introduce two frames of delay into the corrected pitch estimates and +*/ +/* voicing decisions. */ + for (half = 1; half <= 2; ++half) { + voicin_(&vwin[4], inbuf, lpbuf, buflim, &half, &amdf[minptr - 1], & + amdf[maxptr - 1], &mintau, ivrc, obound, voibuf, &c__3, st); + } +/* Find the minimum cost pitch decision over several frames */ +/* given the current voicing decision and the AMDF array */ + dyptrk_(amdf, &c__60, &minptr, &voibuf[7], pitch, &midx, st); + ipitch = tau[midx - 1]; +/* Place spectrum analysis and energy windows */ + placea_(&ipitch, voibuf, &obound[2], &c__3, vwin, awin, ewin, & + contrl_1.lframe, &c__156); +/* Remove short term DC bias over the analysis window, Put result in ABUF +*/ + lanal = awin[5] + 1 - awin[4]; + dcbias_(&lanal, &pebuf[awin[4] - 181], abuf); +/* ABUF(1:LANAL) is now defined. It is equal to */ +/* PEBUF(AWIN(1,AF):AWIN(2,AF)) corrected for short term DC bias. */ +/* Compute RMS over integer number of pitch periods within the */ +/* analysis window. */ +/* Note that in a hardware implementation this computation may be */ +/* simplified by using diagonal elements of PHI computed by MLOAD. */ + i__1 = ewin[5] - ewin[4] + 1; + energy_(&i__1, &abuf[ewin[4] - awin[4]], &rmsbuf[2]); +/* Matrix load and invert, check RC's for stability */ + mload_(&contrl_1.order, &c__1, &lanal, abuf, phi, psi); + invert_(&contrl_1.order, phi, psi, &rcbuf[20]); + rcchk_(&contrl_1.order, &rcbuf[10], &rcbuf[20]); +/* Set return parameters */ + voice[1] = voibuf[2]; + voice[2] = voibuf[3]; + *rms = rmsbuf[0]; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + rc[i__] = rcbuf[i__ - 1]; + } + return 0; +} /* analys_ */ diff --git a/codecs/lpc10/bsynz.c b/codecs/lpc10/bsynz.c new file mode 100644 index 000000000..daf9105d6 --- /dev/null +++ b/codecs/lpc10/bsynz.c @@ -0,0 +1,447 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:18:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:58 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int bsynz_(real *coef, integer *ip, integer *iv, real *sout, real *rms, real *ratio, real *g2pass, struct lpc10_decoder_state *st); +/* comlen contrl_ 12 */ +/*:ref: random_ 4 0 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* ***************************************************************** */ + +/* BSYNZ Version 54 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:18:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:58 jaf + * Initial revision + * */ +/* Revision 1.4 1996/03/27 18:11:22 jaf */ +/* Changed the range of NOISE printed out in the debugging statements, */ +/* even though they are commented out. I didn't discover this until I */ +/* tried comparing two different versions of the LPC-10 coder, each with */ +/* full tracing enabled. */ + +/* Revision 1.3 1996/03/26 19:33:23 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.2 1996/03/20 17:12:54 jaf */ +/* Added comments about which indices of array arguments are read or */ +/* written. */ + +/* Rearranged local variable declarations to indicate which need to be */ +/* saved from one invocation to the next. Added entry INITBSYNZ to */ +/* reinitialize the local state variables, if desired. */ + +/* Revision 1.1 1996/02/07 14:43:15 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Synthesize One Pitch Epoch */ + +/* Input: */ +/* COEF - Predictor coefficients */ +/* Indices 1 through ORDER read. */ +/* IP - Pitch period (number of samples to synthesize) */ +/* IV - Voicing for the current epoch */ +/* RMS - Energy for the current epoch */ +/* RATIO - Energy slope for plosives */ +/* G2PASS- Sharpening factor for 2 pass synthesis */ +/* Output: */ +/* SOUT - Synthesized speech */ +/* Indices 1 through IP written. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITBSYNZ. */ + +/* Subroutine */ int bsynz_(real *coef, integer *ip, integer *iv, + real *sout, real *rms, real *ratio, real *g2pass, + struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + integer *ipo; + real *rmso; + static integer kexc[25] = { 8,-16,26,-48,86,-162,294,-502,718,-728,184, + 672,-610,-672,184,728,718,502,294,162,86,48,26,16,8 }; + real *exc; + real *exc2; + real *lpi1; + real *lpi2; + real *lpi3; + real *hpi1; + real *hpi2; + real *hpi3; + + /* System generated locals */ + integer i__1, i__2; + real r__1, r__2; + + /* Builtin functions */ + double sqrt(doublereal); + + /* Local variables */ + real gain, xssq; + integer i__, j, k; + real noise[166], pulse; + integer px; + real sscale; + extern integer random_(struct lpc10_decoder_state *); + real xy, sum, ssq; + real lpi0, hpi0; + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:18:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:58 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:18:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:58 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Function return value definitions */ +/* Parameters/constants */ +/* KEXC is not a Fortran PARAMETER, but it is an array initialized +*/ +/* with a DATA statement that is never modified. */ +/* Local variables that need not be saved */ +/* NOISE is declared with range (1:MAXPIT+MAXORD), but only indices +*/ +/* ORDER+1 through ORDER+IP are ever used, and I think that IP */ +/* .LE. MAXPIT. Why not declare it to be in the range (1:MAXPIT) */ +/* and use that range? */ +/* Local state */ +/* I believe that only indices 1 through ORDER of EXC need to be */ +/* saved from one invocation to the next, but we may as well save */ +/* the whole array. */ +/* None of these local variables were given initial values in the */ +/* original code. I'm guessing that 0 is a reasonable initial */ +/* value for all of them. */ + /* Parameter adjustments */ + if (coef) { + --coef; + } + if (sout) { + --sout; + } + + /* Function Body */ + ipo = &(st->ipo); + exc = &(st->exc[0]); + exc2 = &(st->exc2[0]); + lpi1 = &(st->lpi1); + lpi2 = &(st->lpi2); + lpi3 = &(st->lpi3); + hpi1 = &(st->hpi1); + hpi2 = &(st->hpi2); + hpi3 = &(st->hpi3); + rmso = &(st->rmso_bsynz); + +/* MAXPIT+MAXORD=166 */ +/* Calculate history scale factor XY and scale filter state */ +/* Computing MIN */ + r__1 = *rmso / (*rms + 1e-6f); + xy = min(r__1,8.f); + *rmso = *rms; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + exc2[i__ - 1] = exc2[*ipo + i__ - 1] * xy; + } + *ipo = *ip; + if (*iv == 0) { +/* Generate white noise for unvoiced */ + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + exc[contrl_1.order + i__ - 1] = (real) (random_(st) / 64); + } +/* Impulse doublet excitation for plosives */ +/* (RANDOM()+32768) is in the range 0 to 2**16-1. Therefore the + */ +/* following expression should be evaluated using integers with +at */ +/* least 32 bits (16 isn't enough), and PX should be in the rang +e */ +/* ORDER+1+0 through ORDER+1+(IP-2) .EQ. ORDER+IP-1. */ + px = (random_(st) + 32768) * (*ip - 1) / 65536 + contrl_1.order + 1; + r__1 = *ratio / 4 * 1.f; + pulse = r__1 * 342; + if (pulse > 2e3f) { + pulse = 2e3f; + } + exc[px - 1] += pulse; + exc[px] -= pulse; +/* Load voiced excitation */ + } else { + sscale = (real)sqrt((real) (*ip)) / 6.928f; + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + exc[contrl_1.order + i__ - 1] = 0.f; + if (i__ <= 25) { + exc[contrl_1.order + i__ - 1] = sscale * kexc[i__ - 1]; + } + lpi0 = exc[contrl_1.order + i__ - 1]; + r__2 = exc[contrl_1.order + i__ - 1] * .125f + *lpi1 * .75f; + r__1 = r__2 + *lpi2 * .125f; + exc[contrl_1.order + i__ - 1] = r__1 + *lpi3 * 0.f; + *lpi3 = *lpi2; + *lpi2 = *lpi1; + *lpi1 = lpi0; + } + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + noise[contrl_1.order + i__ - 1] = random_(st) * 1.f / 64; + hpi0 = noise[contrl_1.order + i__ - 1]; + r__2 = noise[contrl_1.order + i__ - 1] * -.125f + *hpi1 * .25f; + r__1 = r__2 + *hpi2 * -.125f; + noise[contrl_1.order + i__ - 1] = r__1 + *hpi3 * 0.f; + *hpi3 = *hpi2; + *hpi2 = *hpi1; + *hpi1 = hpi0; + } + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + exc[contrl_1.order + i__ - 1] += noise[contrl_1.order + i__ - 1]; + } + } +/* Synthesis filters: */ +/* Modify the excitation with all-zero filter 1 + G*SUM */ + xssq = 0.f; + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + k = contrl_1.order + i__; + sum = 0.f; + i__2 = contrl_1.order; + for (j = 1; j <= i__2; ++j) { + sum += coef[j] * exc[k - j - 1]; + } + sum *= *g2pass; + exc2[k - 1] = sum + exc[k - 1]; + } +/* Synthesize using the all pole filter 1 / (1 - SUM) */ + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + k = contrl_1.order + i__; + sum = 0.f; + i__2 = contrl_1.order; + for (j = 1; j <= i__2; ++j) { + sum += coef[j] * exc2[k - j - 1]; + } + exc2[k - 1] = sum + exc2[k - 1]; + xssq += exc2[k - 1] * exc2[k - 1]; + } +/* Save filter history for next epoch */ + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + exc[i__ - 1] = exc[*ip + i__ - 1]; + exc2[i__ - 1] = exc2[*ip + i__ - 1]; + } +/* Apply gain to match RMS */ + r__1 = *rms * *rms; + ssq = r__1 * *ip; + gain = (real)sqrt(ssq / xssq); + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + sout[i__] = gain * exc2[contrl_1.order + i__ - 1]; + } + return 0; +} /* bsynz_ */ diff --git a/codecs/lpc10/chanwr.c b/codecs/lpc10/chanwr.c new file mode 100644 index 000000000..cefcdd145 --- /dev/null +++ b/codecs/lpc10/chanwr.c @@ -0,0 +1,232 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:20:24 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Revision 1.1 1996/08/19 22:40:31 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +/* *********************************************************************** */ + +/* CHANL Version 49 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:20:24 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Revision 1.1 1996/08/19 22:40:31 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/21 15:14:57 jaf */ +/* Added comments about which indices of argument arrays are read or */ +/* written, and about the one bit of local state in CHANWR. CHANRD */ +/* has no local state. */ + +/* Revision 1.2 1996/03/13 18:55:10 jaf */ +/* Comments added explaining which of the local variables of this */ +/* subroutine need to be saved from one invocation to the next, and which */ +/* do not. */ + +/* Revision 1.1 1996/02/07 14:43:31 jaf */ +/* Initial revision */ + + +/* *********************************************************************** */ + +/* CHANWR: */ +/* Place quantized parameters into bitstream */ + +/* Input: */ +/* ORDER - Number of reflection coefficients (not really variable) */ +/* IPITV - Quantized pitch/voicing parameter */ +/* IRMS - Quantized energy parameter */ +/* IRC - Quantized reflection coefficients */ +/* Indices 1 through ORDER read. */ +/* Output: */ +/* IBITS - Serial bitstream */ +/* Indices 1 through 54 written. */ +/* Bit 54, the SYNC bit, alternates from one call to the next. */ + +/* Subroutine CHANWR maintains one bit of local state from one call to */ +/* the next, in the variable ISYNC. I believe that this one bit is only */ +/* intended to allow a receiver to resynchronize its interpretation of */ +/* the bit stream, by looking for which of the 54 bits alternates every */ +/* frame time. This is just a simple framing mechanism that is not */ +/* useful when other, higher overhead framing mechanisms are used to */ +/* transmit the coded frames. */ + +/* I'm not going to make an entry to reinitialize this bit, since it */ +/* doesn't help a receiver much to know whether the first sync bit is a 0 */ +/* or a 1. It needs to examine several frames in sequence to have */ +/* reasonably good assurance that its framing is correct. */ + + +/* CHANRD: */ +/* Reconstruct parameters from bitstream */ + +/* Input: */ +/* ORDER - Number of reflection coefficients (not really variable) */ +/* IBITS - Serial bitstream */ +/* Indices 1 through 53 read (SYNC bit is ignored). */ +/* Output: */ +/* IPITV - Quantized pitch/voicing parameter */ +/* IRMS - Quantized energy parameter */ +/* IRC - Quantized reflection coefficients */ +/* Indices 1 through ORDER written */ + +/* Entry CHANRD has no local state. */ + + + +/* IBITS is 54 bits of LPC data ordered as follows: */ +/* R1-0, R2-0, R3-0, P-0, A-0, */ +/* R1-1, R2-1, R3-1, P-1, A-1, */ +/* R1-2, R4-0, R3-2, A-2, P-2, R4-1, */ +/* R1-3, R2-2, R3-3, R4-2, A-3, */ +/* R1-4, R2-3, R3-4, R4-3, A-4, */ +/* P-3, R2-4, R7-0, R8-0, P-4, R4-4, */ +/* R5-0, R6-0, R7-1,R10-0, R8-1, */ +/* R5-1, R6-1, R7-2, R9-0, P-5, */ +/* R5-2, R6-2,R10-1, R8-2, P-6, R9-1, */ +/* R5-3, R6-3, R7-3, R9-2, R8-3, SYNC */ +/* Subroutine */ int chanwr_0_(int n__, integer *order, integer *ipitv, + integer *irms, integer *irc, integer *ibits, + struct lpc10_encoder_state *st) +{ + /* Initialized data */ + + integer *isync; + static integer bit[10] = { 2,4,8,8,8,8,16,16,16,16 }; + static integer iblist[53] = { 13,12,11,1,2,13,12,11,1,2,13,10,11,2,1,10, + 13,12,11,10,2,13,12,11,10,2,1,12,7,6,1,10,9,8,7,4,6,9,8,7,5,1,9,8, + 4,6,1,5,9,8,7,5,6 }; + + /* System generated locals */ + integer i__1; + + /* Local variables */ + integer itab[13], i__; + +/* Arguments */ +/* Parameters/constants */ +/* These arrays are not Fortran PARAMETER's, but they are defined */ +/* by DATA statements below, and their contents are never altered. +*/ +/* Local variables that need not be saved */ +/* Local state */ +/* ISYNC is only used by CHANWR, not by ENTRY CHANRD. */ + + /* Parameter adjustments */ + --irc; + --ibits; + + /* Function Body */ + switch(n__) { + case 1: goto L_chanrd; + } + + isync = &(st->isync); + +/* *********************************************************************** + */ +/* Place quantized parameters into bitstream */ +/* *********************************************************************** + */ +/* Place parameters into ITAB */ + itab[0] = *ipitv; + itab[1] = *irms; + itab[2] = 0; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + itab[i__ + 2] = irc[*order + 1 - i__] & 32767; + } +/* Put 54 bits into IBITS array */ + for (i__ = 1; i__ <= 53; ++i__) { + ibits[i__] = itab[iblist[i__ - 1] - 1] & 1; + itab[iblist[i__ - 1] - 1] /= 2; + } + ibits[54] = *isync & 1; + *isync = 1 - *isync; + return 0; +/* *********************************************************************** + */ +/* Reconstruct parameters from bitstream */ +/* *********************************************************************** + */ + +L_chanrd: +/* Reconstruct ITAB */ + for (i__ = 1; i__ <= 13; ++i__) { + itab[i__ - 1] = 0; + } + for (i__ = 1; i__ <= 53; ++i__) { + itab[iblist[54 - i__ - 1] - 1] = (itab[iblist[54 - i__ - 1] - 1] << 1) + + ibits[54 - i__]; + } +/* Sign extend RC's */ + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + if ((itab[i__ + 2] & bit[i__ - 1]) != 0) { + itab[i__ + 2] -= bit[i__ - 1] << 1; + } + } +/* Restore variables */ + *ipitv = itab[0]; + *irms = itab[1]; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + irc[i__] = itab[*order + 4 - i__ - 1]; + } + return 0; +} /* chanwr_ */ + +/* Subroutine */ int chanwr_(integer *order, integer *ipitv, integer *irms, + integer *irc, integer *ibits, struct lpc10_encoder_state *st) +{ + return chanwr_0_(0, order, ipitv, irms, irc, ibits, st); + } + +/* Subroutine */ int chanrd_(integer *order, integer *ipitv, integer *irms, + integer *irc, integer *ibits) +{ + return chanwr_0_(1, order, ipitv, irms, irc, ibits, 0); + } diff --git a/codecs/lpc10/dcbias.c b/codecs/lpc10/dcbias.c new file mode 100644 index 000000000..d5a7d644f --- /dev/null +++ b/codecs/lpc10/dcbias.c @@ -0,0 +1,107 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:40:23 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int dcbias_(integer *len, real *speech, real *sigout); +#endif + +/* ********************************************************************* */ + +/* DCBIAS Version 50 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:40:23 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/18 21:19:22 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:44:53 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:44:21 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Calculate and remove DC bias from buffer. */ + +/* Input: */ +/* LEN - Length of speech buffers */ +/* SPEECH - Input speech buffer */ +/* Indices 1 through LEN read. */ +/* Output: */ +/* SIGOUT - Output speech buffer */ +/* Indices 1 through LEN written */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int dcbias_(integer *len, real *speech, real *sigout) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + real bias; + integer i__; + +/* Arguments */ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + --sigout; + --speech; + + /* Function Body */ + bias = 0.f; + i__1 = *len; + for (i__ = 1; i__ <= i__1; ++i__) { + bias += speech[i__]; + } + bias /= *len; + i__1 = *len; + for (i__ = 1; i__ <= i__1; ++i__) { + sigout[i__] = speech[i__] - bias; + } + return 0; +} /* dcbias_ */ + diff --git a/codecs/lpc10/decode.c b/codecs/lpc10/decode.c new file mode 100644 index 000000000..08b8b9192 --- /dev/null +++ b/codecs/lpc10/decode.c @@ -0,0 +1,625 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.2 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:22:39 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:38 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int decode_(integer *ipitv, integer *irms, integer *irc, integer *voice, integer *pitch, real *rms, real *rc, struct lpc10_decoder_state *st); +/* comlen contrl_ 12 */ +/*:ref: ham84_ 14 3 4 4 4 */ +/*:ref: median_ 4 3 4 4 4 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* Table of constant values */ + +static integer c__2 = 2; + +/* ***************************************************************** */ + +/* DECODE Version 54 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.2 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:22:39 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:38 jaf + * Initial revision + * */ +/* Revision 1.5 1996/05/23 20:06:03 jaf */ +/* Assigned PITCH a "default" value on the first call, since otherwise it */ +/* would be left uninitialized. */ + +/* Revision 1.4 1996/03/26 19:35:18 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.3 1996/03/21 21:10:50 jaf */ +/* Added entry INITDECODE to reinitialize the local state of subroutine */ +/* DECODE. */ + +/* Revision 1.2 1996/03/21 21:04:50 jaf */ +/* Determined which local variables should be saved from one invocation */ +/* to the next, and guessed initial values for some that should have been */ +/* saved, but weren't given initial values. Many of the arrays are */ +/* "constants", and many local variables are only used if the "global" */ +/* variable CORRP is .TRUE. */ + +/* Added comments explaining which indices of array arguments are read or */ +/* written. */ + +/* Revision 1.1 1996/02/12 03:21:10 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* This subroutine provides error correction and decoding */ +/* for all LPC parameters */ + +/* Input: */ +/* IPITV - Index value of pitch */ +/* IRMS - Coded Energy */ +/* CORRP - Error correction: */ +/* If FALSE, parameters are decoded directly with no delay. If TRUE, */ +/* most important parameter bits are protected by Hamming code and */ +/* median smoothed. This requires an additional frame of delay. */ +/* Input/Output: */ +/* IRC - Coded Reflection Coefficients */ +/* Indices 1 through ORDER always read, then written. */ +/* Output: */ +/* VOICE - Half frame voicing decisions */ +/* Indices 1 through 2 written. */ +/* PITCH - Decoded pitch */ +/* RMS - Energy */ +/* RC - Reflection coefficients */ +/* Indices 1 through ORDER written. */ + +/* NOTE: Zero RC's should be done more directly, but this would affect */ +/* coded parameter printout. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITDECODE. */ + +/* Subroutine */ int decode_(integer *ipitv, integer *irms, + integer *irc, integer *voice, integer *pitch, real *rms, real *rc, + struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + logical *first; + static integer ethrs = 2048; + static integer ethrs1 = 128; + static integer ethrs2 = 1024; + static integer ethrs3 = 2048; + static integer ivtab[32] = { 24960,24960,24960,24960,25480,25480,25483, + 25480,16640,1560,1560,1560,16640,1816,1563,1560,24960,24960,24859, + 24856,26001,25881,25915,25913,1560,1560,7800,3640,1561,1561,3643, + 3641 }; + static real corth[32] /* was [4][8] */ = { 32767.f,10.f,5.f,0.f, + 32767.f,8.f,4.f,0.f,32.f,6.4f,3.2f,0.f,32.f,6.4f,3.2f,0.f,32.f, + 11.2f,6.4f,0.f,32.f,11.2f,6.4f,0.f,16.f,5.6f,3.2f,0.f,16.f,5.6f, + 3.2f,0.f }; + static integer detau[128] = { 0,0,0,3,0,3,3,31,0,3,3,21,3,3,29,30,0,3,3, + 20,3,25,27,26,3,23,58,22,3,24,28,3,0,3,3,3,3,39,33,32,3,37,35,36, + 3,38,34,3,3,42,46,44,50,40,48,3,54,3,56,3,52,3,3,1,0,3,3,108,3,78, + 100,104,3,84,92,88,156,80,96,3,3,74,70,72,66,76,68,3,62,3,60,3,64, + 3,3,1,3,116,132,112,148,152,3,3,140,3,136,3,144,3,3,1,124,120,128, + 3,3,3,3,1,3,3,3,1,3,1,1,1 }; + static integer rmst[64] = { 1024,936,856,784,718,656,600,550,502,460,420, + 384,352,328,294,270,246,226,206,188,172,158,144,132,120,110,102, + 92,84,78,70,64,60,54,50,46,42,38,34,32,30,26,24,22,20,18,17,16,15, + 14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 }; + static integer detab7[32] = { 4,11,18,25,32,39,46,53,60,66,72,77,82,87,92, + 96,101,104,108,111,114,115,117,119,121,122,123,124,125,126,127, + 127 }; + static real descl[8] = { .6953f,.625f,.5781f,.5469f,.5312f,.5391f,.4688f, + .3828f }; + integer *ivp2h; + static integer deadd[8] = { 1152,-2816,-1536,-3584,-1280,-2432,768,-1920 } + ; + static integer qb[8] = { 511,511,1023,1023,1023,1023,2047,4095 }; + static integer nbit[10] = { 8,8,5,5,4,4,4,4,3,2 }; + static integer zrc[10] = { 0,0,0,0,0,3,0,2,0,0 }; + static integer bit[5] = { 2,4,8,16,32 }; + integer *iovoic; + integer *iavgp; + integer *iptold; + integer *erate; + integer *drc; + integer *dpit; + integer *drms; + + /* System generated locals */ + integer i__1, i__2; + + /* Builtin functions */ + integer pow_ii(integer *, integer *); + + /* Local variables */ + extern /* Subroutine */ int ham84_(integer *, integer *, integer *); + integer ipit, iout, i__, icorf, index, ivoic, ixcor, i1, i2, i4; + extern integer median_(integer *, integer *, integer *); + integer ishift, errcnt, lsb; + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.2 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:22:39 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:38 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments */ +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.2 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:22:39 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:38 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Function return value definitions */ + +/* Parameters/constants */ + +/* The variables below that are not Fortran PARAMETER's are */ +/* initialized with DATA statements, and then never modified. */ +/* The following are used regardless of CORRP's value. */ + +/* DETAU, NBIT, QB, DEADD, DETAB7, RMST, DESCL */ + +/* The following are used only if CORRP is .TRUE. */ + +/* ETHRS, ETHRS1, ETHRS2, ETHRS3, IVTAB, BIT, CORTH, ZRC */ + +/* Local variables that need not be saved */ + +/* The following are used regardless of CORRP's value */ +/* The following are used only if CORRP is .TRUE. */ + +/* Local state */ + +/* The following are used regardless of CORRP's value */ +/* The following are used only if CORRP is .TRUE. */ +/* I am guessing the initial values for IVP2H, IOVOIC, DRC, DPIT, */ +/* and DRMS. They should be checked to see if they are reasonable. +*/ +/* I'm also guessing for ERATE, but I think 0 is the right initial +*/ +/* value. */ + /* Parameter adjustments */ + if (irc) { + --irc; + } + if (voice) { + --voice; + } + if (rc) { + --rc; + } + + /* Function Body */ + + iptold = &(st->iptold); + first = &(st->first); + ivp2h = &(st->ivp2h); + iovoic = &(st->iovoic); + iavgp = &(st->iavgp); + erate = &(st->erate); + drc = &(st->drc[0]); + dpit = &(st->dpit[0]); + drms = &(st->drms[0]); + +/* DATA statements for "constants" defined above. */ +/* IF (LISTL.GE.3) WRITE(FDEBUG,800) IPITV,IRMS,(IRC(J),J=1,ORDER) */ +/* 800 FORMAT(1X,' <<ERRCOR IN>>',T32,6X,I6,I5,T50,10I8) */ +/* If no error correction, do pitch and voicing then jump to decode */ + i4 = detau[*ipitv]; + if (! contrl_1.corrp) { + voice[1] = 1; + voice[2] = 1; + if (*ipitv <= 1) { + voice[1] = 0; + } + if (*ipitv == 0 || *ipitv == 2) { + voice[2] = 0; + } + *pitch = i4; + if (*pitch <= 4) { + *pitch = *iptold; + } + if (voice[1] == 1 && voice[2] == 1) { + *iptold = *pitch; + } + if (voice[1] != voice[2]) { + *pitch = *iptold; + } + goto L900; + } +/* Do error correction pitch and voicing */ + if (i4 > 4) { + dpit[0] = i4; + ivoic = 2; + *iavgp = (*iavgp * 15 + i4 + 8) / 16; + } else { + ivoic = i4; + dpit[0] = *iavgp; + } + drms[0] = *irms; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + drc[i__ * 3 - 3] = irc[i__]; + } +/* Determine index to IVTAB from V/UV decision */ +/* If error rate is high then use alternate table */ + index = (*ivp2h << 4) + (*iovoic << 2) + ivoic + 1; + i1 = ivtab[index - 1]; + ipit = i1 & 3; + icorf = i1 / 8; + if (*erate < ethrs) { + icorf /= 64; + } +/* Determine error rate: 4=high 1=low */ + ixcor = 4; + if (*erate < ethrs3) { + ixcor = 3; + } + if (*erate < ethrs2) { + ixcor = 2; + } + if (*erate < ethrs1) { + ixcor = 1; + } +/* Voice/unvoice decision determined from bits 0 and 1 of IVTAB */ + voice[1] = icorf / 2 & 1; + voice[2] = icorf & 1; +/* Skip decoding on first frame because present data not yet available */ + if (*first) { + *first = FALSE_; +/* Assign PITCH a "default" value on the first call, since */ +/* otherwise it would be left uninitialized. The two lines +*/ +/* below were copied from above, since it seemed like a */ +/* reasonable thing to do for the first call. */ + *pitch = i4; + if (*pitch <= 4) { + *pitch = *iptold; + } + goto L500; + } +/* If bit 4 of ICORF is set then correct RMS and RC(1) - RC(4). */ +/* Determine error rate and correct errors using a Hamming 8,4 code */ +/* during transition or unvoiced frame. If IOUT is negative, */ +/* more than 1 error occurred, use previous frame's parameters. */ + if ((icorf & bit[3]) != 0) { + errcnt = 0; + lsb = drms[1] & 1; + index = (drc[22] << 4) + drms[1] / 2; + ham84_(&index, &iout, &errcnt); + drms[1] = drms[2]; + if (iout >= 0) { + drms[1] = (iout << 1) + lsb; + } + for (i__ = 1; i__ <= 4; ++i__) { + if (i__ == 1) { + i1 = ((drc[25] & 7) << 1) + (drc[28] & 1); + } else { + i1 = drc[(9 - i__) * 3 - 2] & 15; + } + i2 = drc[(5 - i__) * 3 - 2] & 31; + lsb = i2 & 1; + index = (i1 << 4) + i2 / 2; + ham84_(&index, &iout, &errcnt); + if (iout >= 0) { + iout = (iout << 1) + lsb; + if ((iout & 16) == 16) { + iout += -32; + } + } else { + iout = drc[(5 - i__) * 3 - 1]; + } + drc[(5 - i__) * 3 - 2] = iout; + } +/* Determine error rate */ + *erate = (integer)(*erate * .96875f + errcnt * 102); + } +/* Get unsmoothed RMS, RC's, and PITCH */ + *irms = drms[1]; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + irc[i__] = drc[i__ * 3 - 2]; + } + if (ipit == 1) { + dpit[1] = dpit[2]; + } + if (ipit == 3) { + dpit[1] = dpit[0]; + } + *pitch = dpit[1]; +/* If bit 2 of ICORF is set then smooth RMS and RC's, */ + if ((icorf & bit[1]) != 0) { + if ((i__1 = drms[1] - drms[0], (real) abs(i__1)) >= corth[ixcor + 3] + && (i__2 = drms[1] - drms[2], (real) abs(i__2)) >= corth[ + ixcor + 3]) { + *irms = median_(&drms[2], &drms[1], drms); + } + for (i__ = 1; i__ <= 6; ++i__) { + if ((i__1 = drc[i__ * 3 - 2] - drc[i__ * 3 - 3], (real) abs(i__1)) + >= corth[ixcor + ((i__ + 2) << 2) - 5] && (i__2 = drc[i__ * + 3 - 2] - drc[i__ * 3 - 1], (real) abs(i__2)) >= corth[ + ixcor + ((i__ + 2) << 2) - 5]) { + irc[i__] = median_(&drc[i__ * 3 - 1], &drc[i__ * 3 - 2], &drc[ + i__ * 3 - 3]); + } + } + } +/* If bit 3 of ICORF is set then smooth pitch */ + if ((icorf & bit[2]) != 0) { + if ((i__1 = dpit[1] - dpit[0], (real) abs(i__1)) >= corth[ixcor - 1] + && (i__2 = dpit[1] - dpit[2], (real) abs(i__2)) >= corth[ + ixcor - 1]) { + *pitch = median_(&dpit[2], &dpit[1], dpit); + } + } +/* If bit 5 of ICORF is set then RC(5) - RC(10) are loaded with */ +/* values so that after quantization bias is removed in decode */ +/* the values will be zero. */ +L500: + if ((icorf & bit[4]) != 0) { + i__1 = contrl_1.order; + for (i__ = 5; i__ <= i__1; ++i__) { + irc[i__] = zrc[i__ - 1]; + } + } +/* House keeping - one frame delay */ + *iovoic = ivoic; + *ivp2h = voice[2]; + dpit[2] = dpit[1]; + dpit[1] = dpit[0]; + drms[2] = drms[1]; + drms[1] = drms[0]; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + drc[i__ * 3 - 1] = drc[i__ * 3 - 2]; + drc[i__ * 3 - 2] = drc[i__ * 3 - 3]; + } +L900: +/* IF (LISTL.GE.3)WRITE(FDEBUG,801)VOICE,PITCH,IRMS,(IRC(J),J=1,ORDER) */ +/* 801 FORMAT(1X,'<<ERRCOR OUT>>',T32,2I3,I6,I5,T50,10I8) */ +/* Decode RMS */ + *irms = rmst[(31 - *irms) * 2]; +/* Decode RC(1) and RC(2) from log-area-ratios */ +/* Protect from illegal coded value (-16) caused by bit errors */ + for (i__ = 1; i__ <= 2; ++i__) { + i2 = irc[i__]; + i1 = 0; + if (i2 < 0) { + i1 = 1; + i2 = -i2; + if (i2 > 15) { + i2 = 0; + } + } + i2 = detab7[i2 * 2]; + if (i1 == 1) { + i2 = -i2; + } + ishift = 15 - nbit[i__ - 1]; + irc[i__] = i2 * pow_ii(&c__2, &ishift); + } +/* Decode RC(3)-RC(10) to sign plus 14 bits */ + i__1 = contrl_1.order; + for (i__ = 3; i__ <= i__1; ++i__) { + i2 = irc[i__]; + ishift = 15 - nbit[i__ - 1]; + i2 *= pow_ii(&c__2, &ishift); + i2 += qb[i__ - 3]; + irc[i__] = (integer)(i2 * descl[i__ - 3] + deadd[i__ - 3]); + } +/* IF (LISTL.GE.3) WRITE(FDEBUG,811) IRMS, (IRC(I),I=1,ORDER) */ +/* 811 FORMAT(1X,'<<DECODE OUT>>',T45,I4,1X,10I8) */ +/* Scale RMS and RC's to reals */ + *rms = (real) (*irms); + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + rc[i__] = irc[i__] / 16384.f; + } + return 0; +} /* decode_ */ diff --git a/codecs/lpc10/deemp.c b/codecs/lpc10/deemp.c new file mode 100644 index 000000000..c3b5909ff --- /dev/null +++ b/codecs/lpc10/deemp.c @@ -0,0 +1,154 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:23:46 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:34 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int deemp_(real *x, integer *n, struct lpc10_decoder_state *st); +#endif + +/* ***************************************************************** */ + +/* DEEMP Version 48 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:23:46 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:34 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/20 15:54:37 jaf */ +/* Added comments about which indices of array arguments are read or */ +/* written. */ + +/* Added entry INITDEEMP to reinitialize the local state variables, if */ +/* desired. */ + +/* Revision 1.2 1996/03/14 22:11:13 jaf */ +/* Comments added explaining which of the local variables of this */ +/* subroutine need to be saved from one invocation to the next, and which */ +/* do not. */ + +/* Revision 1.1 1996/02/07 14:44:53 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* De-Emphasize output speech with 1 / ( 1 - .75z**-1 ) */ +/* cascaded with 200 Hz high pass filter */ +/* ( 1 - 1.9998z**-1 + z**-2 ) / ( 1 - 1.75z**-1 + .78z**-2 ) */ + +/* WARNING! The coefficients above may be out of date with the code */ +/* below. Either that, or some kind of transformation was performed */ +/* on the coefficients above to create the code below. */ + +/* Input: */ +/* N - Number of samples */ +/* Input/Output: */ +/* X - Speech */ +/* Indices 1 through N are read before being written. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITDEEMP. */ + +/* Subroutine */ int deemp_(real *x, integer *n, struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + real *dei1; + real *dei2; + real *deo1; + real *deo2; + real *deo3; + + /* System generated locals */ + integer i__1; + real r__1; + + /* Local variables */ + integer k; + real dei0; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Local state */ +/* All of the locals saved below were not given explicit initial */ +/* values in the original code. I think 0 is a safe choice. */ + /* Parameter adjustments */ + if (x) { + --x; + } + + /* Function Body */ + + dei1 = &(st->dei1); + dei2 = &(st->dei2); + deo1 = &(st->deo1); + deo2 = &(st->deo2); + deo3 = &(st->deo3); + + i__1 = *n; + for (k = 1; k <= i__1; ++k) { + dei0 = x[k]; + r__1 = x[k] - *dei1 * 1.9998f + *dei2; + x[k] = r__1 + *deo1 * 2.5f - *deo2 * 2.0925f + *deo3 * .585f; + *dei2 = *dei1; + *dei1 = dei0; + *deo3 = *deo2; + *deo2 = *deo1; + *deo1 = x[k]; + } + return 0; +} /* deemp_ */ diff --git a/codecs/lpc10/difmag.c b/codecs/lpc10/difmag.c new file mode 100644 index 000000000..ab59e8c9a --- /dev/null +++ b/codecs/lpc10/difmag.c @@ -0,0 +1,133 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:31 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int difmag_(real *speech, integer *lpita, integer *tau, integer *ltau, integer *maxlag, real *amdf, integer *minptr, integer *maxptr); +#endif + +/* ********************************************************************** */ + +/* DIFMAG Version 49 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:14 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:32:31 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/15 23:09:39 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 14:41:31 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:45:04 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Compute Average Magnitude Difference Function */ + +/* Inputs: */ +/* SPEECH - Low pass filtered speech */ +/* Indices MIN_N1 through MAX_N1+LPITA-1 are read, where */ +/* MIN_N1 = (MAXLAG - MAX_TAU)/2+1 MAX_TAU = max of TAU(I) for I=1,LTAU +*/ +/* MAX_N1 = (MAXLAG - MIN_TAU)/2+1 MIN_TAU = min of TAU(I) for I=1,LTAU +*/ +/* LPITA - Length of speech buffer */ +/* TAU - Table of lags */ +/* Indices 1 through LTAU read. */ +/* LTAU - Number of lag values to compute */ +/* MAXLAG - Maximum possible lag value */ +/* Outputs: */ +/* (All of these outputs are also read, but only after being written.) */ +/* AMDF - Average Magnitude Difference for each lag in TAU */ +/* Indices 1 through LTAU written */ +/* MINPTR - Index of minimum AMDF value */ +/* MAXPTR - Index of maximum AMDF value */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int difmag_(real *speech, integer *lpita, integer *tau, + integer *ltau, integer *maxlag, real *amdf, integer *minptr, integer * + maxptr) +{ + /* System generated locals */ + integer i__1, i__2; + real r__1; + + /* Local variables */ + integer i__, j, n1, n2; + real sum; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Local state */ +/* None */ + /* Parameter adjustments */ + --amdf; + --tau; + --speech; + + /* Function Body */ + *minptr = 1; + *maxptr = 1; + i__1 = *ltau; + for (i__ = 1; i__ <= i__1; ++i__) { + n1 = (*maxlag - tau[i__]) / 2 + 1; + n2 = n1 + *lpita - 1; + sum = 0.f; + i__2 = n2; + for (j = n1; j <= i__2; j += 4) { + sum += (r__1 = speech[j] - speech[j + tau[i__]], abs(r__1)); + } + amdf[i__] = sum; + if (amdf[i__] < amdf[*minptr]) { + *minptr = i__; + } + if (amdf[i__] > amdf[*maxptr]) { + *maxptr = i__; + } + } + return 0; +} /* difmag_ */ + diff --git a/codecs/lpc10/dyptrk.c b/codecs/lpc10/dyptrk.c new file mode 100644 index 000000000..216b55994 --- /dev/null +++ b/codecs/lpc10/dyptrk.c @@ -0,0 +1,405 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:25:29 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:32:26 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int dyptrk_(real *amdf, integer *ltau, integer *minptr, integer *voice, integer *pitch, integer *midx, struct lpc10_encoder_state *st); +/* comlen contrl_ 12 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* ********************************************************************* */ + +/* DYPTRK Version 52 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:25:29 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:32:26 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/26 19:35:35 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.4 1996/03/19 18:03:22 jaf */ +/* Replaced the initialization "DATA P/60*DEPTH*0/" with "DATA P/120*0/", */ +/* because apparently Fortran (or at least f2c) can't handle expressions */ +/* like that. */ + +/* Revision 1.3 1996/03/19 17:38:32 jaf */ +/* Added comments about the local variables that should be saved from one */ +/* invocation to the next. None of them were given initial values in the */ +/* original code, but from my testing, it appears that initializing them */ +/* all to 0 works. */ + +/* Added entry INITDYPTRK to reinitialize these local variables. */ + +/* Revision 1.2 1996/03/13 16:32:17 jaf */ +/* Comments added explaining which of the local variables of this */ +/* subroutine need to be saved from one invocation to the next, and which */ +/* do not. */ + +/* WARNING! Some of them that should are never given initial values in */ +/* this code. Hopefully, Fortran 77 defines initial values for them, but */ +/* even so, giving them explicit initial values is preferable. */ + +/* Revision 1.1 1996/02/07 14:45:14 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Dynamic Pitch Tracker */ + +/* Input: */ +/* AMDF - Average Magnitude Difference Function array */ +/* Indices 1 through LTAU read, and MINPTR */ +/* LTAU - Number of lags in AMDF */ +/* MINPTR - Location of minimum AMDF value */ +/* VOICE - Voicing decision */ +/* Output: */ +/* PITCH - Smoothed pitch value, 2 frames delayed */ +/* MIDX - Initial estimate of current frame pitch */ +/* Compile time constant: */ +/* DEPTH - Number of frames to trace back */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITDYPTRK. */ + +/* Subroutine */ int dyptrk_(real *amdf, integer *ltau, integer * + minptr, integer *voice, integer *pitch, integer *midx, + struct lpc10_encoder_state *st) +{ + /* Initialized data */ + + real *s; + integer *p; + integer *ipoint; + real *alphax; + + /* System generated locals */ + integer i__1; + + /* Local variables */ + integer pbar; + real sbar; + integer path[2], iptr, i__, j; + real alpha, minsc, maxsc; + +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:25:29 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:32:26 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Parameters/constants */ +/* Local variables that need not be saved */ +/* Note that PATH is only used for debugging purposes, and can be */ +/* removed. */ +/* Local state */ +/* It would be a bit more "general" to define S(LTAU), if Fortran */ +/* allows the argument of a function to be used as the dimension of +*/ +/* a local array variable. */ +/* IPOINT is always in the range 0 to DEPTH-1. */ +/* WARNING! */ + +/* In the original version of this subroutine, IPOINT, ALPHAX, */ +/* every element of S, and potentially any element of P with the */ +/* second index value .NE. IPTR were read without being given */ +/* initial values (all indices of P with second index equal to */ +/* IPTR are all written before being read in this subroutine). */ + +/* From examining the code carefully, it appears that all of these +*/ +/* should be saved from one invocation to the next. */ + +/* I've run lpcsim with the "-l 6" option to see all of the */ +/* debugging information that is printed out by this subroutine */ +/* below, and it appears that S, P, IPOINT, and ALPHAX are all */ +/* initialized to 0 (these initial values would likely be different +*/ +/* on different platforms, compilers, etc.). Given that the output +*/ +/* of the coder sounds reasonable, I'm going to initialize these */ +/* variables to 0 explicitly. */ + + s = &(st->s[0]); + p = &(st->p[0]); + ipoint = &(st->ipoint); + alphax = &(st->alphax); + + + /* Parameter adjustments */ + if (amdf) { + --amdf; + } + + /* Function Body */ + +/* Calculate the confidence factor ALPHA, used as a threshold slope in +*/ +/* SEESAW. If unvoiced, set high slope so that every point in P array +*/ +/* is marked as a potential pitch frequency. A scaled up version (ALPHAX +)*/ +/* is used to maintain arithmetic precision. */ + if (*voice == 1) { + *alphax = *alphax * .75f + amdf[*minptr] / 2.f; + } else { + *alphax *= .984375f; + } + alpha = *alphax / 16; + if (*voice == 0 && *alphax < 128.f) { + alpha = 8.f; + } +/* SEESAW: Construct a pitch pointer array and intermediate winner functio +n*/ +/* Left to right pass: */ + iptr = *ipoint + 1; + p[iptr * 60 - 60] = 1; + i__ = 1; + pbar = 1; + sbar = s[0]; + i__1 = *ltau; + for (i__ = 1; i__ <= i__1; ++i__) { + sbar += alpha; + if (sbar < s[i__ - 1]) { + s[i__ - 1] = sbar; + p[i__ + iptr * 60 - 61] = pbar; + } else { + sbar = s[i__ - 1]; + p[i__ + iptr * 60 - 61] = i__; + pbar = i__; + } + } +/* Right to left pass: */ + i__ = pbar - 1; + sbar = s[i__]; + while(i__ >= 1) { + sbar += alpha; + if (sbar < s[i__ - 1]) { + s[i__ - 1] = sbar; + p[i__ + iptr * 60 - 61] = pbar; + } else { + pbar = p[i__ + iptr * 60 - 61]; + i__ = pbar; + sbar = s[i__ - 1]; + } + --i__; + } +/* Update S using AMDF */ +/* Find maximum, minimum, and location of minimum */ + s[0] += amdf[1] / 2; + minsc = s[0]; + maxsc = minsc; + *midx = 1; + i__1 = *ltau; + for (i__ = 2; i__ <= i__1; ++i__) { + s[i__ - 1] += amdf[i__] / 2; + if (s[i__ - 1] > maxsc) { + maxsc = s[i__ - 1]; + } + if (s[i__ - 1] < minsc) { + *midx = i__; + minsc = s[i__ - 1]; + } + } +/* Subtract MINSC from S to prevent overflow */ + i__1 = *ltau; + for (i__ = 1; i__ <= i__1; ++i__) { + s[i__ - 1] -= minsc; + } + maxsc -= minsc; +/* Use higher octave pitch if significant null there */ + j = 0; + for (i__ = 20; i__ <= 40; i__ += 10) { + if (*midx > i__) { + if (s[*midx - i__ - 1] < maxsc / 4) { + j = i__; + } + } + } + *midx -= j; +/* TRACE: look back two frames to find minimum cost pitch estimate */ + j = *ipoint; + *pitch = *midx; + for (i__ = 1; i__ <= 2; ++i__) { + j = j % 2 + 1; + *pitch = p[*pitch + j * 60 - 61]; + path[i__ - 1] = *pitch; + } + +/* The following statement subtracts one from IPOINT, mod DEPTH. I +*/ +/* think the author chose to add DEPTH-1, instead of subtracting 1, +*/ +/* because then it will work even if MOD doesn't work as desired on +*/ +/* negative arguments. */ + + *ipoint = (*ipoint + 1) % 2; + return 0; +} /* dyptrk_ */ diff --git a/codecs/lpc10/encode.c b/codecs/lpc10/encode.c new file mode 100644 index 000000000..b81799f6b --- /dev/null +++ b/codecs/lpc10/encode.c @@ -0,0 +1,373 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:21 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int encode_(integer *voice, integer *pitch, real *rms, real *rc, integer *ipitch, integer *irms, integer *irc); +/* comlen contrl_ 12 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* Table of constant values */ + +static integer c__2 = 2; + +/* ***************************************************************** */ + +/* ENCODE Version 54 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:32:21 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/26 19:35:50 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.4 1996/03/21 00:26:29 jaf */ +/* Added the comment that this subroutine has no local state. */ + +/* In the last check-in, I forgot to mention that I had added comments */ +/* explaining which indices of array arguments are read or written. */ + +/* Revision 1.3 1996/03/21 00:22:39 jaf */ +/* Added comments explaining that all local arrays are effectively */ +/* constants. */ + +/* Revision 1.2 1996/03/13 18:48:33 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:45:29 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Quantize LPC parameters for transmission */ + +/* INPUTS: */ +/* VOICE - Half frame voicing decisions */ +/* Indices 1 through 2 read. */ +/* PITCH - Pitch */ +/* RMS - Energy */ +/* RC - Reflection coefficients */ +/* Indices 1 through ORDER read. */ +/* CORRP - Error Correction: TRUE = yes, FALSE = none */ +/* (this is defined in file control.fh) */ +/* OUTPUTS: */ +/* IPITCH - Coded pitch and voicing */ +/* IRMS - Quantized energy */ +/* IRC - Quantized reflection coefficients */ +/* Indices 1 through MAX(ORDER,2) written. */ +/* If CORRP is .TRUE., then indices 1 through 10 written */ +/* for unvoiced frames. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int encode_(integer *voice, integer *pitch, real *rms, real * + rc, integer *ipitch, integer *irms, integer *irc) +{ + /* Initialized data */ + + static integer enctab[16] = { 0,7,11,12,13,10,6,1,14,9,5,2,3,4,8,15 }; + static integer entau[60] = { 19,11,27,25,29,21,23,22,30,14,15,7,39,38,46, + 42,43,41,45,37,53,49,51,50,54,52,60,56,58,26,90,88,92,84,86,82,83, + 81,85,69,77,73,75,74,78,70,71,67,99,97,113,112,114,98,106,104,108, + 100,101,76 }; + static integer enadd[8] = { 1920,-768,2432,1280,3584,1536,2816,-1152 }; + static real enscl[8] = { .0204f,.0167f,.0145f,.0147f,.0143f,.0135f,.0125f, + .0112f }; + static integer enbits[8] = { 6,5,4,4,4,4,3,3 }; + static integer entab6[64] = { 0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3, + 3,3,3,3,3,4,4,4,4,4,4,4,5,5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,9,9, + 9,10,10,11,11,12,13,14,15 }; + static integer rmst[64] = { 1024,936,856,784,718,656,600,550,502,460,420, + 384,352,328,294,270,246,226,206,188,172,158,144,132,120,110,102, + 92,84,78,70,64,60,54,50,46,42,38,34,32,30,26,24,22,20,18,17,16,15, + 14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 }; + + /* System generated locals */ + integer i__1, i__2; + + /* Builtin functions */ + integer pow_ii(integer *, integer *); + + /* Local variables */ + integer idel, nbit, i__, j, i2, i3, mrk; + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:32:21 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:32:21 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Parameters/constants */ +/* These arrays are not Fortran PARAMETER's, but they are defined */ +/* by DATA statements below, and their contents are never altered. +*/ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + --irc; + --rc; + --voice; + + /* Function Body */ +/* Scale RMS and RC's to integers */ + *irms = (integer)*rms; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + irc[i__] = (integer)(rc[i__] * 32768.f); + } +/* IF(LISTL.GE.3)WRITE(FDEBUG,800)VOICE,PITCH,IRMS,(IRC(I),I=1,ORDER) */ +/* 800 FORMAT(1X,/,' <<ENCODE IN>>',T32,2I3,I6,I5,T50,10I8) */ +/* Encode pitch and voicing */ + if (voice[1] != 0 && voice[2] != 0) { + *ipitch = entau[*pitch - 1]; + } else { + if (contrl_1.corrp) { + *ipitch = 0; + if (voice[1] != voice[2]) { + *ipitch = 127; + } + } else { + *ipitch = (voice[1] << 1) + voice[2]; + } + } +/* Encode RMS by binary table search */ + j = 32; + idel = 16; + *irms = min(*irms,1023); + while(idel > 0) { + if (*irms > rmst[j - 1]) { + j -= idel; + } + if (*irms < rmst[j - 1]) { + j += idel; + } + idel /= 2; + } + if (*irms > rmst[j - 1]) { + --j; + } + *irms = 31 - j / 2; +/* Encode RC(1) and (2) as log-area-ratios */ + for (i__ = 1; i__ <= 2; ++i__) { + i2 = irc[i__]; + mrk = 0; + if (i2 < 0) { + i2 = -i2; + mrk = 1; + } + i2 /= 512; + i2 = min(i2,63); + i2 = entab6[i2]; + if (mrk != 0) { + i2 = -i2; + } + irc[i__] = i2; + } +/* Encode RC(3) - (10) linearly, remove bias then scale */ + i__1 = contrl_1.order; + for (i__ = 3; i__ <= i__1; ++i__) { + i2 = irc[i__] / 2; + i2 = (integer)((i2 + enadd[contrl_1.order + 1 - i__ - 1]) * enscl[ + contrl_1.order + 1 - i__ - 1]); +/* Computing MIN */ + i__2 = max(i2,-127); + i2 = min(i__2,127); + nbit = enbits[contrl_1.order + 1 - i__ - 1]; + i3 = 0; + if (i2 < 0) { + i3 = -1; + } + i2 /= pow_ii(&c__2, &nbit); + if (i3 == -1) { + --i2; + } + irc[i__] = i2; + } +/* Protect the most significant bits of the most */ +/* important parameters during non-voiced frames. */ +/* RC(1) - RC(4) are protected using 20 parity bits */ +/* replacing RC(5) - RC(10). */ + if (contrl_1.corrp) { + if (*ipitch == 0 || *ipitch == 127) { + irc[5] = enctab[(irc[1] & 30) / 2]; + irc[6] = enctab[(irc[2] & 30) / 2]; + irc[7] = enctab[(irc[3] & 30) / 2]; + irc[8] = enctab[(*irms & 30) / 2]; + irc[9] = enctab[(irc[4] & 30) / 2] / 2; + irc[10] = enctab[(irc[4] & 30) / 2] & 1; + } + } +/* IF(LISTL.GE.3)WRITE(FDEBUG,801)VOICE,IPITCH,IRMS,(IRC(J),J=1,ORDER) */ +/* 801 FORMAT(1X,'<<ENCODE OUT>>',T32,2I3,I6,I5,T50,10I8) */ + return 0; +} /* encode_ */ + diff --git a/codecs/lpc10/energy.c b/codecs/lpc10/energy.c new file mode 100644 index 000000000..eada04bef --- /dev/null +++ b/codecs/lpc10/energy.c @@ -0,0 +1,103 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:17 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int energy_(integer *len, real *speech, real *rms); +#endif + +/* ********************************************************************* */ + +/* ENERGY Version 50 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:32:17 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/18 21:17:41 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:46:02 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:45:40 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Compute RMS energy. */ + +/* Input: */ +/* LEN - Length of speech buffer */ +/* SPEECH - Speech buffer */ +/* Indices 1 through LEN read. */ +/* Output: */ +/* RMS - Root Mean Square energy */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int energy_(integer *len, real *speech, real *rms) +{ + /* System generated locals */ + integer i__1; + + /* Builtin functions */ + double sqrt(doublereal); + + /* Local variables */ + integer i__; + +/* Arguments */ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + --speech; + + /* Function Body */ + *rms = 0.f; + i__1 = *len; + for (i__ = 1; i__ <= i__1; ++i__) { + *rms += speech[i__] * speech[i__]; + } + *rms = (real)sqrt(*rms / *len); + return 0; +} /* energy_ */ + diff --git a/codecs/lpc10/f2c.h b/codecs/lpc10/f2c.h new file mode 100644 index 000000000..e50d642e0 --- /dev/null +++ b/codecs/lpc10/f2c.h @@ -0,0 +1,325 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:26:28 jaf + * Any typedef defining a type that was used in lpc10_encoder_state or + * lpc10_decoder_state struct's was commented out here and added to + * lpc10.h. + * + * Revision 1.1 1996/08/19 22:32:13 jaf + * Initial revision + * + +*/ + +/* + * f2c.h + * + * SCCS ID: @(#)f2c.h 1.2 96/05/19 + */ + +/* f2c.h -- Standard Fortran to C header file */ + +/** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed." + + - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */ + +#ifndef F2C_INCLUDE +#define F2C_INCLUDE + +#include "lpc10.h" + +/*typedef long int integer;*/ +/*typedef INT32 integer;*/ +/*typedef short int shortint;*/ +/*typedef INT16 shortint;*/ +/*typedef float real;*/ +/* doublereal only used for function arguments to sqrt, exp, etc. */ +typedef double doublereal; +/* 32 bits seems wasteful, but there really aren't that many logical + * variables around, and making them 32 bits could avoid word + * alignment problems, perhaps. */ +/*typedef long int logical;*/ +/*typedef INT32 logical;*/ +/* The following types are not used in the translated C code for the + * LPC-10 coder, but they might be needed by the definitions down + * below, so they don't cause compilation errors. */ +typedef char *address; +typedef struct { real r, i; } complex; +typedef struct { doublereal r, i; } doublecomplex; +typedef short int shortlogical; +typedef char logical1; +typedef char integer1; +/* typedef long long longint; */ /* system-dependent */ + +#define TRUE_ (1) +#define FALSE_ (0) + +/* Extern is for use with -E */ +#ifndef Extern +#define Extern extern +#endif + +/* I/O stuff */ + +#ifdef f2c_i2 +/* for -i2 */ +typedef short flag; +typedef short ftnlen; +typedef short ftnint; +#else +typedef long int flag; +typedef long int ftnlen; +typedef long int ftnint; +#endif + +/*external read, write*/ +typedef struct +{ flag cierr; + ftnint ciunit; + flag ciend; + char *cifmt; + ftnint cirec; +} cilist; + +/*internal read, write*/ +typedef struct +{ flag icierr; + char *iciunit; + flag iciend; + char *icifmt; + ftnint icirlen; + ftnint icirnum; +} icilist; + +/*open*/ +typedef struct +{ flag oerr; + ftnint ounit; + char *ofnm; + ftnlen ofnmlen; + char *osta; + char *oacc; + char *ofm; + ftnint orl; + char *oblnk; +} olist; + +/*close*/ +typedef struct +{ flag cerr; + ftnint cunit; + char *csta; +} cllist; + +/*rewind, backspace, endfile*/ +typedef struct +{ flag aerr; + ftnint aunit; +} alist; + +/* inquire */ +typedef struct +{ flag inerr; + ftnint inunit; + char *infile; + ftnlen infilen; + ftnint *inex; /*parameters in standard's order*/ + ftnint *inopen; + ftnint *innum; + ftnint *innamed; + char *inname; + ftnlen innamlen; + char *inacc; + ftnlen inacclen; + char *inseq; + ftnlen inseqlen; + char *indir; + ftnlen indirlen; + char *infmt; + ftnlen infmtlen; + char *inform; + ftnint informlen; + char *inunf; + ftnlen inunflen; + ftnint *inrecl; + ftnint *innrec; + char *inblank; + ftnlen inblanklen; +} inlist; + +#define VOID void + +union Multitype { /* for multiple entry points */ + integer1 g; + shortint h; + integer i; + /* longint j; */ + real r; + doublereal d; + complex c; + doublecomplex z; + }; + +typedef union Multitype Multitype; + +/*typedef long int Long;*/ /* No longer used; formerly in Namelist */ + +struct Vardesc { /* for Namelist */ + char *name; + char *addr; + ftnlen *dims; + int type; + }; +typedef struct Vardesc Vardesc; + +struct Namelist { + char *name; + Vardesc **vars; + int nvars; + }; +typedef struct Namelist Namelist; + +#define abs(x) ((x) >= 0 ? (x) : -(x)) +#define dabs(x) (doublereal)abs(x) +#define min(a,b) ((a) <= (b) ? (a) : (b)) +#define max(a,b) ((a) >= (b) ? (a) : (b)) +#define dmin(a,b) (doublereal)min(a,b) +#define dmax(a,b) (doublereal)max(a,b) + +/* procedure parameter types for -A and -C++ */ + +#define F2C_proc_par_types 1 +#ifdef __cplusplus +typedef int /* Unknown procedure type */ (*U_fp)(...); +typedef shortint (*J_fp)(...); +typedef integer (*I_fp)(...); +typedef real (*R_fp)(...); +typedef doublereal (*D_fp)(...), (*E_fp)(...); +typedef /* Complex */ VOID (*C_fp)(...); +typedef /* Double Complex */ VOID (*Z_fp)(...); +typedef logical (*L_fp)(...); +typedef shortlogical (*K_fp)(...); +typedef /* Character */ VOID (*H_fp)(...); +typedef /* Subroutine */ int (*S_fp)(...); +#else +typedef int /* Unknown procedure type */ (*U_fp)(VOID); +typedef shortint (*J_fp)(VOID); +typedef integer (*I_fp)(VOID); +typedef real (*R_fp)(VOID); +typedef doublereal (*D_fp)(VOID), (*E_fp)(VOID); +typedef /* Complex */ VOID (*C_fp)(VOID); +typedef /* Double Complex */ VOID (*Z_fp)(VOID); +typedef logical (*L_fp)(VOID); +typedef shortlogical (*K_fp)(VOID); +typedef /* Character */ VOID (*H_fp)(VOID); +typedef /* Subroutine */ int (*S_fp)(VOID); +#endif +/* E_fp is for real functions when -R is not specified */ +typedef VOID C_f; /* complex function */ +typedef VOID H_f; /* character function */ +typedef VOID Z_f; /* double complex function */ +typedef doublereal E_f; /* real function with -R not specified */ + +/* undef any lower-case symbols that your C compiler predefines, e.g.: */ + +#ifndef Skip_f2c_Undefs +#undef cray +#undef gcos +#undef mc68010 +#undef mc68020 +#undef mips +#undef pdp11 +#undef sgi +#undef sparc +#undef sun +#undef sun2 +#undef sun3 +#undef sun4 +#undef u370 +#undef u3b +#undef u3b2 +#undef u3b5 +#undef unix +#undef vax +#endif + +#ifdef KR_headers +extern integer pow_ii(ap, bp); +extern double r_sign(a,b); +extern integer i_nint(x); +#else +extern integer pow_ii(integer *ap, integer *bp); +extern double r_sign(real *a, real *b); +extern integer i_nint(real *x); + +#endif +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int bsynz_(real *coef, integer *ip, integer *iv, + real *sout, real *rms, real *ratio, real *g2pass, + struct lpc10_decoder_state *st); +extern int chanwr_(integer *order, integer *ipitv, integer *irms, + integer *irc, integer *ibits, struct lpc10_encoder_state *st); +extern int chanrd_(integer *order, integer *ipitv, integer *irms, + integer *irc, integer *ibits); +extern int chanwr_0_(int n__, integer *order, integer *ipitv, + integer *irms, integer *irc, integer *ibits, + struct lpc10_encoder_state *st); +extern int dcbias_(integer *len, real *speech, real *sigout); +extern int decode_(integer *ipitv, integer *irms, integer *irc, + integer *voice, integer *pitch, real *rms, + real *rc, struct lpc10_decoder_state *st); +extern int deemp_(real *x, integer *n, struct lpc10_decoder_state *st); +extern int difmag_(real *speech, integer *lpita, integer *tau, integer *ltau, + integer *maxlag, real *amdf, integer *minptr, integer *maxptr); +extern int dyptrk_(real *amdf, integer *ltau, integer * + minptr, integer *voice, integer *pitch, integer *midx, + struct lpc10_encoder_state *st); +extern int encode_(integer *voice, integer *pitch, real *rms, real *rc, + integer *ipitch, integer *irms, integer *irc); +extern int energy_(integer *len, real *speech, real *rms); +extern int ham84_(integer *input, integer *output, integer *errcnt); +extern int hp100_(real *speech, integer *start, integer *end, + struct lpc10_encoder_state *st); +extern int inithp100_(void); +extern int invert_(integer *order, real *phi, real *psi, real *rc); +extern int irc2pc_(real *rc, real *pc, integer *order, real *gprime, real *g2pass); +extern int ivfilt_(real *lpbuf, real *ivbuf, integer *len, integer *nsamp, real *ivrc); +extern int lpcdec_(integer *bits, real *speech); +extern int initlpcdec_(void); +extern int lpcenc_(real *speech, integer *bits); +extern int initlpcenc_(void); +extern int lpfilt_(real *inbuf, real *lpbuf, integer *len, integer *nsamp); +extern integer median_(integer *d1, integer *d2, integer *d3); +extern int mload_(integer *order, integer *awins, integer *awinf, real *speech, real *phi, real *psi); +extern int onset_(real *pebuf, integer *osbuf, integer *osptr, integer *oslen, integer *sbufl, integer *sbufh, integer *lframe, struct lpc10_encoder_state *st); +extern int pitsyn_(integer *order, integer *voice, integer *pitch, real *rms, real *rc, integer *lframe, integer *ivuv, integer *ipiti, real *rmsi, real *rci, integer *nout, real *ratio, struct lpc10_decoder_state *st); +extern int placea_(integer *ipitch, integer *voibuf, integer *obound, integer *af, integer *vwin, integer *awin, integer *ewin, integer *lframe, integer *maxwin); +extern int placev_(integer *osbuf, integer *osptr, integer *oslen, integer *obound, integer *vwin, integer *af, integer *lframe, integer *minwin, integer *maxwin, integer *dvwinl, integer *dvwinh); +extern int preemp_(real *inbuf, real *pebuf, integer *nsamp, real *coef, real *z__); +extern int prepro_(real *speech, integer *length, + struct lpc10_encoder_state *st); +extern int decode_(integer *ipitv, integer *irms, integer *irc, integer *voice, integer *pitch, real *rms, real *rc, struct lpc10_decoder_state *st); +extern integer random_(struct lpc10_decoder_state *st); +extern int rcchk_(integer *order, real *rc1f, real *rc2f); +extern int synths_(integer *voice, integer *pitch, real *rms, real *rc, real *speech, integer *k, struct lpc10_decoder_state *st); +extern int tbdm_(real *speech, integer *lpita, integer *tau, integer *ltau, real *amdf, integer *minptr, integer *maxptr, integer *mintau); +extern int voicin_(integer *vwin, real *inbuf, real *lpbuf, integer *buflim, integer *half, real *minamd, real *maxamd, integer *mintau, real *ivrc, integer *obound, integer *voibuf, integer *af, struct lpc10_encoder_state *st); +extern int vparms_(integer *vwin, real *inbuf, real *lpbuf, integer *buflim, integer *half, real *dither, integer *mintau, integer *zc, integer *lbe, integer *fbe, real *qs, real *rc1, real *ar_b__, real *ar_f__); + +#endif + + +#endif /* ! defined F2C_INCLUDE */ diff --git a/codecs/lpc10/f2clib.c b/codecs/lpc10/f2clib.c new file mode 100644 index 000000000..037172828 --- /dev/null +++ b/codecs/lpc10/f2clib.c @@ -0,0 +1,85 @@ +/* + +$Log$ +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:10 jaf + * Initial revision + * + +*/ + +/* + * f2clib.c + * + * SCCS ID: @(#)f2clib.c 1.2 96/05/19 + */ + +#include "f2c.h" + +#ifdef KR_headers +integer pow_ii(ap, bp) integer *ap, *bp; +#else +integer pow_ii(integer *ap, integer *bp) +#endif +{ + integer pow, x, n; + unsigned long u; + + x = *ap; + n = *bp; + + if (n <= 0) { + if (n == 0 || x == 1) + return 1; + if (x != -1) + return x == 0 ? 0 : 1/x; + n = -n; + } + u = n; + for(pow = 1; ; ) + { + if(u & 01) + pow *= x; + if(u >>= 1) + x *= x; + else + break; + } + return(pow); + } + + + +#ifdef KR_headers +double r_sign(a,b) real *a, *b; +#else +double r_sign(real *a, real *b) +#endif +{ +double x; +x = (*a >= 0 ? *a : - *a); +return( *b >= 0 ? x : -x); +} + + + +#ifdef KR_headers +double floor(); +integer i_nint(x) real *x; +#else +#undef abs +#include "math.h" +integer i_nint(real *x) +#endif +{ +return( (integer)((*x)>=0 ? + floor(*x + .5) : -floor(.5 - *x)) ); +} diff --git a/codecs/lpc10/ham84.c b/codecs/lpc10/ham84.c new file mode 100644 index 000000000..fddd8f3c0 --- /dev/null +++ b/codecs/lpc10/ham84.c @@ -0,0 +1,126 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:07 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int ham84_(integer *input, integer *output, integer *errcnt); +#endif + +/* ***************************************************************** */ + +/* HAM84 Version 45G */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:32:07 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/21 15:26:00 jaf */ +/* Put comment header in standard form. */ + +/* Revision 1.2 1996/03/13 22:00:13 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:47:04 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Hamming 8,4 Decoder - can correct 1 out of seven bits */ +/* and can detect up to two errors. */ + +/* Input: */ +/* INPUT - Seven bit data word, 4 bits parameter and */ +/* 4 bits parity information */ +/* Input/Output: */ +/* ERRCNT - Sums errors detected by Hamming code */ +/* Output: */ +/* OUTPUT - 4 corrected parameter bits */ + +/* This subroutine is entered with an eight bit word in INPUT. The 8th */ +/* bit is parity and is stripped off. The remaining 7 bits address the */ +/* hamming 8,4 table and the output OUTPUT from the table gives the 4 */ +/* bits of corrected data. If bit 4 is set, no error was detected. */ +/* ERRCNT is the number of errors counted. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int ham84_(integer *input, integer *output, integer *errcnt) +{ + /* Initialized data */ + + static integer dactab[128] = { 16,0,0,3,0,5,14,7,0,9,14,11,14,13,30,14,0, + 9,2,7,4,7,7,23,9,25,10,9,12,9,14,7,0,5,2,11,5,21,6,5,8,11,11,27, + 12,5,14,11,2,1,18,2,12,5,2,7,12,9,2,11,28,12,12,15,0,3,3,19,4,13, + 6,3,8,13,10,3,13,29,14,13,4,1,10,3,20,4,4,7,10,9,26,10,4,13,10,15, + 8,1,6,3,6,5,22,6,24,8,8,11,8,13,6,15,1,17,2,1,4,1,6,15,8,1,10,15, + 12,15,15,31 }; + + integer i__, j, parity; + +/* Arguments */ +/* Parameters/constants */ +/* Local variables that need not be saved */ +/* Determine parity of input word */ + parity = *input & 255; + parity ^= parity / 16; + parity ^= parity / 4; + parity ^= parity / 2; + parity &= 1; + i__ = dactab[*input & 127]; + *output = i__ & 15; + j = i__ & 16; + if (j != 0) { +/* No errors detected in seven bits */ + if (parity != 0) { + ++(*errcnt); + } + } else { +/* One or two errors detected */ + ++(*errcnt); + if (parity == 0) { +/* Two errors detected */ + ++(*errcnt); + *output = -1; + } + } + return 0; +} /* ham84_ */ + diff --git a/codecs/lpc10/hp100.c b/codecs/lpc10/hp100.c new file mode 100644 index 000000000..9df9e5939 --- /dev/null +++ b/codecs/lpc10/hp100.c @@ -0,0 +1,169 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:28:05 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:32:04 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int hp100_(real *speech, integer *start, integer *end, + struct lpc10_encoder_state *st); +extern int inithp100_(void); +#endif + +/* ********************************************************************* */ + +/* HP100 Version 55 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:28:05 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:32:04 jaf + * Initial revision + * */ +/* Revision 1.6 1996/03/15 16:45:25 jaf */ +/* Rearranged a few comments. */ + +/* Revision 1.5 1996/03/14 23:20:54 jaf */ +/* Added comments about when INITHP100 should be used. */ + +/* Revision 1.4 1996/03/14 23:08:08 jaf */ +/* Added an entry named INITHP100 that initializes the local state of */ +/* subroutine HP100. */ + +/* Revision 1.3 1996/03/14 22:09:20 jaf */ +/* Comments added explaining which of the local variables of this */ +/* subroutine need to be saved from one invocation to the next, and which */ +/* do not. */ + +/* Revision 1.2 1996/02/12 15:05:54 jaf */ +/* Added lots of comments explaining why I changed one line, which was a */ +/* declaration with initializations. */ + +/* Revision 1.1 1996/02/07 14:47:12 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* 100 Hz High Pass Filter */ + +/* Jan 92 - corrected typo (1.937148 to 1.935715), */ +/* rounded coefficients to 7 places, */ +/* corrected and merged gain (.97466**4), */ +/* merged numerator into first two sections. */ + +/* Input: */ +/* start, end - Range of samples to filter */ +/* Input/Output: */ +/* speech(end) - Speech data. */ +/* Indices start through end are read and modified. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITHP100. */ +/* Subroutine */ int hp100_(real *speech, integer *start, integer *end, + struct lpc10_encoder_state *st) +{ + /* Temporary local copies of variables in lpc10_encoder_state. + I've only created these because it might cause the loop below + to execute a bit faster to access local variables, rather than + variables in the lpc10_encoder_state structure. It is just a + guess that it will be faster. */ + + real z11; + real z21; + real z12; + real z22; + + /* System generated locals */ + integer i__1; + + /* Local variables */ + integer i__; + real si, err; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Local state */ + /* Parameter adjustments */ + if (speech) { + --speech; + } + + /* Function Body */ + + z11 = st->z11; + z21 = st->z21; + z12 = st->z12; + z22 = st->z22; + + i__1 = *end; + for (i__ = *start; i__ <= i__1; ++i__) { + si = speech[i__]; + err = si + z11 * 1.859076f - z21 * .8648249f; + si = err - z11 * 2.f + z21; + z21 = z11; + z11 = err; + err = si + z12 * 1.935715f - z22 * .9417004f; + si = err - z12 * 2.f + z22; + z22 = z12; + z12 = err; + speech[i__] = si * .902428f; + } + + st->z11 = z11; + st->z21 = z21; + st->z12 = z12; + st->z22 = z22; + + return 0; +} /* hp100_ */ diff --git a/codecs/lpc10/invert.c b/codecs/lpc10/invert.c new file mode 100644 index 000000000..912117f9c --- /dev/null +++ b/codecs/lpc10/invert.c @@ -0,0 +1,193 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:00 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int invert_(integer *order, real *phi, real *psi, real *rc); +#endif + +/* **************************************************************** */ + +/* INVERT Version 45G */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:32:00 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/18 20:52:47 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:51:32 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Eliminated a comment from the original, describing a local array X */ +/* that appeared nowhere in the code. */ + +/* Revision 1.1 1996/02/07 14:47:20 jaf */ +/* Initial revision */ + + +/* **************************************************************** */ + +/* Invert a covariance matrix using Choleski decomposition method. */ + +/* Input: */ +/* ORDER - Analysis order */ +/* PHI(ORDER,ORDER) - Covariance matrix */ +/* Indices (I,J) read, where ORDER .GE. I .GE. J .GE. 1.*/ +/* All other indices untouched. */ +/* PSI(ORDER) - Column vector to be predicted */ +/* Indices 1 through ORDER read. */ +/* Output: */ +/* RC(ORDER) - Pseudo reflection coefficients */ +/* Indices 1 through ORDER written, and then possibly read. +*/ +/* Internal: */ +/* V(ORDER,ORDER) - Temporary matrix */ +/* Same indices written as read from PHI. */ +/* Many indices may be read and written again after */ +/* initially being copied from PHI, but all indices */ +/* are written before being read. */ + +/* NOTE: Temporary matrix V is not needed and may be replaced */ +/* by PHI if the original PHI values do not need to be preserved. */ + +/* Subroutine */ int invert_(integer *order, real *phi, real *psi, real *rc) +{ + /* System generated locals */ + integer phi_dim1, phi_offset, i__1, i__2, i__3; + real r__1, r__2; + + /* Local variables */ + real save; + integer i__, j, k; + real v[100] /* was [10][10] */; + +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:32:00 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Parameters/constants */ +/* Local variables that need not be saved */ +/* Decompose PHI into V * D * V' where V is a triangular matrix whose */ +/* main diagonal elements are all 1, V' is the transpose of V, and */ +/* D is a vector. Here D(n) is stored in location V(n,n). */ + /* Parameter adjustments */ + --rc; + --psi; + phi_dim1 = *order; + phi_offset = phi_dim1 + 1; + phi -= phi_offset; + + /* Function Body */ + i__1 = *order; + for (j = 1; j <= i__1; ++j) { + i__2 = *order; + for (i__ = j; i__ <= i__2; ++i__) { + v[i__ + j * 10 - 11] = phi[i__ + j * phi_dim1]; + } + i__2 = j - 1; + for (k = 1; k <= i__2; ++k) { + save = v[j + k * 10 - 11] * v[k + k * 10 - 11]; + i__3 = *order; + for (i__ = j; i__ <= i__3; ++i__) { + v[i__ + j * 10 - 11] -= v[i__ + k * 10 - 11] * save; + } + } +/* Compute intermediate results, which are similar to RC's */ + if ((r__1 = v[j + j * 10 - 11], abs(r__1)) < 1e-10f) { + goto L100; + } + rc[j] = psi[j]; + i__2 = j - 1; + for (k = 1; k <= i__2; ++k) { + rc[j] -= rc[k] * v[j + k * 10 - 11]; + } + v[j + j * 10 - 11] = 1.f / v[j + j * 10 - 11]; + rc[j] *= v[j + j * 10 - 11]; +/* Computing MAX */ +/* Computing MIN */ + r__2 = rc[j]; + r__1 = min(r__2,.999f); + rc[j] = max(r__1,-.999f); + } + return 0; +/* Zero out higher order RC's if algorithm terminated early */ +L100: + i__1 = *order; + for (i__ = j; i__ <= i__1; ++i__) { + rc[i__] = 0.f; + } +/* Back substitute for PC's (if needed) */ +/* 110 DO J = ORDER,1,-1 */ +/* PC(J) = RC(J) */ +/* DO I = 1,J-1 */ +/* PC(J) = PC(J) - PC(I)*V(J,I) */ +/* END DO */ +/* END DO */ + return 0; +} /* invert_ */ + diff --git a/codecs/lpc10/irc2pc.c b/codecs/lpc10/irc2pc.c new file mode 100644 index 000000000..b96ff0d66 --- /dev/null +++ b/codecs/lpc10/irc2pc.c @@ -0,0 +1,151 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:56 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int irc2pc_(real *rc, real *pc, integer *order, real *gprime, real *g2pass); +#endif + +/* ***************************************************************** */ + +/* IRC2PC Version 48 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:31:56 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/20 15:47:19 jaf */ +/* Added comments about which indices of array arguments are read or */ +/* written. */ + +/* Revision 1.2 1996/03/14 16:59:04 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:47:27 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Convert Reflection Coefficients to Predictor Coeficients */ + +/* Inputs: */ +/* RC - Reflection coefficients */ +/* Indices 1 through ORDER read. */ +/* ORDER - Number of RC's */ +/* GPRIME - Excitation modification gain */ +/* Outputs: */ +/* PC - Predictor coefficients */ +/* Indices 1 through ORDER written. */ +/* Indices 1 through ORDER-1 are read after being written. */ +/* G2PASS - Excitation modification sharpening factor */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int irc2pc_(real *rc, real *pc, integer *order, real *gprime, + real *g2pass) +{ + /* System generated locals */ + integer i__1, i__2; + + /* Builtin functions */ + double sqrt(doublereal); + + /* Local variables */ + real temp[10]; + integer i__, j; + +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:31:56 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + --pc; + --rc; + + /* Function Body */ + *g2pass = 1.f; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + *g2pass *= 1.f - rc[i__] * rc[i__]; + } + *g2pass = *gprime * (real)sqrt(*g2pass); + pc[1] = rc[1]; + i__1 = *order; + for (i__ = 2; i__ <= i__1; ++i__) { + i__2 = i__ - 1; + for (j = 1; j <= i__2; ++j) { + temp[j - 1] = pc[j] - rc[i__] * pc[i__ - j]; + } + i__2 = i__ - 1; + for (j = 1; j <= i__2; ++j) { + pc[j] = temp[j - 1]; + } + pc[i__] = rc[i__]; + } + return 0; +} /* irc2pc_ */ + diff --git a/codecs/lpc10/ivfilt.c b/codecs/lpc10/ivfilt.c new file mode 100644 index 000000000..784de2571 --- /dev/null +++ b/codecs/lpc10/ivfilt.c @@ -0,0 +1,136 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.2 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:53 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int ivfilt_(real *lpbuf, real *ivbuf, integer *len, integer *nsamp, real *ivrc); +#endif + +/* ********************************************************************* */ + +/* IVFILT Version 48 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.2 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:31:53 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/15 21:36:29 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 00:01:00 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:47:34 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* 2nd order inverse filter, speech is decimated 4:1 */ + +/* Input: */ +/* LEN - Length of speech buffers */ +/* NSAMP - Number of samples to filter */ +/* LPBUF - Low pass filtered speech buffer */ +/* Indices LEN-NSAMP-7 through LEN read. */ +/* Output: */ +/* IVBUF - Inverse filtered speech buffer */ +/* Indices LEN-NSAMP+1 through LEN written. */ +/* IVRC - Inverse filter reflection coefficients (for voicing) */ +/* Indices 1 and 2 both written (also read, but only after writing). +*/ + +/* This subroutine has no local state. */ + +/* Subroutine */ int ivfilt_(real *lpbuf, real *ivbuf, integer *len, integer * + nsamp, real *ivrc) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + integer i__, j, k; + real r__[3], pc1, pc2; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Local state */ +/* None */ +/* Calculate Autocorrelations */ + /* Parameter adjustments */ + --ivbuf; + --lpbuf; + --ivrc; + + /* Function Body */ + for (i__ = 1; i__ <= 3; ++i__) { + r__[i__ - 1] = 0.f; + k = (i__ - 1) << 2; + i__1 = *len; + for (j = (i__ << 2) + *len - *nsamp; j <= i__1; j += 2) { + r__[i__ - 1] += lpbuf[j] * lpbuf[j - k]; + } + } +/* Calculate predictor coefficients */ + pc1 = 0.f; + pc2 = 0.f; + ivrc[1] = 0.f; + ivrc[2] = 0.f; + if (r__[0] > 1e-10f) { + ivrc[1] = r__[1] / r__[0]; + ivrc[2] = (r__[2] - ivrc[1] * r__[1]) / (r__[0] - ivrc[1] * r__[1]); + pc1 = ivrc[1] - ivrc[1] * ivrc[2]; + pc2 = ivrc[2]; + } +/* Inverse filter LPBUF into IVBUF */ + i__1 = *len; + for (i__ = *len + 1 - *nsamp; i__ <= i__1; ++i__) { + ivbuf[i__] = lpbuf[i__] - pc1 * lpbuf[i__ - 4] - pc2 * lpbuf[i__ - 8]; + } + return 0; +} /* ivfilt_ */ + diff --git a/codecs/lpc10/liblpc10.vcproj b/codecs/lpc10/liblpc10.vcproj new file mode 100644 index 000000000..a2449a109 --- /dev/null +++ b/codecs/lpc10/liblpc10.vcproj @@ -0,0 +1,305 @@ +<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="liblpc10" + ProjectGUID="{FF1D238A-9D59-4850-838E-78182E05736B}" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="4" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="WIN32;_DEBUG;_LIB;P_R_O_T_O_T_Y_P_E_S" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="4" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + PreprocessorDefinitions="WIN32;NDEBUG;_LIB;P_R_O_T_O_T_Y_P_E_S" + RuntimeLibrary="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath=".\f2c.h" + > + </File> + <File + RelativePath=".\lpc10.h" + > + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + </Filter> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath=".\analys.c" + > + </File> + <File + RelativePath=".\bsynz.c" + > + </File> + <File + RelativePath=".\chanwr.c" + > + </File> + <File + RelativePath=".\dcbias.c" + > + </File> + <File + RelativePath=".\decode.c" + > + </File> + <File + RelativePath=".\deemp.c" + > + </File> + <File + RelativePath=".\difmag.c" + > + </File> + <File + RelativePath=".\dyptrk.c" + > + </File> + <File + RelativePath=".\encode.c" + > + </File> + <File + RelativePath=".\energy.c" + > + </File> + <File + RelativePath=".\f2clib.c" + > + </File> + <File + RelativePath=".\ham84.c" + > + </File> + <File + RelativePath=".\hp100.c" + > + </File> + <File + RelativePath=".\invert.c" + > + </File> + <File + RelativePath=".\irc2pc.c" + > + </File> + <File + RelativePath=".\ivfilt.c" + > + </File> + <File + RelativePath=".\lpcdec.c" + > + </File> + <File + RelativePath=".\lpcenc.c" + > + </File> + <File + RelativePath=".\lpcini.c" + > + </File> + <File + RelativePath=".\lpfilt.c" + > + </File> + <File + RelativePath=".\median.c" + > + </File> + <File + RelativePath=".\mload.c" + > + </File> + <File + RelativePath=".\onset.c" + > + </File> + <File + RelativePath=".\pitsyn.c" + > + </File> + <File + RelativePath=".\placea.c" + > + </File> + <File + RelativePath=".\placev.c" + > + </File> + <File + RelativePath=".\preemp.c" + > + </File> + <File + RelativePath=".\prepro.c" + > + </File> + <File + RelativePath=".\random.c" + > + </File> + <File + RelativePath=".\rcchk.c" + > + </File> + <File + RelativePath=".\synths.c" + > + </File> + <File + RelativePath=".\tbdm.c" + > + </File> + <File + RelativePath=".\voicin.c" + > + </File> + <File + RelativePath=".\vparms.c" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/codecs/lpc10/lpc10.h b/codecs/lpc10/lpc10.h new file mode 100644 index 000000000..a57f84f3f --- /dev/null +++ b/codecs/lpc10/lpc10.h @@ -0,0 +1,256 @@ +/* + +$Log$ +Revision 1.18 2004/08/31 13:32:11 markster +Merge NetBSD and Courtesty tone with modifications (bug #2329) + +Revision 1.17 2003/10/26 18:50:49 markster +Make it build and run on MacOS X + +Revision 1.3 2003/10/26 18:50:49 markster +Make it build and run on MacOS X + +Revision 1.2 2003/04/23 19:13:35 markster +More OpenBSD patches + +Revision 1.1.1.2 2003/03/16 22:37:30 matteo +dom mar 16 23:37:23 CET 2003 + +Revision 1.2 2003/03/16 16:09:48 markster +Mere James's cleanups for fewer build warnings + +Revision 1.1 2000/01/05 00:20:06 markster +Add broken lpc10 code... It's not too far from working I don't think... + + * Revision 1.1 1996/08/19 22:47:31 jaf + * Initial revision + * + +*/ + +#ifndef __LPC10_H__ +#define __LPC10_H__ + +#define P_R_O_T_O_T_Y_P_E_S + +#define LPC10_SAMPLES_PER_FRAME 180 +#define LPC10_BITS_IN_COMPRESSED_FRAME 54 + + +/* + + The "#if defined"'s in this file are by no means intended to be + complete. They are what Nautilus uses, which has been successfully + compiled under DOS with the Microsoft C compiler, and under a few + versions of Unix with the GNU C compiler. + + */ + +#if defined(unix) || defined(__unix__) || defined(__NetBSD__) +typedef short INT16; +typedef int INT32; +#endif + + +#if defined(__MSDOS__) || defined(MSDOS) +typedef int INT16; +typedef long INT32; +#endif + +#if defined(__APPLE__) +typedef short INT16; +typedef int INT32; +#endif + +#if defined(WIN32) && defined(_MSC_VER) +typedef __int16 INT16; +typedef __int32 INT32; +#pragma warning(disable: 4005) +#endif + + +/* The initial values for every member of this structure is 0, except + where noted in comments. */ + +/* These two lines are copied from f2c.h. There should be a more + elegant way of doing this than having the same declarations in two + files. */ + +typedef float real; +typedef INT32 integer; +typedef INT32 logical; +typedef INT16 shortint; + +struct lpc10_encoder_state { + /* State used only by function hp100 */ + real z11; + real z21; + real z12; + real z22; + + /* State used by function analys */ + real inbuf[540], pebuf[540]; + real lpbuf[696], ivbuf[312]; + real bias; + integer osbuf[10]; /* no initial value necessary */ + integer osptr; /* initial value 1 */ + integer obound[3]; + integer vwin[6] /* was [2][3] */; /* initial value vwin[4] = 307; vwin[5] = 462; */ + integer awin[6] /* was [2][3] */; /* initial value awin[4] = 307; awin[5] = 462; */ + integer voibuf[8] /* was [2][4] */; + real rmsbuf[3]; + real rcbuf[30] /* was [10][3] */; + real zpre; + + + /* State used by function onset */ + real n; + real d__; /* initial value 1.f */ + real fpc; /* no initial value necessary */ + real l2buf[16]; + real l2sum1; + integer l2ptr1; /* initial value 1 */ + integer l2ptr2; /* initial value 9 */ + integer lasti; /* no initial value necessary */ + logical hyst; /* initial value FALSE_ */ + + /* State used by function voicin */ + real dither; /* initial value 20.f */ + real snr; + real maxmin; + real voice[6] /* was [2][3] */; /* initial value is probably unnecessary */ + integer lbve, lbue, fbve, fbue; + integer ofbue, sfbue; + integer olbue, slbue; + /* Initial values: + lbve = 3000; + fbve = 3000; + fbue = 187; + ofbue = 187; + sfbue = 187; + lbue = 93; + olbue = 93; + slbue = 93; + snr = (real) (fbve / fbue << 6); + */ + + /* State used by function dyptrk */ + real s[60]; + integer p[120] /* was [60][2] */; + integer ipoint; + real alphax; + + /* State used by function chanwr */ + integer isync; + +}; + + +struct lpc10_decoder_state { + + /* State used by function decode */ + integer iptold; /* initial value 60 */ + logical first; /* initial value TRUE_ */ + integer ivp2h; + integer iovoic; + integer iavgp; /* initial value 60 */ + integer erate; + integer drc[30] /* was [3][10] */; + integer dpit[3]; + integer drms[3]; + + /* State used by function synths */ + real buf[360]; + integer buflen; /* initial value 180 */ + + /* State used by function pitsyn */ + integer ivoico; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + integer ipito; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + real rmso; /* initial value 1.f */ + real rco[10]; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + integer jsamp; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + logical first_pitsyn; /* initial value TRUE_ */ + + /* State used by function bsynz */ + integer ipo; + real exc[166]; + real exc2[166]; + real lpi1; + real lpi2; + real lpi3; + real hpi1; + real hpi2; + real hpi3; + real rmso_bsynz; + + /* State used by function random */ + integer j; /* initial value 2 */ + integer k; /* initial value 5 */ + shortint y[5]; /* initial value { -21161,-8478,30892,-10216,16950 } */ + + /* State used by function deemp */ + real dei1; + real dei2; + real deo1; + real deo2; + real deo3; + +}; + + + +/* + + Calling sequence: + + Call create_lpc10_encoder_state(), which returns a pointer to an + already initialized lpc10_encoder_state structure. + + lpc10_encode reads indices 0 through (LPC10_SAMPLES_PER_FRAME-1) of + array speech[], and writes indices 0 through + (LPC10_BITS_IN_COMPRESSED_FRAME-1) of array bits[], and both reads + and writes the lpc10_encoder_state structure contents. The + lpc10_encoder_state structure should *not* be initialized for every + frame of encoded speech. Once at the beginning of execution, done + automatically for you by create_lpc10_encoder_state(), is enough. + + init_lpc10_encoder_state() reinitializes the lpc10_encoder_state + structure. This might be useful if you are finished processing one + sound sample, and want to reuse the same lpc10_encoder_state + structure to process another sound sample. There might be other + uses as well. + + Note that the comments in the lpc10/lpcenc.c file imply that indices + 1 through 180 of array speech[] are read. These comments were + written for the Fortran version of the code, before it was + automatically converted to C by the conversion program f2c. f2c + seems to use the convention that the pointers to arrays passed as + function arguments point to the first index used in the Fortran + code, whatever index that might be (usually 1), and then it modifies + the pointer inside of the function, like so: + + if (speech) { + --speech; + } + + So that the code can access the first value at index 1 and the last + at index 180. This makes the translated C code "closer" to the + original Fortran code. + + The calling sequence for the decoder is similar to the encoder. The + only significant difference is that the array bits[] is read + (indices 0 through (LPC10_BITS_IN_COMPRESSED_FRAME-1)), and the + array speech[] is written (indices 0 through + (LPC10_SAMPLES_PER_FRAME-1)). + + */ + +struct lpc10_encoder_state * create_lpc10_encoder_state (void); +void init_lpc10_encoder_state (struct lpc10_encoder_state *st); +int lpc10_encode (real *speech, INT32 *bits, struct lpc10_encoder_state *st); + +struct lpc10_decoder_state * create_lpc10_decoder_state (void); +void init_lpc10_decoder_state (struct lpc10_decoder_state *st); +int lpc10_decode (INT32 *bits, real *speech, struct lpc10_decoder_state *st); + +#endif /* __LPC10_H__ */ diff --git a/codecs/lpc10/lpcdec.c b/codecs/lpc10/lpcdec.c new file mode 100644 index 000000000..dd859ffce --- /dev/null +++ b/codecs/lpc10/lpcdec.c @@ -0,0 +1,297 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:30:11 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:48 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int lpcdec_(integer *bits, real *speech); +extern int initlpcdec_(void); +/* comlen contrl_ 12 */ +/*:ref: chanrd_ 14 5 4 4 4 4 4 */ +/*:ref: decode_ 14 7 4 4 4 4 4 6 6 */ +/*:ref: synths_ 14 6 4 4 6 6 6 4 */ +/*:ref: initdecode_ 14 0 */ +/*:ref: initsynths_ 14 0 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* Table of constant values */ + +static integer c__10 = 10; + +/* ***************************************************************** */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:30:11 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:48 jaf + * Initial revision + * */ +/* Revision 1.1 1996/03/28 00:03:00 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Decode 54 bits to one frame of 180 speech samples. */ + +/* Input: */ +/* BITS - 54 encoded bits, stored 1 per array element. */ +/* Indices 1 through 53 read (SYNC bit ignored). */ +/* Output: */ +/* SPEECH - Speech encoded as real values in the range [-1,+1]. */ +/* Indices 1 through 180 written. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITLPCDEC. */ + +/* Subroutine */ int lpc10_decode(integer *bits, real *speech, + struct lpc10_decoder_state *st) +{ + integer irms, voice[2], pitch, ipitv; + extern /* Subroutine */ int decode_(integer *, integer *, integer *, + integer *, integer *, real *, real *, struct lpc10_decoder_state *); + real rc[10]; + extern /* Subroutine */ int chanrd_(integer *, integer *, integer *, + integer *, integer *), synths_(integer *, + integer *, real *, real *, real *, integer *, + struct lpc10_decoder_state *); + integer irc[10], len; + real rms; + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:30:11 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:48 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:30:11 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:48 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Local variables that need not be saved */ +/* Uncoded speech parameters */ +/* Coded speech parameters */ +/* Others */ +/* Local state */ +/* None */ + /* Parameter adjustments */ + if (bits) { + --bits; + } + if (speech) { + --speech; + } + + /* Function Body */ + + chanrd_(&c__10, &ipitv, &irms, irc, &bits[1]); + decode_(&ipitv, &irms, irc, voice, &pitch, &rms, rc, st); + synths_(voice, &pitch, &rms, rc, &speech[1], &len, st); + return 0; +} /* lpcdec_ */ diff --git a/codecs/lpc10/lpcenc.c b/codecs/lpc10/lpcenc.c new file mode 100644 index 000000000..989a2defd --- /dev/null +++ b/codecs/lpc10/lpcenc.c @@ -0,0 +1,181 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:31:21 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:44 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int lpcenc_(real *speech, integer *bits); +extern int initlpcenc_(void); +/*:ref: prepro_ 14 2 6 4 */ +/*:ref: analys_ 14 5 6 4 4 6 6 */ +/*:ref: encode_ 14 7 4 4 6 6 4 4 4 */ +/*:ref: chanwr_ 14 5 4 4 4 4 4 */ +/*:ref: initprepro_ 14 0 */ +/*:ref: initanalys_ 14 0 */ +#endif + +/* Table of constant values */ + +static integer c__180 = 180; +static integer c__10 = 10; + +/* ***************************************************************** */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:31:21 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:44 jaf + * Initial revision + * */ +/* Revision 1.2 1996/03/28 00:01:22 jaf */ +/* Commented out some trace statements. */ + +/* Revision 1.1 1996/03/28 00:00:27 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Encode one frame of 180 speech samples to 54 bits. */ + +/* Input: */ +/* SPEECH - Speech encoded as real values in the range [-1,+1]. */ +/* Indices 1 through 180 read, and modified (by PREPRO). */ +/* Output: */ +/* BITS - 54 encoded bits, stored 1 per array element. */ +/* Indices 1 through 54 written. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITLPCENC. */ + +/* Subroutine */ int lpc10_encode(real *speech, integer *bits, + struct lpc10_encoder_state *st) +{ + integer irms, voice[2], pitch, ipitv; + real rc[10]; + extern /* Subroutine */ int encode_(integer *, integer *, real *, real *, + integer *, integer *, integer *), chanwr_(integer *, integer *, + integer *, integer *, integer *, struct lpc10_encoder_state *), + analys_(real *, integer *, + integer *, real *, real *, struct lpc10_encoder_state *), + prepro_(real *, integer *, struct lpc10_encoder_state *); + integer irc[10]; + real rms; + +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:31:21 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:44 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Local variables that need not be saved */ +/* Uncoded speech parameters */ +/* Coded speech parameters */ +/* Local state */ +/* None */ + /* Parameter adjustments */ + if (speech) { + --speech; + } + if (bits) { + --bits; + } + + /* Function Body */ + prepro_(&speech[1], &c__180, st); + analys_(&speech[1], voice, &pitch, &rms, rc, st); + encode_(voice, &pitch, &rms, rc, &ipitv, &irms, irc); + chanwr_(&c__10, &ipitv, &irms, irc, &bits[1], st); + return 0; +} /* lpcenc_ */ diff --git a/codecs/lpc10/lpcini.c b/codecs/lpc10/lpcini.c new file mode 100644 index 000000000..ebe229a5c --- /dev/null +++ b/codecs/lpc10/lpcini.c @@ -0,0 +1,446 @@ +/* + +$Log$ +Revision 1.18 2003/10/21 18:08:11 markster +Fix include order + +Revision 1.5 2003/10/21 18:08:11 markster +Fix include order + +Revision 1.4 2003/10/21 02:57:29 markster +FreeBSD patch, take 2 + +Revision 1.3 2003/10/16 21:11:30 martinp +Revert the previous patch since it's braking compilation + +Revision 1.1 2003/02/12 13:59:15 matteo +Initial revision + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:35:41 jaf + * Added functions for allocating and initializing lpc10_encoder_state + * and lpc10_decoder_state structures. + * + * Revision 1.1 1996/08/19 22:31:40 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include <stdlib.h> +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int lpcini_(void); +/* comlen contrl_ 12 */ +/*:ref: initlpcenc_ 14 0 */ +/*:ref: initlpcdec_ 14 0 */ +#endif + +/* Common Block Declarations */ + +struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* ***************************************************************** */ + +/* $Log$ + * Revision 1.18 2003/10/21 18:08:11 markster + * Fix include order + * + * Revision 1.5 2003/10/21 18:08:11 markster + * Fix include order + * + * Revision 1.4 2003/10/21 02:57:29 markster + * FreeBSD patch, take 2 + * + * Revision 1.3 2003/10/16 21:11:30 martinp + * Revert the previous patch since it's braking compilation + * + * Revision 1.1 2003/02/12 13:59:15 matteo + * Initial revision + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:35:41 jaf + * Added functions for allocating and initializing lpc10_encoder_state + * and lpc10_decoder_state structures. + * + * Revision 1.1 1996/08/19 22:31:40 jaf + * Initial revision + * */ +/* Revision 1.1 1996/03/28 00:04:05 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Initialize COMMON block variables used by LPC-10 encoder and decoder, */ +/* and call initialization routines for both of them. */ + +/* Subroutine */ int lpcini_(void) +{ + +/* $Log$ + * Revision 1.18 2003/10/21 18:08:11 markster + * Fix include order + * + * Revision 1.5 2003/10/21 18:08:11 markster + * Fix include order + * + * Revision 1.4 2003/10/21 02:57:29 markster + * FreeBSD patch, take 2 + * + * Revision 1.3 2003/10/16 21:11:30 martinp + * Revert the previous patch since it's braking compilation + * + * Revision 1.1 2003/02/12 13:59:15 matteo + * Initial revision + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:35:41 jaf + * Added functions for allocating and initializing lpc10_encoder_state + * and lpc10_decoder_state structures. + * + * Revision 1.1 1996/08/19 22:31:40 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* $Log$ + * Revision 1.18 2003/10/21 18:08:11 markster + * Fix include order + * + * Revision 1.5 2003/10/21 18:08:11 markster + * Fix include order + * + * Revision 1.4 2003/10/21 02:57:29 markster + * FreeBSD patch, take 2 + * + * Revision 1.3 2003/10/16 21:11:30 martinp + * Revert the previous patch since it's braking compilation + * + * Revision 1.1 2003/02/12 13:59:15 matteo + * Initial revision + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:35:41 jaf + * Added functions for allocating and initializing lpc10_encoder_state + * and lpc10_decoder_state structures. + * + * Revision 1.1 1996/08/19 22:31:40 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ + contrl_1.order = 10; + contrl_1.lframe = 180; + contrl_1.corrp = TRUE_; + return 0; +} /* lpcini_ */ + + + +/* Allocate memory for, and initialize, the state that needs to be + kept from encoding one frame to the next for a single + LPC-10-compressed audio stream. Return 0 if malloc fails, + otherwise return pointer to new structure. */ + +struct lpc10_encoder_state * +create_lpc10_encoder_state() +{ + struct lpc10_encoder_state *st; + + st = (struct lpc10_encoder_state *) + malloc((unsigned) sizeof (struct lpc10_encoder_state)); + if (st != 0) { + init_lpc10_encoder_state(st); + } + return (st); +} + + + +void init_lpc10_encoder_state(struct lpc10_encoder_state *st) +{ + int i; + + lpcini_(); + + /* State used only by function hp100 */ + st->z11 = 0.0f; + st->z21 = 0.0f; + st->z12 = 0.0f; + st->z22 = 0.0f; + + /* State used by function analys */ + for (i = 0; i < 540; i++) { + st->inbuf[i] = 0.0f; + st->pebuf[i] = 0.0f; + } + for (i = 0; i < 696; i++) { + st->lpbuf[i] = 0.0f; + } + for (i = 0; i < 312; i++) { + st->ivbuf[i] = 0.0f; + } + st->bias = 0.0f; + /* integer osbuf[10]; */ /* no initial value necessary */ + st->osptr = 1; + for (i = 0; i < 3; i++) { + st->obound[i] = 0; + } + st->vwin[4] = 307; + st->vwin[5] = 462; + st->awin[4] = 307; + st->awin[5] = 462; + for (i = 0; i < 8; i++) { + st->voibuf[i] = 0; + } + for (i = 0; i < 3; i++) { + st->rmsbuf[i] = 0.0f; + } + for (i = 0; i < 30; i++) { + st->rcbuf[i] = 0.0f; + } + st->zpre = 0.0f; + + + /* State used by function onset */ + st->n = 0.0f; + st->d__ = 1.0f; + /* real fpc; */ /* no initial value necessary */ + for (i = 0; i < 16; i++) { + st->l2buf[i] = 0.0f; + } + st->l2sum1 = 0.0f; + st->l2ptr1 = 1; + st->l2ptr2 = 9; + /* integer lasti; */ /* no initial value necessary */ + st->hyst = FALSE_; + + /* State used by function voicin */ + st->dither = 20.0f; + st->maxmin = 0.0f; + for (i = 0; i < 6; i++) { + st->voice[i] = 0.0f; + } + st->lbve = 3000; + st->fbve = 3000; + st->fbue = 187; + st->ofbue = 187; + st->sfbue = 187; + st->lbue = 93; + st->olbue = 93; + st->slbue = 93; + st->snr = (real) (st->fbve / st->fbue << 6); + + /* State used by function dyptrk */ + for (i = 0; i < 60; i++) { + st->s[i] = 0.0f; + } + for (i = 0; i < 120; i++) { + st->p[i] = 0; + } + st->ipoint = 0; + st->alphax = 0.0f; + + /* State used by function chanwr */ + st->isync = 0; + +} + + + +/* Allocate memory for, and initialize, the state that needs to be + kept from decoding one frame to the next for a single + LPC-10-compressed audio stream. Return 0 if malloc fails, + otherwise return pointer to new structure. */ + +struct lpc10_decoder_state * +create_lpc10_decoder_state() +{ + struct lpc10_decoder_state *st; + + st = (struct lpc10_decoder_state *) + malloc((unsigned) sizeof (struct lpc10_decoder_state)); + if (st != 0) { + init_lpc10_decoder_state(st); + } + return (st); +} + + + +void init_lpc10_decoder_state(struct lpc10_decoder_state *st) +{ + int i; + + lpcini_(); + + /* State used by function decode */ + st->iptold = 60; + st->first = TRUE_; + st->ivp2h = 0; + st->iovoic = 0; + st->iavgp = 60; + st->erate = 0; + for (i = 0; i < 30; i++) { + st->drc[i] = 0; + } + for (i = 0; i < 3; i++) { + st->dpit[i] = 0; + st->drms[i] = 0; + } + + /* State used by function synths */ + for (i = 0; i < 360; i++) { + st->buf[i] = 0.0f; + } + st->buflen = 180; + + /* State used by function pitsyn */ + /* ivoico; */ /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + /* ipito; */ /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + st->rmso = 1.0f; + /* rco[10]; */ /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + /* integer jsamp; */ /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + st->first_pitsyn = TRUE_; + + /* State used by function bsynz */ + st->ipo = 0; + for (i = 0; i < 166; i++) { + st->exc[i] = 0.0f; + st->exc2[i] = 0.0f; + } + st->lpi1 = 0.0f; + st->lpi2 = 0.0f; + st->lpi3 = 0.0f; + st->hpi1 = 0.0f; + st->hpi2 = 0.0f; + st->hpi3 = 0.0f; + st->rmso_bsynz = 0.0f; + + /* State used by function random */ + st->j = 2; + st->k = 5; + st->y[0] = (shortint) -21161; + st->y[1] = (shortint) -8478; + st->y[2] = (shortint) 30892; + st->y[3] = (shortint) -10216; + st->y[4] = (shortint) 16950; + + /* State used by function deemp */ + st->dei1 = 0.0f; + st->dei2 = 0.0f; + st->deo1 = 0.0f; + st->deo2 = 0.0f; + st->deo3 = 0.0f; +} diff --git a/codecs/lpc10/lpfilt.c b/codecs/lpc10/lpfilt.c new file mode 100644 index 000000000..375528921 --- /dev/null +++ b/codecs/lpc10/lpfilt.c @@ -0,0 +1,125 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:35 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int lpfilt_(real *inbuf, real *lpbuf, integer *len, integer *nsamp); +#endif + +/* *********************************************************************** */ + +/* LPFILT Version 55 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:31:35 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/15 16:53:49 jaf */ +/* Just put comment header in standard form. */ + +/* Revision 1.2 1996/03/12 23:58:06 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:47:44 jaf */ +/* Initial revision */ + + +/* *********************************************************************** */ + +/* 31 Point Equiripple FIR Low-Pass Filter */ +/* Linear phase, delay = 15 samples */ + +/* Passband: ripple = 0.25 dB, cutoff = 800 Hz */ +/* Stopband: atten. = 40. dB, cutoff = 1240 Hz */ + +/* Inputs: */ +/* LEN - Length of speech buffers */ +/* NSAMP - Number of samples to filter */ +/* INBUF - Input speech buffer */ +/* Indices len-nsamp-29 through len are read. */ +/* Output: */ +/* LPBUF - Low passed speech buffer (must be different array than INBUF) */ +/* Indices len+1-nsamp through len are written. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int lpfilt_(real *inbuf, real *lpbuf, integer *len, integer * + nsamp) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + integer j; + real t; + +/* Arguments */ +/* Parameters/constants */ +/* Local variables that need not be saved */ +/* Local state */ +/* None */ + /* Parameter adjustments */ + --lpbuf; + --inbuf; + + /* Function Body */ + i__1 = *len; + for (j = *len + 1 - *nsamp; j <= i__1; ++j) { + t = (inbuf[j] + inbuf[j - 30]) * -.0097201988f; + t += (inbuf[j - 1] + inbuf[j - 29]) * -.0105179986f; + t += (inbuf[j - 2] + inbuf[j - 28]) * -.0083479648f; + t += (inbuf[j - 3] + inbuf[j - 27]) * 5.860774e-4f; + t += (inbuf[j - 4] + inbuf[j - 26]) * .0130892089f; + t += (inbuf[j - 5] + inbuf[j - 25]) * .0217052232f; + t += (inbuf[j - 6] + inbuf[j - 24]) * .0184161253f; + t += (inbuf[j - 7] + inbuf[j - 23]) * 3.39723e-4f; + t += (inbuf[j - 8] + inbuf[j - 22]) * -.0260797087f; + t += (inbuf[j - 9] + inbuf[j - 21]) * -.0455563702f; + t += (inbuf[j - 10] + inbuf[j - 20]) * -.040306855f; + t += (inbuf[j - 11] + inbuf[j - 19]) * 5.029835e-4f; + t += (inbuf[j - 12] + inbuf[j - 18]) * .0729262903f; + t += (inbuf[j - 13] + inbuf[j - 17]) * .1572008878f; + t += (inbuf[j - 14] + inbuf[j - 16]) * .2247288674f; + t += inbuf[j - 15] * .250535965f; + lpbuf[j] = t; + } + return 0; +} /* lpfilt_ */ + diff --git a/codecs/lpc10/median.c b/codecs/lpc10/median.c new file mode 100644 index 000000000..383c46e89 --- /dev/null +++ b/codecs/lpc10/median.c @@ -0,0 +1,89 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:31 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern integer median_(integer *d1, integer *d2, integer *d3); +#endif + +/* ********************************************************************* */ + +/* MEDIAN Version 45G */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:31:31 jaf + * Initial revision + * */ +/* Revision 1.2 1996/03/14 22:30:22 jaf */ +/* Just rearranged the comments and local variable declarations a bit. */ + +/* Revision 1.1 1996/02/07 14:47:53 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Find median of three values */ + +/* Input: */ +/* D1,D2,D3 - Three input values */ +/* Output: */ +/* MEDIAN - Median value */ + +integer median_(integer *d1, integer *d2, integer *d3) +{ + /* System generated locals */ + integer ret_val; + +/* Arguments */ + ret_val = *d2; + if (*d2 > *d1 && *d2 > *d3) { + ret_val = *d1; + if (*d3 > *d1) { + ret_val = *d3; + } + } else if (*d2 < *d1 && *d2 < *d3) { + ret_val = *d1; + if (*d3 < *d1) { + ret_val = *d3; + } + } + return ret_val; +} /* median_ */ + diff --git a/codecs/lpc10/mload.c b/codecs/lpc10/mload.c new file mode 100644 index 000000000..1cdb0647c --- /dev/null +++ b/codecs/lpc10/mload.c @@ -0,0 +1,163 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:25 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int mload_(integer *order, integer *awins, integer *awinf, real *speech, real *phi, real *psi); +#endif + +/* ***************************************************************** */ + +/* MLOAD Version 48 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:31:25 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/27 23:59:51 jaf */ +/* Added some more accurate comments about which indices of the argument */ +/* array SPEECH are read. I thought that this might be the cause of a */ +/* problem I've been having, but it isn't. */ + +/* Revision 1.4 1996/03/26 19:16:53 jaf */ +/* Commented out the code at the end that copied the lower triangular */ +/* half of PHI into the upper triangular half (making the resulting */ +/* matrix symmetric). The upper triangular half was never used by later */ +/* code in subroutine ANALYS. */ + +/* Revision 1.3 1996/03/18 21:16:00 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:47:41 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:48:01 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Load a covariance matrix. */ + +/* Input: */ +/* ORDER - Analysis order */ +/* AWINS - Analysis window start */ +/* AWINF - Analysis window finish */ +/* SPEECH(AWINF) - Speech buffer */ +/* Indices MIN(AWINS, AWINF-(ORDER-1)) through */ +/* MAX(AWINF, AWINS+(ORDER-1)) read. */ +/* As long as (AWINF-AWINS) .GE. (ORDER-1), */ +/* this is just indices AWINS through AWINF. */ +/* Output: */ +/* PHI(ORDER,ORDER) - Covariance matrix */ +/* Lower triangular half and diagonal written, and read.*/ +/* Upper triangular half untouched. */ +/* PSI(ORDER) - Prediction vector */ +/* Indices 1 through ORDER written, */ +/* and most are read after that. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int mload_(integer *order, integer *awins, integer *awinf, + real *speech, real *phi, real *psi) +{ + /* System generated locals */ + integer phi_dim1, phi_offset, i__1, i__2; + + /* Local variables */ + integer c__, i__, r__, start; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Load first column of triangular covariance matrix PHI */ + /* Parameter adjustments */ + --psi; + phi_dim1 = *order; + phi_offset = phi_dim1 + 1; + phi -= phi_offset; + --speech; + + /* Function Body */ + start = *awins + *order; + i__1 = *order; + for (r__ = 1; r__ <= i__1; ++r__) { + phi[r__ + phi_dim1] = 0.f; + i__2 = *awinf; + for (i__ = start; i__ <= i__2; ++i__) { + phi[r__ + phi_dim1] += speech[i__ - 1] * speech[i__ - r__]; + } + } +/* Load last element of vector PSI */ + psi[*order] = 0.f; + i__1 = *awinf; + for (i__ = start; i__ <= i__1; ++i__) { + psi[*order] += speech[i__] * speech[i__ - *order]; + } +/* End correct to get additional columns of PHI */ + i__1 = *order; + for (r__ = 2; r__ <= i__1; ++r__) { + i__2 = r__; + for (c__ = 2; c__ <= i__2; ++c__) { + phi[r__ + c__ * phi_dim1] = phi[r__ - 1 + (c__ - 1) * phi_dim1] - + speech[*awinf + 1 - r__] * speech[*awinf + 1 - c__] + + speech[start - r__] * speech[start - c__]; + } + } +/* End correct to get additional elements of PSI */ + i__1 = *order - 1; + for (c__ = 1; c__ <= i__1; ++c__) { + psi[c__] = phi[c__ + 1 + phi_dim1] - speech[start - 1] * speech[start + - 1 - c__] + speech[*awinf] * speech[*awinf - c__]; + } +/* Copy lower triangular section into upper (why bother?) */ +/* I'm commenting this out, since the upper triangular half of PHI +*/ +/* is never used by later code, unless a sufficiently high level of +*/ +/* tracing is turned on. */ +/* DO R = 1,ORDER */ +/* DO C = 1,R-1 */ +/* PHI(C,R) = PHI(R,C) */ +/* END DO */ +/* END DO */ + return 0; +} /* mload_ */ + diff --git a/codecs/lpc10/onset.c b/codecs/lpc10/onset.c new file mode 100644 index 000000000..ddca3b477 --- /dev/null +++ b/codecs/lpc10/onset.c @@ -0,0 +1,324 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:37:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:31:18 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int onset_(real *pebuf, integer *osbuf, integer *osptr, integer *oslen, integer *sbufl, integer *sbufh, integer *lframe, struct lpc10_encoder_state *st); +#endif + +/* Table of constant values */ + +static real c_b2 = 1.f; + +/* ****************************************************************** */ + +/* ONSET Version 49 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:37:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:31:18 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/15 16:41:01 jaf */ +/* Just rearranged INITONSET assignment orders to be consistent with */ +/* order of DATA statements in ONSET. */ + +/* Revision 1.4 1996/03/15 15:48:27 jaf */ +/* Changed some comments, and only reordered the DATA statements (their */ +/* meaning wasn't changed). */ + +/* Revision 1.3 1996/03/14 23:53:06 jaf */ +/* Added an entry INITONSET that reinitializes the local state variables */ +/* of subroutine ONSET. */ + +/* Rearranged quite a few comments, adding more explaining which */ +/* arguments were inputs, and how the modified ones can be changed. */ + +/* Revision 1.2 1996/03/12 23:53:00 jaf */ +/* Lots of comments added about the local state of this subroutine that */ +/* must be saved from one invocation to the next. */ + +/* One constant 180 replaced with LFRAME, which should be "more general", */ +/* even though it would probably require many more changes than this to */ +/* get this coder to work for other frame sizes. */ + +/* Revision 1.1 1996/02/07 14:48:09 jaf */ +/* Initial revision */ + + +/* ****************************************************************** */ + +/* Floating point version */ + + +/* Detection of onsets in (or slightly preceding) the futuremost frame */ +/* of speech. */ + + +/* Input: */ +/* PEBUF(SBUFL:SBUFH) - Preemphasized speech */ +/* Indices SBUFH-LFRAME through SBUFH are read. */ +/* OSLEN - Maximum number of onsets that can be stored in OSBUF. */ +/* SBUFL, SBUFH - Range of PEBUF */ +/* LFRAME - length of a frame, in samples */ +/* Input/Output: */ +/* OSBUF(OSLEN) - Buffer which holds sorted indexes of onsets */ +/* Indices A through B are modified, where A */ +/* is the original value of OSPTR, and B is the final */ +/* value of OSPTR-1. B is at most OSLEN. */ +/* OSPTR - Free pointer into OSBUF */ +/* Initial value should be .LE. OSLEN+1. */ +/* If so, final value grows by one for each new onset */ +/* found, and final value will be .LE. OSLEN+1. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this subroutine, or */ +/* reinitialize its state for any other reason, call the ENTRY INITONSET. */ + +/* Subroutine */ int onset_(real *pebuf, integer *osbuf, integer * + osptr, integer *oslen, integer *sbufl, integer *sbufh, integer * + lframe, struct lpc10_encoder_state *st) +{ + /* Initialized data */ + + real *n; + real *d__; + real *l2buf; + real *l2sum1; + integer *l2ptr1; + integer *l2ptr2; + logical *hyst; + + /* System generated locals */ + integer pebuf_offset, i__1; + real r__1; + + /* Builtin functions */ + double r_sign(real *, real *); + + /* Local variables */ + integer i__; + integer *lasti; + real l2sum2; + real *fpc; + +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:37:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:31:18 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Parameters/constants */ +/* Parameters for onset detection algorithm: */ +/* L2 Threshold for filtered slope of FPC (function of L2WID!) */ +/* L2LAG Lag due to both filters which compute filtered slope of FPC */ +/* L2WID Width of the filter which computes the slope of FPC */ +/* OSHYST The number of samples of slope(FPC) which must be below */ +/* the threshold before a new onset may be declared. */ +/* Local variables that need not be saved */ +/* Local state */ +/* Variables */ +/* N, D Numerator and denominator of prediction filters */ +/* FPC Current prediction coefs */ +/* L2BUF, L2SUM1, L2SUM2 State of slope filter */ +/* The only "significant" change I've made is to change L2SUM2 out +*/ +/* of the list of local variables that need to be saved, since it */ +/* didn't need to be. */ +/* L2SUM1 need not be, but avoiding saving it would require a small +*/ +/* change to the body of the code. See comments below for an */ +/* example of how the code could be changed to avoid saving L2SUM1. +*/ +/* FPC and LASTI are saved from one invocation to the next, but */ +/* they are not given initial values. This is acceptable, because +*/ +/* FPC will be assigned a value the first time that this function */ +/* is called after D is initialized to 1, since the formula to */ +/* change D will not change it to 0 in one step, and the IF (D */ +/* .NE. 0) statement will execute its THEN part, initializing FPC. +*/ + +/* LASTI's value will not be used until HYST is .TRUE., and */ +/* whenever HYST is changed from its initial value of .FALSE., */ +/* LASTI is assigned a value. */ +/* In a C version of this coder, it would be nice if all of these */ +/* saved things, in this and all other subroutines, could be stored +*/ +/* in a single struct lpc10_coder_state_t, initialized with a call +*/ +/* to a function like lpc10_init(&lpc10_coder_state). In this way, +*/ +/* a program that used these functions could conveniently alternate +*/ +/* coding more than one distinct audio stream. */ + + n = &(st->n); + d__ = &(st->d__); + fpc = &(st->fpc); + l2buf = &(st->l2buf[0]); + l2sum1 = &(st->l2sum1); + l2ptr1 = &(st->l2ptr1); + l2ptr2 = &(st->l2ptr2); + lasti = &(st->lasti); + hyst = &(st->hyst); + + /* Parameter adjustments */ + if (osbuf) { + --osbuf; + } + if (pebuf) { + pebuf_offset = *sbufl; + pebuf -= pebuf_offset; + } + + /* Function Body */ + +/* The following line subtracted a hard-coded "180" from LASTI, */ +/* instead of using a variable like LFRAME or a constant like */ +/* MAXFRM. I changed it to LFRAME, for "generality". */ + if (*hyst) { + *lasti -= *lframe; + } + i__1 = *sbufh; + for (i__ = *sbufh - *lframe + 1; i__ <= i__1; ++i__) { +/* Compute FPC; Use old FPC on divide by zero; Clamp FPC to +/- 1. +*/ + *n = (pebuf[i__] * pebuf[i__ - 1] + (*n) * 63.f) / 64.f; +/* Computing 2nd power */ + r__1 = pebuf[i__ - 1]; + *d__ = (r__1 * r__1 + (*d__) * 63.f) / 64.f; + if ((*d__) != 0.f) { + if (abs(*n) > (*d__)) { + *fpc = (real)r_sign(&c_b2, n); + } else { + *fpc = (*n) / (*d__); + } + } +/* Filter FPC */ +/* In order to allow L2SUM1 not to be saved from one invocation +of */ +/* this subroutine to the next, one could change the sequence of + */ +/* assignments below, up to the IF statement, to the following. + In */ +/* addition, the initial value of L2PTR2 should be changed to */ +/* L2WID/2 instead of L2WID/2+1. */ + +/* L2SUM1 = L2BUF(L2PTR2) */ +/* L2PTR2 = MOD(L2PTR2,L2WID)+1 */ +/* L2SUM1 = L2SUM1 - L2BUF(L2PTR2) + FPC */ +/* L2BUF(L2PTR2) = L2SUM1 */ + +/* * The following lines didn't change from the original: */ +/* L2SUM2 = L2BUF(L2PTR1) */ +/* L2BUF(L2PTR1) = FPC */ +/* L2PTR1 = MOD(L2PTR1,L2WID)+1 */ + + l2sum2 = l2buf[*l2ptr1 - 1]; + *l2sum1 = *l2sum1 - l2buf[*l2ptr2 - 1] + *fpc; + l2buf[*l2ptr2 - 1] = *l2sum1; + l2buf[*l2ptr1 - 1] = *fpc; + *l2ptr1 = *l2ptr1 % 16 + 1; + *l2ptr2 = *l2ptr2 % 16 + 1; + if ((r__1 = *l2sum1 - l2sum2, abs(r__1)) > 1.7f) { + if (! (*hyst)) { +/* Ignore if buffer full */ + if (*osptr <= *oslen) { + osbuf[*osptr] = i__ - 9; + ++(*osptr); + } + *hyst = TRUE_; + } + *lasti = i__; +/* After one onset detection, at least OSHYST sample times m +ust go */ +/* by before another is allowed to occur. */ + } else if ((*hyst) && i__ - *lasti >= 10) { + *hyst = FALSE_; + } + } + return 0; +} /* onset_ */ diff --git a/codecs/lpc10/pitsyn.c b/codecs/lpc10/pitsyn.c new file mode 100644 index 000000000..ea8177e22 --- /dev/null +++ b/codecs/lpc10/pitsyn.c @@ -0,0 +1,583 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/11/23 22:14:32 markster +Various warning cleanups + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:40:12 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:31:12 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int pitsyn_(integer *order, integer *voice, integer *pitch, real *rms, real *rc, integer *lframe, integer *ivuv, integer *ipiti, real *rmsi, real *rci, integer *nout, real *ratio, struct lpc10_decoder_state *st); +#endif + +/* ***************************************************************** */ + +/* PITSYN Version 53 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/11/23 22:14:32 markster + * Various warning cleanups + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:40:12 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:31:12 jaf + * Initial revision + * */ +/* Revision 1.2 1996/03/25 18:49:07 jaf */ +/* Added commments about which indices of array arguments are read or */ +/* written. */ + +/* Rearranged local variable declarations to indicate which need to be */ +/* saved from one invocation to the next. Added entry INITPITSYN to */ +/* reinitialize local state variables, if desired. */ + +/* Added lots of comments about proving that the maximum number of pitch */ +/* periods (NOUT) that can be returned is 16. The call to STOP that */ +/* could happen if NOUT got too large was removed as a result. */ + +/* Also proved that the total number of samples returned from N calls, */ +/* each with identical values of LFRAME, will always be in the range */ +/* N*LFRAME-MAXPIT+1 to N*LFRAME. */ + +/* Revision 1.1 1996/02/07 14:48:18 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Synthesize a single pitch epoch */ + +/* Input: */ +/* ORDER - Synthesis order (number of RC's) */ +/* VOICE - Half frame voicing decisions */ +/* Indices 1 through 2 read. */ +/* LFRAME - Length of speech buffer */ +/* Input/Output: */ +/* PITCH - Pitch */ +/* This value should be in the range MINPIT (20) to MAXPIT */ +/* (156), inclusive. */ +/* PITCH can be modified under some conditions. */ +/* RMS - Energy (can be modified) */ +/* RMS is changed to 1 if the value passed in is less than 1. */ +/* RC - Reflection coefficients */ +/* Indices 1 through ORDER can be temporarily overwritten with */ +/* RCO, and then replaced with original values, under some */ +/* conditions. */ +/* Output: */ +/* IVUV - Pitch epoch voicing decisions */ +/* Indices (I) of IVUV, IPITI, and RMSI are written, */ +/* and indices (J,I) of RCI are written, */ +/* where I ranges from 1 to NOUT, and J ranges from 1 to ORDER. */ +/* IPITI - Pitch epoch length */ +/* RMSI - Pitch epoch energy */ +/* RCI - Pitch epoch RC's */ +/* NOUT - Number of pitch periods in this frame */ +/* This is at least 0, at least 1 if MAXPIT .LT. LFRAME (this */ +/* is currently true on every call), and can never be more than */ +/* (LFRAME+MAXPIT-1)/PITCH, which is currently 16 with */ +/* LFRAME=180, MAXPIT=156, and PITCH .GE. 20, as SYNTHS */ +/* guarantees when it calls this subroutine. */ +/* RATIO - Previous to present energy ratio */ +/* Always assigned a value. */ + +/* Subroutine */ int pitsyn_(integer *order, integer *voice, + integer *pitch, real *rms, real *rc, integer *lframe, integer *ivuv, + integer *ipiti, real *rmsi, real *rci, integer *nout, real *ratio, + struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + real *rmso; + logical *first; + + /* System generated locals */ + integer rci_dim1 = 0, rci_offset, i__1, i__2; + real r__1; + + /* Builtin functions */ + double log(doublereal), exp(doublereal); + + /* Local variables */ + real alrn, alro, yarc[10], prop; + integer i__, j, vflag, jused, lsamp; + integer *jsamp; + real slope; + integer *ipito; + real uvpit; + integer ip, nl, ivoice; + integer *ivoico; + integer istart; + real *rco; + real xxy; + +/* Arguments */ +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/11/23 22:14:32 markster + * Various warning cleanups + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:40:12 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:31:12 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Local variables that need not be saved */ +/* LSAMP is initialized in the IF (FIRST) THEN clause, but it is */ +/* not used the first time through, and it is given a value before +*/ +/* use whenever FIRST is .FALSE., so it appears unnecessary to */ +/* assign it a value when FIRST is .TRUE. */ +/* Local state */ +/* FIRST - .TRUE. only on first call to PITSYN. */ +/* IVOICO - Previous VOICE(2) value. */ +/* IPITO - Previous PITCH value. */ +/* RMSO - Previous RMS value. */ +/* RCO - Previous RC values. */ + +/* JSAMP - If this routine is called N times with identical values of */ +/* LFRAME, then the total length of all pitch periods returned */ +/* is always N*LFRAME-JSAMP, and JSAMP is always in the range 0 +*/ +/* to MAXPIT-1 (see below for why this is so). Thus JSAMP is */ +/* the number of samples "left over" from the previous call to */ +/* PITSYN, that haven't been "used" in a pitch period returned */ +/* from this subroutine. Every time this subroutine is called, +*/ +/* it returns pitch periods with a total length of at most */ +/* LFRAME+JSAMP. */ + +/* IVOICO, IPITO, RCO, and JSAMP need not be assigned an initial value */ +/* with a DATA statement, because they are always initialized on the */ +/* first call to PITSYN. */ + +/* FIRST and RMSO should be initialized with DATA statements, because */ +/* even on the first call, they are used before being initialized. */ + /* Parameter adjustments */ + if (rc) { + --rc; + } + if (rci) { + rci_dim1 = *order; + rci_offset = rci_dim1 + 1; + rci -= rci_offset; + } + if (voice) { + --voice; + } + if (ivuv) { + --ivuv; + } + if (ipiti) { + --ipiti; + } + if (rmsi) { + --rmsi; + } + + /* Function Body */ + ivoico = &(st->ivoico); + ipito = &(st->ipito); + rmso = &(st->rmso); + rco = &(st->rco[0]); + jsamp = &(st->jsamp); + first = &(st->first_pitsyn); + + if (*rms < 1.f) { + *rms = 1.f; + } + if (*rmso < 1.f) { + *rmso = 1.f; + } + uvpit = 0.f; + *ratio = *rms / (*rmso + 8.f); + if (*first) { + lsamp = 0; + ivoice = voice[2]; + if (ivoice == 0) { + *pitch = *lframe / 4; + } + *nout = *lframe / *pitch; + *jsamp = *lframe - *nout * *pitch; + +/* SYNTHS only calls this subroutine with PITCH in the range +20 */ +/* to 156. LFRAME = MAXFRM = 180, so NOUT is somewhere in th +e */ +/* range 1 to 9. */ + +/* JSAMP is "LFRAME mod PITCH", so it is in the range 0 to */ +/* (PITCH-1), or 0 to MAXPIT-1=155, after the first call. */ + + i__1 = *nout; + for (i__ = 1; i__ <= i__1; ++i__) { + i__2 = *order; + for (j = 1; j <= i__2; ++j) { + rci[j + i__ * rci_dim1] = rc[j]; + } + ivuv[i__] = ivoice; + ipiti[i__] = *pitch; + rmsi[i__] = *rms; + } + *first = FALSE_; + } else { + vflag = 0; + lsamp = *lframe + *jsamp; + slope = (*pitch - *ipito) / (real) lsamp; + *nout = 0; + jused = 0; + istart = 1; + if (voice[1] == *ivoico && voice[2] == voice[1]) { + if (voice[2] == 0) { +/* SSUV - - 0 , 0 , 0 */ + *pitch = *lframe / 4; + *ipito = *pitch; + if (*ratio > 8.f) { + *rmso = *rms; + } + } +/* SSVC - - 1 , 1 , 1 */ + slope = (*pitch - *ipito) / (real) lsamp; + ivoice = voice[2]; + } else { + if (*ivoico != 1) { + if (*ivoico == voice[1]) { +/* UV2VC2 - - 0 , 0 , 1 */ + nl = lsamp - *lframe / 4; + } else { +/* UV2VC1 - - 0 , 1 , 1 */ + nl = lsamp - *lframe * 3 / 4; + } + ipiti[1] = nl / 2; + ipiti[2] = nl - ipiti[1]; + ivuv[1] = 0; + ivuv[2] = 0; + rmsi[1] = *rmso; + rmsi[2] = *rmso; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + rci[i__ + rci_dim1] = rco[i__ - 1]; + rci[i__ + (rci_dim1 << 1)] = rco[i__ - 1]; + rco[i__ - 1] = rc[i__]; + } + slope = 0.f; + *nout = 2; + *ipito = *pitch; + jused = nl; + istart = nl + 1; + ivoice = 1; + } else { + if (*ivoico != voice[1]) { +/* VC2UV1 - - 1 , 0 , 0 */ + lsamp = *lframe / 4 + *jsamp; + } else { +/* VC2UV2 - - 1 , 1 , 0 */ + lsamp = *lframe * 3 / 4 + *jsamp; + } + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + yarc[i__ - 1] = rc[i__]; + rc[i__] = rco[i__ - 1]; + } + ivoice = 1; + slope = 0.f; + vflag = 1; + } + } +/* Here is the value of most variables that are used below, depending +on */ +/* the values of IVOICO, VOICE(1), and VOICE(2). VOICE(1) and VOICE(2 +) */ +/* are input arguments, and IVOICO is the value of VOICE(2) on the */ +/* previous call (see notes for the IF (NOUT .NE. 0) statement near th +e */ +/* end). Each of these three values is either 0 or 1. These three */ +/* values below are given as 3-bit long strings, in the order IVOICO, +*/ +/* VOICE(1), and VOICE(2). It appears that the code above assumes tha +t */ +/* the bit sequences 010 and 101 never occur, but I wonder whether a +*/ +/* large enough number of bit errors in the channel could cause such a + */ +/* thing to happen, and if so, could that cause NOUT to ever go over 1 +1? */ + +/* Note that all of the 180 values in the table are really LFRAME, but + */ +/* 180 has fewer characters, and it makes the table a little more */ +/* concrete. If LFRAME is ever changed, keep this in mind. Similarly +, */ +/* 135's are 3*LFRAME/4, and 45's are LFRAME/4. If LFRAME is not a */ +/* multiple of 4, then the 135 for NL-JSAMP is actually LFRAME-LFRAME/ +4, */ +/* and the 45 for NL-JSAMP is actually LFRAME-3*LFRAME/4. */ + +/* Note that LSAMP-JSAMP is given as the variable. This was just for +*/ +/* brevity, to avoid adding "+JSAMP" to all of the column entries. */ +/* Similarly for NL-JSAMP. */ + +/* Variable | 000 001 011,010 111 110 100,101 */ +/* ------------+-------------------------------------------------- */ +/* ISTART | 1 NL+1 NL+1 1 1 1 */ +/* LSAMP-JSAMP | 180 180 180 180 135 45 */ +/* IPITO | 45 PITCH PITCH oldPITCH oldPITCH oldPITCH */ +/* SLOPE | 0 0 0 seebelow 0 0 */ +/* JUSED | 0 NL NL 0 0 0 */ +/* PITCH | 45 PITCH PITCH PITCH PITCH PITCH */ +/* NL-JSAMP | -- 135 45 -- -- -- */ +/* VFLAG | 0 0 0 0 1 1 */ +/* NOUT | 0 2 2 0 0 0 */ +/* IVOICE | 0 1 1 1 1 1 */ + +/* while_loop | once once once once twice twice */ + +/* ISTART | -- -- -- -- JUSED+1 JUSED+1 */ +/* LSAMP-JSAMP | -- -- -- -- 180 180 */ +/* IPITO | -- -- -- -- oldPITCH oldPITCH */ +/* SLOPE | -- -- -- -- 0 0 */ +/* JUSED | -- -- -- -- ?? ?? */ +/* PITCH | -- -- -- -- PITCH PITCH */ +/* NL-JSAMP | -- -- -- -- -- -- */ +/* VFLAG | -- -- -- -- 0 0 */ +/* NOUT | -- -- -- -- ?? ?? */ +/* IVOICE | -- -- -- -- 0 0 */ + + +/* UVPIT is always 0.0 on the first pass through the DO WHILE (.TRUE.) + */ +/* loop below. */ + +/* The only possible non-0 value of SLOPE (in column 111) is */ +/* (PITCH-IPITO)/FLOAT(LSAMP) */ + +/* Column 101 is identical to 100. Any good properties we can prove +*/ +/* for 100 will also hold for 101. Similarly for 010 and 011. */ + +/* SYNTHS calls this subroutine with PITCH restricted to the range 20 +to */ +/* 156. IPITO is similarly restricted to this range, after the first +*/ +/* call. IP below is also restricted to this range, given the */ +/* definitions of IPITO, SLOPE, UVPIT, and that I is in the range ISTA +RT */ +/* to LSAMP. */ + + while(TRUE_) { + +/* JUSED is the total length of all pitch periods curr +ently */ +/* in the output arrays, in samples. */ + +/* An invariant of the DO I = ISTART,LSAMP loop below, + under */ +/* the condition that IP is always in the range 1 thro +ugh */ +/* MAXPIT, is: */ + +/* (I - MAXPIT) .LE. JUSED .LE. (I-1) */ + +/* Note that the final value of I is LSAMP+1, so that +after */ +/* the DO loop is complete, we know: */ + +/* (LSAMP - MAXPIT + 1) .LE. JUSED .LE. LSAMP */ + + i__1 = lsamp; + for (i__ = istart; i__ <= i__1; ++i__) { + r__1 = *ipito + slope * i__; + ip = (integer)(r__1 + .5f); + if (uvpit != 0.f) { + ip = (integer)uvpit; + } + if (ip <= i__ - jused) { + ++(*nout); + +/* The following check is no longer nece +ssary, now that */ +/* we can prove that NOUT will never go +over 16. */ + +/* IF (NOUT .GT. 16) STOP 'PITSYN: too many epochs' +*/ + + ipiti[*nout] = ip; + *pitch = ip; + ivuv[*nout] = ivoice; + jused += ip; + prop = (jused - ip / 2) / (real) lsamp; + i__2 = *order; + for (j = 1; j <= i__2; ++j) { + alro = (real)log((rco[j - 1] + 1) / (1 - rco[j - 1])); + alrn = (real)log((rc[j] + 1) / (1 - rc[j])); + xxy = alro + prop * (alrn - alro); + xxy = (real)exp(xxy); + rci[j + *nout * rci_dim1] = (xxy - 1) / (xxy + 1); + } + rmsi[*nout] = (real)(log(*rmso) + prop * (log(*rms) - log(*rmso))); + rmsi[*nout] = (real)exp(rmsi[*nout]); + } + } + if (vflag != 1) { + goto L100; + } + +/* I want to prove what range UVPIT must lie in after +the */ +/* assignments to it below. To do this, I must determ +ine */ +/* what range (LSAMP-ISTART) must lie in, after the */ +/* assignments to ISTART and LSAMP below. */ + +/* Let oldLSAMP be the value of LSAMP at this point in + the */ +/* execution. This is 135+JSAMP in state 110, or 45+J +SAMP in */ +/* states 100 or 101. */ + +/* Given the loop invariant on JUSED above, we know th +at: */ + +/* (oldLSAMP - MAXPIT + 1) .LE. JUSED .LE. oldLSAMP */ + +/* ISTART is one more than this. */ + +/* Let newLSAMP be the value assigned to LSAMP below. + This */ +/* is 180+JSAMP. Thus (newLSAMP-oldLSAMP) is either 4 +5 or */ +/* 135, depending on the state. */ + +/* Thus, the range of newLSAMP-ISTART is: */ + +/* (newLSAMP-(oldLSAMP+1)) .LE. newLSAMP-ISTART */ +/* .LE. (newLSAMP-(oldLSAMP - MAXPIT + 2)) */ + +/* or: */ + +/* 46 .LE. newLSAMP-ISTART .LE. 133+MAXPIT .EQ. 289 */ + +/* Therefore, UVPIT is in the range 23 to 144 after th +e first */ +/* assignment to UVPIT below, and after the conditiona +l */ +/* assignment, it is in the range 23 to 90. */ + +/* The important thing is that it is in the range 20 t +o 156, */ +/* so that in the loop above, IP is always in this ran +ge. */ + + vflag = 0; + istart = jused + 1; + lsamp = *lframe + *jsamp; + slope = 0.f; + ivoice = 0; + uvpit = (real) ((lsamp - istart) / 2); + if (uvpit > 90.f) { + uvpit /= 2; + } + *rmso = *rms; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + rc[i__] = yarc[i__ - 1]; + rco[i__ - 1] = yarc[i__ - 1]; + } + } +L100: + *jsamp = lsamp - jused; + } +/* Given that the maximum pitch period MAXPIT .LT. LFRAME (this is +*/ +/* currently true on every call, since SYNTHS always sets */ +/* LFRAME=180), NOUT will always be .GE. 1 at this point. */ + if (*nout != 0) { + *ivoico = voice[2]; + *ipito = *pitch; + *rmso = *rms; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + rco[i__ - 1] = rc[i__]; + } + } + return 0; +} /* pitsyn_ */ diff --git a/codecs/lpc10/placea.c b/codecs/lpc10/placea.c new file mode 100644 index 000000000..dacb50e7a --- /dev/null +++ b/codecs/lpc10/placea.c @@ -0,0 +1,242 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.2 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.3 2001/04/12 21:27:53 markh +app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set. + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:07 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int placea_(integer *ipitch, integer *voibuf, integer *obound, integer *af, integer *vwin, integer *awin, integer *ewin, integer *lframe, integer *maxwin); +#endif + +/* *********************************************************************** */ + +/* PLACEA Version 48 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.2 2003/09/19 01:20:22 markster + * Code cleanups (bug #66) + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.3 2001/04/12 21:27:53 markh + * app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set. + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:31:07 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/19 20:41:55 jaf */ +/* Added some conditions satisfied by the output values in EWIN. */ + +/* Revision 1.4 1996/03/19 20:24:17 jaf */ +/* Added some conditions satisfied by the output values in AWIN. */ + +/* Revision 1.3 1996/03/18 21:40:04 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:43:09 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:48:31 jaf */ +/* Initial revision */ + + +/* *********************************************************************** */ +/* Input: */ +/* IPITCH */ +/* VOIBUF */ +/* Indices (2,AF-2), (1,AF-1), (2,AF-1), (1,AF), and (2,AF) read.*/ +/* All other indices untouched. */ +/* OBOUND */ +/* AF */ +/* VWIN */ +/* Indices (1,AF) and (2,AF) read. */ +/* All other indices untouched. */ +/* LFRAME */ +/* MAXWIN */ +/* Input/Output: */ +/* AWIN */ +/* Index (1,AF-1) read. */ +/* Indices (1,AF) and (2,AF) written, and then read. */ +/* All other indices untouched. */ +/* In all cases (except possibly one), the final values will */ +/* satisfy the condition: AWIN(2,AF)-AWIN(1,AF)+1 = MAXWIN. */ +/* In that other case, */ +/* AWIN(1,AF)=VWIN(1,AF) and AWIN(2,AF)=VWIN(2,AF). */ +/* Output: */ +/* EWIN */ +/* Indices (1,AF) and (2,AF) written. */ +/* All other indices untouched. */ +/* In all cases, the final values will satisfy the condition: */ +/* AWIN(1,AF) .LE. EWIN(1,AF) .LE. EWIN(2,AF) .LE. AWIN(2,AF) */ +/* In other words, the energy window is a sub-window of */ +/* the analysis window. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int placea_(integer *ipitch, integer *voibuf, integer * + obound, integer *af, integer *vwin, integer *awin, integer *ewin, + integer *lframe, integer *maxwin) +{ + /* System generated locals */ + real r__1; + + /* Builtin functions */ + integer i_nint(real *); + + /* Local variables */ + logical allv, winv; + integer i__, j, k, l, hrange; + logical ephase; + integer lrange; + +/* Arguments */ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + ewin -= 3; + awin -= 3; + vwin -= 3; + --voibuf; + + /* Function Body */ + lrange = (*af - 2) * *lframe + 1; + hrange = *af * *lframe; +/* Place the Analysis window based on the voicing window */ +/* placement, onsets, tentative voicing decision, and pitch. */ + +/* Case 1: Sustained Voiced Speech */ +/* If the five most recent voicing decisions are */ +/* voiced, then the window is placed phase-synchronously with the */ +/* previous window, as close to the present voicing window if possible. +*/ +/* If onsets bound the voicing window, then preference is given to */ +/* a phase-synchronous placement which does not overlap these onsets. */ + +/* Case 2: Voiced Transition */ +/* If at least one voicing decision in AF is voicied, and there are no +*/ +/* onsets, then the window is placed as in case 1. */ + +/* Case 3: Unvoiced Speech or Onsets */ +/* If both voicing decisions in AF are unvoiced, or there are onsets, */ +/* then the window is placed coincident with the voicing window. */ + +/* Note: During phase-synchronous placement of windows, the length */ +/* is not altered from MAXWIN, since this would defeat the purpose */ +/* of phase-synchronous placement. */ +/* Check for case 1 and case 2 */ + allv = voibuf[((*af - 2) << 1) + 2] == 1; + allv = allv && voibuf[((*af - 1) << 1) + 1] == 1; + allv = allv && voibuf[((*af - 1) << 1) + 2] == 1; + allv = allv && voibuf[(*af << 1) + 1] == 1; + allv = allv && voibuf[(*af << 1) + 2] == 1; + winv = voibuf[(*af << 1) + 1] == 1 || voibuf[(*af << 1) + 2] == 1; + if (allv || (winv && *obound == 0)) { +/* APHASE: Phase synchronous window placement. */ +/* Get minimum lower index of the window. */ + i__ = (lrange + *ipitch - 1 - awin[((*af - 1) << 1) + 1]) / *ipitch; + i__ *= *ipitch; + i__ += awin[((*af - 1) << 1) + 1]; +/* L = the actual length of this frame's analysis window. */ + l = *maxwin; +/* Calculate the location where a perfectly centered window would star +t. */ + k = (vwin[(*af << 1) + 1] + vwin[(*af << 1) + 2] + 1 - l) / 2; +/* Choose the actual location to be the pitch multiple closest to this +. */ + r__1 = (real) (k - i__) / *ipitch; + awin[(*af << 1) + 1] = i__ + i_nint(&r__1) * *ipitch; + awin[(*af << 1) + 2] = awin[(*af << 1) + 1] + l - 1; +/* If there is an onset bounding the right of the voicing window and t +he */ +/* analysis window overlaps that, then move the analysis window backwa +rd */ +/* to avoid this onset. */ + if (*obound >= 2 && awin[(*af << 1) + 2] > vwin[(*af << 1) + 2]) { + awin[(*af << 1) + 1] -= *ipitch; + awin[(*af << 1) + 2] -= *ipitch; + } +/* Similarly for the left of the voicing window. */ + if ((*obound == 1 || *obound == 3) && awin[(*af << 1) + 1] < vwin[(* + af << 1) + 1]) { + awin[(*af << 1) + 1] += *ipitch; + awin[(*af << 1) + 2] += *ipitch; + } +/* If this placement puts the analysis window above HRANGE, then */ +/* move it backward an integer number of pitch periods. */ + while(awin[(*af << 1) + 2] > hrange) { + awin[(*af << 1) + 1] -= *ipitch; + awin[(*af << 1) + 2] -= *ipitch; + } +/* Similarly if the placement puts the analysis window below LRANGE. +*/ + while(awin[(*af << 1) + 1] < lrange) { + awin[(*af << 1) + 1] += *ipitch; + awin[(*af << 1) + 2] += *ipitch; + } +/* Make Energy window be phase-synchronous. */ + ephase = TRUE_; +/* Case 3 */ + } else { + awin[(*af << 1) + 1] = vwin[(*af << 1) + 1]; + awin[(*af << 1) + 2] = vwin[(*af << 1) + 2]; + ephase = FALSE_; + } +/* RMS is computed over an integer number of pitch periods in the analysis + */ +/*window. When it is not placed phase-synchronously, it is placed as clos +e*/ +/* as possible to onsets. */ + j = (awin[(*af << 1) + 2] - awin[(*af << 1) + 1] + 1) / *ipitch * *ipitch; + if (j == 0 || ! winv) { + ewin[(*af << 1) + 1] = vwin[(*af << 1) + 1]; + ewin[(*af << 1) + 2] = vwin[(*af << 1) + 2]; + } else if (! ephase && *obound == 2) { + ewin[(*af << 1) + 1] = awin[(*af << 1) + 2] - j + 1; + ewin[(*af << 1) + 2] = awin[(*af << 1) + 2]; + } else { + ewin[(*af << 1) + 1] = awin[(*af << 1) + 1]; + ewin[(*af << 1) + 2] = awin[(*af << 1) + 1] + j - 1; + } + return 0; +} /* placea_ */ + diff --git a/codecs/lpc10/placev.c b/codecs/lpc10/placev.c new file mode 100644 index 000000000..56e72c4b8 --- /dev/null +++ b/codecs/lpc10/placev.c @@ -0,0 +1,275 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.3 2001/04/12 21:27:53 markh +app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set. + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:02 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int placev_(integer *osbuf, integer *osptr, integer *oslen, integer *obound, integer *vwin, integer *af, integer *lframe, integer *minwin, integer *maxwin, integer *dvwinl, integer *dvwinh); +#endif + +/* ****************************************************************** */ + +/* PLACEV Version 48 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.3 2001/04/12 21:27:53 markh + * app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set. + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:31:02 jaf + * Initial revision + * */ +/* Revision 1.6 1996/03/19 20:42:19 jaf */ +/* Added some conditions satisfied by the output values in VWIN. */ + +/* Revision 1.5 1996/03/19 18:37:56 jaf */ +/* Strengthened the specification of which indices of VWIN are read and */ +/* written. */ + +/* Revision 1.4 1996/03/15 16:38:33 jaf */ +/* One tiny comment added. */ + +/* Revision 1.3 1996/03/15 16:36:13 jaf */ +/* Added comments giving In/Out status of arguments. */ + +/* Revision 1.2 1996/03/12 23:56:01 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:48:39 jaf */ +/* Initial revision */ + + +/* ****************************************************************** */ + +/* Input: */ +/* OSBUF Buffer which holds sorted indexes of onsets */ +/* I believe that only indices 1 through OSPTR-1 can be read. */ +/* OSLEN */ +/* OSPTR Free pointer into OSBUF */ +/* AF */ +/* LFRAME */ +/* MINWIN */ +/* MAXWIN */ +/* DVWINL */ +/* DVWINH (This argument is never used. Should it be?) */ +/* Input/Output: */ +/* VWIN Buffer of Voicing Window Positions (Modified) */ +/* Index (2,AF-1) is read. */ +/* Indices (1,AF) and (2,AF) are written, */ +/* and then possibly read. */ +/* All other indices are unused. */ +/* In all cases, the final values will satsify the condition:*/ +/* VWIN(2,AF)-VWIN(1,AF)+1 .LE. MAXWIN */ +/* I'm not certain yet, but they may also satisfy: */ +/* MINWIN .LE. VWIN(2,AF)-VWIN(1,AF)+1 */ +/* Output: */ +/* OBOUND This variable is set by this procedure and used */ +/* in placing analysis windows (PLACEA). Bit 1 */ +/* indicates whether an onset bounds the left side */ +/* of the voicing window, and bit 2 indicates whether */ +/* an onset bounds the right side of the voicing window. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int placev_(integer *osbuf, integer *osptr, integer *oslen, + integer *obound, integer *vwin, integer *af, integer *lframe, integer + *minwin, integer *maxwin, integer *dvwinl, integer *dvwinh) +{ + /* System generated locals */ + integer i__1, i__2; + + /* Local variables */ + logical crit; + integer i__, q, osptr1, hrange, lrange; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Variables */ +/* LRANGE, HRANGE Range in which window is placed */ +/* OSPTR1 OSPTR excluding samples in 3F */ +/* Local state */ +/* None */ +/* Voicing Window Placement */ + +/* __________________ __________________ ______________ */ +/* | | | */ +/* | 1F | 2F | 3F ... */ +/* |__________________|__________________|______________ */ + +/* Previous | */ +/* Window | */ +/* ...________| */ + +/* | | */ +/* ------>| This window's placement range |<------ */ +/* | | */ + +/* There are three cases. Note that these are different from those */ +/* given in the LPC-10e phase 1 report. */ + +/* 1. If there are no onsets in this range, then the voicing window */ +/* is centered in the pitch window. If such a placement is not within +*/ +/* the window's placement range, then the window is placed in the left- +*/ +/* most portion of the placement range. Its length is always MAXWIN. */ + +/* 2. If the first onset is in 2F and there is sufficient room to place + */ +/* the window immediately before this onset, then the window is placed +*/ +/* there, and its length is set to the maximum possible under these */ +/* constraints. */ + +/* "Critical Region Exception": If there is another onset in 2F */ +/* such that a window can be placed between the two onsets, the */ +/* window is placed there (ie, as in case 3). */ + +/* 3. Otherwise, the window is placed immediately after the onset. The + */ +/* window's length */ +/* is the longest length that can fit in the range under these constraint +s,*/ +/* except that the window may be shortened even further to avoid overlapp +ing*/ +/* other onsets in the placement range. In any case, the window's length +*/ +/* is at least MINWIN. */ + +/* Note that the values of MINWIN and LFRAME must be chosen such */ +/* that case 2 = false implies case 3 = true. This means that */ +/* MINWIN <= LFRAME/2. If this were not the case, then a fourth case */ +/* would have to be added for when the window cannot fit either before +*/ +/* or after the onset. */ + +/* Note also that onsets which weren't in 2F last time may be in 1F this + */ +/* time, due to the filter delays in computing onsets. The result is tha +t*/ +/* occasionally a voicing window will overlap that onset. The only way +*/ +/* to circumvent this problem is to add more delay in processing input +*/ +/* speech. In the trade-off between delay and window-placement, window +*/ +/* placement lost. */ +/* Compute the placement range */ + /* Parameter adjustments */ + --osbuf; + vwin -= 3; + + /* Function Body */ +/* Computing MAX */ + i__1 = vwin[((*af - 1) << 1) + 2] + 1, i__2 = (*af - 2) * *lframe + 1; + lrange = max(i__1,i__2); + hrange = *af * *lframe; +/* Compute OSPTR1, so the following code only looks at relevant onsets. */ + for (osptr1 = *osptr - 1; osptr1 >= 1; --osptr1) { + if (osbuf[osptr1] <= hrange) { + goto L90; + } + } +L90: + ++osptr1; +/* Check for case 1 first (fast case): */ + if (osptr1 <= 1 || osbuf[osptr1 - 1] < lrange) { +/* Computing MAX */ + i__1 = vwin[((*af - 1) << 1) + 2] + 1; + vwin[(*af << 1) + 1] = max(i__1,*dvwinl); + vwin[(*af << 1) + 2] = vwin[(*af << 1) + 1] + *maxwin - 1; + *obound = 0; + } else { +/* Search backward in OSBUF for first onset in range. */ +/* This code relies on the above check being performed first. */ + for (q = osptr1 - 1; q >= 1; --q) { + if (osbuf[q] < lrange) { + goto L100; + } + } +L100: + ++q; +/* Check for case 2 (placement before onset): */ +/* Check for critical region exception: */ + i__1 = osptr1 - 1; + for (i__ = q + 1; i__ <= i__1; ++i__) { + if (osbuf[i__] - osbuf[q] >= *minwin) { + crit = TRUE_; + goto L105; + } + } + crit = FALSE_; +L105: +/* Computing MAX */ + i__1 = (*af - 1) * *lframe, i__2 = lrange + *minwin - 1; + if (! crit && osbuf[q] > max(i__1,i__2)) { + vwin[(*af << 1) + 2] = osbuf[q] - 1; +/* Computing MAX */ + i__1 = lrange, i__2 = vwin[(*af << 1) + 2] - *maxwin + 1; + vwin[(*af << 1) + 1] = max(i__1,i__2); + *obound = 2; +/* Case 3 (placement after onset) */ + } else { + vwin[(*af << 1) + 1] = osbuf[q]; +L110: + ++q; + if (q >= osptr1) { + goto L120; + } + if (osbuf[q] > vwin[(*af << 1) + 1] + *maxwin) { + goto L120; + } + if (osbuf[q] < vwin[(*af << 1) + 1] + *minwin) { + goto L110; + } + vwin[(*af << 1) + 2] = osbuf[q] - 1; + *obound = 3; + return 0; +L120: +/* Computing MIN */ + i__1 = vwin[(*af << 1) + 1] + *maxwin - 1; + vwin[(*af << 1) + 2] = min(i__1,hrange); + *obound = 1; + } + } + return 0; +} /* placev_ */ + diff --git a/codecs/lpc10/preemp.c b/codecs/lpc10/preemp.c new file mode 100644 index 000000000..645428c3c --- /dev/null +++ b/codecs/lpc10/preemp.c @@ -0,0 +1,144 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:30:58 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int preemp_(real *inbuf, real *pebuf, integer *nsamp, real *coef, real *z__); +#endif + +/* ******************************************************************* */ + +/* PREEMP Version 55 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:30:58 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/14 23:16:29 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/11 23:23:34 jaf */ +/* Added a bunch of comments to an otherwise simple subroutine. */ + +/* Revision 1.1 1996/02/07 14:48:48 jaf */ +/* Initial revision */ + + +/* ******************************************************************* */ + +/* Preemphasize speech with a single-zero filter. */ +/* (When coef = .9375, preemphasis is as in LPC43.) */ + +/* Inputs: */ +/* NSAMP - Number of samples to filter */ +/* INBUF - Input speech buffer */ +/* Indices 1 through NSAMP are read. */ +/* COEF - Preemphasis coefficient */ +/* Input/Output: */ +/* Z - Filter state */ +/* Output: */ +/* PEBUF - Preemphasized speech buffer (can be equal to INBUF) */ +/* Indices 1 through NSAMP are modified. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int preemp_(real *inbuf, real *pebuf, integer *nsamp, real * + coef, real *z__) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + real temp; + integer i__; + +/* Arguments */ +/* Local variables */ + +/* None of these need to have their values saved from one */ +/* invocation to the next. */ + +/* Logically, this subroutine computes the output sequence */ +/* pebuf(1:nsamp) defined by: */ + +/* pebuf(i) = inbuf(i) - coef * inbuf(i-1) */ + +/* where inbuf(0) is defined by the value of z given as input to */ +/* this subroutine. */ + +/* What is this filter's frequency response and phase response? */ + +/* Why is this filter applied to the speech? */ + +/* Could it be more efficient to apply multiple filters */ +/* simultaneously, by combining them into one equivalent filter? */ + +/* Are there ever cases when "factoring" one high-order filter into +*/ +/* multiple smaller-order filter actually reduces the number of */ +/* arithmetic operations needed to perform them? */ +/* When I first read this subroutine, I didn't understand why the */ +/* variable temp was used. It seemed that the statements in the do +*/ +/* loop could be replaced with the following: */ + +/* pebuf(i) = inbuf(i) - coef * z */ +/* z = inbuf(i) */ + +/* The reason for temp is so that even if pebuf and inbuf are the */ +/* same arrays in memory (i.e., they are aliased), then this */ +/* subroutine will still work correctly. I didn't realize this */ +/* until seeing the comment after PEBUF above that says "(can be */ +/* equal to INBUF)". */ + /* Parameter adjustments */ + --pebuf; + --inbuf; + + /* Function Body */ + i__1 = *nsamp; + for (i__ = 1; i__ <= i__1; ++i__) { + temp = inbuf[i__] - *coef * *z__; + *z__ = inbuf[i__]; + pebuf[i__] = temp; +/* L10: */ + } + return 0; +} /* preemp_ */ + diff --git a/codecs/lpc10/prepro.c b/codecs/lpc10/prepro.c new file mode 100644 index 000000000..d24ce0da3 --- /dev/null +++ b/codecs/lpc10/prepro.c @@ -0,0 +1,116 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:40:51 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:30:54 jaf + * Initial revision + * + */ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int prepro_(real *speech, integer *length, + struct lpc10_encoder_state *st); +/*:ref: hp100_ 14 3 6 4 4 */ +/*:ref: inithp100_ 14 0 */ +#endif + +/* Table of constant values */ + +static integer c__1 = 1; + +/* ********************************************************************* */ + +/* PREPRO Version 48 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:40:51 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:30:54 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/14 23:22:56 jaf */ +/* Added comments about when INITPREPRO should be used. */ + +/* Revision 1.2 1996/03/14 23:09:27 jaf */ +/* Added an entry named INITPREPRO that initializes the local state of */ +/* this subroutine, and those it calls (if any). */ + +/* Revision 1.1 1996/02/07 14:48:54 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Pre-process input speech: */ + +/* Inputs: */ +/* LENGTH - Number of SPEECH samples */ +/* Input/Output: */ +/* SPEECH(LENGTH) - Speech data. */ +/* Indices 1 through LENGTH are read and modified. */ + +/* This subroutine has no local state maintained from one call to the */ +/* next, but HP100 does. If you want to switch to using a new audio */ +/* stream for this filter, or reinitialize its state for any other */ +/* reason, call the ENTRY INITPREPRO. */ + +/* Subroutine */ int prepro_(real *speech, integer *length, + struct lpc10_encoder_state *st) +{ + extern /* Subroutine */ int hp100_(real *, integer *, integer *, struct lpc10_encoder_state *); + +/* Arguments */ +/* High Pass Filter at 100 Hz */ + /* Parameter adjustments */ + if (speech) { + --speech; + } + + /* Function Body */ + hp100_(&speech[1], &c__1, length, st); + return 0; +} /* prepro_ */ diff --git a/codecs/lpc10/random.c b/codecs/lpc10/random.c new file mode 100644 index 000000000..0f8e9b209 --- /dev/null +++ b/codecs/lpc10/random.c @@ -0,0 +1,125 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:41:32 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:49 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern integer random_(struct lpc10_decoder_state *st); +#endif + +/* ********************************************************************** */ + +/* RANDOM Version 49 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:41:32 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:49 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/20 16:13:54 jaf */ +/* Rearranged comments a little bit, and added comments explaining that */ +/* even though there is local state here, there is no need to create an */ +/* ENTRY for reinitializing it. */ + +/* Revision 1.2 1996/03/14 22:25:29 jaf */ +/* Just rearranged the comments and local variable declarations a bit. */ + +/* Revision 1.1 1996/02/07 14:49:01 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Pseudo random number generator based on Knuth, Vol 2, p. 27. */ + +/* Function Return: */ +/* RANDOM - Integer variable, uniformly distributed over -32768 to 32767 */ + +/* This subroutine maintains local state from one call to the next. */ +/* In the context of the LPC10 coder, there is no reason to reinitialize */ +/* this local state when switching between audio streams, because its */ +/* results are only used to generate noise for unvoiced frames. */ + +integer random_(struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + integer *j; + integer *k; + shortint *y; + + /* System generated locals */ + integer ret_val; + +/* Parameters/constants */ +/* Local state */ +/* The following is a 16 bit 2's complement addition, */ +/* with overflow checking disabled */ + + j = &(st->j); + k = &(st->k); + y = &(st->y[0]); + + y[*k - 1] += y[*j - 1]; + ret_val = y[*k - 1]; + --(*k); + if (*k <= 0) { + *k = 5; + } + --(*j); + if (*j <= 0) { + *j = 5; + } + return ret_val; +} /* random_ */ + diff --git a/codecs/lpc10/rcchk.c b/codecs/lpc10/rcchk.c new file mode 100644 index 000000000..6cb76ef7d --- /dev/null +++ b/codecs/lpc10/rcchk.c @@ -0,0 +1,119 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:30:41 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int rcchk_(integer *order, real *rc1f, real *rc2f); +#endif + +/* ********************************************************************* */ + +/* RCCHK Version 45G */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:30:41 jaf + * Initial revision + * */ +/* Revision 1.4 1996/03/27 18:13:47 jaf */ +/* Commented out a call to subroutine ERROR. */ + +/* Revision 1.3 1996/03/18 15:48:53 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:55:22 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:49:08 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Check RC's, repeat previous frame's RC's if unstable */ + +/* Input: */ +/* ORDER - Number of RC's */ +/* RC1F - Previous frame's RC's */ +/* Indices 1 through ORDER may be read. */ +/* Input/Output: */ +/* RC2F - Present frame's RC's */ +/* Indices 1 through ORDER may be read, and written. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int rcchk_(integer *order, real *rc1f, real *rc2f) +{ + /* System generated locals */ + integer i__1; + real r__1; + + /* Local variables */ + integer i__; + +/* Arguments */ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + --rc2f; + --rc1f; + + /* Function Body */ + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + if ((r__1 = rc2f[i__], abs(r__1)) > .99f) { + goto L10; + } + } + return 0; +/* Note: In version embedded in other software, all calls to ERROR +*/ +/* should probably be removed. */ +L10: + +/* This call to ERROR is only needed for debugging purposes. */ + +/* CALL ERROR('RCCHK',2,I) */ + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + rc2f[i__] = rc1f[i__]; + } + return 0; +} /* rcchk_ */ + diff --git a/codecs/lpc10/synths.c b/codecs/lpc10/synths.c new file mode 100644 index 000000000..4c5a70fac --- /dev/null +++ b/codecs/lpc10/synths.c @@ -0,0 +1,425 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/09/27 02:45:37 markster +Fix various compiler warnings (bug #322) + +Revision 1.2 2003/09/27 02:45:37 markster +Fix various compiler warnings (bug #322) + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:42:59 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:33 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int synths_(integer *voice, integer *pitch, real *rms, real *rc, real *speech, integer *k, struct lpc10_decoder_state *st); +/* comlen contrl_ 12 */ +/*:ref: pitsyn_ 14 12 4 4 4 6 6 4 4 4 6 6 4 6 */ +/*:ref: irc2pc_ 14 5 6 6 4 6 6 */ +/*:ref: bsynz_ 14 7 6 4 4 6 6 6 6 */ +/*:ref: deemp_ 14 2 6 4 */ +/*:ref: initpitsyn_ 14 0 */ +/*:ref: initbsynz_ 14 0 */ +/*:ref: initdeemp_ 14 0 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* Table of constant values */ + +static real c_b2 = .7f; + +/* ***************************************************************** */ + +/* SYNTHS Version 54 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/27 02:45:37 markster + * Fix various compiler warnings (bug #322) + * + * Revision 1.2 2003/09/27 02:45:37 markster + * Fix various compiler warnings (bug #322) + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:42:59 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:33 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/26 19:31:58 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.4 1996/03/25 19:41:01 jaf */ +/* Changed so that MAXFRM samples are always returned in the output array */ +/* SPEECH. */ + +/* This required delaying the returned samples by MAXFRM sample times, */ +/* and remembering any "left over" samples returned by PITSYN from one */ +/* call of SYNTHS to the next. */ + +/* Changed size of SPEECH from 2*MAXFRM to MAXFRM. Removed local */ +/* variable SOUT. Added local state variables BUF and BUFLEN. */ + +/* Revision 1.3 1996/03/25 19:20:10 jaf */ +/* Added comments about the range of possible return values for argument */ +/* K, and increased the size of the arrays filled in by PITSYN from 11 to */ +/* 16, as has been already done inside of PITSYN. */ + +/* Revision 1.2 1996/03/22 00:18:18 jaf */ +/* Added comments explaining meanings of input and output parameters, and */ +/* indicating which array indices can be read or written. */ + +/* Added entry INITSYNTHS, which does nothing except call the */ +/* corresponding initialization entries for subroutines PITSYN, BSYNZ, */ +/* and DEEMP. */ + +/* Revision 1.1 1996/02/07 14:49:44 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* The note below is from the distributed version of the LPC10 coder. */ +/* The version of the code below has been modified so that SYNTHS always */ +/* has a constant frame length output of MAXFRM. */ + +/* Also, BSYNZ and DEEMP need not be modified to work on variable */ +/* positions within an array. It is only necessary to pass the first */ +/* index desired as the array argument. What actually gets passed is the */ +/* address of that array position, which the subroutine treats as the */ +/* first index of the array. */ + +/* This technique is used in subroutine ANALYS when calling PREEMP, so it */ +/* appears that multiple people wrote different parts of this LPC10 code, */ +/* and that they didn't necessarily have equivalent knowledge of Fortran */ +/* (not surprising). */ + +/* NOTE: There is excessive buffering here, BSYNZ and DEEMP should be */ +/* changed to operate on variable positions within SOUT. Also, */ +/* the output length parameter is bogus, and PITSYN should be */ +/* rewritten to allow a constant frame length output. */ + +/* Input: */ +/* VOICE - Half frame voicing decisions */ +/* Indices 1 through 2 read. */ +/* Input/Output: */ +/* PITCH - Pitch */ +/* PITCH is restricted to range 20 to 156, inclusive, */ +/* before calling subroutine PITSYN, and then PITSYN */ +/* can modify it further under some conditions. */ +/* RMS - Energy */ +/* Only use is for debugging, and passed to PITSYN. */ +/* See comments there for how it can be modified. */ +/* RC - Reflection coefficients */ +/* Indices 1 through ORDER restricted to range -.99 to .99, */ +/* before calling subroutine PITSYN, and then PITSYN */ +/* can modify it further under some conditions. */ +/* Output: */ +/* SPEECH - Synthesized speech samples. */ +/* Indices 1 through the final value of K are written. */ +/* K - Number of samples placed into array SPEECH. */ +/* This is always MAXFRM. */ + +/* Subroutine */ int synths_(integer *voice, integer *pitch, real * + rms, real *rc, real *speech, integer *k, struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + real *buf; + integer *buflen; + + /* System generated locals */ + integer i__1; + real r__1, r__2; + + /* Local variables */ + real rmsi[16]; + integer nout, ivuv[16], i__, j; + extern /* Subroutine */ int deemp_(real *, integer *, struct lpc10_decoder_state *); + real ratio; + integer ipiti[16]; + real g2pass; + real pc[10]; + extern /* Subroutine */ int pitsyn_(integer *, integer *, integer *, real + *, real *, integer *, integer *, integer *, real *, real *, + integer *, real *, struct lpc10_decoder_state *); + real rci[160] /* was [10][16] */; + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/27 02:45:37 markster + * Fix various compiler warnings (bug #322) + * + * Revision 1.2 2003/09/27 02:45:37 markster + * Fix various compiler warnings (bug #322) + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:42:59 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:33 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments */ +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/09/27 02:45:37 markster + * Fix various compiler warnings (bug #322) + * + * Revision 1.2 2003/09/27 02:45:37 markster + * Fix various compiler warnings (bug #322) + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:39 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:42:59 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:33 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Parameters/constants */ +/* Local variables that need not be saved */ +/* Local state */ +/* BUF is a buffer of speech samples that would have been returned +*/ +/* by the older version of SYNTHS, but the newer version doesn't, */ +/* so that the newer version can always return MAXFRM samples on */ +/* every call. This has the effect of delaying the return of */ +/* samples for one additional frame time. */ + +/* Indices 1 through BUFLEN contain samples that are left over from +*/ +/* the last call to SYNTHS. Given the way that PITSYN works, */ +/* BUFLEN should always be in the range MAXFRM-MAXPIT+1 through */ +/* MAXFRM, inclusive, after a call to SYNTHS is complete. */ + +/* On the first call to SYNTHS (or the first call after */ +/* reinitializing with the entry INITSYNTHS), BUFLEN is MAXFRM, and +*/ +/* a frame of silence is always returned. */ + /* Parameter adjustments */ + if (voice) { + --voice; + } + if (rc) { + --rc; + } + if (speech) { + --speech; + } + + /* Function Body */ + buf = &(st->buf[0]); + buflen = &(st->buflen); + +/* Computing MAX */ + i__1 = min(*pitch,156); + *pitch = max(i__1,20); + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { +/* Computing MAX */ +/* Computing MIN */ + r__2 = rc[i__]; + r__1 = min(r__2,.99f); + rc[i__] = max(r__1,-.99f); + } + pitsyn_(&contrl_1.order, &voice[1], pitch, rms, &rc[1], &contrl_1.lframe, + ivuv, ipiti, rmsi, rci, &nout, &ratio, st); + if (nout > 0) { + i__1 = nout; + for (j = 1; j <= i__1; ++j) { + +/* Add synthesized speech for pitch period J to the en +d of */ +/* BUF. */ + + irc2pc_(&rci[j * 10 - 10], pc, &contrl_1.order, &c_b2, &g2pass); + bsynz_(pc, &ipiti[j - 1], &ivuv[j - 1], &buf[*buflen], &rmsi[j - 1] + , &ratio, &g2pass, st); + deemp_(&buf[*buflen], &ipiti[j - 1], st); + *buflen += ipiti[j - 1]; + } + +/* Copy first MAXFRM samples from BUF to output array SPEECH +*/ +/* (scaling them), and then remove them from the beginning of + */ +/* BUF. */ + + for (i__ = 1; i__ <= 180; ++i__) { + speech[i__] = buf[i__ - 1] / 4096.f; + } + *k = 180; + *buflen += -180; + i__1 = *buflen; + for (i__ = 1; i__ <= i__1; ++i__) { + buf[i__ - 1] = buf[i__ + 179]; + } + } + return 0; +} /* synths_ */ diff --git a/codecs/lpc10/tbdm.c b/codecs/lpc10/tbdm.c new file mode 100644 index 000000000..2f6f3d692 --- /dev/null +++ b/codecs/lpc10/tbdm.c @@ -0,0 +1,188 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:40 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:30:26 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int tbdm_(real *speech, integer *lpita, integer *tau, integer *ltau, real *amdf, integer *minptr, integer *maxptr, integer *mintau); +/*:ref: difmag_ 14 8 6 4 4 4 4 6 4 4 */ +#endif + +/* ********************************************************************** */ + +/* TBDM Version 49 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:40 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:30:26 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/18 22:14:00 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 14:48:37 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:49:54 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/*TURBO DIFMAG: Compute High Resolution Average Magnitude Difference Function +*/ + +/* Note: There are several constants in here that appear to depend on a */ +/* particular TAU table. That's not a problem for the LPC10 coder, but */ +/* watch out if you change the contents of TAU in the subroutine ANALYS. */ + +/* Input: */ +/* SPEECH - Low pass filtered speech */ +/* Indices 1 through MAX+LPITA-1 are read, where: */ +/* MAX = (TAU(LTAU)-TAU(1))/2+1 */ +/* (If TAU(1) .LT. 39, then larger indices could be read */ +/* by the last call to DIFMAG below.) */ +/* LPITA - Length of speech buffer */ +/* TAU - Table of lags, sorted in increasing order. */ +/* Indices 1 through LTAU read. */ +/* LTAU - Number of lag values to compute */ +/* Output: */ +/* AMDF - Average Magnitude Difference for each lag in TAU */ +/* Indices 1 through LTAU written, and several might then be read.*/ +/* MINPTR - Index of minimum AMDF value */ +/* MAXPTR - Index of maximum AMDF value within +/- 1/2 octave of min */ +/* MINTAU - Lag corresponding to minimum AMDF value */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int tbdm_(real *speech, integer *lpita, integer *tau, + integer *ltau, real *amdf, integer *minptr, integer *maxptr, integer * + mintau) +{ + /* System generated locals */ + integer i__1, i__2, i__3, i__4; + + /* Local variables */ + real amdf2[6]; + integer minp2, ltau2, maxp2, i__; + extern /* Subroutine */ int difmag_(real *, integer *, integer *, integer + *, integer *, real *, integer *, integer *); + integer minamd, ptr, tau2[6]; + +/* Arguments */ +/* REAL SPEECH(LPITA+TAU(LTAU)), AMDF(LTAU) */ +/* Stupid TOAST doesn't understand expressions */ +/* Local variables that need not be saved */ +/* Local state */ +/* None */ +/* Compute full AMDF using log spaced lags, find coarse minimum */ + /* Parameter adjustments */ + --speech; + --amdf; + --tau; + + /* Function Body */ + difmag_(&speech[1], lpita, &tau[1], ltau, &tau[*ltau], &amdf[1], minptr, + maxptr); + *mintau = tau[*minptr]; + minamd = (integer)amdf[*minptr]; +/* Build table containing all lags within +/- 3 of the AMDF minimum */ +/* excluding all that have already been computed */ + ltau2 = 0; + ptr = *minptr - 2; +/* Computing MAX */ + i__1 = *mintau - 3; +/* Computing MIN */ + i__3 = *mintau + 3, i__4 = tau[*ltau] - 1; + i__2 = min(i__3,i__4); + for (i__ = max(i__1,41); i__ <= i__2; ++i__) { + while(tau[ptr] < i__) { + ++ptr; + } + if (tau[ptr] != i__) { + ++ltau2; + tau2[ltau2 - 1] = i__; + } + } +/* Compute AMDF of the new lags, if there are any, and choose one */ +/* if it is better than the coarse minimum */ + if (ltau2 > 0) { + difmag_(&speech[1], lpita, tau2, <au2, &tau[*ltau], amdf2, &minp2, & + maxp2); + if (amdf2[minp2 - 1] < (real) minamd) { + *mintau = tau2[minp2 - 1]; + minamd = (integer)amdf2[minp2 - 1]; + } + } +/* Check one octave up, if there are any lags not yet computed */ + if (*mintau >= 80) { + i__ = *mintau / 2; + if ((i__ & 1) == 0) { + ltau2 = 2; + tau2[0] = i__ - 1; + tau2[1] = i__ + 1; + } else { + ltau2 = 1; + tau2[0] = i__; + } + difmag_(&speech[1], lpita, tau2, <au2, &tau[*ltau], amdf2, &minp2, & + maxp2); + if (amdf2[minp2 - 1] < (real) minamd) { + *mintau = tau2[minp2 - 1]; + minamd = (integer)amdf2[minp2 - 1]; + *minptr += -20; + } + } +/* Force minimum of the AMDF array to the high resolution minimum */ + amdf[*minptr] = (real) minamd; +/* Find maximum of AMDF within 1/2 octave of minimum */ +/* Computing MAX */ + i__2 = *minptr - 5; + *maxptr = max(i__2,1); +/* Computing MIN */ + i__1 = *minptr + 5; + i__2 = min(i__1,*ltau); + for (i__ = *maxptr + 1; i__ <= i__2; ++i__) { + if (amdf[i__] > amdf[*maxptr]) { + *maxptr = i__; + } + } + return 0; +} /* tbdm_ */ + diff --git a/codecs/lpc10/voicin.c b/codecs/lpc10/voicin.c new file mode 100644 index 000000000..3605d2f2e --- /dev/null +++ b/codecs/lpc10/voicin.c @@ -0,0 +1,786 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/11/23 22:14:32 markster +Various warning cleanups + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:40 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:45:00 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:30:14 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int voicin_(integer *vwin, real *inbuf, real *lpbuf, integer *buflim, integer *half, real *minamd, real *maxamd, integer *mintau, real *ivrc, integer *obound, integer *voibuf, integer *af, struct lpc10_encoder_state *st); +/* comlen contrl_ 12 */ +/*:ref: vparms_ 14 14 4 6 6 4 4 6 4 4 4 4 6 6 6 6 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/****************************************************************************/ + +/* VOICIN Version 52 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/11/23 22:14:32 markster + * Various warning cleanups + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:40 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:45:00 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:30:14 jaf + * Initial revision + * */ +/* Revision 1.10 1996/03/29 17:59:14 jaf */ +/* Avoided using VALUE(9), although it shouldn't affect the function of */ +/* the code at all, because it was always multiplied by VDC(9,SNRL), */ +/* which is 0 for all values of SNRL. Still, if VALUE(9) had an initial */ +/* value of IEEE NaN, it might cause trouble (I don't know how IEEE */ +/* defines Nan * 0. It should either be NaN or 0.) */ + +/* Revision 1.9 1996/03/29 17:54:46 jaf */ +/* Added a few comments about the accesses made to argument array VOIBUF */ +/* and the local saved array VOICE. */ + +/* Revision 1.8 1996/03/27 18:19:54 jaf */ +/* Added an assignment to VSTATE that does not affect the function of the */ +/* program at all. The only reason I put it in was so that the tracing */ +/* statements at the end, when enabled, will print a consistent value for */ +/* VSTATE when HALF .EQ. 1, rather than a garbage value that could change */ +/* from one call to the next. */ + +/* Revision 1.7 1996/03/26 20:00:06 jaf */ +/* Removed the inclusion of the file "vcomm.fh", and put its contents */ +/* into this file. It was included nowhere else but here. */ + +/* Revision 1.6 1996/03/26 19:38:09 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.5 1996/03/19 20:43:45 jaf */ +/* Added comments about which indices of OBOUND and VOIBUF can be */ +/* accessed, and whether they are read or written. VOIBUF is fairly */ +/* messy. */ + +/* Revision 1.4 1996/03/19 15:00:58 jaf */ +/* Moved the DATA statements for the *VDC* variables later, as it is */ +/* apparently illegal to have DATA statements before local variable */ +/* declarations. */ + +/* Revision 1.3 1996/03/19 00:10:49 jaf */ +/* Heavily commented the local variables that are saved from one */ +/* invocation to the next, and how the local variable FIRST is used to */ +/* avoid the need to assign most of them initial values with DATA */ +/* statements. */ + +/* A few should be initialized, but aren't. I've guessed initial values */ +/* for two of these, SFBUE and SLBUE, and I've convinced myself that for */ +/* VOICE, the effects of uninitialized values will die out after 2 or 3 */ +/* frame times. It would still be good to choose initial values for */ +/* these, but I don't know what reasonable values would be (0 comes to */ +/* mind). */ + +/* Revision 1.2 1996/03/13 16:09:28 jaf */ +/* Comments added explaining which of the local variables of this */ +/* subroutine need to be saved from one invocation to the next, and which */ +/* do not. */ + +/* WARNING! Some of them that should are never given initial values in */ +/* this code. Hopefully, Fortran 77 defines initial values for them, but */ +/* even so, giving them explicit initial values is preferable. */ + +/* WARNING! VALUE(9) is used, but never assigned a value. It should */ +/* probably be eliminated from the code. */ + +/* Revision 1.1 1996/02/07 14:50:28 jaf */ +/* Initial revision */ + + +/****************************************************************************/ + +/* Voicing Detection (VOICIN) makes voicing decisions for each half */ +/* frame of input speech. Tentative voicing decisions are made two frames*/ +/* in the future (2F) for each half frame. These decisions are carried */ +/* through one frame in the future (1F) to the present (P) frame where */ +/* they are examined and smoothed, resulting in the final voicing */ +/* decisions for each half frame. */ +/* The voicing parameter (signal measurement) column vector (VALUE) */ +/* is based on a rectangular window of speech samples determined by the */ +/* window placement algorithm. The voicing parameter vector contains the*/ +/* AMDF windowed maximum-to-minimum ratio, the zero crossing rate, energy*/ +/* measures, reflection coefficients, and prediction gains. The voicing */ +/* window is placed to avoid contamination of the voicing parameter vector*/ +/* with speech onsets. */ +/* The input signal is then classified as unvoiced (including */ +/* silence) or voiced. This decision is made by a linear discriminant */ +/* function consisting of a dot product of the voicing decision */ +/* coefficient (VDC) row vector with the measurement column vector */ +/* (VALUE). The VDC vector is 2-dimensional, each row vector is optimized*/ +/* for a particular signal-to-noise ratio (SNR). So, before the dot */ +/* product is performed, the SNR is estimated to select the appropriate */ +/* VDC vector. */ +/* The smoothing algorithm is a modified median smoother. The */ +/* voicing discriminant function is used by the smoother to determine how*/ +/* strongly voiced or unvoiced a signal is. The smoothing is further */ +/* modified if a speech onset and a voicing decision transition occur */ +/* within one half frame. In this case, the voicing decision transition */ +/* is extended to the speech onset. For transmission purposes, there are*/ +/* constraints on the duration and transition of voicing decisions. The */ +/* smoother takes these constraints into account. */ +/* Finally, the energy estimates are updated along with the dither */ +/* threshold used to calculate the zero crossing rate (ZC). */ + +/* Inputs: */ +/* VWIN - Voicing window limits */ +/* The indices read of arrays VWIN, INBUF, LPBUF, and BUFLIM */ +/* are the same as those read by subroutine VPARMS. */ +/* INBUF - Input speech buffer */ +/* LPBUF - Low-pass filtered speech buffer */ +/* BUFLIM - INBUF and LPBUF limits */ +/* HALF - Present analysis half frame number */ +/* MINAMD - Minimum value of the AMDF */ +/* MAXAMD - Maximum value of the AMDF */ +/* MINTAU - Pointer to the lag of the minimum AMDF value */ +/* IVRC(2) - Inverse filter's RC's */ +/* Only index 2 of array IVRC read under normal operation. */ +/* (Index 1 is also read when debugging is turned on.) */ +/* OBOUND - Onset boundary descriptions */ +/* Indices 1 through 3 read if (HALF .NE. 1), otherwise untouched. +*/ +/* AF - The analysis frame number */ +/* Output: */ +/* VOIBUF(2,0:AF) - Buffer of voicing decisions */ +/* Index (HALF,3) written. */ +/* If (HALF .EQ. 1), skip down to "Read (HALF,3)" below. */ +/* Indices (1,2), (2,1), (1,2), and (2,2) read. */ +/* One of the following is then done: */ +/* read (1,3) and possibly write (1,2) */ +/* read (1,3) and write (1,2) or (2,2) */ +/* write (2,1) */ +/* write (2,1) or (1,2) */ +/* read (1,0) and (1,3) and then write (2,2) or (1,1) */ +/* no reads or writes on VOIBUF */ +/* Finally, read (HALF,3) */ +/* Internal: */ +/* QS - Ratio of preemphasized to full-band energies */ +/* RC1 - First reflection coefficient */ +/* AR_B - Product of the causal forward and reverse pitch prediction gain +s*/ +/* AR_F - Product of the noncausal forward and rev. pitch prediction gain +s*/ +/* ZC - Zero crossing rate */ +/* DITHER - Zero crossing threshold level */ +/* MAXMIN - AMDF's 1 octave windowed maximum-to-minimum ratio */ +/* MINPTR - Location of minimum AMDF value */ +/* NVDC - Number of elements in each VDC vector */ +/* NVDCL - Number of VDC vectors */ +/* VDCL - SNR values corresponding to the set of VDC's */ +/* VDC - 2-D voicing decision coefficient vector */ +/* VALUE(9) - Voicing Parameters */ +/* VOICE(2,3)- History of LDA results */ +/* On every call when (HALF .EQ. 1), VOICE(*,I+1) is */ +/* shifted back to VOICE(*,I), for I=1,2. */ +/* VOICE(HALF,3) is written on every call. */ +/* Depending on several conditions, one or more of */ +/* (1,1), (1,2), (2,1), and (2,2) might then be read. */ +/* LBE - Ratio of low-band instantaneous to average energies */ +/* FBE - Ratio of full-band instantaneous to average energies */ +/* LBVE - Low band voiced energy */ +/* LBUE - Low band unvoiced energy */ +/* FBVE - Full band voiced energy */ +/* FBUE - Full band unvoiced energy */ +/* OFBUE - Previous full-band unvoiced energy */ +/* OLBUE - Previous low-band unvoiced energy */ +/* REF - Reference energy for initialization and DITHER threshold */ +/* SNR - Estimate of signal-to-noise ratio */ +/* SNR2 - Estimate of low-band signal-to-noise ratio */ +/* SNRL - SNR level number */ +/* OT - Onset transition present */ +/* VSTATE - Decimal interpretation of binary voicing classifications */ +/* FIRST - First call flag */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITVOICIN. */ + +/* Subroutine */ int voicin_(integer *vwin, real *inbuf, real * + lpbuf, integer *buflim, integer *half, real *minamd, real *maxamd, + integer *mintau, real *ivrc, integer *obound, integer *voibuf, + integer *af, struct lpc10_encoder_state *st) +{ + /* Initialized data */ + + real *dither; + static real vdc[100] /* was [10][10] */ = { 0.f,1714.f,-110.f, + 334.f,-4096.f,-654.f,3752.f,3769.f,0.f,1181.f,0.f,874.f,-97.f, + 300.f,-4096.f,-1021.f,2451.f,2527.f,0.f,-500.f,0.f,510.f,-70.f, + 250.f,-4096.f,-1270.f,2194.f,2491.f,0.f,-1500.f,0.f,500.f,-10.f, + 200.f,-4096.f,-1300.f,2e3f,2e3f,0.f,-2e3f,0.f,500.f,0.f,0.f, + -4096.f,-1300.f,2e3f,2e3f,0.f,-2500.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f, + 0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f, + 0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f, + 0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f }; + static integer nvdcl = 5; + static real vdcl[10] = { 600.f,450.f,300.f,200.f,0.f,0.f,0.f,0.f,0.f,0.f } + ; + + /* System generated locals */ + integer inbuf_offset = 0, lpbuf_offset = 0, i__1, i__2; + real r__1, r__2; + + /* Builtin functions */ + integer i_nint(real *); + double sqrt(doublereal); + + /* Local variables */ + real ar_b__, ar_f__; + integer *lbve, *lbue, *fbve, *fbue; + integer snrl, i__; + integer *ofbue, *sfbue; + real *voice; + integer *olbue, *slbue; + real value[9]; + integer zc; + logical ot; + real qs; + real *maxmin; + integer vstate; + real rc1; + extern /* Subroutine */ int vparms_(integer *, real *, real *, integer *, + integer *, real *, integer *, integer *, integer *, integer *, + real *, real *, real *, real *); + integer fbe, lbe; + real *snr; + real snr2; + +/* Global Variables: */ +/* Arguments */ +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.15 2003/11/23 22:14:32 markster + * Various warning cleanups + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:40 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.2 1996/08/20 20:45:00 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:30:14 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Parameters/constants */ +/* Voicing coefficient and Linear Discriminant Analysis variables: +*/ +/* Max number of VDC's and VDC levels */ +/* The following are not Fortran PARAMETER's, but they are */ +/* initialized with DATA statements, and never modified. */ +/* Actual number of VDC's and levels */ +/* Local variables that need not be saved */ +/* Note: */ + +/* VALUE(1) through VALUE(8) are assigned values, but VALUE(9) */ +/* never is. Yet VALUE(9) is read in the loop that begins "DO I = +*/ +/* 1, 9" below. I believe that this doesn't cause any problems in +*/ +/* this subroutine, because all VDC(9,*) array elements are 0, and +*/ +/* this is what is multiplied by VALUE(9) in all cases. Still, it +*/ +/* would save a multiplication to change the loop to "DO I = 1, 8". +*/ +/* Local state */ +/* WARNING! */ + +/* VOICE, SFBUE, and SLBUE should be saved from one invocation to */ +/* the next, but they are never given an initial value. */ + +/* Does Fortran 77 specify some default initial value, like 0, or */ +/* is it undefined? If it is undefined, then this code should be */ +/* corrected to specify an initial value. */ + +/* For VOICE, note that it is "shifted" in the statement that */ +/* begins "IF (HALF .EQ. 1) THEN" below. Also, uninitialized */ +/* values in the VOICE array can only affect entries in the VOIBUF +*/ +/* array that are for the same frame, or for an older frame. Thus +*/ +/* the effects of uninitialized values in VOICE cannot linger on */ +/* for more than 2 or 3 frame times. */ + +/* For SFBUE and SLBUE, the effects of uninitialized values can */ +/* linger on for many frame times, because their previous values */ +/* are exponentially decayed. Thus it is more important to choose +*/ +/* initial values for these variables. I would guess that a */ +/* reasonable initial value for SFBUE is REF/16, the same as used */ +/* for FBUE and OFBUE. Similarly, SLBUE can be initialized to */ +/* REF/32, the same as for LBUE and OLBUE. */ + +/* These guessed initial values should be validated by re-running */ +/* the modified program on some audio samples. */ + +/* Declare and initialize filters: */ + + dither = (&st->dither); + snr = (&st->snr); + maxmin = (&st->maxmin); + voice = (&st->voice[0]); + lbve = (&st->lbve); + lbue = (&st->lbue); + fbve = (&st->fbve); + fbue = (&st->fbue); + ofbue = (&st->ofbue); + olbue = (&st->olbue); + sfbue = (&st->sfbue); + slbue = (&st->slbue); + + /* Parameter adjustments */ + if (vwin) { + --vwin; + } + if (buflim) { + --buflim; + } + if (inbuf) { + inbuf_offset = buflim[1]; + inbuf -= inbuf_offset; + } + if (lpbuf) { + lpbuf_offset = buflim[3]; + lpbuf -= lpbuf_offset; + } + if (ivrc) { + --ivrc; + } + if (obound) { + --obound; + } + if (voibuf) { + --voibuf; + } + + /* Function Body */ + +/* The following variables are saved from one invocation to the */ +/* next, but are not initialized with DATA statements. This is */ +/* acceptable, because FIRST is initialized ot .TRUE., and the */ +/* first time that this subroutine is then called, they are all */ +/* given initial values. */ + +/* SNR */ +/* LBVE, LBUE, FBVE, FBUE, OFBUE, OLBUE */ + +/* MAXMIN is initialized on the first call, assuming that HALF */ +/* .EQ. 1 on first call. This is how ANALYS calls this subroutine. +*/ + +/* Voicing Decision Parameter vector (* denotes zero coefficient): */ + +/* * MAXMIN */ +/* LBE/LBVE */ +/* ZC */ +/* RC1 */ +/* QS */ +/* IVRC2 */ +/* aR_B */ +/* aR_F */ +/* * LOG(LBE/LBVE) */ +/* Define 2-D voicing decision coefficient vector according to the voicin +g*/ +/* parameter order above. Each row (VDC vector) is optimized for a speci +fic*/ +/* SNR. The last element of the vector is the constant. */ +/* E ZC RC1 Qs IVRC2 aRb aRf c */ + +/* The VOICE array contains the result of the linear discriminant functio +n*/ +/* (analog values). The VOIBUF array contains the hard-limited binary +*/ +/* voicing decisions. The VOICE and VOIBUF arrays, according to FORTRAN + */ +/* memory allocation, are addressed as: */ + +/* (half-frame number, future-frame number) */ + +/* | Past | Present | Future1 | Future2 | */ +/* | 1,0 | 2,0 | 1,1 | 2,1 | 1,2 | 2,2 | 1,3 | 2,3 | ---> time */ + +/* Update linear discriminant function history each frame: */ + if (*half == 1) { + voice[0] = voice[2]; + voice[1] = voice[3]; + voice[2] = voice[4]; + voice[3] = voice[5]; + *maxmin = *maxamd / max(*minamd,1.f); + } +/* Calculate voicing parameters twice per frame: */ + vparms_(&vwin[1], &inbuf[inbuf_offset], &lpbuf[lpbuf_offset], &buflim[1], + half, dither, mintau, &zc, &lbe, &fbe, &qs, &rc1, &ar_b__, & + ar_f__); +/* Estimate signal-to-noise ratio to select the appropriate VDC vector. +*/ +/* The SNR is estimated as the running average of the ratio of the */ +/* running average full-band voiced energy to the running average */ +/* full-band unvoiced energy. SNR filter has gain of 63. */ + r__1 = (*snr + *fbve / (real) max(*fbue,1)) * 63 / 64.f; + *snr = (real) i_nint(&r__1); + snr2 = *snr * *fbue / max(*lbue,1); +/* Quantize SNR to SNRL according to VDCL thresholds. */ + snrl = 1; + i__1 = nvdcl - 1; + for (snrl = 1; snrl <= i__1; ++snrl) { + if (snr2 > vdcl[snrl - 1]) { + goto L69; + } + } +/* (Note: SNRL = NVDCL here) */ +L69: +/* Linear discriminant voicing parameters: */ + value[0] = *maxmin; + value[1] = (real) lbe / max(*lbve,1); + value[2] = (real) zc; + value[3] = rc1; + value[4] = qs; + value[5] = ivrc[2]; + value[6] = ar_b__; + value[7] = ar_f__; +/* Evaluation of linear discriminant function: */ + voice[*half + 3] = vdc[snrl * 10 - 1]; + for (i__ = 1; i__ <= 8; ++i__) { + voice[*half + 3] += vdc[i__ + snrl * 10 - 11] * value[i__ - 1]; + } +/* Classify as voiced if discriminant > 0, otherwise unvoiced */ +/* Voicing decision for current half-frame: 1 = Voiced; 0 = Unvoiced */ + if (voice[*half + 3] > 0.f) { + voibuf[*half + 6] = 1; + } else { + voibuf[*half + 6] = 0; + } +/* Skip voicing decision smoothing in first half-frame: */ +/* Give a value to VSTATE, so that trace statements below will print +*/ +/* a consistent value from one call to the next when HALF .EQ. 1. */ +/* The value of VSTATE is not used for any other purpose when this is +*/ +/* true. */ + vstate = -1; + if (*half == 1) { + goto L99; + } +/* Voicing decision smoothing rules (override of linear combination): */ + +/* Unvoiced half-frames: At least two in a row. */ +/* -------------------- */ + +/* Voiced half-frames: At least two in a row in one frame. */ +/* ------------------- Otherwise at least three in a row. */ +/* (Due to the way transition frames are encoded) */ + +/* In many cases, the discriminant function determines how to smooth. */ +/* In the following chart, the decisions marked with a * may be overridden +.*/ + +/* Voicing override of transitions at onsets: */ +/* If a V/UV or UV/V voicing decision transition occurs within one-half +*/ +/* frame of an onset bounding a voicing window, then the transition is */ +/* moved to occur at the onset. */ + +/* P 1F */ +/* ----- ----- */ +/* 0 0 0 0 */ +/* 0 0 0* 1 (If there is an onset there) */ +/* 0 0 1* 0* (Based on 2F and discriminant distance) */ +/* 0 0 1 1 */ +/* 0 1* 0 0 (Always) */ +/* 0 1* 0* 1 (Based on discriminant distance) */ +/* 0* 1 1 0* (Based on past, 2F, and discriminant distance) */ +/* 0 1* 1 1 (If there is an onset there) */ +/* 1 0* 0 0 (If there is an onset there) */ +/* 1 0 0 1 */ +/* 1 0* 1* 0 (Based on discriminant distance) */ +/* 1 0* 1 1 (Always) */ +/* 1 1 0 0 */ +/* 1 1 0* 1* (Based on 2F and discriminant distance) */ +/* 1 1 1* 0 (If there is an onset there) */ +/* 1 1 1 1 */ + +/* Determine if there is an onset transition between P and 1F. */ +/* OT (Onset Transition) is true if there is an onset between */ +/* P and 1F but not after 1F. */ + ot = ((obound[1] & 2) != 0 || obound[2] == 1) && (obound[3] & 1) == 0; +/* Multi-way dispatch on voicing decision history: */ + vstate = (voibuf[3] << 3) + (voibuf[4] << 2) + (voibuf[5] << 1) + voibuf[ + 6]; + switch (vstate + 1) { + case 1: goto L99; + case 2: goto L1; + case 3: goto L2; + case 4: goto L99; + case 5: goto L4; + case 6: goto L5; + case 7: goto L6; + case 8: goto L7; + case 9: goto L8; + case 10: goto L99; + case 11: goto L10; + case 12: goto L11; + case 13: goto L99; + case 14: goto L13; + case 15: goto L14; + case 16: goto L99; + } +L1: + if (ot && voibuf[7] == 1) { + voibuf[5] = 1; + } + goto L99; +L2: + if (voibuf[7] == 0 || voice[2] < -voice[3]) { + voibuf[5] = 0; + } else { + voibuf[6] = 1; + } + goto L99; +L4: + voibuf[4] = 0; + goto L99; +L5: + if (voice[1] < -voice[2]) { + voibuf[4] = 0; + } else { + voibuf[5] = 1; + } + goto L99; +/* VOIBUF(2,0) must be 0 */ +L6: + if (voibuf[1] == 1 || voibuf[7] == 1 || voice[3] > voice[0]) { + voibuf[6] = 1; + } else { + voibuf[3] = 1; + } + goto L99; +L7: + if (ot) { + voibuf[4] = 0; + } + goto L99; +L8: + if (ot) { + voibuf[4] = 1; + } + goto L99; +L10: + if (voice[2] < -voice[1]) { + voibuf[5] = 0; + } else { + voibuf[4] = 1; + } + goto L99; +L11: + voibuf[4] = 1; + goto L99; +L13: + if (voibuf[7] == 0 && voice[3] < -voice[2]) { + voibuf[6] = 0; + } else { + voibuf[5] = 1; + } + goto L99; +L14: + if (ot && voibuf[7] == 0) { + voibuf[5] = 0; + } +/* GOTO 99 */ +L99: +/* Now update parameters: */ +/* ---------------------- */ + +/* During unvoiced half-frames, update the low band and full band unvoice +d*/ +/* energy estimates (LBUE and FBUE) and also the zero crossing */ +/* threshold (DITHER). (The input to the unvoiced energy filters is */ +/* restricted to be less than 10dB above the previous inputs of the */ +/* filters.) */ +/* During voiced half-frames, update the low-pass (LBVE) and all-pass */ +/* (FBVE) voiced energy estimates. */ + if (voibuf[*half + 6] == 0) { +/* Computing MIN */ + i__1 = fbe, i__2 = *ofbue * 3; + r__1 = (*sfbue * 63 + (min(i__1,i__2) << 3)) / 64.f; + *sfbue = i_nint(&r__1); + *fbue = *sfbue / 8; + *ofbue = fbe; +/* Computing MIN */ + i__1 = lbe, i__2 = *olbue * 3; + r__1 = (*slbue * 63 + (min(i__1,i__2) << 3)) / 64.f; + *slbue = i_nint(&r__1); + *lbue = *slbue / 8; + *olbue = lbe; + } else { + r__1 = (*lbve * 63 + lbe) / 64.f; + *lbve = i_nint(&r__1); + r__1 = (*fbve * 63 + fbe) / 64.f; + *fbve = i_nint(&r__1); + } +/* Set dither threshold to yield proper zero crossing rates in the */ +/* presence of low frequency noise and low level signal input. */ +/* NOTE: The divisor is a function of REF, the expected energies. */ +/* Computing MIN */ +/* Computing MAX */ + r__2 = (real)(sqrt((real) (*lbue * *lbve)) * 64 / 3000); + r__1 = max(r__2,1.f); + *dither = min(r__1,20.f); +/* Voicing decisions are returned in VOIBUF. */ + return 0; +} /* voicin_ */ diff --git a/codecs/lpc10/vparms.c b/codecs/lpc10/vparms.c new file mode 100644 index 000000000..c75b1b17d --- /dev/null +++ b/codecs/lpc10/vparms.c @@ -0,0 +1,255 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:40 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:30:04 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int vparms_(integer *vwin, real *inbuf, real *lpbuf, integer *buflim, integer *half, real *dither, integer *mintau, integer *zc, integer *lbe, integer *fbe, real *qs, real *rc1, real *ar_b__, real *ar_f__); +#endif + +/* Table of constant values */ + +static real c_b2 = 1.f; + +/* ********************************************************************* */ + +/* VPARMS Version 50 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * + * Revision 1.14 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.1.1.1 2003/02/12 13:59:15 matteo + * mer feb 12 14:56:57 CET 2003 + * + * Revision 1.2 2000/01/05 08:20:40 markster + * Some OSS fixes and a few lpc changes to make it actually work + * + * Revision 1.1 1996/08/19 22:30:04 jaf + * Initial revision + * */ +/* Revision 1.6 1996/03/29 18:01:16 jaf */ +/* Added some more comments about the range of INBUF and LPBUF that can */ +/* be read. Note that it is possible for index VWIN(2)+1 to be read from */ +/* INBUF, which might be outside of its defined range, although that will */ +/* require more careful checking. */ + +/* Revision 1.5 1996/03/19 00:02:02 jaf */ +/* I just noticed that the argument DITHER is modified inside of this */ +/* subroutine. Comments were added explaining the possible final values. */ + +/* Revision 1.4 1996/03/18 22:22:59 jaf */ +/* Finishing the job I said I did with the last check-in comments. */ + +/* Revision 1.3 1996/03/18 22:22:17 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 15:02:58 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:50:42 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Calculate voicing parameters: */ + +/* Input: */ +/* VWIN - Voicing window limits */ +/* Indices 1 through 2 read. */ +/* INBUF - Input speech buffer */ +/* Indices START-1 through STOP read, */ +/* where START and STOP are defined in the code (only written once). +*/ +/* Note that STOP can be as large as VWIN(2)+1 ! */ +/* LPBUF - Low pass filtered speech */ +/* Indices START-MINTAU through STOP+MINTAU read, */ +/* where START and STOP are defined in the code (only written once). +*/ +/* BUFLIM - Array bounds for INBUF and LPBUF */ +/* Indices 1 through 4 read. */ +/* HALF - Half frame (1 or 2) */ +/* MINTAU - Lag corresponding to minimum AMDF value (pitch estimate) */ +/* Input/Output: */ +/* DITHER - Zero crossing threshold */ +/* The resulting value might be the negation of the input */ +/* value. It might always be the same as the input value, */ +/* if the DO loop below always executes an even number of times. */ +/* Output: (all of them are written on every call) */ +/* ZC - Zero crossing rate */ +/* LBE - Low band energy (sum of magnitudes - SM) */ +/* FBE - Full band energy (SM) */ +/* QS - Ratio of 6 dB/oct preemphasized energy to full band energy */ +/* RC1 - First reflection coefficient */ +/* AR_B - Product of the causal forward and reverse pitch */ +/* prediction gains */ +/* AR_F - Product of the noncausal forward and reverse pitch */ +/* prediction gains */ +/* Internal: */ +/* OLDSGN - Previous sign of dithered signal */ +/* VLEN - Length of voicing window */ +/* START - Lower address of current half of voicing window */ +/* STOP - Upper address of current half of voicing window */ +/* E_0 - Energy of LPF speech (sum of squares - SS) */ +/* E_B - Energy of LPF speech backward one pitch period (SS) */ +/* E_F - Energy of LPF speech forward one pitch period (SS) */ +/* R_B - Autocovariance of LPF speech backward one pitch period */ +/* R_F - Autocovariance of LPF speech forward one pitch period */ +/* LP_RMS - Energy of LPF speech (sum of magnitudes - SM) */ +/* AP_RMS - Energy of all-pass speech (SM) */ +/* E_PRE - Energy of 6dB preemphasized speech (SM) */ +/* E0AP - Energy of all-pass speech (SS) */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int vparms_(integer *vwin, real *inbuf, real *lpbuf, integer + *buflim, integer *half, real *dither, integer *mintau, integer *zc, + integer *lbe, integer *fbe, real *qs, real *rc1, real *ar_b__, real * + ar_f__) +{ + /* System generated locals */ + integer inbuf_offset, lpbuf_offset, i__1; + real r__1, r__2; + + /* Builtin functions */ + double r_sign(real *, real *); + integer i_nint(real *); + + /* Local variables */ + integer vlen, stop, i__; + real e_pre__; + integer start; + real ap_rms__, e_0__, oldsgn, lp_rms__, e_b__, e_f__, r_b__, r_f__, e0ap; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Calculate zero crossings (ZC) and several energy and correlation */ +/* measures on low band and full band speech. Each measure is taken */ +/* over either the first or the second half of the voicing window, */ +/* depending on the variable HALF. */ + /* Parameter adjustments */ + --vwin; + --buflim; + lpbuf_offset = buflim[3]; + lpbuf -= lpbuf_offset; + inbuf_offset = buflim[1]; + inbuf -= inbuf_offset; + + /* Function Body */ + lp_rms__ = 0.f; + ap_rms__ = 0.f; + e_pre__ = 0.f; + e0ap = 0.f; + *rc1 = 0.f; + e_0__ = 0.f; + e_b__ = 0.f; + e_f__ = 0.f; + r_f__ = 0.f; + r_b__ = 0.f; + *zc = 0; + vlen = vwin[2] - vwin[1] + 1; + start = vwin[1] + (*half - 1) * vlen / 2 + 1; + stop = start + vlen / 2 - 1; + +/* I'll use the symbol HVL in the table below to represent the value */ +/* VLEN/2. Note that if VLEN is odd, then HVL should be rounded down, */ +/* i.e., HVL = (VLEN-1)/2. */ + +/* HALF START STOP */ + +/* 1 VWIN(1)+1 VWIN(1)+HVL */ +/* 2 VWIN(1)+HVL+1 VWIN(1)+2*HVL */ + +/* Note that if VLEN is even and HALF is 2, then STOP will be */ +/* VWIN(1)+VLEN = VWIN(2)+1. That could be bad, if that index of INBUF */ +/* is undefined. */ + + r__1 = inbuf[start - 1] - *dither; + oldsgn = (real)r_sign(&c_b2, &r__1); + i__1 = stop; + for (i__ = start; i__ <= i__1; ++i__) { + lp_rms__ += (r__1 = lpbuf[i__], abs(r__1)); + ap_rms__ += (r__1 = inbuf[i__], abs(r__1)); + e_pre__ += (r__1 = inbuf[i__] - inbuf[i__ - 1], abs(r__1)); +/* Computing 2nd power */ + r__1 = inbuf[i__]; + e0ap += r__1 * r__1; + *rc1 += inbuf[i__] * inbuf[i__ - 1]; +/* Computing 2nd power */ + r__1 = lpbuf[i__]; + e_0__ += r__1 * r__1; +/* Computing 2nd power */ + r__1 = lpbuf[i__ - *mintau]; + e_b__ += r__1 * r__1; +/* Computing 2nd power */ + r__1 = lpbuf[i__ + *mintau]; + e_f__ += r__1 * r__1; + r_f__ += lpbuf[i__] * lpbuf[i__ + *mintau]; + r_b__ += lpbuf[i__] * lpbuf[i__ - *mintau]; + r__1 = inbuf[i__] + *dither; + if (r_sign(&c_b2, &r__1) != oldsgn) { + ++(*zc); + oldsgn = -oldsgn; + } + *dither = -(*dither); + } +/* Normalized short-term autocovariance coefficient at unit sample delay + */ + *rc1 /= max(e0ap,1.f); +/* Ratio of the energy of the first difference signal (6 dB/oct preemphas +is)*/ +/* to the energy of the full band signal */ +/* Computing MAX */ + r__1 = ap_rms__ * 2.f; + *qs = e_pre__ / max(r__1,1.f); +/* aR_b is the product of the forward and reverse prediction gains, */ +/* looking backward in time (the causal case). */ + *ar_b__ = r_b__ / max(e_b__,1.f) * (r_b__ / max(e_0__,1.f)); +/* aR_f is the same as aR_b, but looking forward in time (non causal case +).*/ + *ar_f__ = r_f__ / max(e_f__,1.f) * (r_f__ / max(e_0__,1.f)); +/* Normalize ZC, LBE, and FBE to old fixed window length of 180. */ +/* (The fraction 90/VLEN has a range of .58 to 1) */ + r__2 = (real) (*zc << 1); + r__1 = r__2 * (90.f / vlen); + *zc = i_nint(&r__1); +/* Computing MIN */ + r__1 = lp_rms__ / 4 * (90.f / vlen); + i__1 = i_nint(&r__1); + *lbe = min(i__1,32767); +/* Computing MIN */ + r__1 = ap_rms__ / 4 * (90.f / vlen); + i__1 = i_nint(&r__1); + *fbe = min(i__1,32767); + return 0; +} /* vparms_ */ + diff --git a/codecs/lpc10_slin_ex.h b/codecs/lpc10_slin_ex.h new file mode 100644 index 000000000..cf9f05999 --- /dev/null +++ b/codecs/lpc10_slin_ex.h @@ -0,0 +1,13 @@ +/*! \file + * \brief 8-bit raw data + * + * Source: example.lpc10 + * + * Copyright (C) 1999-2005, Digium Inc. + * + * 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_adpcm_ex.h b/codecs/slin_adpcm_ex.h new file mode 100644 index 000000000..801549a3c --- /dev/null +++ b/codecs/slin_adpcm_ex.h @@ -0,0 +1,25 @@ +/*! \file + * \brief slin_adpcm_ex.h -- + * + * Signed 16-bit audio data, 10 milliseconds worth at 8 kHz. + * + * Source: g723.example + * + * Copyright (C) 2001-2005, Digium Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static signed short slin_adpcm_ex[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; diff --git a/codecs/slin_g726_ex.h b/codecs/slin_g726_ex.h new file mode 100644 index 000000000..8dad39cbd --- /dev/null +++ b/codecs/slin_g726_ex.h @@ -0,0 +1,25 @@ +/*! \file + * \brief slin_adpcm_ex.h -- + * + * Signed 16-bit audio data, 10 milliseconds worth at 8 kHz. + * + * Source: g726.example + * + * Copyright (C) 2001-2005, Digium Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static signed short slin_g726_ex[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; diff --git a/codecs/slin_gsm_ex.h b/codecs/slin_gsm_ex.h new file mode 100644 index 000000000..7ac281800 --- /dev/null +++ b/codecs/slin_gsm_ex.h @@ -0,0 +1,28 @@ +/*! \file + * \brief Signed 16-bit audio data + * + * Source: gsm.example + * + * Copyright (C) 1999-2005, Digium Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static signed short slin_gsm_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, 0xfff8, 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, 0x0008, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +0x0008, 000000, 000000, 000000, 0xfff8, 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, 0x0008, 000000, 000000, 000000 }; diff --git a/codecs/slin_ilbc_ex.h b/codecs/slin_ilbc_ex.h new file mode 100644 index 000000000..b89655c6b --- /dev/null +++ b/codecs/slin_ilbc_ex.h @@ -0,0 +1,28 @@ +/*! \file + * \brief Signed 16-bit audio data + * + * Source: gsm.example + * + * Copyright (C) 1999-2005, Digium Inc + * + * Distributed under the terms of the GNU General Public License + * + */ + +static signed short slin_ilbc_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, 0xfff8, 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, 0x0008, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, +0x0008, 000000, 000000, 000000, 0xfff8, 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, 0x0008, 000000, 000000, 000000 }; diff --git a/codecs/slin_lpc10_ex.h b/codecs/slin_lpc10_ex.h new file mode 100644 index 000000000..169e9a9e1 --- /dev/null +++ b/codecs/slin_lpc10_ex.h @@ -0,0 +1,21 @@ +/*! \file + * \brief Signed 16-bit audio data + * + * Source: example.slin + * + * Copyright (C) 1999-2005, Digium Inc. + * + * 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 }; diff --git a/codecs/slin_speex_ex.h b/codecs/slin_speex_ex.h new file mode 100644 index 000000000..0c6258c37 --- /dev/null +++ b/codecs/slin_speex_ex.h @@ -0,0 +1,262 @@ +/*! \file + * \brief Signed 16-bit audio data, 500ms of speech at 8kHz to ensure no DTX triggered + * + * Source: speex.example + * + * Copyright (C) 1999-2005, Digium Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static signed short slin_speex_ex[] = { +0x4a00, 0xa700, 0x6d00, 0x4900, 0x5800, 0x3e00, 0x1b00, 0x1400, 0xf9ff, 0xe4ff, 0x0a00, 0xf0ff, 0xbbff, 0x0200, 0x0800, 0xd6ff, +0xf1ff, 0x1200, 0x0500, 0x1000, 0x0f00, 0x0700, 0x4100, 0x2800, 0xf4ff, 0x2900, 0x3100, 0xf4ff, 0xefff, 0xdaff, 0xdaff, 0xc2ff, +0xa5ff, 0xccff, 0xd4ff, 0xc7ff, 0xe6ff, 0x0600, 0x0c00, 0x1900, 0x1200, 0x0d00, 0x2900, 0x1e00, 0xf4ff, 0x0000, 0x1200, 0xf5ff, +0xe5ff, 0x0000, 0x0000, 0xf1ff, 0x0300, 0x0b00, 0xfdff, 0x0500, 0x0f00, 0x0600, 0x0d00, 0x0f00, 0x0000, 0xfdff, 0xfcff, 0xe5ff, +0xdcff, 0xe0ff, 0xafff, 0xb2ff, 0xe4ff, 0xceff, 0xe2ff, 0x0000, 0x1600, 0x2600, 0x2400, 0x3f00, 0x4a00, 0x3d00, 0x2b00, 0x2f00, +0x4300, 0x1000, 0x0300, 0x0700, 0xe9ff, 0xf3ff, 0xebff, 0xd9ff, 0xe5ff, 0xf9ff, 0xeeff, 0xe9ff, 0x0500, 0x0a00, 0x0300, 0x0800, +0x1800, 0x1c00, 0x1000, 0x1300, 0x0d00, 0x0400, 0x0200, 0xf9ff, 0xe4ff, 0xe6ff, 0xe0ff, 0xd9ff, 0xecff, 0xf2ff, 0xe8ff, 0xfdff, +0x1100, 0x0d00, 0x0b00, 0x1100, 0x1100, 0x1200, 0x0c00, 0x0400, 0x0900, 0x0d00, 0x0100, 0xfdff, 0x0000, 0xfdff, 0x0000, 0xffff, +0xf5ff, 0xfcff, 0x0600, 0xfeff, 0x0000, 0x0300, 0x1300, 0x1700, 0x0300, 0x0700, 0xf0ff, 0xe1ff, 0xd7ff, 0xd1ff, 0xc6ff, 0xc2ff, +0xf2ff, 0xf0ff, 0xecff, 0x0700, 0x3200, 0x2d00, 0x0400, 0x2200, 0x2900, 0x1900, 0x2400, 0x0500, 0x1900, 0x1f00, 0xfeff, 0x0d00, +0x0600, 0xebff, 0xf5ff, 0x0600, 0xebff, 0xe3ff, 0x0c00, 0x0d00, 0xefff, 0x1100, 0x3a00, 0x0700, 0x1700, 0x2f00, 0xf7ff, 0x0700, +0x2600, 0xd9ff, 0xb8ff, 0xeaff, 0xbeff, 0x9eff, 0xc7ff, 0xccff, 0xc4ff, 0xeeff, 0x0000, 0xfdff, 0x1200, 0x1d00, 0x3100, 0x3600, +0x2d00, 0x3c00, 0x4700, 0x3000, 0x2000, 0x2300, 0x1800, 0x0900, 0xffff, 0xeaff, 0xe7ff, 0xe8ff, 0xd3ff, 0xc5ff, 0xe1ff, 0xedff, +0xe4ff, 0xfaff, 0xe3ff, 0xacff, 0xcdff, 0xd4ff, 0xabff, 0xa6ff, 0xdaff, 0x0500, 0xf1ff, 0xfaff, 0x3800, 0x7000, 0x4100, 0x1c00, +0x4b00, 0x5300, 0x3a00, 0x2a00, 0x1400, 0x2000, 0x1c00, 0x1500, 0x0500, 0xf6ff, 0x0000, 0x1300, 0xfaff, 0xe9ff, 0x0000, 0x0a00, +0xfcff, 0xfaff, 0x1000, 0x1200, 0x0900, 0x0c00, 0x0400, 0x0000, 0x0800, 0xffff, 0xe7ff, 0xe2ff, 0xe6ff, 0xd5ff, 0xdaff, 0xe0ff, +0xdcff, 0xeeff, 0x0200, 0xfbff, 0x0000, 0x1000, 0x1100, 0x1500, 0x1900, 0x1400, 0x1900, 0x1c00, 0x1500, 0x1000, 0x0d00, 0x0b00, +0x0700, 0x0200, 0xf6ff, 0xf5ff, 0xf9ff, 0xecff, 0xe8ff, 0xeeff, 0xf4ff, 0xf4ff, 0xeeff, 0xecff, 0xebff, 0xd7ff, 0xd8ff, 0xeaff, +0xe0ff, 0xddff, 0x0100, 0x0500, 0xf8ff, 0x1800, 0x2d00, 0x1d00, 0x1a00, 0x2100, 0x1f00, 0x1f00, 0x1a00, 0x0f00, 0x0300, 0x0d00, +0x0e00, 0xfeff, 0x0000, 0xfeff, 0x0000, 0x0000, 0xf1ff, 0xfaff, 0x0a00, 0x0100, 0xf5ff, 0x0300, 0x0e00, 0x0300, 0x0200, 0x0000, +0x0800, 0x0700, 0xf8ff, 0xf5ff, 0xf1ff, 0xefff, 0xe9ff, 0xe0ff, 0xe0ff, 0xedff, 0xf0ff, 0xedff, 0xfcff, 0xffff, 0xfdff, 0x0a00, +0x0f00, 0x0e00, 0x0f00, 0x1700, 0x1400, 0x0700, 0x0500, 0x0800, 0x0000, 0x0200, 0x0400, 0xfaff, 0xffff, 0x0200, 0xfaff, 0xfbff, +0x0300, 0x0400, 0x0400, 0x0100, 0xe7ff, 0xd4ff, 0xdbff, 0xe2ff, 0xe0ff, 0xd0ff, 0xe7ff, 0x0700, 0xf2ff, 0x0000, 0x2d00, 0x2000, +0x1800, 0x2c00, 0x1f00, 0x2600, 0x2200, 0x0e00, 0x0e00, 0x0000, 0x0400, 0x0800, 0x0300, 0xfbff, 0x0500, 0x1d00, 0x0000, 0xfbff, +0x2e00, 0x2500, 0x0600, 0x1c00, 0x2600, 0x1600, 0x0e00, 0x0200, 0xf9ff, 0x0000, 0xe1ff, 0xc0ff, 0xd5ff, 0xc9ff, 0xb6ff, 0xbcff, +0xccff, 0xc9ff, 0xcbff, 0xe5ff, 0xeaff, 0xf0ff, 0xfeff, 0x0000, 0x0b00, 0x1f00, 0x2000, 0x1b00, 0x2000, 0x2400, 0x1800, 0x1200, +0x1700, 0x0c00, 0x0b00, 0x0d00, 0xfdff, 0xf5ff, 0x0000, 0xf9ff, 0xefff, 0xfaff, 0xf7ff, 0xf0ff, 0xe7ff, 0xcbff, 0xd1ff, 0xedff, +0xf5ff, 0xfcff, 0xfeff, 0x1e00, 0x3200, 0x2200, 0x3800, 0x4f00, 0x3800, 0x2c00, 0x4000, 0x3e00, 0x2e00, 0x2900, 0x1200, 0x0500, +0x0700, 0x0000, 0xf2ff, 0xf2ff, 0xf8ff, 0xf5ff, 0xf7ff, 0xeaff, 0xefff, 0x0100, 0xfcff, 0xf9ff, 0x0000, 0x0700, 0xf9ff, 0xf2ff, +0xf9ff, 0xf0ff, 0xf1ff, 0xe7ff, 0xddff, 0xe1ff, 0xddff, 0xd9ff, 0xdaff, 0xe1ff, 0xe2ff, 0xe5ff, 0xe5ff, 0xf0ff, 0xfaff, 0xf4ff, +0xfdff, 0x1100, 0x0e00, 0x0e00, 0x1800, 0x1600, 0x1200, 0x1400, 0x1500, 0x1200, 0x0b00, 0x0600, 0x0c00, 0x0500, 0x0100, 0x0b00, +0x0200, 0xfaff, 0xffff, 0xf9ff, 0xe8ff, 0xd0ff, 0xc9ff, 0xd5ff, 0xe0ff, 0xe6ff, 0xedff, 0xf5ff, 0x1100, 0x1300, 0x1f00, 0x3600, +0x2900, 0x2200, 0x2c00, 0x3700, 0x2d00, 0x2000, 0x1a00, 0x0800, 0xfaff, 0xfcff, 0xf6ff, 0xf2ff, 0xebff, 0xf7ff, 0x0200, 0xf1ff, +0xf5ff, 0x0d00, 0x0900, 0xf9ff, 0x1000, 0x2000, 0x0a00, 0xf9ff, 0xffff, 0xf9ff, 0xf2ff, 0xeeff, 0xdbff, 0xd8ff, 0xdbff, 0xdaff, +0xdaff, 0xdfff, 0xe6ff, 0xecff, 0xedff, 0xf0ff, 0x0500, 0x0900, 0x0400, 0x0f00, 0x2600, 0x2700, 0x2200, 0x2b00, 0x1700, 0x1100, +0x2a00, 0x2200, 0x0c00, 0x0200, 0x0100, 0x0200, 0xfeff, 0xfaff, 0xf7ff, 0xf3ff, 0xf1ff, 0xf5ff, 0xf6ff, 0xe8ff, 0xd3ff, 0xcdff, +0xdbff, 0xebff, 0xedff, 0xf0ff, 0xfbff, 0x1400, 0x1700, 0x2000, 0x3400, 0x2700, 0x1a00, 0x2100, 0x2e00, 0x2900, 0x1e00, 0x0c00, +0xfbff, 0xfbff, 0xf9ff, 0xf3ff, 0xf4ff, 0xe8ff, 0xecff, 0x0300, 0xf8ff, 0xf4ff, 0x0100, 0x0600, 0xf7ff, 0x0900, 0x1e00, 0x0f00, +0x0900, 0x0700, 0x0000, 0x0000, 0x0000, 0xf5ff, 0xebff, 0xefff, 0xf3ff, 0xeeff, 0xf0ff, 0xf1ff, 0xefff, 0xf0ff, 0xf6ff, 0xfcff, +0xf9ff, 0xf8ff, 0xfbff, 0x0300, 0x0900, 0x0800, 0x0900, 0x0100, 0x0200, 0x0c00, 0x0e00, 0x0300, 0xfdff, 0xfcff, 0xfbff, 0xfbff, +0xf9ff, 0xf3ff, 0xf3ff, 0xecff, 0xf6ff, 0xfbff, 0xf4ff, 0xecff, 0xd6ff, 0xdcff, 0xf1ff, 0xf1ff, 0xeeff, 0xf6ff, 0x0600, 0x0a00, +0x1000, 0x1e00, 0x1b00, 0x1100, 0x1800, 0x2800, 0x2500, 0x2600, 0x1c00, 0x0e00, 0x0900, 0x0e00, 0x0800, 0x0200, 0xfaff, 0xf5ff, +0x0300, 0xf8ff, 0xfcff, 0x0500, 0x0500, 0x0000, 0xfaff, 0x0b00, 0x1c00, 0x0d00, 0xfdff, 0x0200, 0x0100, 0xfbff, 0xf5ff, 0xe8ff, +0xe8ff, 0xecff, 0xdaff, 0xd1ff, 0xddff, 0xdeff, 0xd8ff, 0xdeff, 0xedff, 0xf3ff, 0xf8ff, 0x0100, 0x1100, 0x2300, 0x2800, 0x3100, +0x3200, 0x3500, 0x3a00, 0x3e00, 0x3400, 0x2700, 0x2100, 0x1400, 0x0900, 0xf7ff, 0xfaff, 0xf3ff, 0xe2ff, 0xeaff, 0xe3ff, 0xdfff, +0xd7ff, 0xc9ff, 0xdaff, 0xe4ff, 0xe0ff, 0xe4ff, 0xefff, 0xf4ff, 0xf6ff, 0x0000, 0x0100, 0x0000, 0x0600, 0x0c00, 0x0c00, 0x1000, +0x1900, 0x1600, 0x1500, 0x1600, 0x1100, 0x1400, 0x1200, 0x1300, 0x0900, 0x0d00, 0x1400, 0x0e00, 0x1900, 0x1400, 0x0900, 0x0600, +0x1600, 0x1900, 0x0800, 0x0300, 0x0000, 0xf5ff, 0xedff, 0xeaff, 0xdbff, 0xdcff, 0xcbff, 0xb7ff, 0xbfff, 0xc3ff, 0xc2ff, 0xbfff, +0xcbff, 0xdaff, 0xe7ff, 0xf9ff, 0x0600, 0x1b00, 0x2c00, 0x2900, 0x3d00, 0x4b00, 0x4700, 0x4b00, 0x4a00, 0x4300, 0x3700, 0x3300, +0x1f00, 0x1400, 0x1000, 0x0f00, 0x0c00, 0x0000, 0xf6ff, 0xe7ff, 0xe7ff, 0xdeff, 0xd3ff, 0xe1ff, 0xdeff, 0xd9ff, 0xe0ff, 0xe8ff, +0xf1ff, 0xeaff, 0xe8ff, 0xf5ff, 0xf7ff, 0xf6ff, 0xf7ff, 0xf4ff, 0xf8ff, 0xfcff, 0x0100, 0xfcff, 0xf7ff, 0x0100, 0x0600, 0x0100, +0x0700, 0x0200, 0x0c00, 0x1000, 0x0e00, 0x1c00, 0x1a00, 0x1a00, 0x1800, 0x2200, 0x1f00, 0x1600, 0x1700, 0x0b00, 0xfbff, 0xfcff, +0xeaff, 0xd6ff, 0xdfff, 0xcbff, 0xc0ff, 0xc0ff, 0xbcff, 0xc1ff, 0xc5ff, 0xd1ff, 0xdaff, 0xecff, 0xffff, 0xfeff, 0x1000, 0x2700, +0x2400, 0x2400, 0x3800, 0x3600, 0x3100, 0x3300, 0x2800, 0x2000, 0x1e00, 0x1d00, 0x0800, 0x0400, 0x1600, 0x0900, 0x0000, 0x0d00, +0x0100, 0xefff, 0xf1ff, 0xedff, 0xe0ff, 0xe6ff, 0xf5ff, 0xe1ff, 0xdaff, 0xf3ff, 0xf6ff, 0xeeff, 0xf1ff, 0xf9ff, 0xfbff, 0x0000, +0x0700, 0x0900, 0x0d00, 0x1c00, 0x1d00, 0x1b00, 0x1a00, 0x2500, 0x2500, 0x1a00, 0x1600, 0x0e00, 0x0c00, 0x0b00, 0x0500, 0x0100, +0x0200, 0x0000, 0xfbff, 0xfcff, 0xfdff, 0xfcff, 0xfcff, 0xf9ff, 0xf6ff, 0xf3ff, 0xeaff, 0xe6ff, 0xecff, 0xe8ff, 0xdfff, 0xe6ff, +0xddff, 0xdaff, 0xecff, 0xefff, 0xf2ff, 0xfdff, 0x0100, 0xffff, 0x0800, 0x1700, 0x1000, 0x1300, 0x2100, 0x1b00, 0x1800, 0x1a00, +0x1200, 0x1000, 0x2000, 0x1100, 0x0000, 0x0700, 0x0500, 0xfdff, 0xfcff, 0x0300, 0xf2ff, 0xeaff, 0xe1ff, 0xcdff, 0xd2ff, 0xe0ff, +0xe0ff, 0xd5ff, 0xdfff, 0xf3ff, 0xf7ff, 0xfcff, 0x1100, 0x1800, 0x1900, 0x2100, 0x2600, 0x2800, 0x2900, 0x2d00, 0x2400, 0x1b00, +0x1a00, 0x1000, 0x0800, 0x0500, 0xfcff, 0xf1ff, 0xf4ff, 0xf6ff, 0xf2ff, 0xf6ff, 0xffff, 0xffff, 0x0000, 0x0a00, 0x0a00, 0xfbff, +0x0200, 0x0700, 0xf9ff, 0xf2ff, 0xeaff, 0xedff, 0xdfff, 0xd9ff, 0xe3ff, 0xd8ff, 0xdbff, 0xddff, 0xe2ff, 0xefff, 0xf6ff, 0xffff, +0x0000, 0x0d00, 0x1500, 0x1600, 0x2200, 0x2800, 0x2700, 0x2900, 0x3700, 0x2d00, 0x2500, 0x2c00, 0x2900, 0x1100, 0x0600, 0xfdff, +0xedff, 0xeaff, 0xddff, 0xcfff, 0xc9ff, 0xc0ff, 0xa8ff, 0xa8ff, 0xbeff, 0xceff, 0xd6ff, 0xe1ff, 0xf4ff, 0x1000, 0x1100, 0x1e00, +0x3e00, 0x3c00, 0x3c00, 0x3d00, 0x3e00, 0x3300, 0x3000, 0x2b00, 0x1300, 0x0b00, 0x0600, 0xfaff, 0xf6ff, 0xf4ff, 0xe9ff, 0xedff, +0x0000, 0xf8ff, 0xfbff, 0x0400, 0x0300, 0x0a00, 0x1400, 0x1300, 0x0100, 0x0b00, 0x0400, 0xf9ff, 0xf8ff, 0xeeff, 0xe9ff, 0xdeff, +0xe1ff, 0xdaff, 0xd7ff, 0xe5ff, 0xd2ff, 0xd3ff, 0xe3ff, 0xe7ff, 0xedff, 0xf5ff, 0x0000, 0x0600, 0x1300, 0x1f00, 0x1c00, 0x2600, +0x2b00, 0x3100, 0x2d00, 0x3100, 0x2e00, 0x2600, 0x1900, 0x1100, 0x0400, 0xf3ff, 0xf3ff, 0xdcff, 0xdbff, 0xddff, 0xd2ff, 0xccff, +0xbbff, 0xc3ff, 0xe4ff, 0xf4ff, 0xf6ff, 0xfbff, 0x1600, 0x2100, 0x1600, 0x2000, 0x2500, 0x1b00, 0x2700, 0x2100, 0x1400, 0x0d00, +0x1300, 0x0800, 0xfbff, 0xf8ff, 0xecff, 0xeeff, 0x0000, 0xefff, 0xeeff, 0xfcff, 0x0000, 0xfeff, 0x0600, 0x0700, 0x0200, 0x1400, +0x1600, 0x0700, 0x0d00, 0x1400, 0x0e00, 0x0900, 0x0b00, 0x0500, 0xfaff, 0x0600, 0x0000, 0xf2ff, 0xfaff, 0xf6ff, 0xe9ff, 0xecff, +0xecff, 0xe2ff, 0xe7ff, 0xf3ff, 0xf6ff, 0xf4ff, 0x0000, 0x0000, 0xffff, 0x1400, 0x0f00, 0x0f00, 0x1500, 0x1400, 0x1100, 0x1200, +0x0c00, 0x0400, 0x0500, 0xffff, 0x0200, 0xfbff, 0xf5ff, 0xfeff, 0xf5ff, 0xe5ff, 0xe3ff, 0xe4ff, 0xe6ff, 0x0a00, 0xffff, 0xf3ff, +0x0900, 0x0d00, 0xfbff, 0x0700, 0x0c00, 0xffff, 0x1200, 0x1e00, 0xfdff, 0x0700, 0x1c00, 0x1200, 0x0f00, 0x1200, 0x1500, 0xfbff, +0x1200, 0x2300, 0xf9ff, 0x0300, 0x0d00, 0xf2ff, 0xf2ff, 0xf5ff, 0xd8ff, 0xd0ff, 0xddff, 0xd8ff, 0xc4ff, 0xdbff, 0xe0ff, 0xd6ff, +0xecff, 0xd8ff, 0xf7ff, 0x1100, 0xffff, 0x1500, 0x2a00, 0x1c00, 0x1800, 0x2200, 0x1500, 0x0800, 0x1d00, 0x1600, 0x0800, 0x1300, +0x0500, 0xecff, 0x1100, 0x0a00, 0x1700, 0x0900, 0xffff, 0x2700, 0x1b00, 0x0b00, 0x1400, 0x1200, 0xecff, 0x1000, 0x1800, 0xdfff, +0xfbff, 0xf1ff, 0x9bff, 0x90ff, 0x97ff, 0x81ff, 0xf2ff, 0xf9ff, 0x8cff, 0xcbff, 0x3300, 0x0200, 0x1300, 0x4f00, 0x1600, 0x2700, +0x7400, 0x4000, 0x2a00, 0x4e00, 0x4b00, 0x1800, 0x2b00, 0x3900, 0x1c00, 0x2500, 0x1000, 0xf1ff, 0xf9ff, 0xf5ff, 0xdbff, 0xdbff, +0x0000, 0x0b00, 0xd7ff, 0xcbff, 0xecff, 0xdfff, 0xebff, 0xe5ff, 0xafff, 0xdfff, 0xe5ff, 0xbeff, 0xc9ff, 0x0000, 0xe0ff, 0xcdff, +0x1d00, 0x1b00, 0xefff, 0x1c00, 0x2100, 0x1100, 0x3200, 0x3400, 0x1d00, 0x2d00, 0x2600, 0x3b00, 0x3600, 0x4200, 0x0a00, 0x0000, +0x5f00, 0x4000, 0x0000, 0x1000, 0x2800, 0xeaff, 0xd9ff, 0xcdff, 0xf8ff, 0x8400, 0xc1ff, 0xbefe, 0x56ff, 0x7fff, 0xe5fe, 0xf5ff, +0x3600, 0x4aff, 0x24ff, 0x6800, 0xdf00, 0x1600, 0x6d00, 0x7b00, 0xf200, 0xd500, 0x0700, 0x2300, 0x3500, 0x0600, 0xeaff, 0xd1ff, +0x95ff, 0xd5ff, 0x0300, 0xbcff, 0xe0ff, 0x0000, 0x2500, 0x3100, 0xdf00, 0x6700, 0x0300, 0x6900, 0x2a00, 0x3f00, 0x0400, 0x7dff, +0x58ff, 0xb2ff, 0x7bff, 0x71ff, 0xa1ff, 0x7dff, 0xd0ff, 0x1700, 0x0000, 0x0700, 0x5900, 0x4b00, 0x4b00, 0x4700, 0xf8ff, 0x4300, +0x5e00, 0x0d00, 0xdaff, 0x1300, 0x0e00, 0x0f00, 0x2d00, 0xeaff, 0x1400, 0x6200, 0x3a00, 0xe3ff, 0x0c00, 0x1600, 0xfbff, 0xe8ff, +0xfbff, 0x6700, 0xe3ff, 0x8eff, 0xf2fe, 0x25fe, 0x9bfe, 0x54ff, 0x94ff, 0x94ff, 0x7dff, 0x3000, 0x9401, 0xce01, 0x5601, 0x0e01, +0xd300, 0x4f01, 0xdf00, 0x6fff, 0x25ff, 0x79ff, 0x5eff, 0x51ff, 0xd4ff, 0xbaff, 0x1b00, 0xbe00, 0x4a00, 0xf3ff, 0x2800, 0x4500, +0x5e00, 0x1800, 0x84ff, 0x8aff, 0xc7ff, 0xc2ff, 0x8aff, 0xd7fe, 0x16ff, 0x0000, 0x1300, 0xf7ff, 0xbcff, 0xc3ff, 0x5500, 0x7c00, +0x5a00, 0x5400, 0x2d00, 0x2d00, 0x2b00, 0xf9ff, 0xfcff, 0x0500, 0xddff, 0x1d00, 0x6600, 0x7a00, 0x9200, 0x3700, 0x0e00, 0x5600, +0x2500, 0xcfff, 0xfdff, 0xe3ff, 0xc5ff, 0xcdff, 0x00ff, 0x67ff, 0xb100, 0x3200, 0x3200, 0xc800, 0xcdff, 0xaaff, 0x4dff, 0x42fd, +0xc4fd, 0x3500, 0x2a00, 0x99ff, 0x1d00, 0xe500, 0x4e02, 0xf802, 0x6f01, 0xd4ff, 0x4f00, 0x7300, 0x88ff, 0x20ff, 0x81fe, 0x9afe, +0xb2ff, 0x6800, 0x9100, 0x9700, 0x3001, 0x5500, 0xf4ff, 0xa400, 0xb2ff, 0xdeff, 0x1500, 0x05ff, 0x4fff, 0xe6ff, 0xaaff, 0xc9ff, +0x0000, 0xafff, 0xeeff, 0x8200, 0x1800, 0xc7ff, 0xf1ff, 0xd5ff, 0x3000, 0x1d00, 0x50ff, 0x89ff, 0x82ff, 0x7cff, 0x2000, 0x1d00, +0x0d00, 0x9500, 0x8c00, 0x2d00, 0x5b00, 0x2200, 0xf8ff, 0x6700, 0x7800, 0x3e00, 0xa800, 0x9100, 0xbfff, 0xccff, 0xdaff, 0x9bff, +0x8400, 0x98ff, 0xa4fe, 0xddff, 0x1200, 0x2e00, 0xf100, 0x3500, 0x73ff, 0x99ff, 0xd1fd, 0x97fd, 0x0500, 0x7800, 0x3400, 0xc700, +0xfc00, 0x8201, 0x6002, 0x8201, 0xb5ff, 0xaeff, 0xa5ff, 0x15ff, 0x90ff, 0x53ff, 0xccfe, 0x8eff, 0x9d00, 0xef00, 0x0601, 0xf300, +0xa4ff, 0x5cff, 0x0b00, 0xfcff, 0x0d00, 0xd9ff, 0x3cff, 0x60ff, 0x5400, 0x3400, 0x2b00, 0x4800, 0xbbff, 0x0300, 0x5a00, 0xf5ff, +0xc7ff, 0xe5ff, 0x91ff, 0xfeff, 0x0000, 0x51ff, 0xa8ff, 0x57ff, 0x74ff, 0x3a00, 0x6500, 0x5400, 0x0e00, 0x2900, 0x3800, 0x3d00, +0x3300, 0x1100, 0x4400, 0x7200, 0x5c00, 0x6f00, 0x4c00, 0xc8ff, 0xa6ff, 0xc4ff, 0x9bff, 0x6a00, 0x1000, 0xccfe, 0xc6ff, 0x7e00, +0x8aff, 0x6b00, 0xae00, 0x7bff, 0x71ff, 0xa0fd, 0x05fd, 0xc5ff, 0x5001, 0x1801, 0x9a01, 0x3f01, 0x1701, 0xc102, 0xd901, 0x83ff, +0x35ff, 0xa7fe, 0x52fe, 0x98ff, 0x9eff, 0xcbfe, 0x90ff, 0xe100, 0x4801, 0xa001, 0x5101, 0x59ff, 0x04ff, 0xc3ff, 0x1800, 0x4400, +0xe7ff, 0x22ff, 0x1dff, 0x4000, 0x2c00, 0x4b00, 0x7800, 0xa3ff, 0xd9ff, 0x7b00, 0x1a00, 0xb7ff, 0xb4ff, 0x70ff, 0xb6ff, 0x2200, +0xc9ff, 0x35ff, 0xaeff, 0x2b00, 0x4700, 0x5100, 0xe6ff, 0x1100, 0x5900, 0x0500, 0xf0ff, 0x2300, 0x5b00, 0xbd00, 0xec00, 0xc500, +0x8200, 0x93ff, 0x39ff, 0xafff, 0xbfff, 0x5200, 0x9cff, 0x49fe, 0x7fff, 0xa600, 0xfcff, 0xaa00, 0x7000, 0xf8fe, 0x64fe, 0xf7fc, +0x73fd, 0x2100, 0xa001, 0xe501, 0x4a02, 0x3701, 0xe500, 0x7402, 0x6601, 0xb5ff, 0x5eff, 0x69fe, 0x40fe, 0xc8ff, 0xe6ff, 0x1cff, +0xd1ff, 0xc900, 0x6601, 0xdf01, 0xf300, 0x67ff, 0xdcfe, 0x50ff, 0x2500, 0x7400, 0x0900, 0x42ff, 0x32ff, 0xe2ff, 0x2e00, 0x8700, +0x2800, 0x84ff, 0xd4ff, 0x5a00, 0x1000, 0xc1ff, 0xafff, 0x62ff, 0xa7ff, 0x2700, 0x1100, 0xc5ff, 0xe2ff, 0xeeff, 0xb8ff, 0x3200, +0x8b00, 0x0d00, 0x2600, 0x7b00, 0xf4ff, 0x6dff, 0x3d00, 0x9600, 0x8800, 0x2201, 0xa500, 0xf1ff, 0xe7ff, 0x9fff, 0x70ff, 0xe9ff, +0x3a00, 0x5fff, 0xe8fe, 0x52ff, 0x0f00, 0x8e00, 0xb300, 0x3800, 0x1aff, 0x77fe, 0x13fd, 0x9afc, 0x6dff, 0xe301, 0x5602, 0x9902, +0x3b01, 0xa6ff, 0x1501, 0x1a02, 0xa300, 0xebff, 0x1aff, 0xe6fd, 0x09ff, 0x6700, 0x5800, 0xefff, 0x4500, 0xd100, 0x6601, 0x5301, +0x5600, 0x0eff, 0x9dfe, 0x91ff, 0x2400, 0x8500, 0xd7ff, 0xeffe, 0x39ff, 0xddff, 0x8c00, 0xa500, 0x0c00, 0x86ff, 0xd0ff, 0x2f00, +0x1200, 0xf1ff, 0xbfff, 0x88ff, 0xd1ff, 0x4900, 0x2100, 0xbcff, 0xb1ff, 0x9aff, 0xf1ff, 0x8300, 0x6400, 0x3b00, 0x3e00, 0x2400, +0xa3ff, 0x0000, 0x8200, 0x4b00, 0xa800, 0xe600, 0x0300, 0x2cff, 0x82ff, 0x0b00, 0x4300, 0x5600, 0xa9ff, 0xcdfe, 0x15ff, 0x6700, +0xed00, 0x8a00, 0xe3ff, 0x74fe, 0xe3fc, 0xd1fc, 0x98fe, 0x2601, 0x7b02, 0x8d02, 0x8001, 0x3f00, 0xd300, 0x9501, 0xfe00, 0xeeff, +0x50ff, 0x67fe, 0x81fe, 0xe8ff, 0x4900, 0x1200, 0x6800, 0xc000, 0xc200, 0x0c01, 0xb100, 0x7bff, 0x2fff, 0x91ff, 0xd6ff, 0xfeff, +0xfeff, 0x63ff, 0x35ff, 0x0700, 0x7100, 0x6600, 0x4400, 0xceff, 0x9cff, 0x1100, 0x4500, 0xdfff, 0xabff, 0x96ff, 0x96ff, 0x1000, +0x5b00, 0x0f00, 0xc2ff, 0xe3ff, 0xfdff, 0x3a00, 0x9000, 0x4c00, 0x1400, 0xe6ff, 0xe2ff, 0xc0ff, 0xf3ff, 0x4300, 0x1a00, 0x5100, +0x7300, 0x3100, 0xc2ff, 0xebff, 0x5a00, 0x1e00, 0xafff, 0x3aff, 0x3cff, 0x80ff, 0x5a00, 0xf500, 0xffff, 0x57ff, 0x39ff, 0xe8fd, +0x65fd, 0x65ff, 0x7d01, 0xfb01, 0x5b02, 0x7501, 0x9aff, 0x6000, 0x7701, 0x6b00, 0x94ff, 0x31ff, 0xe2fd, 0x85fe, 0x9300, 0xab00, +0x4900, 0x9300, 0x5900, 0x3b00, 0x0701, 0x9000, 0x47ff, 0x4eff, 0x6cff, 0xedff, 0x5c00, 0x0000, 0x33ff, 0x81ff, 0x6200, 0x7400, +0x9b00, 0x3400, 0x67ff, 0x94ff, 0x3100, 0x2800, 0xfeff, 0xfdff, 0xa3ff, 0x9fff, 0x2100, 0x2400, 0xebff, 0xf5ff, 0xe4ff, 0xe0ff, +0x3f00, 0x5100, 0x1600, 0x1a00, 0xe7ff, 0xe0ff, 0xd4ff, 0x0000, 0x1200, 0x0500, 0x5b00, 0xc200, 0x5000, 0xcbff, 0x3b00, 0xe5ff, +0x9fff, 0xf0ff, 0xd4ff, 0x76ff, 0x40ff, 0x2200, 0x8c00, 0x0f00, 0x5700, 0x5fff, 0xdffc, 0xfbfc, 0xe8ff, 0xc501, 0xa202, 0xbc02, +0x6300, 0x49ff, 0x0b01, 0x7001, 0x6f00, 0xe2ff, 0x72fe, 0x84fd, 0x7dff, 0xcc00, 0x7300, 0x7c00, 0x5e00, 0xf1ff, 0xa200, 0x2101, +0xd4ff, 0x46ff, 0x5eff, 0x82ff, 0x4800, 0x7d00, 0xd2ff, 0x71ff, 0xe3ff, 0x1b00, 0x7b00, 0x5c00, 0xc4ff, 0x84ff, 0x76ff, 0xe5ff, +0x2b00, 0x3500, 0x1500, 0xe2ff, 0x99ff, 0x73ff, 0x9bff, 0xc7ff, 0xc8ff, 0x0000, 0x2d00, 0x4100, 0x3400, 0x2600, 0xf1ff, 0xd6ff, +0x0900, 0x1300, 0xe0ff, 0x5c00, 0xbc00, 0x4700, 0x2500, 0xd5ff, 0x5eff, 0xb5ff, 0x4800, 0x3200, 0x0a00, 0x5bff, 0x91ff, 0x9b00, +0x7000, 0x6400, 0x0800, 0xa7fd, 0x41fc, 0x8dfe, 0x3c01, 0x0102, 0x4b03, 0x0002, 0x58ff, 0x8b00, 0xc401, 0xad00, 0x5c00, 0x7aff, +0x8efd, 0x85fe, 0x5600, 0x4000, 0x5700, 0xd200, 0xa700, 0xd400, 0xbb01, 0x7500, 0x1bff, 0x11ff, 0x47ff, 0x0700, 0x7500, 0x3c00, +0x67ff, 0x05ff, 0x91ff, 0x4300, 0x6700, 0x3300, 0x1200, 0x94ff, 0x8dff, 0x1e00, 0xd6ff, 0x98ff, 0xafff, 0x9bff, 0x55ff, 0x97ff, +0xaeff, 0x86ff, 0xc1ff, 0x2f00, 0x5200, 0x7100, 0x7600, 0xfdff, 0x9fff, 0xc3ff, 0xe5ff, 0xd9ff, 0x1500, 0x7e00, 0x3c00, 0x8200, +0x5900, 0x60ff, 0x8cff, 0x1e00, 0x3400, 0x4300, 0x3800, 0x1dff, 0xbffe, 0xd2ff, 0xcf00, 0xff00, 0x5c00, 0x36ff, 0xd4fd, 0x85fc, +0x18fe, 0xa301, 0x2e02, 0xfc01, 0x9d02, 0xf400, 0x4400, 0xbf01, 0xea00, 0x40ff, 0x83ff, 0x05ff, 0x5afe, 0xc5ff, 0x5100, 0xa4ff, +0x8f00, 0x8501, 0x2501, 0x2e01, 0xd300, 0x21ff, 0xe0fe, 0xd1ff, 0x0400, 0x5a00, 0xd2ff, 0x62ff, 0xcfff, 0xc0ff, 0xfbff, 0x2b00, +0xf9ff, 0xd6ff, 0xf7ff, 0xfbff, 0xb7ff, 0xc6ff, 0x2eff, 0x52ff, 0x3900, 0x1500, 0xc2ff, 0xf0ff, 0xc6ff, 0xccff, 0x7f00, 0x9500, +0x0200, 0x0b00, 0x0000, 0x98ff, 0xa3ff, 0xb9ff, 0xacff, 0x4600, 0x8a00, 0x9300, 0x1300, 0x94ff, 0xd4ff, 0x2a00, 0x1301, 0xce00, +0x78ff, 0xa7fe, 0xa1fe, 0x76ff, 0xe200, 0xfe00, 0xecff, 0xadff, 0x6fff, 0xe4fd, 0x2afd, 0x51ff, 0x3f01, 0x8c01, 0x9202, 0xac01, +0xf4ff, 0x0d01, 0x7601, 0x0800, 0xd5ff, 0xafff, 0x9cfe, 0x2dff, 0x2200, 0x85ff, 0xbdff, 0xd500, 0xc000, 0xd300, 0x2701, 0x0700, +0x12ff, 0xb6ff, 0xf5ff, 0xebff, 0x7900, 0xc7ff, 0x4dff, 0x5c00, 0x9800, 0xf9ff, 0xa4ff, 0xa4ff, 0x6bff, 0xafff, 0x2a00, 0xceff, +0xc2ff, 0xc6ff, 0xb9ff, 0x3600, 0x5a00, 0xdbff, 0xa1ff, 0xe1ff, 0x1500, 0x3e00, 0x5d00, 0x0400, 0xccff, 0x2000, 0x1900, 0xa7ff, +0x77ff, 0x9dff, 0xfdff, 0x4a00, 0xcd00, 0x0300, 0x8bff, 0x0000, 0xf0ff, 0xa100, 0xbf00, 0xdaff, 0x04ff, 0x2aff, 0x76ff, 0xe1ff, +0x8b00, 0x8100, 0x3700, 0x4700, 0x2fff, 0x1ffd, 0xd7fd, 0x6a00, 0x6c01, 0x9301, 0x9c01, 0x5900, 0x3c00, 0x9f01, 0x6201, 0xbfff, +0x28ff, 0x69ff, 0x63ff, 0xf5ff, 0x0a00, 0x2cff, 0x91ff, 0x9e00, 0x1c01, 0x0d01, 0x7900, 0xa9ff, 0x3aff, 0x2b00, 0x3500, 0xc4ff, +0xc5ff, 0x77ff, 0xb8ff, 0x9600, 0xaa00, 0xd4ff, 0x97ff, 0xdfff, 0xc3ff, 0x1a00, 0xf9ff, 0x65ff, 0x81ff, 0xa7ff, 0xd0ff, 0x2a00, +0x0600, 0x0800, 0x2d00, 0xebff, 0x2000, 0x6d00, 0x6a00, 0x5900, 0x5700, 0x0c00, 0x85ff, 0x9bff, 0xe4ff, 0x0400, 0x4000, 0xd7ff, +0x0f00, 0x1f00, 0xf2ff, 0xb800, 0x6c00, 0xacff, 0x59ff, 0x2eff, 0x5fff, 0x1f00, 0x5200, 0x1f00, 0x2700, 0x3e00, 0xcdfe, 0x09fd, +0x87fd, 0x2300, 0x0802, 0x8401, 0x2f01, 0x7c00, 0x9c00, 0x0302, 0xb301, 0x8fff, 0xc2fe, 0x25ff, 0x0000, 0x6e00, 0xabff, 0xedfe, +0x54ff, 0xa800, 0xa301, 0x4801, 0x1900, 0x8eff, 0xf2ff, 0x7000, 0x6c00, 0xc6ff, 0x02ff, 0x34ff, 0x0000, 0x6c00, 0x4f00, 0x55ff, +0x65ff, 0x3c00, 0x4d00, 0x1d00, 0x81ff, 0x49ff, 0xaaff, 0x2300, 0x1600, 0xaaff, 0x92ff, 0xb7ff, 0x7100, 0x4900, 0xf8ff, 0x4900, +0x5700, 0x9f00, 0xa100, 0x5b00, 0xb6ff, 0x8bff, 0x0700, 0x3300, 0x3e00, 0xa2ff, 0x99ff, 0x2e00, 0x1200, 0x9500, 0x9200, 0xceff, +0x99ff, 0xa9ff, 0x77ff, 0x5fff, 0xc7ff, 0x1c00, 0x1b00, 0x5400, 0x9fff, 0xd8fd, 0xe8fc, 0xaefe, 0x7301, 0x8a01, 0xd700, 0x6b00, +0x6600, 0xfa01, 0x9d02, 0x5e00, 0xddfe, 0x75ff, 0x1f00, 0x8500, 0x6dff, 0x3ffe, 0xc4fe, 0x7200, 0x5401, 0xe600, 0x2900, 0xd8ff, +0x6900, 0xe800, 0x9400, 0xd8ff, 0x45ff, 0x6aff, 0xedff, 0xf4ff, 0xf3ff, 0x8cff, 0x7aff, 0x1e00, 0x3a00, 0xfcff, 0xc7ff, 0xbbff, +0xd1ff, 0x1300, 0x1c00, 0xc1ff, 0xbfff, 0xd6ff, 0x1300, 0x5100, 0xf7ff, 0x77ff, 0xe4ff, 0x9000, 0xa400, 0x9a00, 0x5300, 0xacff, +0xa5ff, 0x3a00, 0x3800, 0x0000, 0xe2ff, 0xe3ff, 0x4300, 0xc400, 0x5e00, 0x90ff, 0xb4ff, 0x3a00, 0xf6ff, 0x8eff, 0x86ff, 0xcbfe, +0x49ff, 0xe400, 0x7f00, 0x5cff, 0x80fe, 0x61fd, 0x78fe, 0xf601, 0x4001, 0xabff, 0xc500, 0xe000, 0xf201, 0x0c03, 0x7e00, 0x6ffe, +0xceff, 0x7100, 0xd0ff, 0x6dff, 0x5cfe, 0x4afe, 0x5800, 0x6d01, 0x0e00, 0xc7ff, 0x2e00, 0x2a00, 0xc800, 0xe500, 0x89ff, 0x3cff, +0x5900, 0x1a00, 0xcfff, 0x0b00, 0x71ff, 0x87ff, 0x7000, 0x3100, 0x95ff, 0xe1ff, 0x0000, 0xe9ff, 0x4700, 0x0300, 0x7aff, 0xf1ff, +0x3700, 0xc9ff, 0xfcff, 0x0000, 0xd0ff, 0x6800, 0x9500, 0xdfff, 0xfaff, 0xe7ff, 0xe9ff, 0x9600, 0x1700, 0xbbff, 0x0b00, 0x5300, +0x9000, 0x9c00, 0x1900, 0x97ff, 0xd7ff, 0x6100, 0x2400, 0xbdfe, 0xe0fe, 0xb0ff, 0xb0ff, 0x6400, 0x5500, 0x0dff, 0xdafe, 0x38fe, +0xe1fd, 0x6200, 0x3801, 0xeaff, 0xe200, 0xf901, 0xd901, 0x4802, 0x8001, 0x25ff, 0xd7ff, 0xfa00, 0x7bff, 0xc8fe, 0xe4fe, 0x76fe, +0xb4ff, 0xa800, 0xd5ff, 0xa7ff, 0x4d00, 0x6d00, 0x6e00, 0xb600, 0xe3ff, 0xc3ff, 0x6600, 0x1b00, 0xa3ff, 0xc0ff, 0xbaff, 0x90ff, +0x0a00, 0x1c00, 0x99ff, 0x0900, 0x5000, 0xd6ff, 0x0e00, 0x7400, 0x1f00, 0xf5ff, 0x0d00, 0xc3ff, 0xe6ff, 0x4400, 0xebff, 0x9dff, +0xdfff, 0x5a00, 0x1c00, 0x80ff, 0xd4ff, 0x1f00, 0x1200, 0x4e00, 0x6f00, 0xd900, 0x7d00, 0x9aff, 0xdbff, 0x4000, 0x2300, 0xd1ff, +0xa3ff, 0x89ff, 0x74ff, 0xbdff, 0xb5ff, 0xe8ff, 0x4900, 0x0b00, 0xc6ff, 0x5aff, 0x6dfe, 0xc6fe, 0x3400, 0x6700, 0x2300, 0x9500, +0xa300, 0x2901, 0x0a02, 0xf200, 0x7fff, 0x3800, 0x7e00, 0xedff, 0xb8ff, 0x0fff, 0xeafe, 0xdeff, 0x4500, 0xdcff, 0xcaff, 0x0d00, +0x3d00, 0x7b00, 0x7c00, 0xffff, 0xf5ff, 0x2600, 0x1500, 0xe2ff, 0xd8ff, 0xc6ff, 0xb8ff, 0xf7ff, 0xf6ff, 0xd4ff, 0xf7ff, 0x1300, +0xf7ff, 0x0800, 0xf3ff, 0xbbff, 0xb5ff, 0xfcff, 0xcaff, 0xc4ff, 0xfcff, 0xd2ff, 0xfeff, 0x2500, 0x2000, 0x0400, 0x0000, 0x0200, +0x1000, 0x1e00, 0x1900, 0x2a00, 0x1600, 0x2e00, 0x5500, 0x1b00, 0x1f00, 0x1200, 0x2600, 0x6600, 0x3700, 0xfbff, 0x2200, 0x1300, +0xffff, 0xfbff, 0xcaff, 0x97ff, 0x9eff, 0x95ff, 0x9aff, 0xceff, 0xa2ff, 0x6fff, 0xabff, 0x0000, 0x2400, 0x0c00, 0xf2ff, 0x0f00, +0x6100, 0x7500, 0x4200, 0xfeff, 0x1c00, 0x5a00, 0x4a00, 0x2300, 0x0b00, 0x0f00, 0x0900, 0x1900, 0xfcff, 0xe0ff, 0xfdff, 0x1200, +0x1100, 0x1200, 0x1700, 0x1800, 0x1500, 0x1500, 0x0500, 0xf7ff, 0xf9ff, 0x0800, 0xffff, 0x0300, 0x0000, 0xccff, 0xdaff, 0x0200, +0xe5ff, 0xa7ff, 0x9cff, 0xb4ff, 0xd0ff, 0xcaff, 0xdbff, 0xc9ff, 0xd3ff, 0x0a00, 0x0500, 0x0600, 0x1500, 0x1400, 0x2d00, 0x5900, +0x3000, 0x0900, 0x1300, 0x0800, 0x2000, 0x3600, 0x0500, 0x0000, 0xf6ff, 0x0700, 0x1900, 0xf5ff, 0x1000, 0x1300, 0xcdff, 0xbdff, +0xd7ff, 0xe0ff, 0xd6ff, 0xe6ff, 0xbfff, 0xdfff, 0x3500, 0x1700, 0x0000, 0x2900, 0x4c00, 0x4600, 0x4500, 0x4a00, 0x2100, 0x3c00, +0x4000, 0x0a00, 0xeeff, 0xedff, 0xe6ff, 0xe1ff, 0xe0ff, 0xeeff, 0x0100, 0x0a00, 0x1300, 0x0900, 0x0500, 0x0c00, 0x0600, 0xf2ff, +0xecff, 0xe1ff, 0xe3ff, 0xe2ff, 0xe6ff, 0xe6ff, 0xf8ff, 0x0500, 0x0200, 0x0800, 0xe2ff, 0xdfff, 0x0000, 0x0300, 0xffff, 0x0000, +0x1200, 0x1300, 0x0600, 0x0c00, 0xfcff, 0x1200, 0x1000, 0xfcff, 0x0800, 0x0900, 0xfbff, 0xf6ff, 0xfeff, 0xfbff, 0xfeff, 0xf1ff, +0xfbff, 0x0400, 0x0600, 0x1700, 0x2500, 0x0e00, 0xdbff, 0xb8ff, 0xc9ff, 0xcfff, 0xb2ff, 0xbeff, 0xcdff, 0xc7ff, 0xe2ff, 0x0500, +0x2400, 0x1600, 0x2300, 0x3900, 0x4c00, 0x5400, 0x4200, 0x3a00, 0x3100, 0x3e00, 0x2e00, 0x0800, 0xf6ff, 0xf2ff, 0xf7ff, 0xfaff, +0xf7ff, 0xf3ff, 0x0600, 0x0f00, 0x0300, 0xffff, 0xf9ff, 0xe6ff, 0x0a00, 0x1f00, 0x0a00, 0x0300, 0xf8ff, 0xecff, 0xf2ff, 0xfdff, +0xccff, 0xbbff, 0xe5ff, 0xe6ff, 0xb3ff, 0xc7ff, 0x0000, 0xfaff, 0xf2ff, 0x0d00, 0x1000, 0x0e00, 0x2300, 0x1c00, 0x0f00, 0x1c00, +0x1700, 0x0b00, 0x1000, 0x0c00, 0x0400, 0x0100, 0x0200, 0x0300, 0x0000, 0xfdff, 0x0300, 0x0500, 0x0700, 0x0a00, 0x0600, 0x0400, +0x0100, 0xf5ff, 0xecff, 0xf2ff, 0xf5ff, 0xecff, 0x0200, 0xfdff, 0xe0ff, 0x0800, 0x1b00, 0x0300, 0x0000, 0x0700, 0x0500, 0x0400, +0x0100, 0xf0ff, 0xefff, 0x0100, 0xfcff, 0xfaff, 0x0700, 0x0600, 0x0e00, 0x1500, 0x0800, 0x0500, 0x0d00, 0x1100, 0x0800, 0x0a00, +0x0600, 0xf8ff, 0xfdff, 0x0400, 0x2200, 0x2800, 0x1500, 0x0f00, 0x1800, 0x0e00, 0xfcff, 0xf9ff, 0xefff, 0xe5ff, 0xc5ff, 0xb4ff, +0xc3ff, 0xcfff, 0xcbff, 0xcdff, 0xe4ff, 0xf7ff, 0x0300, 0x1300, 0xffff, 0xf8ff, 0x0e00, 0x0900, 0xfeff, 0xfeff, 0xfeff, 0xfbff, +0x0300, 0x0a00, 0x0a00, 0x0f00, 0x1100, 0x0d00, 0x0800, 0x0e00, 0x1600, 0x0d00, 0x0900, 0x0900, 0x0100, 0x0200, 0x0000, 0xebff, +0xfbff, 0x0200, 0xdeff, 0xf8ff, 0x0c00, 0xf8ff, 0xefff, 0x0100, 0x0000, 0x0200, 0x0500, 0x0f00, 0x1900, 0x2400, 0x2d00, 0x1b00, +0x1500, 0x1b00, 0x1e00, 0x1200, 0x0100, 0x0000, 0xfeff, 0x0200, 0x0400, 0xfeff, 0xfaff, 0x0200, 0x0b00, 0x1d00, 0x2e00, 0x0100, +0xf7ff, 0x0d00, 0x0300, 0xf7ff, 0xfbff, 0xf5ff, 0xeaff, 0xe8ff, 0xc9ff, 0xccff, 0xe2ff, 0xe2ff, 0xdeff, 0xe5ff, 0xf0ff, 0xfaff, +0x0900, 0x0700, 0xe8ff, 0xedff, 0x0300, 0xfdff, 0xf3ff, 0xf8ff, 0x0e00, 0x0b00, 0x1800, 0x1200, 0x0100, 0x0f00, 0x1300, 0x1100, +0x0e00, 0x1700, 0x1500, 0x0800, 0x0500, 0xf1ff, 0xe5ff, 0xe3ff, 0xd9ff, 0xceff, 0xc6ff, 0xbeff, 0xe5ff, 0xf2ff, 0xebff, 0xf1ff, +0x0200, 0xffff, 0x0900, 0x1000, 0x1000, 0x1300, 0x2a00, 0x3700, 0x2c00, 0x3000, 0x3000, 0x2300, 0x2100, 0x2500, 0x1d00, 0x1700, +0x1b00, 0x1800, 0x1800, 0x1900, 0x0f00, 0x0a00, 0x1300, 0x1e00, 0x1600, 0x0f00, 0xffff, 0x0200, 0xf2ff, 0xe3ff, 0xdfff, 0xdbff, +0xd5ff, 0xc2ff, 0xb8ff, 0xb3ff, 0xbaff, 0xc4ff, 0xc9ff, 0xd1ff, 0xe4ff, 0xfcff, 0xfbff, 0xfeff, 0x0c00, 0x0c00, 0x1300, 0x2200, +0x2300, 0x2100, 0x2b00, 0x3700, 0x2c00, 0x2d00, 0x2d00, 0x2300, 0x2800, 0x2300, 0x1300, 0x1800, 0x1000, 0xedff, 0xe1ff, 0xd6ff, +0xbcff, 0xb8ff, 0xb3ff, 0x98ff, 0x9bff, 0xb7ff, 0xcfff, 0xd6ff, 0xe5ff, 0xecff, 0xf5ff, 0x0000, 0x0600, 0x1600, 0x1100, 0x1a00, +0x3100, 0x3700, 0x3800, 0x3700, 0x3b00, 0x3900, 0x3700, 0x3200, 0x3400, 0x3600, 0x2e00, 0x2800, 0x2700, 0x1e00, 0x1800, 0x1800, +0x1000, 0x1400, 0x0900, 0xfcff, 0xf7ff, 0xf1ff, 0xe4ff, 0xd7ff, 0xd7ff, 0xd2ff, 0xc1ff, 0xc1ff, 0xc8ff, 0xc3ff, 0xc5ff, 0xd6ff, +0xddff, 0xdfff, 0xf0ff, 0x0000, 0x0300, 0x0300, 0x0900, 0x0a00, 0x1700, 0x2200, 0x1700, 0x2000, 0x3100, 0x3200, 0x3300, 0x2e00, +0x2800, 0x1d00, 0x2600, 0x2200, 0x1800, 0x1300, 0x0200, 0xf0ff, 0xd3ff, 0xc8ff, 0xc0ff, 0xbbff, 0xbbff, 0xb4ff, 0xaaff, 0xbaff, +0xd7ff, 0xe9ff, 0xf2ff, 0xfcff, 0x0500, 0x1000, 0x1900, 0x1a00, 0x2100, 0x1b00, 0x1d00, 0x2a00, 0x1d00, 0x1000, 0x0b00, 0x0c00, +0x0b00, 0x0600, 0x0100, 0x0400, 0x0900, 0x0900, 0x0600, 0x0500, 0x0800, 0x0f00, 0x1100, 0xfcff, 0x0900, 0x0c00, 0x0400, 0x0500, +0x0000, 0xf8ff, 0xf3ff, 0xf7ff, 0xefff, 0xe7ff, 0xeeff, 0xf1ff, 0xf2ff, 0xf5ff, 0xfbff, 0xfdff, 0xffff, 0x0000, 0x0100, 0x0000, +0xfeff, 0xffff, 0x0000, 0x0000, 0x0100, 0xffff, 0x0000, 0x0400, 0x0500, 0x0200, 0xffff, 0x0000, 0xfeff, 0xfcff, 0xfbff, 0xf7ff, +0xf3ff, 0xf1ff, 0xf6ff, 0xf1ff, 0xf4ff, 0xf7ff, 0xfaff, 0xfeff, 0x0700, 0x0e00, 0x1300, 0x1e00, 0x2000, 0x2200, 0x2000, 0x2200, +0x1d00, 0x1c00, 0x1d00, 0x1b00, 0x1600, 0x1b00, 0x1900, 0x1200, 0x0d00, 0x0a00, 0x0500, 0x0000, 0xebff, 0xddff, 0xe1ff, 0xe0ff, +0xddff, 0xdcff, 0xdeff, 0xdeff, 0xe6ff, 0xebff, 0xeeff, 0xf4ff, 0xffff, 0x0100, 0x0a00, 0x0b00, 0x0100, 0x0600, 0x1600, 0x0e00, +0x0a00, 0x1100, 0x1500, 0x1000, 0x1000, 0x0d00, 0x0b00, 0x0900, 0x0500, 0xfbff, 0xffff, 0x0200, 0x0000, 0x0100, 0x0100, 0x0200, +0xfbff, 0x0000, 0xfaff, 0xf4ff, 0xedff, 0xedff, 0xe9ff, 0xe4ff, 0xe2ff, 0xdeff, 0xdbff, 0xe0ff, 0xe0ff, 0xe3ff, 0xe9ff, 0xf3ff, +0xf7ff, 0x0700, 0x0b00, 0x0000, 0x0f00, 0x1b00, 0x1700, 0x1600, 0x2100, 0x2600, 0x2700, 0x2e00, 0x2600, 0x2300, 0x2000, 0x1800, +0x0e00, 0x0b00, 0x0200, 0x0300, 0xf3ff, 0xe2ff, 0xe0ff, 0xe0ff, 0xe1ff, 0xdeff, 0xe3ff, 0xe4ff, 0xf2ff, 0xf1ff, 0xfcff, 0xf9ff, +0xf8ff, 0x0000, 0x0300, 0x0900, 0x0a00, 0x0e00, 0x0300, 0x0600, 0x0400, 0x0400, 0x0100, 0x0200, 0x0000, 0x0000, 0xffff, 0xfcff, +0x0100, 0x0100, 0x0300, 0x0400, 0x0800, 0x0500, 0x0500, 0x0000, 0xfaff, 0xffff, 0x0100, 0xfcff, 0xfeff, 0x0000, 0xfcff, 0xf6ff, +0xf5ff, 0xf3ff, 0xf3ff, 0xf0ff, 0xf7ff, 0xfcff, 0x0100, 0x0e00, 0x1800, 0x1900, 0x1d00, 0x2800, 0x2400, 0x2000, 0x2400, 0x2000, +0x1400, 0x0d00, 0x0000, 0xf9ff, 0xeeff, 0xe7ff, 0xe6ff, 0xe3ff, 0xe0ff, 0xdbff, 0xe6ff, 0xeeff, 0xf4ff, 0xfdff, 0xfeff, 0xffff, +0x0000, 0x0400, 0x0000, 0x0500, 0x0500, 0x0900, 0x0500, 0x0600, 0x0c00, 0x0d00, 0x1200, 0x0c00, 0x0d00, 0x0a00, 0x0d00, 0x0b00, +0x0500, 0x0100, 0x0100, 0xfeff, 0xfdff, 0xfaff, 0xfaff, 0xfaff, 0xfbff, 0xf9ff, 0xf8ff, 0xf8ff, 0xf7ff, 0xf8ff, 0xf6ff, 0xf3ff, +0xf8ff, 0xf6ff, 0xf4ff, 0xf2ff, 0xf1ff, 0xefff, 0xf5ff, 0xf3ff, 0xf6ff, 0xfcff, 0xfdff, 0xfcff, 0xffff, 0x0100, 0x0000, 0x0000, +0x0400, 0x1000, 0x1000, 0x1300, 0x1700, 0x1e00, 0x1400, 0x1200, 0x1400, 0x0e00, 0x1400, 0x1100, 0x0600, 0xfbff, 0xf3ff, 0xe9ff, +0xebff, 0xe8ff, 0xe2ff, 0xe7ff, 0xebff, 0xf1ff, 0xf5ff, 0xfeff, 0x0100, 0xffff, 0xfaff, 0xfdff, 0xfeff, 0xfeff, 0xfeff, 0xffff, +0x0900, 0x0c00, 0x1100, 0x1400, 0x1100, 0x1200, 0x0d00, 0x0b00, 0x0f00, 0x0f00, 0x0a00, 0x0600, 0xfeff, 0x0000, 0xfeff, 0xf9ff, +0xfcff, 0xfaff, 0xf8ff, 0xfbff, 0xfeff, 0xf9ff, 0xfcff, 0xf7ff, 0xfbff, 0xf5ff, 0xfcff, 0x0900, 0x0000, 0x0a00, 0x0600, 0xfeff, +0xfbff, 0x1700, 0x1000, 0x0800, 0x1100, 0x0800, 0xf2ff, 0x0400, 0x0300, 0x0000, 0x1d00, 0x1b00, 0x0b00, 0xf1ff, 0xd8ff, 0xddff, +0xeeff, 0xdfff, 0xd0ff, 0xf0ff, 0xf3ff, 0xf4ff, 0x0300, 0x1000, 0xf9ff, 0xf3ff, 0x1000, 0x1e00, 0x0e00, 0xfdff, 0xfaff, 0xfdff, +0x1100, 0xfeff, 0x1d00, 0x3100, 0x0300, 0xf8ff, 0x0c00, 0x1700, 0x1300, 0x0200, 0xfdff, 0x0900, 0x0800, 0xf8ff, 0xf9ff, 0xfaff, +0xf3ff, 0x0400, 0xfcff, 0xf5ff, 0x0100, 0xfaff, 0xe3ff, 0xe4ff, 0xf8ff, 0x0000, 0x0300, 0xf1ff, 0xe1ff, 0x0000, 0xf7ff, 0xf4ff, +0xefff, 0xdfff, 0x0900, 0x1600, 0xe0ff, 0xf5ff, 0x1500, 0x0900, 0xfdff, 0x0300, 0x1200, 0x1900, 0xffff, 0x0e00, 0x3e00, 0x3400, +0xe3ff, 0xfbff, 0x2c00, 0xfdff, 0xe5ff, 0x0300, 0x0800, 0x0200, 0xe5ff, 0xe0ff, 0x0900, 0x1500, 0xdeff, 0xe1ff, 0xf8ff, 0xe0ff, +0xddff, 0x1500, 0x1f00, 0xecff, 0x0c00, 0x6aff, 0x0700, 0x2600, 0xecfe, 0xac01, 0x8500, 0xa9fe, 0xa200, 0x6700, 0xb8ff, 0x8f00, +0xf9ff, 0xa1ff, 0xd100, 0xc1fe, 0x8900, 0x4a01, 0x6dfe, 0xf9ff, 0x1301, 0xb1ff, 0xbaff, 0xac00, 0x1401, 0x7bfe, 0x16ff, 0x8e01, +0x92ff, 0x03ff, 0x7202, 0xedff, 0x58fe, 0x6b00, 0x0300, 0xc6ff, 0x5600, 0xadff, 0xd5ff, 0xe800, 0x85ff, 0x16ff, 0xd000, 0x2600, +0xacff, 0x3f00, 0x47fe, 0x6000, 0x3b02, 0xc1fe, 0x56fe, 0x3001, 0xc2ff, 0xfffe, 0xf4ff, 0x2400, 0x5000, 0x1f00, 0x38ff, 0x0200, +0x6800, 0xc800, 0x45ff, 0xb1ff, 0xeb00, 0x0100, 0xaaff, 0x0f00, 0x7f00, 0x2400, 0x8d00, 0xa5ff, 0x0600, 0xa501, 0xa5ff, 0x67ff, +0xb700, 0x0e00, 0xa6ff, 0xe1ff, 0x0c00, 0xf4ff, 0xf1ff, 0x29ff, 0x0cff, 0xb1ff, 0x2fff, 0xfffe, 0xe0ff, 0x1900, 0xe1ff, 0x1600, +0x5b00, 0x6200, 0x7d00, 0x1f00, 0x1300, 0x6100, 0x4500, 0xf3ff, 0xb400, 0x7800, 0x5d00, 0x1600, 0x4500, 0x4700, 0x1200, 0x0a00, +0xd5ff, 0x5a00, 0x3400, 0xf4ff, 0x3600, 0xbeff, 0xe1ff, 0x0300, 0xb6ff, 0xa5ff, 0xc2ff, 0x98ff, 0xc5ff, 0x2100, 0xdbff, 0x2d00, +0x1400, 0xd4ff, 0x2e00, 0x0a00, 0xfaff, 0x0a00, 0x0300, 0xd9ff, 0xc3ff, 0x6600, 0x1d00, 0x80ff, 0x0700, 0x2300, 0x0eff, 0xacff, +0x0500, 0xacff, 0x1400, 0x4600, 0x5000, 0x6400, 0xad00, 0x4900, 0x2c00, 0x7900, 0x3000, 0xc7ff, 0xbbff, 0x8cff, 0xa3ff, 0x5800, +0xcfff, 0xddfe, 0x8fff, 0xc3ff, 0x78fe, 0x51ff, 0xceff, 0x62ff, 0x2b00, 0xbd00, 0x7300, 0xe000, 0x7901, 0x8900, 0x6e00, 0xf000, +0x5100, 0xd5ff, 0xcfff, 0xacff, 0xe1ff, 0xc400, 0x71ff, 0xbffd, 0xacff, 0xfdff, 0x5dfe, 0x43ff, 0xa000, 0x9b00, 0xab00, 0x1f01, +0x0b01, 0x7e01, 0x1f01, 0xddff, 0xfcff, 0x3200, 0x3fff, 0x16ff, 0x1500, 0xc7ff, 0xddfe, 0x64ff, 0xe6fe, 0x4efe, 0x26ff, 0x4dff, +0x30ff, 0x2800, 0x2401, 0xe300, 0x6301, 0xdf01, 0xa801, 0xb001, 0x5701, 0xc500, 0x8100, 0x3600, 0xa7ff, 0xd6ff, 0x6100, 0x0eff, +0x82fe, 0x9eff, 0xa8ff, 0x03ff, 0x97ff, 0x7300, 0x8200, 0x6600, 0x6000, 0x6700, 0x7c00, 0xdeff, 0x2fff, 0x57ff, 0x83ff, 0x26ff, +0xf3fe, 0x37ff, 0x49ff, 0xe6fe, 0x04ff, 0x66ff, 0x8dff, 0xa6ff, 0x0100, 0x8300, 0xbc00, 0xf200, 0x2501, 0x6301, 0x6601, 0x2b01, +0xed00, 0xbe00, 0x6400, 0x2400, 0x2f00, 0x0d00, 0xe0ff, 0xe5ff, 0xbeff, 0xc4ff, 0x0e00, 0x0600, 0xebff, 0xfbff, 0xd1ff, 0xa5ff, +0x7eff, 0x48ff, 0x2dff, 0x35ff, 0x19ff, 0x62ff, 0x30ff, 0x40ff, 0xbfff, 0x6fff, 0x7eff, 0x0600, 0xe4ff, 0xbaff, 0x4000, 0xae00, +0x8f00, 0x8500, 0xab00, 0xd500, 0xa900, 0x5800, 0x4d00, 0x4a00, 0x1f00, 0xe3ff, 0xd5ff, 0x0500, 0x0e00, 0x5eff, 0xbfff, 0x9500 }; diff --git a/codecs/slin_ulaw_ex.h b/codecs/slin_ulaw_ex.h new file mode 100644 index 000000000..9af79eba2 --- /dev/null +++ b/codecs/slin_ulaw_ex.h @@ -0,0 +1,25 @@ +/*! \file + * \brief slin_ulaw_ex.h -- + * + * Signed 16-bit audio data, 10 milliseconds worth at 8 kHz. + * + * Source: g723.example + * + * Copyright (C) 2001-2005, Digium Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static signed short slin_ulaw_ex[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; diff --git a/codecs/speex_slin_ex.h b/codecs/speex_slin_ex.h new file mode 100644 index 000000000..404743799 --- /dev/null +++ b/codecs/speex_slin_ex.h @@ -0,0 +1,16 @@ +/*! \file + * \brief Random Data data + * + * Source: speex.raw + * + * Copyright (C) 1999-2005, Digium Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static unsigned char speex_slin_ex[] = { +0x2e, 0x8e, 0x0f, 0x9a, 0x20, 0000, 0x01, 0x7f, 0xff, 0xff, +0xff, 0xff, 0xff, 0x91, 0000, 0xbf, 0xff, 0xff, 0xff, 0xff, +0xff, 0xdc, 0x80, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x98, 0x7f, 0xff, 0xff, 0xff, 0xe8, 0xff, 0xf7, 0x80 }; diff --git a/codecs/ulaw_slin_ex.h b/codecs/ulaw_slin_ex.h new file mode 100644 index 000000000..9f0417a6b --- /dev/null +++ b/codecs/ulaw_slin_ex.h @@ -0,0 +1,25 @@ +/*! \file + * \brief ulaw_slin_ex.h -- + * + * 4-bit ADPCM data, 20 milliseconds worth at 8 kHz. + * + * Source: g723.example + * + * Copyright (C) 2001-2005, Digium Inc. + * + * Distributed under the terms of the GNU General Public License + * + */ + +static unsigned char ulaw_slin_ex[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; |