1 /*****************************************************************************
2 * linear.c : linear interpolation resampler
3 *****************************************************************************
4 * Copyright (C) 2002, 2006 the VideoLAN team
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
8 * Sigmund Augdal Helberg <dnumgis@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
35 #include <vlc_filter.h>
36 #include <vlc_block.h>
38 /*****************************************************************************
40 *****************************************************************************/
41 static int Create ( vlc_object_t * );
42 static void Close ( vlc_object_t * );
43 static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
46 static int OpenFilter ( vlc_object_t * );
47 static void CloseFilter( vlc_object_t * );
48 static block_t *Resample( filter_t *, block_t * );
50 /*****************************************************************************
52 *****************************************************************************/
55 int32_t *p_prev_sample; /* this filter introduces a 1 sample delay */
57 unsigned int i_remainder; /* remainder of previous sample */
59 audio_date_t end_date;
62 /*****************************************************************************
64 *****************************************************************************/
66 set_description( _("Audio filter for linear interpolation resampling") );
67 set_category( CAT_AUDIO );
68 set_subcategory( SUBCAT_AUDIO_MISC );
69 set_capability( "audio filter", 5 );
70 set_callbacks( Create, Close );
73 set_description( _("Audio filter for linear interpolation resampling") );
74 set_capability( "audio filter2", 5 );
75 set_callbacks( OpenFilter, CloseFilter );
78 /*****************************************************************************
79 * Create: allocate linear resampler
80 *****************************************************************************/
81 static int Create( vlc_object_t *p_this )
83 aout_filter_t * p_filter = (aout_filter_t *)p_this;
84 struct filter_sys_t * p_sys;
86 if ( p_filter->input.i_rate == p_filter->output.i_rate
87 || p_filter->input.i_format != p_filter->output.i_format
88 || p_filter->input.i_physical_channels
89 != p_filter->output.i_physical_channels
90 || p_filter->input.i_original_channels
91 != p_filter->output.i_original_channels
92 || p_filter->input.i_format != VLC_FOURCC('f','l','3','2') )
97 /* Allocate the memory needed to store the module's structure */
98 p_sys = malloc( sizeof(filter_sys_t) );
99 p_filter->p_sys = (struct aout_filter_sys_t *)p_sys;
102 msg_Err( p_filter, "out of memory" );
105 p_sys->p_prev_sample = malloc(
106 p_filter->input.i_channels * sizeof(int32_t) );
107 if( p_sys->p_prev_sample == NULL )
109 msg_Err( p_filter, "out of memory" );
112 aout_DateInit( &p_sys->end_date, p_filter->output.i_rate );
114 p_filter->pf_do_work = DoWork;
116 /* We don't want a new buffer to be created because we're not sure we'll
117 * actually need to resample anything. */
118 p_filter->b_in_place = true;
123 /*****************************************************************************
124 * Close: free our resources
125 *****************************************************************************/
126 static void Close( vlc_object_t * p_this )
128 aout_filter_t * p_filter = (aout_filter_t *)p_this;
129 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
131 free( p_sys->p_prev_sample );
135 /*****************************************************************************
136 * DoWork: convert a buffer
137 *****************************************************************************/
138 static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
139 aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
141 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
145 float *p_in, *p_out = (float *)p_out_buf->p_buffer;
146 float *p_prev_sample = (float *)p_sys->p_prev_sample;
148 int i_nb_channels = p_filter->input.i_channels;
149 int i_in_nb = p_in_buf->i_nb_samples;
150 int i_chan, i_in, i_out = 0;
152 /* Check if we really need to run the resampler */
153 if( p_aout->mixer.mixer.i_rate == p_filter->input.i_rate )
155 if( p_filter->b_continuity &&
157 p_in_buf->i_nb_bytes + sizeof(float) * i_nb_channels )
159 /* output the whole thing with the last sample from last time */
160 memmove( ((float *)(p_in_buf->p_buffer)) + i_nb_channels,
161 p_in_buf->p_buffer, p_in_buf->i_nb_bytes );
162 memcpy( p_in_buf->p_buffer, p_prev_sample,
163 i_nb_channels * sizeof(float) );
165 p_filter->b_continuity = false;
170 p_in = (float *)alloca( p_in_buf->i_nb_bytes );
172 p_in_orig = p_in = (float *)malloc( p_in_buf->i_nb_bytes );
179 p_aout->p_libvlc->pf_memcpy( p_in, p_in_buf->p_buffer, p_in_buf->i_nb_bytes );
181 /* Take care of the previous input sample (if any) */
182 if( !p_filter->b_continuity )
184 p_filter->b_continuity = true;
185 p_sys->i_remainder = 0;
186 aout_DateInit( &p_sys->end_date, p_filter->output.i_rate );
190 while( p_sys->i_remainder < p_filter->output.i_rate )
192 for( i_chan = i_nb_channels ; i_chan ; )
195 p_out[i_chan] = p_prev_sample[i_chan];
196 p_out[i_chan] += ( ( p_in[i_chan] - p_prev_sample[i_chan] )
198 / p_filter->output.i_rate );
200 p_out += i_nb_channels;
203 p_sys->i_remainder += p_filter->input.i_rate;
205 p_sys->i_remainder -= p_filter->output.i_rate;
208 /* Take care of the current input samples (minus last one) */
209 for( i_in = 0; i_in < i_in_nb - 1; i_in++ )
211 while( p_sys->i_remainder < p_filter->output.i_rate )
213 for( i_chan = i_nb_channels ; i_chan ; )
216 p_out[i_chan] = p_in[i_chan];
217 p_out[i_chan] += ( ( p_in[i_chan + i_nb_channels]
219 * p_sys->i_remainder / p_filter->output.i_rate );
221 p_out += i_nb_channels;
224 p_sys->i_remainder += p_filter->input.i_rate;
227 p_in += i_nb_channels;
228 p_sys->i_remainder -= p_filter->output.i_rate;
231 /* Backup the last input sample for next time */
232 for( i_chan = i_nb_channels ; i_chan ; )
235 p_prev_sample[i_chan] = p_in[i_chan];
238 p_out_buf->i_nb_samples = i_out;
239 p_out_buf->start_date = p_in_buf->start_date;
241 if( p_in_buf->start_date !=
242 aout_DateGet( &p_sys->end_date ) )
244 aout_DateSet( &p_sys->end_date, p_in_buf->start_date );
247 p_out_buf->end_date = aout_DateIncrement( &p_sys->end_date,
248 p_out_buf->i_nb_samples );
250 p_out_buf->i_nb_bytes = p_out_buf->i_nb_samples *
251 i_nb_channels * sizeof(int32_t);
259 /*****************************************************************************
261 *****************************************************************************/
262 static int OpenFilter( vlc_object_t *p_this )
264 filter_t *p_filter = (filter_t *)p_this;
266 int i_out_rate = p_filter->fmt_out.audio.i_rate;
268 if( p_filter->fmt_in.audio.i_rate == p_filter->fmt_out.audio.i_rate ||
269 p_filter->fmt_in.i_codec != VLC_FOURCC('f','l','3','2') )
274 /* Allocate the memory needed to store the module's structure */
275 p_filter->p_sys = p_sys = malloc( sizeof(struct filter_sys_t) );
278 msg_Err( p_filter, "out of memory" );
282 p_sys->p_prev_sample = malloc(
283 p_filter->fmt_in.audio.i_channels * sizeof(int32_t) );
284 if( p_sys->p_prev_sample == NULL )
286 msg_Err( p_filter, "out of memory" );
290 aout_DateInit( &p_sys->end_date, p_filter->fmt_in.audio.i_rate );
292 p_filter->pf_audio_filter = Resample;
294 msg_Dbg( p_this, "%4.4s/%iKHz/%i->%4.4s/%iKHz/%i",
295 (char *)&p_filter->fmt_in.i_codec,
296 p_filter->fmt_in.audio.i_rate,
297 p_filter->fmt_in.audio.i_channels,
298 (char *)&p_filter->fmt_out.i_codec,
299 p_filter->fmt_out.audio.i_rate,
300 p_filter->fmt_out.audio.i_channels);
302 p_filter->fmt_out = p_filter->fmt_in;
303 p_filter->fmt_out.audio.i_rate = i_out_rate;
308 /*****************************************************************************
309 * CloseFilter : deallocate data structures
310 *****************************************************************************/
311 static void CloseFilter( vlc_object_t *p_this )
313 filter_t *p_filter = (filter_t *)p_this;
314 free( p_filter->p_sys->p_prev_sample );
315 free( p_filter->p_sys );
318 /*****************************************************************************
320 *****************************************************************************/
321 static block_t *Resample( filter_t *p_filter, block_t *p_block )
323 aout_filter_t aout_filter;
324 aout_buffer_t in_buf, out_buf;
327 int i_bytes_per_frame;
329 if( !p_block || !p_block->i_samples )
331 if( p_block ) p_block->pf_release( p_block );
335 i_bytes_per_frame = p_filter->fmt_out.audio.i_channels *
336 p_filter->fmt_out.audio.i_bitspersample / 8;
338 i_out_size = i_bytes_per_frame * ( 1 + (p_block->i_samples *
339 p_filter->fmt_out.audio.i_rate / p_filter->fmt_in.audio.i_rate));
341 p_out = p_filter->pf_audio_buffer_new( p_filter, i_out_size );
344 msg_Warn( p_filter, "can't get output buffer" );
345 p_block->pf_release( p_block );
349 p_out->i_samples = i_out_size / i_bytes_per_frame;
350 p_out->i_dts = p_block->i_dts;
351 p_out->i_pts = p_block->i_pts;
352 p_out->i_length = p_block->i_length;
354 aout_filter.p_sys = (struct aout_filter_sys_t *)p_filter->p_sys;
355 aout_filter.input = p_filter->fmt_in.audio;
356 aout_filter.output = p_filter->fmt_out.audio;
357 aout_filter.b_continuity = false;
359 in_buf.p_buffer = p_block->p_buffer;
360 in_buf.i_nb_bytes = p_block->i_buffer;
361 in_buf.i_nb_samples = p_block->i_samples;
362 out_buf.p_buffer = p_out->p_buffer;
363 out_buf.i_nb_bytes = p_out->i_buffer;
364 out_buf.i_nb_samples = p_out->i_samples;
366 DoWork( (aout_instance_t *)p_filter, &aout_filter, &in_buf, &out_buf );
368 p_block->pf_release( p_block );
370 p_out->i_buffer = out_buf.i_nb_bytes;
371 p_out->i_samples = out_buf.i_nb_samples;