codec_resample.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2011, Digium, Inc.
00005  *
00006  * Russell Bryant <russell@digium.com>
00007  * David Vossel <dvossel@digium.com>
00008  *
00009  * See http://www.asterisk.org for more information about
00010  * the Asterisk project. Please do not directly contact
00011  * any of the maintainers of this project for assistance;
00012  * the project provides a web site, mailing lists and IRC
00013  * channels for your use.
00014  *
00015  * This program is free software, distributed under the terms of
00016  * the GNU General Public License Version 2. See the LICENSE file
00017  * at the top of the source tree.
00018  */
00019 
00020 /*! 
00021  * \file
00022  *
00023  * \brief Resample slinear audio
00024  * 
00025  * \ingroup codecs
00026  */
00027 
00028 /*** MODULEINFO
00029    <support_level>core</support_level>
00030  ***/
00031 
00032 #include "asterisk.h"
00033 #include "speex/speex_resampler.h"
00034 
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 419044 $")
00036 
00037 #include "asterisk/module.h"
00038 #include "asterisk/translate.h"
00039 #include "asterisk/slin.h"
00040 
00041 #define OUTBUF_SIZE   8096
00042 
00043 static struct ast_translator *translators;
00044 static int trans_size;
00045 static struct ast_codec codec_list[] = {
00046    {
00047       .name = "slin",
00048       .type = AST_MEDIA_TYPE_AUDIO,
00049       .sample_rate = 8000,
00050    },
00051    {
00052       .name = "slin",
00053       .type = AST_MEDIA_TYPE_AUDIO,
00054       .sample_rate = 12000,
00055    },
00056    {
00057       .name = "slin",
00058       .type = AST_MEDIA_TYPE_AUDIO,
00059       .sample_rate = 16000,
00060    },
00061    {
00062       .name = "slin",
00063       .type = AST_MEDIA_TYPE_AUDIO,
00064       .sample_rate = 24000,
00065    },
00066    {
00067       .name = "slin",
00068       .type = AST_MEDIA_TYPE_AUDIO,
00069       .sample_rate = 32000,
00070    },
00071    {
00072       .name = "slin",
00073       .type = AST_MEDIA_TYPE_AUDIO,
00074       .sample_rate = 44100,
00075    },
00076    {
00077       .name = "slin",
00078       .type = AST_MEDIA_TYPE_AUDIO,
00079       .sample_rate = 48000,
00080    },
00081    {
00082       .name = "slin",
00083       .type = AST_MEDIA_TYPE_AUDIO,
00084       .sample_rate = 96000,
00085    },
00086    {
00087       .name = "slin",
00088       .type = AST_MEDIA_TYPE_AUDIO,
00089       .sample_rate = 192000,
00090    },
00091 };
00092 
00093 static int resamp_new(struct ast_trans_pvt *pvt)
00094 {
00095    int err;
00096 
00097    if (!(pvt->pvt = speex_resampler_init(1, pvt->t->src_codec.sample_rate, pvt->t->dst_codec.sample_rate, 5, &err))) {
00098       return -1;
00099    }
00100 
00101    ast_assert(pvt->f.subclass.format == NULL);
00102    pvt->f.subclass.format = ao2_bump(ast_format_cache_get_slin_by_rate(pvt->t->dst_codec.sample_rate));
00103 
00104    return 0;
00105 }
00106 
00107 static void resamp_destroy(struct ast_trans_pvt *pvt)
00108 {
00109    SpeexResamplerState *resamp_pvt = pvt->pvt;
00110 
00111    speex_resampler_destroy(resamp_pvt);
00112 }
00113 
00114 static int resamp_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00115 {
00116    SpeexResamplerState *resamp_pvt = pvt->pvt;
00117    unsigned int out_samples = (OUTBUF_SIZE / sizeof(int16_t)) - pvt->samples;
00118    unsigned int in_samples;
00119 
00120    if (!f->datalen) {
00121       return -1;
00122    }
00123    in_samples = f->datalen / 2;
00124 
00125    speex_resampler_process_int(resamp_pvt,
00126       0,
00127       f->data.ptr,
00128       &in_samples,
00129       pvt->outbuf.i16 + pvt->samples,
00130       &out_samples);
00131 
00132    pvt->samples += out_samples;
00133    pvt->datalen += out_samples * 2;
00134 
00135    return 0;
00136 }
00137 
00138 static int unload_module(void)
00139 {
00140    int res = 0;
00141    int idx;
00142 
00143    for (idx = 0; idx < trans_size; idx++) {
00144       res |= ast_unregister_translator(&translators[idx]);
00145    }
00146    ast_free(translators);
00147 
00148    return res;
00149 }
00150 
00151 static int load_module(void)
00152 {
00153    int res = 0;
00154    int x, y, idx = 0;
00155 
00156    trans_size = ARRAY_LEN(codec_list) * (ARRAY_LEN(codec_list) - 1);
00157    if (!(translators = ast_calloc(1, sizeof(struct ast_translator) * trans_size))) {
00158       return AST_MODULE_LOAD_FAILURE;
00159    }
00160 
00161    for (x = 0; x < ARRAY_LEN(codec_list); x++) {
00162       for (y = 0; y < ARRAY_LEN(codec_list); y++) {
00163          if (x == y) {
00164             continue;
00165          }
00166          translators[idx].newpvt = resamp_new;
00167          translators[idx].destroy = resamp_destroy;
00168          translators[idx].framein = resamp_framein;
00169          translators[idx].desc_size = 0;
00170          translators[idx].buffer_samples = (OUTBUF_SIZE / sizeof(int16_t));
00171          translators[idx].buf_size = OUTBUF_SIZE;
00172          memcpy(&translators[idx].src_codec, &codec_list[x], sizeof(struct ast_codec));
00173          memcpy(&translators[idx].dst_codec, &codec_list[y], sizeof(struct ast_codec));
00174          snprintf(translators[idx].name, sizeof(translators[idx].name), "slin %ukhz -> %ukhz",
00175             translators[idx].src_codec.sample_rate, translators[idx].dst_codec.sample_rate);
00176          res |= ast_register_translator(&translators[idx]);
00177          idx++;
00178       }
00179 
00180    }
00181    /* in case ast_register_translator() failed, we call unload_module() and
00182    ast_unregister_translator won't fail.*/
00183    if (res) {
00184       unload_module();
00185       return AST_MODULE_LOAD_FAILURE;
00186    }
00187 
00188    return AST_MODULE_LOAD_SUCCESS;
00189 }
00190 
00191 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SLIN Resampling Codec");

Generated on Thu Apr 16 06:27:30 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6