]> sjero.net Git - linphone/blob - linphone/mediastreamer2/src/msresample.c
remote ortp and add it as a submodule instead.
[linphone] / linphone / mediastreamer2 / src / msresample.c
1 /*
2 mediastreamer2 library - modular sound and video processing and streaming
3 Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19
20 #include "mediastreamer2/msfilter.h"
21
22 #ifdef _MSC_VER
23 #include <malloc.h>
24 #endif
25
26 #include <speex/speex_resampler.h>
27 #include <math.h>
28
29 typedef struct _ResampleData{
30         MSBufferizer *bz;
31         uint32_t ts;
32         uint32_t input_rate;
33         uint32_t output_rate;
34
35         SpeexResamplerState *handle;
36         int nb_unprocessed;
37 } ResampleData;
38
39 static ResampleData * resample_data_new(){
40         ResampleData *obj=(ResampleData *)ms_new(ResampleData,1);
41         obj->bz=ms_bufferizer_new();
42         obj->ts=0;
43         obj->input_rate=8000;
44         obj->output_rate=16000;
45         obj->handle=NULL;
46
47         obj->nb_unprocessed=0;
48         return obj;
49 }
50
51 static void resample_data_destroy(ResampleData *obj){
52         if (obj->handle!=NULL)
53                 speex_resampler_destroy(obj->handle);
54         ms_bufferizer_destroy(obj->bz);
55         ms_free(obj);
56 }
57
58 static void resample_init(MSFilter *obj){
59         obj->data=resample_data_new();
60 }
61
62 static void resample_uninit(MSFilter *obj){
63         resample_data_destroy((ResampleData*)obj->data);
64  
65 }
66
67 #if 0
68 static void resample_process_ms2(MSFilter *obj){
69         ResampleData *dt=(ResampleData*)obj->data;
70         MSBufferizer *bz=dt->bz;
71         uint8_t buffer[2240];
72         int size_of_input;
73         int size_of_output;
74
75         mblk_t *m;
76         
77         if (dt->output_rate==dt->input_rate)
78           {
79             while((m=ms_queue_get(obj->inputs[0]))!=NULL){
80               ms_queue_put(obj->outputs[0],m);
81             }
82             return;
83           }
84         if (dt->handle!=NULL){
85                 unsigned int inrate=0, outrate=0;
86                 speex_resampler_get_rate(dt->handle,&inrate,&outrate);
87                 if (inrate!=dt->input_rate || outrate!=dt->output_rate){
88                         speex_resampler_destroy(dt->handle);
89                         dt->handle=0;
90                 }
91         }
92         if (dt->handle==NULL){
93                 int err=0;
94                 dt->handle=speex_resampler_init(1, dt->input_rate, dt->output_rate, SPEEX_RESAMPLER_QUALITY_VOIP, &err);
95         }
96
97
98         if (dt->input_rate<dt->output_rate)
99             size_of_input=320*dt->input_rate/8000;
100         else
101             size_of_input=320*dt->input_rate/8000;
102         size_of_output = (size_of_input * dt->output_rate)/dt->input_rate;
103
104         while((m=ms_queue_get(obj->inputs[0]))!=NULL){
105                 ms_bufferizer_put(bz,m);
106         }
107         while (ms_bufferizer_read(bz,buffer,size_of_input)==size_of_input){
108                 mblk_t *obl=allocb(size_of_output,0);
109
110                 float *in;
111                 float *out;
112                 spx_uint32_t in_len;
113                 spx_uint32_t out_len;
114                 int err;
115
116                 short *data = (short*)buffer;
117                 short *data_out = (short*)obl->b_wptr;
118
119                 int i;
120                 spx_uint32_t idx;
121     
122                 in = (float*) alloca((size_of_input/2)*sizeof(float));
123                 out = (float*) alloca((size_of_output/2)*sizeof(float));
124
125                 /* Convert the samples to floats */
126                 for (i = 0; i < size_of_input/2; i++)
127                         in[i] = (float) data[i];
128
129                 in_len = size_of_input/2;
130                 out_len = size_of_output/2;
131                 err = speex_resampler_process_float(dt->handle, 0, in, &in_len, out, &out_len);
132
133                 /* ms_message("resampling info: err=%i in_len=%i, out_len=%i", err, in_len, out_len); */
134
135                 for (idx=0;idx<out_len;idx++)
136                   data_out[idx]=(short)floor(.5+out[idx]);
137                 obl->b_wptr=obl->b_wptr+(out_len*2); /* size_of_output; */
138
139                 mblk_set_timestamp_info(obl,dt->ts);
140                 dt->ts+=160;
141                 ms_queue_put(obj->outputs[0],obl);
142         }
143 }
144
145 #else
146 static void resample_process_ms2(MSFilter *obj){
147         ResampleData *dt=(ResampleData*)obj->data;
148         mblk_t *m;
149         
150         if (dt->output_rate==dt->input_rate){
151                 while((m=ms_queue_get(obj->inputs[0]))!=NULL){
152                         ms_queue_put(obj->outputs[0],m);
153                 }
154                 return;
155         }
156
157         if (dt->handle!=NULL){
158                 unsigned int inrate=0, outrate=0;
159                 speex_resampler_get_rate(dt->handle,&inrate,&outrate);
160                 if (inrate!=dt->input_rate || outrate!=dt->output_rate){
161                         speex_resampler_destroy(dt->handle);
162                         dt->handle=0;
163                 }
164         }
165         if (dt->handle==NULL){
166                 int err=0;
167                 dt->handle=speex_resampler_init(1, dt->input_rate, dt->output_rate, SPEEX_RESAMPLER_QUALITY_VOIP, &err);
168         }
169
170         
171         while((m=ms_queue_get(obj->inputs[0]))!=NULL){
172                 unsigned int inlen=(m->b_wptr-m->b_rptr)/2;
173                 unsigned int outlen=((inlen*dt->output_rate)/dt->input_rate)+1;
174                 unsigned int inlen_orig=inlen;
175                 mblk_t *om=allocb(outlen*2,0);
176                 speex_resampler_process_int(dt->handle, 
177                                  0, 
178                                  (int16_t*)m->b_rptr, 
179                                  &inlen, 
180                                  (int16_t*)om->b_wptr, 
181                                  &outlen);
182                 if (inlen_orig!=inlen){
183                         ms_error("Bug in resampler ! only %u samples consumed instead of %u, out=%u",
184                                 inlen,inlen_orig,outlen);
185                 }
186                 om->b_wptr+=outlen*2;
187                 mblk_set_timestamp_info(om,dt->ts);
188                 dt->ts+=outlen;
189                 ms_queue_put(obj->outputs[0],om);
190                 freemsg(m);
191         }
192 }
193
194 #endif
195
196
197
198 int ms_resample_set_sr(MSFilter *obj, void *arg){
199   ResampleData *dt=(ResampleData*)obj->data;
200   dt->input_rate=((int*)arg)[0];
201   return 0;
202 }
203
204 int ms_resample_set_output_sr(MSFilter *obj, void *arg){
205   ResampleData *dt=(ResampleData*)obj->data;
206   dt->output_rate=((int*)arg)[0];
207   return 0;
208 }
209
210 static MSFilterMethod enc_methods[]={
211   {     MS_FILTER_SET_SAMPLE_RATE        ,      ms_resample_set_sr              },
212   {     MS_FILTER_SET_OUTPUT_SAMPLE_RATE ,      ms_resample_set_output_sr       },
213   {     0                                ,      NULL    }
214 };
215
216 #ifdef _MSC_VER
217
218 MSFilterDesc ms_resample_desc={
219         MS_RESAMPLE_ID,
220         "MSResample",
221         N_("frequency resampler"),
222         MS_FILTER_OTHER,
223         NULL,
224         1,
225         1,
226         resample_init,
227         NULL,
228         resample_process_ms2,
229         NULL,
230         resample_uninit,
231         enc_methods
232 };
233
234 #else
235
236 MSFilterDesc ms_resample_desc={
237         .id=MS_RESAMPLE_ID,
238         .name="MSResample",
239         .text=N_("frequency resampler"),
240         .category=MS_FILTER_OTHER,
241         .ninputs=1,
242         .noutputs=1,
243         .init=resample_init,
244         .process=resample_process_ms2,
245         .uninit=resample_uninit,
246         .methods=enc_methods
247 };
248
249 #endif
250
251 MS_FILTER_DESC_EXPORT(ms_resample_desc)
252