Wed Oct 28 11:51:02 2009

Asterisk developer's documentation


codec_resample.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2007, Digium, Inc.
00005  *
00006  * Russell Bryant <russell@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! 
00020  * \file
00021  *
00022  * \brief Resample slinear audio
00023  * 
00024  * \note To install libresample, check it out of the following repository:
00025  * <code>$ svn co http://svn.digium.com/svn/thirdparty/libresample/trunk</code>
00026  *
00027  * \ingroup codecs
00028  */
00029 
00030 /*** MODULEINFO
00031    <depend>resample</depend>
00032  ***/
00033 
00034 #include "asterisk.h"
00035 
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 140568 $")
00037 
00038 /* These are for SHRT_MAX and FLT_MAX -- { */
00039 #if defined(__Darwin__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__CYGWIN__)
00040 #include <float.h>
00041 #else
00042 #include <values.h>
00043 #endif
00044 #include <limits.h>
00045 /* } */
00046 
00047 #include <libresample.h>
00048 
00049 #include "asterisk/module.h"
00050 #include "asterisk/translate.h"
00051 
00052 #include "slin_resample_ex.h"
00053 
00054 #define RESAMPLER_QUALITY 1
00055 
00056 #define OUTBUF_SIZE   8096
00057 
00058 struct slin16_to_slin8_pvt {
00059    void *resampler;
00060    float resample_factor;
00061 };
00062 
00063 struct slin8_to_slin16_pvt {
00064    void *resampler;
00065    float resample_factor;
00066 };
00067 
00068 static int slin16_to_slin8_new(struct ast_trans_pvt *pvt)
00069 {
00070    struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
00071 
00072    resamp_pvt->resample_factor = 0.5;
00073 
00074    if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, 0.5, 0.5)))
00075       return -1;
00076 
00077    return 0;
00078 }
00079 
00080 static int slin8_to_slin16_new(struct ast_trans_pvt *pvt)
00081 {
00082    struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
00083 
00084    resamp_pvt->resample_factor = 2.0;
00085 
00086    if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, 2.0, 2.0)))
00087       return -1;
00088 
00089    return 0;
00090 }
00091 
00092 static void slin16_to_slin8_destroy(struct ast_trans_pvt *pvt)
00093 {
00094    struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
00095 
00096    if (resamp_pvt->resampler)
00097       resample_close(resamp_pvt->resampler);
00098 }
00099 
00100 static void slin8_to_slin16_destroy(struct ast_trans_pvt *pvt)
00101 {
00102    struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
00103 
00104    if (resamp_pvt->resampler)
00105       resample_close(resamp_pvt->resampler);
00106 }
00107 
00108 static int resample_frame(struct ast_trans_pvt *pvt,
00109    void *resampler, float resample_factor, struct ast_frame *f)
00110 {
00111    int total_in_buf_used = 0;
00112    int total_out_buf_used = 0;
00113    int16_t *in_buf = (int16_t *) f->data.ptr;
00114    int16_t *out_buf = pvt->outbuf.i16 + pvt->samples;
00115    float in_buf_f[f->samples];
00116    float out_buf_f[2048];
00117    int res = 0;
00118    int i;
00119 
00120    for (i = 0; i < f->samples; i++)
00121       in_buf_f[i] = in_buf[i] * (FLT_MAX / SHRT_MAX);
00122 
00123    while (total_in_buf_used < f->samples) {
00124       int in_buf_used, out_buf_used;
00125 
00126       out_buf_used = resample_process(resampler, resample_factor,
00127          &in_buf_f[total_in_buf_used], f->samples - total_in_buf_used,
00128          0, &in_buf_used,
00129          &out_buf_f[total_out_buf_used], ARRAY_LEN(out_buf_f) - total_out_buf_used);
00130 
00131       if (out_buf_used < 0)
00132          break;
00133 
00134       total_out_buf_used += out_buf_used;
00135       total_in_buf_used += in_buf_used;
00136 
00137       if (total_out_buf_used == ARRAY_LEN(out_buf_f)) {
00138          ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n");
00139          res = -1;
00140          break;
00141       }
00142    }
00143 
00144    for (i = 0; i < total_out_buf_used; i++)
00145       out_buf[i] = out_buf_f[i] * (SHRT_MAX / FLT_MAX);  
00146 
00147    pvt->samples += total_out_buf_used;
00148    pvt->datalen += (total_out_buf_used * sizeof(int16_t));
00149 
00150    return res;
00151 }
00152 
00153 static int slin16_to_slin8_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00154 {
00155    struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
00156    void *resampler = resamp_pvt->resampler;
00157    float resample_factor = resamp_pvt->resample_factor;
00158 
00159    return resample_frame(pvt, resampler, resample_factor, f);
00160 }
00161 
00162 static int slin8_to_slin16_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00163 {
00164    struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
00165    void *resampler = resamp_pvt->resampler;
00166    float resample_factor = resamp_pvt->resample_factor;
00167 
00168    return resample_frame(pvt, resampler, resample_factor, f);
00169 }
00170 
00171 static struct ast_frame *slin16_to_slin8_sample(void)
00172 {
00173    static struct ast_frame f = {
00174       .frametype = AST_FRAME_VOICE,
00175       .subclass = AST_FORMAT_SLINEAR16,
00176       .datalen = sizeof(slin16_slin8_ex),
00177       .samples = ARRAY_LEN(slin16_slin8_ex),
00178       .src = __PRETTY_FUNCTION__,
00179       .data.ptr = slin16_slin8_ex,
00180    };
00181 
00182    return &f;
00183 }
00184 
00185 static struct ast_frame *slin8_to_slin16_sample(void)
00186 {
00187    static struct ast_frame f = {
00188       .frametype = AST_FRAME_VOICE,
00189       .subclass = AST_FORMAT_SLINEAR,
00190       .datalen = sizeof(slin8_slin16_ex),
00191       .samples = ARRAY_LEN(slin8_slin16_ex),
00192       .src = __PRETTY_FUNCTION__,
00193       .data.ptr = slin8_slin16_ex,
00194    };
00195 
00196    return &f;
00197 }
00198 
00199 static struct ast_translator slin16_to_slin8 = {
00200    .name = "slin16_to_slin8",
00201    .srcfmt = AST_FORMAT_SLINEAR16,
00202    .dstfmt = AST_FORMAT_SLINEAR,
00203    .newpvt = slin16_to_slin8_new,
00204    .destroy = slin16_to_slin8_destroy,
00205    .framein = slin16_to_slin8_framein,
00206    .sample = slin16_to_slin8_sample,
00207    .desc_size = sizeof(struct slin16_to_slin8_pvt),
00208    .buffer_samples = (OUTBUF_SIZE / sizeof(int16_t)),
00209    .buf_size = OUTBUF_SIZE,
00210 };
00211 
00212 static struct ast_translator slin8_to_slin16 = {
00213    .name = "slin8_to_slin16",
00214    .srcfmt = AST_FORMAT_SLINEAR,
00215    .dstfmt = AST_FORMAT_SLINEAR16,
00216    .newpvt = slin8_to_slin16_new,
00217    .destroy = slin8_to_slin16_destroy,
00218    .framein = slin8_to_slin16_framein,
00219    .sample = slin8_to_slin16_sample,
00220    .desc_size = sizeof(struct slin8_to_slin16_pvt),
00221    .buffer_samples = (OUTBUF_SIZE / sizeof(int16_t)),
00222    .buf_size = OUTBUF_SIZE,
00223 };
00224 
00225 static int unload_module(void)
00226 {
00227    int res = 0;
00228 
00229    res |= ast_unregister_translator(&slin16_to_slin8);
00230    res |= ast_unregister_translator(&slin8_to_slin16);
00231 
00232    return res;
00233 }
00234 
00235 static int load_module(void)
00236 {
00237    int res = 0;
00238 
00239    res |= ast_register_translator(&slin16_to_slin8);
00240    res |= ast_register_translator(&slin8_to_slin16);
00241 
00242    return AST_MODULE_LOAD_SUCCESS;
00243 }
00244 
00245 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SLIN Resampling Codec");

Generated on Wed Oct 28 11:51:02 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6