2 mediastreamer2 library - modular sound and video processing and streaming
3 Copyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)
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.
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.
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.
20 #include "mediastreamer2/msfilter.h"
26 #include <speex/speex_resampler.h>
29 typedef struct _ResampleData{
35 SpeexResamplerState *handle;
39 static ResampleData * resample_data_new(){
40 ResampleData *obj=(ResampleData *)ms_new(ResampleData,1);
41 obj->bz=ms_bufferizer_new();
44 obj->output_rate=16000;
47 obj->nb_unprocessed=0;
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);
58 static void resample_init(MSFilter *obj){
59 obj->data=resample_data_new();
62 static void resample_uninit(MSFilter *obj){
63 resample_data_destroy((ResampleData*)obj->data);
68 static void resample_process_ms2(MSFilter *obj){
69 ResampleData *dt=(ResampleData*)obj->data;
70 MSBufferizer *bz=dt->bz;
77 if (dt->output_rate==dt->input_rate)
79 while((m=ms_queue_get(obj->inputs[0]))!=NULL){
80 ms_queue_put(obj->outputs[0],m);
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);
92 if (dt->handle==NULL){
94 dt->handle=speex_resampler_init(1, dt->input_rate, dt->output_rate, SPEEX_RESAMPLER_QUALITY_VOIP, &err);
98 if (dt->input_rate<dt->output_rate)
99 size_of_input=320*dt->input_rate/8000;
101 size_of_input=320*dt->input_rate/8000;
102 size_of_output = (size_of_input * dt->output_rate)/dt->input_rate;
104 while((m=ms_queue_get(obj->inputs[0]))!=NULL){
105 ms_bufferizer_put(bz,m);
107 while (ms_bufferizer_read(bz,buffer,size_of_input)==size_of_input){
108 mblk_t *obl=allocb(size_of_output,0);
113 spx_uint32_t out_len;
116 short *data = (short*)buffer;
117 short *data_out = (short*)obl->b_wptr;
122 in = (float*) alloca((size_of_input/2)*sizeof(float));
123 out = (float*) alloca((size_of_output/2)*sizeof(float));
125 /* Convert the samples to floats */
126 for (i = 0; i < size_of_input/2; i++)
127 in[i] = (float) data[i];
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);
133 /* ms_message("resampling info: err=%i in_len=%i, out_len=%i", err, in_len, out_len); */
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; */
139 mblk_set_timestamp_info(obl,dt->ts);
141 ms_queue_put(obj->outputs[0],obl);
146 static void resample_process_ms2(MSFilter *obj){
147 ResampleData *dt=(ResampleData*)obj->data;
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);
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);
165 if (dt->handle==NULL){
167 dt->handle=speex_resampler_init(1, dt->input_rate, dt->output_rate, SPEEX_RESAMPLER_QUALITY_VOIP, &err);
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,
180 (int16_t*)om->b_wptr,
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);
186 om->b_wptr+=outlen*2;
187 mblk_set_timestamp_info(om,dt->ts);
189 ms_queue_put(obj->outputs[0],om);
198 int ms_resample_set_sr(MSFilter *obj, void *arg){
199 ResampleData *dt=(ResampleData*)obj->data;
200 dt->input_rate=((int*)arg)[0];
204 int ms_resample_set_output_sr(MSFilter *obj, void *arg){
205 ResampleData *dt=(ResampleData*)obj->data;
206 dt->output_rate=((int*)arg)[0];
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 },
218 MSFilterDesc ms_resample_desc={
221 N_("frequency resampler"),
228 resample_process_ms2,
236 MSFilterDesc ms_resample_desc={
239 .text=N_("frequency resampler"),
240 .category=MS_FILTER_OTHER,
244 .process=resample_process_ms2,
245 .uninit=resample_uninit,
251 MS_FILTER_DESC_EXPORT(ms_resample_desc)