git migration: Refactor the ASTERISK_FILE_VERSION macro
[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         <support_level>core</support_level>
30  ***/
31
32 #include "asterisk.h"
33 #include "speex/speex_resampler.h"
34
35 ASTERISK_REGISTER_FILE()
36
37 #include "asterisk/module.h"
38 #include "asterisk/translate.h"
39 #include "asterisk/slin.h"
40
41 #define OUTBUF_SIZE   8096
42
43 static struct ast_translator *translators;
44 static int trans_size;
45 static struct ast_codec codec_list[] = {
46         {
47                 .name = "slin",
48                 .type = AST_MEDIA_TYPE_AUDIO,
49                 .sample_rate = 8000,
50         },
51         {
52                 .name = "slin",
53                 .type = AST_MEDIA_TYPE_AUDIO,
54                 .sample_rate = 12000,
55         },
56         {
57                 .name = "slin",
58                 .type = AST_MEDIA_TYPE_AUDIO,
59                 .sample_rate = 16000,
60         },
61         {
62                 .name = "slin",
63                 .type = AST_MEDIA_TYPE_AUDIO,
64                 .sample_rate = 24000,
65         },
66         {
67                 .name = "slin",
68                 .type = AST_MEDIA_TYPE_AUDIO,
69                 .sample_rate = 32000,
70         },
71         {
72                 .name = "slin",
73                 .type = AST_MEDIA_TYPE_AUDIO,
74                 .sample_rate = 44100,
75         },
76         {
77                 .name = "slin",
78                 .type = AST_MEDIA_TYPE_AUDIO,
79                 .sample_rate = 48000,
80         },
81         {
82                 .name = "slin",
83                 .type = AST_MEDIA_TYPE_AUDIO,
84                 .sample_rate = 96000,
85         },
86         {
87                 .name = "slin",
88                 .type = AST_MEDIA_TYPE_AUDIO,
89                 .sample_rate = 192000,
90         },
91 };
92
93 static int resamp_new(struct ast_trans_pvt *pvt)
94 {
95         int err;
96
97         if (!(pvt->pvt = speex_resampler_init(1, pvt->t->src_codec.sample_rate, pvt->t->dst_codec.sample_rate, 5, &err))) {
98                 return -1;
99         }
100
101         ast_assert(pvt->f.subclass.format == NULL);
102         pvt->f.subclass.format = ao2_bump(ast_format_cache_get_slin_by_rate(pvt->t->dst_codec.sample_rate));
103
104         return 0;
105 }
106
107 static void resamp_destroy(struct ast_trans_pvt *pvt)
108 {
109         SpeexResamplerState *resamp_pvt = pvt->pvt;
110
111         speex_resampler_destroy(resamp_pvt);
112 }
113
114 static int resamp_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
115 {
116         SpeexResamplerState *resamp_pvt = pvt->pvt;
117         unsigned int out_samples = (OUTBUF_SIZE / sizeof(int16_t)) - pvt->samples;
118         unsigned int in_samples;
119
120         if (!f->datalen) {
121                 return -1;
122         }
123         in_samples = f->datalen / 2;
124
125         speex_resampler_process_int(resamp_pvt,
126                 0,
127                 f->data.ptr,
128                 &in_samples,
129                 pvt->outbuf.i16 + pvt->samples,
130                 &out_samples);
131
132         pvt->samples += out_samples;
133         pvt->datalen += out_samples * 2;
134
135         return 0;
136 }
137
138 static int unload_module(void)
139 {
140         int res = 0;
141         int idx;
142
143         for (idx = 0; idx < trans_size; idx++) {
144                 res |= ast_unregister_translator(&translators[idx]);
145         }
146         ast_free(translators);
147
148         return res;
149 }
150
151 static int load_module(void)
152 {
153         int res = 0;
154         int x, y, idx = 0;
155
156         trans_size = ARRAY_LEN(codec_list) * (ARRAY_LEN(codec_list) - 1);
157         if (!(translators = ast_calloc(1, sizeof(struct ast_translator) * trans_size))) {
158                 return AST_MODULE_LOAD_FAILURE;
159         }
160
161         for (x = 0; x < ARRAY_LEN(codec_list); x++) {
162                 for (y = 0; y < ARRAY_LEN(codec_list); y++) {
163                         if (x == y) {
164                                 continue;
165                         }
166                         translators[idx].newpvt = resamp_new;
167                         translators[idx].destroy = resamp_destroy;
168                         translators[idx].framein = resamp_framein;
169                         translators[idx].desc_size = 0;
170                         translators[idx].buffer_samples = (OUTBUF_SIZE / sizeof(int16_t));
171                         translators[idx].buf_size = OUTBUF_SIZE;
172                         memcpy(&translators[idx].src_codec, &codec_list[x], sizeof(struct ast_codec));
173                         memcpy(&translators[idx].dst_codec, &codec_list[y], sizeof(struct ast_codec));
174                         snprintf(translators[idx].name, sizeof(translators[idx].name), "slin %ukhz -> %ukhz",
175                                 translators[idx].src_codec.sample_rate, translators[idx].dst_codec.sample_rate);
176                         res |= ast_register_translator(&translators[idx]);
177                         idx++;
178                 }
179
180         }
181         /* in case ast_register_translator() failed, we call unload_module() and
182         ast_unregister_translator won't fail.*/
183         if (res) {
184                 unload_module();
185                 return AST_MODULE_LOAD_FAILURE;
186         }
187
188         return AST_MODULE_LOAD_SUCCESS;
189 }
190
191 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SLIN Resampling Codec");