Instead of linking libresample into the main Asterisk binary, build it as
[asterisk/asterisk.git] / codecs / codec_resample.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007, Digium, Inc.
5  *
6  * Russell Bryant <russell@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! 
20  * \file
21  *
22  * \brief Resample slinear audio
23  *
24  * \ingroup codecs
25  */
26
27 /*** MODULEINFO
28         <depend>res_resample</depend>
29  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34
35 /* These are for SHRT_MAX and FLT_MAX -- { */
36 #if defined(__Darwin__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__CYGWIN__)
37 #include <float.h>
38 #else
39 #include <values.h>
40 #endif
41 #include <limits.h>
42 /* } */
43
44 #include "asterisk/module.h"
45 #include "asterisk/translate.h"
46
47 #include "libresample.h"
48
49 #include "slin_resample_ex.h"
50
51 #define RESAMPLER_QUALITY 0
52
53 #define OUTBUF_SIZE   8096
54
55 struct slin16_to_slin8_pvt {
56         void *resampler;
57         double resample_factor;
58 };
59
60 struct slin8_to_slin16_pvt {
61         void *resampler;
62         double resample_factor;
63 };
64
65 static int slin16_to_slin8_new(struct ast_trans_pvt *pvt)
66 {
67         struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
68
69         resamp_pvt->resample_factor = 0.5;
70
71         if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, 0.5, 0.5)))
72                 return -1;
73
74         return 0;
75 }
76
77 static int slin8_to_slin16_new(struct ast_trans_pvt *pvt)
78 {
79         struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
80
81         resamp_pvt->resample_factor = 2.0;
82
83         if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, 2.0, 2.0)))
84                 return -1;
85
86         return 0;
87 }
88
89 static void slin16_to_slin8_destroy(struct ast_trans_pvt *pvt)
90 {
91         struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
92
93         if (resamp_pvt->resampler)
94                 resample_close(resamp_pvt->resampler);
95 }
96
97 static void slin8_to_slin16_destroy(struct ast_trans_pvt *pvt)
98 {
99         struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
100
101         if (resamp_pvt->resampler)
102                 resample_close(resamp_pvt->resampler);
103 }
104
105 static int resample_frame(struct ast_trans_pvt *pvt,
106         void *resampler, double resample_factor, struct ast_frame *f)
107 {
108         int total_in_buf_used = 0;
109         int total_out_buf_used = 0;
110         int16_t *in_buf = (int16_t *) f->data;
111         int16_t *out_buf = (int16_t *) pvt->outbuf + pvt->samples;
112         float in_buf_f[f->samples];
113         float out_buf_f[2048];
114         int res = 0;
115         int i;
116
117         for (i = 0; i < f->samples; i++)
118                 in_buf_f[i] = in_buf[i] * (FLT_MAX / SHRT_MAX);
119
120         while (total_in_buf_used < f->samples) {
121                 int in_buf_used, out_buf_used;
122
123                 out_buf_used = resample_process(resampler, resample_factor,
124                         &in_buf_f[total_in_buf_used], f->samples - total_in_buf_used,
125                         0, &in_buf_used,
126                         &out_buf_f[total_out_buf_used], ARRAY_LEN(out_buf_f) - total_out_buf_used);
127
128                 if (out_buf_used < 0)
129                         break;
130
131                 total_out_buf_used += out_buf_used;
132                 total_in_buf_used += in_buf_used;
133
134                 if (total_out_buf_used == ARRAY_LEN(out_buf_f)) {
135                         ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n");
136                         res = -1;
137                         break;
138                 }
139         }
140
141         for (i = 0; i < total_out_buf_used; i++)
142                 out_buf[i] = out_buf_f[i] * (SHRT_MAX / FLT_MAX);       
143
144         pvt->samples += total_out_buf_used;
145         pvt->datalen += (total_out_buf_used * sizeof(int16_t));
146
147         return res;
148 }
149
150 static int slin16_to_slin8_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
151 {
152         struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
153
154         return resample_frame(pvt, resamp_pvt->resampler, resamp_pvt->resample_factor, f);
155 }
156
157 static int slin8_to_slin16_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
158 {
159         struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
160
161         return resample_frame(pvt, resamp_pvt->resampler, resamp_pvt->resample_factor, f);
162 }
163
164 static struct ast_frame *slin16_to_slin8_sample(void)
165 {
166         static struct ast_frame f = {
167                 .frametype = AST_FRAME_VOICE,
168                 .subclass = AST_FORMAT_SLINEAR16,
169                 .datalen = sizeof(slin16_slin8_ex),
170                 .samples = sizeof(slin16_slin8_ex) / sizeof(slin16_slin8_ex[0]),
171                 .src = __PRETTY_FUNCTION__,
172                 .data = slin16_slin8_ex,
173         };
174
175         return &f;
176 }
177
178 static struct ast_frame *slin8_to_slin16_sample(void)
179 {
180         static struct ast_frame f = {
181                 .frametype = AST_FRAME_VOICE,
182                 .subclass = AST_FORMAT_SLINEAR,
183                 .datalen = sizeof(slin8_slin16_ex),
184                 .samples = sizeof(slin8_slin16_ex) / sizeof(slin8_slin16_ex[0]),
185                 .src = __PRETTY_FUNCTION__,
186                 .data = slin8_slin16_ex,
187         };
188
189         return &f;
190 }
191
192 static struct ast_translator slin16_to_slin8 = {
193         .name = "slin16_to_slin8",
194         .srcfmt = AST_FORMAT_SLINEAR16,
195         .dstfmt = AST_FORMAT_SLINEAR,
196         .newpvt = slin16_to_slin8_new,
197         .destroy = slin16_to_slin8_destroy,
198         .framein = slin16_to_slin8_framein,
199         .sample = slin16_to_slin8_sample,
200         .desc_size = sizeof(struct slin16_to_slin8_pvt),
201         .buffer_samples = (OUTBUF_SIZE / sizeof(int16_t)),
202         .buf_size = OUTBUF_SIZE,
203 };
204
205 static struct ast_translator slin8_to_slin16 = {
206         .name = "slin8_to_slin16",
207         .srcfmt = AST_FORMAT_SLINEAR,
208         .dstfmt = AST_FORMAT_SLINEAR16,
209         .newpvt = slin8_to_slin16_new,
210         .destroy = slin8_to_slin16_destroy,
211         .framein = slin8_to_slin16_framein,
212         .sample = slin8_to_slin16_sample,
213         .desc_size = sizeof(struct slin8_to_slin16_pvt),
214         .buffer_samples = OUTBUF_SIZE,
215         .buf_size = OUTBUF_SIZE,
216 };
217
218 static int unload_module(void)
219 {
220         int res = 0;
221
222         res |= ast_unregister_translator(&slin16_to_slin8);
223         res |= ast_unregister_translator(&slin8_to_slin16);
224
225         return res;
226 }
227
228 static int load_module(void)
229 {
230         int res = 0;
231
232         res |= ast_register_translator(&slin16_to_slin8);
233         res |= ast_register_translator(&slin8_to_slin16);
234
235         return AST_MODULE_LOAD_SUCCESS;
236 }
237
238 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SLIN Resampling Codec");