Merged revisions 328247 via svnmerge from
[asterisk/asterisk.git] / codecs / codec_resample.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2011, Digium, Inc.
5  *
6  * Russell Bryant <russell@digium.com>
7  * David Vossel <dvossel@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 /*! 
21  * \file
22  *
23  * \brief Resample slinear audio
24  * 
25  * \ingroup codecs
26  */
27
28 /*** MODULEINFO
29         <depend>resample</depend>
30         <support_level>core</support_level>
31  ***/
32
33 #include "asterisk.h"
34 #include "speex/speex_resampler.h"
35
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37
38 #include "asterisk/module.h"
39 #include "asterisk/translate.h"
40 #include "asterisk/slin.h"
41
42 #define OUTBUF_SIZE   8096
43
44 static struct ast_translator *translators;
45 static int trans_size;
46 static int id_list[] = {
47         AST_FORMAT_SLINEAR,
48         AST_FORMAT_SLINEAR12,
49         AST_FORMAT_SLINEAR16,
50         AST_FORMAT_SLINEAR24,
51         AST_FORMAT_SLINEAR32,
52         AST_FORMAT_SLINEAR44,
53         AST_FORMAT_SLINEAR48,
54         AST_FORMAT_SLINEAR96,
55         AST_FORMAT_SLINEAR192,
56 };
57
58 static int resamp_new(struct ast_trans_pvt *pvt)
59 {
60         int err;
61
62         if (!(pvt->pvt = speex_resampler_init(1, ast_format_rate(&pvt->t->src_format), ast_format_rate(&pvt->t->dst_format), 5, &err))) {
63                 return -1;
64         }
65
66         return 0;
67 }
68
69 static void resamp_destroy(struct ast_trans_pvt *pvt)
70 {
71         SpeexResamplerState *resamp_pvt = pvt->pvt;
72         speex_resampler_destroy(resamp_pvt);
73 }
74
75 static int resamp_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
76 {
77         SpeexResamplerState *resamp_pvt = pvt->pvt;
78         unsigned int out_samples = (OUTBUF_SIZE / sizeof(int16_t)) - pvt->samples;
79         unsigned int in_samples;
80
81         if (!f->datalen) {
82                 return -1;
83         }
84         in_samples = f->datalen / 2;
85
86         speex_resampler_process_int(resamp_pvt,
87                 0,
88                 f->data.ptr,
89                 &in_samples,
90                 pvt->outbuf.i16 + pvt->samples,
91                 &out_samples);
92
93         pvt->samples += out_samples;
94         pvt->datalen += out_samples * 2;
95
96         return 0;
97 }
98
99 static int unload_module(void)
100 {
101         int res = 0;
102         int idx;
103
104         for (idx = 0; idx < trans_size; idx++) {
105                 res |= ast_unregister_translator(&translators[idx]);
106         }
107         ast_free(translators);
108
109         return res;
110 }
111
112 static int load_module(void)
113 {
114         int res = 0;
115         int x, y, idx = 0;
116
117         trans_size = ARRAY_LEN(id_list) * ARRAY_LEN(id_list);
118         if (!(translators = ast_calloc(1, sizeof(struct ast_translator) * trans_size))) {
119                 return AST_MODULE_LOAD_FAILURE;
120         }
121
122         for (x = 0; x < ARRAY_LEN(id_list); x++) {
123                 for (y = 0; y < ARRAY_LEN(id_list); y++) {
124                         if (x == y) {
125                                 continue;
126                         }
127                         translators[idx].newpvt = resamp_new;
128                         translators[idx].destroy = resamp_destroy;
129                         translators[idx].framein = resamp_framein;
130                         translators[idx].desc_size = 0;
131                         translators[idx].buffer_samples = (OUTBUF_SIZE / sizeof(int16_t));
132                         translators[idx].buf_size = OUTBUF_SIZE;
133                         ast_format_set(&translators[idx].src_format, id_list[x], 0);
134                         ast_format_set(&translators[idx].dst_format, id_list[y], 0);
135                         snprintf(translators[idx].name, sizeof(translators[idx].name), "slin %dkhz -> %dkhz",
136                                 ast_format_rate(&translators[idx].src_format), ast_format_rate(&translators[idx].dst_format));
137                         res |= ast_register_translator(&translators[idx]);
138                         idx++;
139                 }
140
141         }
142
143         return AST_MODULE_LOAD_SUCCESS;
144 }
145
146 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SLIN Resampling Codec");