Remove libresample from the Asterisk source tree. It is now available in its
[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  * \arg http://svn.digium.com/svn/libresample/trunk
25  *
26  * \ingroup codecs
27  */
28
29 /*** MODULEINFO
30         <depend>resample</depend>
31  ***/
32
33 #include "asterisk.h"
34
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36
37 /* These are for SHRT_MAX and FLT_MAX -- { */
38 #if defined(__Darwin__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__CYGWIN__)
39 #include <float.h>
40 #else
41 #include <values.h>
42 #endif
43 #include <limits.h>
44 /* } */
45
46 #include <libresample.h>
47
48 #include "asterisk/module.h"
49 #include "asterisk/translate.h"
50
51 #include "slin_resample_ex.h"
52
53 #define RESAMPLER_QUALITY 1
54
55 #define OUTBUF_SIZE   8096
56
57 struct slin16_to_slin8_pvt {
58         void *resampler;
59         float resample_factor;
60 };
61
62 struct slin8_to_slin16_pvt {
63         void *resampler;
64         float resample_factor;
65 };
66
67 static int slin16_to_slin8_new(struct ast_trans_pvt *pvt)
68 {
69         struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
70
71         resamp_pvt->resample_factor = 0.5;
72
73         if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, 0.5, 0.5)))
74                 return -1;
75
76         return 0;
77 }
78
79 static int slin8_to_slin16_new(struct ast_trans_pvt *pvt)
80 {
81         struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
82
83         resamp_pvt->resample_factor = 2.0;
84
85         if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, 2.0, 2.0)))
86                 return -1;
87
88         return 0;
89 }
90
91 static void slin16_to_slin8_destroy(struct ast_trans_pvt *pvt)
92 {
93         struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
94
95         if (resamp_pvt->resampler)
96                 resample_close(resamp_pvt->resampler);
97 }
98
99 static void slin8_to_slin16_destroy(struct ast_trans_pvt *pvt)
100 {
101         struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
102
103         if (resamp_pvt->resampler)
104                 resample_close(resamp_pvt->resampler);
105 }
106
107 static int resample_frame(struct ast_trans_pvt *pvt,
108         void *resampler, float resample_factor, struct ast_frame *f)
109 {
110         int total_in_buf_used = 0;
111         int total_out_buf_used = 0;
112         int16_t *in_buf = (int16_t *) f->data.ptr;
113         int16_t *out_buf = pvt->outbuf.i16 + pvt->samples;
114         float in_buf_f[f->samples];
115         float out_buf_f[2048];
116         int res = 0;
117         int i;
118
119         for (i = 0; i < f->samples; i++)
120                 in_buf_f[i] = in_buf[i] * (FLT_MAX / SHRT_MAX);
121
122         while (total_in_buf_used < f->samples) {
123                 int in_buf_used, out_buf_used;
124
125                 out_buf_used = resample_process(resampler, resample_factor,
126                         &in_buf_f[total_in_buf_used], f->samples - total_in_buf_used,
127                         0, &in_buf_used,
128                         &out_buf_f[total_out_buf_used], ARRAY_LEN(out_buf_f) - total_out_buf_used);
129
130                 if (out_buf_used < 0)
131                         break;
132
133                 total_out_buf_used += out_buf_used;
134                 total_in_buf_used += in_buf_used;
135
136                 if (total_out_buf_used == ARRAY_LEN(out_buf_f)) {
137                         ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n");
138                         res = -1;
139                         break;
140                 }
141         }
142
143         for (i = 0; i < total_out_buf_used; i++)
144                 out_buf[i] = out_buf_f[i] * (SHRT_MAX / FLT_MAX);       
145
146         pvt->samples += total_out_buf_used;
147         pvt->datalen += (total_out_buf_used * sizeof(int16_t));
148
149         return res;
150 }
151
152 static int slin16_to_slin8_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
153 {
154         struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
155         void *resampler = resamp_pvt->resampler;
156         float resample_factor = resamp_pvt->resample_factor;
157
158         return resample_frame(pvt, resampler, resample_factor, f);
159 }
160
161 static int slin8_to_slin16_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
162 {
163         struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
164         void *resampler = resamp_pvt->resampler;
165         float resample_factor = resamp_pvt->resample_factor;
166
167         return resample_frame(pvt, resampler, resample_factor, f);
168 }
169
170 static struct ast_frame *slin16_to_slin8_sample(void)
171 {
172         static struct ast_frame f = {
173                 .frametype = AST_FRAME_VOICE,
174                 .subclass = AST_FORMAT_SLINEAR16,
175                 .datalen = sizeof(slin16_slin8_ex),
176                 .samples = ARRAY_LEN(slin16_slin8_ex),
177                 .src = __PRETTY_FUNCTION__,
178                 .data.ptr = slin16_slin8_ex,
179         };
180
181         return &f;
182 }
183
184 static struct ast_frame *slin8_to_slin16_sample(void)
185 {
186         static struct ast_frame f = {
187                 .frametype = AST_FRAME_VOICE,
188                 .subclass = AST_FORMAT_SLINEAR,
189                 .datalen = sizeof(slin8_slin16_ex),
190                 .samples = ARRAY_LEN(slin8_slin16_ex),
191                 .src = __PRETTY_FUNCTION__,
192                 .data.ptr = slin8_slin16_ex,
193         };
194
195         return &f;
196 }
197
198 static struct ast_translator slin16_to_slin8 = {
199         .name = "slin16_to_slin8",
200         .srcfmt = AST_FORMAT_SLINEAR16,
201         .dstfmt = AST_FORMAT_SLINEAR,
202         .newpvt = slin16_to_slin8_new,
203         .destroy = slin16_to_slin8_destroy,
204         .framein = slin16_to_slin8_framein,
205         .sample = slin16_to_slin8_sample,
206         .desc_size = sizeof(struct slin16_to_slin8_pvt),
207         .buffer_samples = (OUTBUF_SIZE / sizeof(int16_t)),
208         .buf_size = OUTBUF_SIZE,
209 };
210
211 static struct ast_translator slin8_to_slin16 = {
212         .name = "slin8_to_slin16",
213         .srcfmt = AST_FORMAT_SLINEAR,
214         .dstfmt = AST_FORMAT_SLINEAR16,
215         .newpvt = slin8_to_slin16_new,
216         .destroy = slin8_to_slin16_destroy,
217         .framein = slin8_to_slin16_framein,
218         .sample = slin8_to_slin16_sample,
219         .desc_size = sizeof(struct slin8_to_slin16_pvt),
220         .buffer_samples = (OUTBUF_SIZE / sizeof(int16_t)),
221         .buf_size = OUTBUF_SIZE,
222 };
223
224 static int unload_module(void)
225 {
226         int res = 0;
227
228         res |= ast_unregister_translator(&slin16_to_slin8);
229         res |= ast_unregister_translator(&slin8_to_slin16);
230
231         return res;
232 }
233
234 static int load_module(void)
235 {
236         int res = 0;
237
238         res |= ast_register_translator(&slin16_to_slin8);
239         res |= ast_register_translator(&slin8_to_slin16);
240
241         return AST_MODULE_LOAD_SUCCESS;
242 }
243
244 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SLIN Resampling Codec");