From 21cb767db7d4854769d6a9d15e2008ab27c404a5 Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Mon, 31 Dec 2007 21:22:31 +0000 Subject: Merge changes from team/russell/codec_resample This commit imports libresample for use in Asterisk. It also adds a new codec module, codec_resample. This module uses libresample to re-sample signed linear audio between 8 kHz and 16 kHz. It also provides an alternative for converting between 16 kHz G.722 and 8 kHz signed linear when using G.722, which will likely be useful as some people have complained about volume issues when the current codec_g722 converts to 8 kHz signed linear. But, to test this, you will have to disable the g722-to-slin and g722-to-slin16 translators in codec_g722.c. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@95501 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- codecs/Makefile | 2 + codecs/codec_resample.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++ codecs/slin_resample_ex.h | 43 +++++++++ 3 files changed, 279 insertions(+) create mode 100644 codecs/codec_resample.c create mode 100644 codecs/slin_resample_ex.h (limited to 'codecs') diff --git a/codecs/Makefile b/codecs/Makefile index d96e7cf57..a09f67149 100644 --- a/codecs/Makefile +++ b/codecs/Makefile @@ -54,3 +54,5 @@ $(LIBG722): @$(MAKE) -C g722 all $(if $(filter codec_g722,$(EMBEDDED_MODS)),modules.link,codec_g722.so): $(LIBG722) + +codec_resample.o: ASTCFLAGS+=-I$(ASTTOPDIR)/main/libresample/include diff --git a/codecs/codec_resample.c b/codecs/codec_resample.c new file mode 100644 index 000000000..88af225ff --- /dev/null +++ b/codecs/codec_resample.c @@ -0,0 +1,234 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2007, Digium, Inc. + * + * Russell Bryant + * + * 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 Resample slinear audio + * + * \ingroup codecs + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +/* These are for SHRT_MAX and FLT_MAX -- { */ +#ifdef __Darwin__ +#include +#else +#include +#endif +#include +/* } */ + +#include "asterisk/module.h" +#include "asterisk/translate.h" + +#include "libresample.h" + +#include "slin_resample_ex.h" + +#define RESAMPLER_QUALITY 0 + +#define OUTBUF_SIZE 8096 + +struct slin16_to_slin8_pvt { + void *resampler; + double resample_factor; +}; + +struct slin8_to_slin16_pvt { + void *resampler; + double resample_factor; +}; + +static int slin16_to_slin8_new(struct ast_trans_pvt *pvt) +{ + struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt; + + resamp_pvt->resample_factor = 0.5; + + if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, 0.5, 0.5))) + return -1; + + return 0; +} + +static int slin8_to_slin16_new(struct ast_trans_pvt *pvt) +{ + struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt; + + resamp_pvt->resample_factor = 2.0; + + if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, 2.0, 2.0))) + return -1; + + return 0; +} + +static void slin16_to_slin8_destroy(struct ast_trans_pvt *pvt) +{ + struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt; + + if (resamp_pvt->resampler) + resample_close(resamp_pvt->resampler); +} + +static void slin8_to_slin16_destroy(struct ast_trans_pvt *pvt) +{ + struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt; + + if (resamp_pvt->resampler) + resample_close(resamp_pvt->resampler); +} + +static int resample_frame(struct ast_trans_pvt *pvt, + void *resampler, double resample_factor, struct ast_frame *f) +{ + int total_in_buf_used = 0; + int total_out_buf_used = 0; + int16_t *in_buf = (int16_t *) f->data; + int16_t *out_buf = (int16_t *) pvt->outbuf + pvt->samples; + float in_buf_f[f->samples]; + float out_buf_f[2048]; + int res = 0; + int i; + + for (i = 0; i < f->samples; i++) + in_buf_f[i] = in_buf[i] * (FLT_MAX / SHRT_MAX); + + while (total_in_buf_used < f->samples) { + int in_buf_used, out_buf_used; + + out_buf_used = resample_process(resampler, resample_factor, + &in_buf_f[total_in_buf_used], f->samples - total_in_buf_used, + 0, &in_buf_used, + &out_buf_f[total_out_buf_used], ARRAY_LEN(out_buf_f) - total_out_buf_used); + + if (out_buf_used < 0) + break; + + total_out_buf_used += out_buf_used; + total_in_buf_used += in_buf_used; + + if (total_out_buf_used == ARRAY_LEN(out_buf_f)) { + ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n"); + res = -1; + break; + } + } + + for (i = 0; i < total_out_buf_used; i++) + out_buf[i] = out_buf_f[i] * (SHRT_MAX / FLT_MAX); + + pvt->samples += total_out_buf_used; + pvt->datalen += (total_out_buf_used * sizeof(int16_t)); + + return res; +} + +static int slin16_to_slin8_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt; + + return resample_frame(pvt, resamp_pvt->resampler, resamp_pvt->resample_factor, f); +} + +static int slin8_to_slin16_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) +{ + struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt; + + return resample_frame(pvt, resamp_pvt->resampler, resamp_pvt->resample_factor, f); +} + +static struct ast_frame *slin16_to_slin8_sample(void) +{ + static struct ast_frame f = { + .frametype = AST_FRAME_VOICE, + .subclass = AST_FORMAT_SLINEAR16, + .datalen = sizeof(slin16_slin8_ex), + .samples = sizeof(slin16_slin8_ex) / sizeof(slin16_slin8_ex[0]), + .src = __PRETTY_FUNCTION__, + .data = slin16_slin8_ex, + }; + + return &f; +} + +static struct ast_frame *slin8_to_slin16_sample(void) +{ + static struct ast_frame f = { + .frametype = AST_FRAME_VOICE, + .subclass = AST_FORMAT_SLINEAR, + .datalen = sizeof(slin8_slin16_ex), + .samples = sizeof(slin8_slin16_ex) / sizeof(slin8_slin16_ex[0]), + .src = __PRETTY_FUNCTION__, + .data = slin8_slin16_ex, + }; + + return &f; +} + +static struct ast_translator slin16_to_slin8 = { + .name = "slin16_to_slin8", + .srcfmt = AST_FORMAT_SLINEAR16, + .dstfmt = AST_FORMAT_SLINEAR, + .newpvt = slin16_to_slin8_new, + .destroy = slin16_to_slin8_destroy, + .framein = slin16_to_slin8_framein, + .sample = slin16_to_slin8_sample, + .desc_size = sizeof(struct slin16_to_slin8_pvt), + .buffer_samples = (OUTBUF_SIZE / sizeof(int16_t)), + .buf_size = OUTBUF_SIZE, +}; + +static struct ast_translator slin8_to_slin16 = { + .name = "slin8_to_slin16", + .srcfmt = AST_FORMAT_SLINEAR, + .dstfmt = AST_FORMAT_SLINEAR16, + .newpvt = slin8_to_slin16_new, + .destroy = slin8_to_slin16_destroy, + .framein = slin8_to_slin16_framein, + .sample = slin8_to_slin16_sample, + .desc_size = sizeof(struct slin8_to_slin16_pvt), + .buffer_samples = OUTBUF_SIZE, + .buf_size = OUTBUF_SIZE, +}; + +static int unload_module(void) +{ + int res = 0; + + res |= ast_unregister_translator(&slin16_to_slin8); + res |= ast_unregister_translator(&slin8_to_slin16); + + return res; +} + +static int load_module(void) +{ + int res = 0; + + res |= ast_register_translator(&slin16_to_slin8); + res |= ast_register_translator(&slin8_to_slin16); + + return AST_MODULE_LOAD_SUCCESS; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SLIN Resampling Codec"); diff --git a/codecs/slin_resample_ex.h b/codecs/slin_resample_ex.h new file mode 100644 index 000000000..701654e39 --- /dev/null +++ b/codecs/slin_resample_ex.h @@ -0,0 +1,43 @@ +/*! \file + * \brief slin_resample_ex.h -- + * + * Copyright (C) 2007, Digium Inc. + * + * Distributed under the terms of the GNU General Public License + */ + +static signed short slin16_slin8_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, + 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 +}; + +static signed short slin8_slin16_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 +}; -- cgit v1.2.3