qt: playlist: use item title if available
[vlc.git] / modules / audio_filter / resampler / bandlimited.c
1 /*****************************************************************************
2  * bandlimited.c : band-limited interpolation resampler
3  *****************************************************************************
4  * Copyright (C) 2002, 2006 VLC authors and VideoLAN
5  *
6  * Authors: Gildas Bazin <gbazin@netcourrier.com>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble:
25  *
26  * This implementation of the band-limited interpolationis based on the
27  * following paper:
28  * http://ccrma-www.stanford.edu/~jos/resample/resample.html
29  *
30  * It uses a Kaiser-windowed sinc-function low-pass filter and the width of the
31  * filter is 13 samples.
32  *
33  *****************************************************************************/
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <vlc_common.h>
40 #include <vlc_plugin.h>
41 #include <vlc_aout.h>
42 #include <vlc_filter.h>
43 #include <vlc_block.h>
44
45 #include <assert.h>
46
47 #include "bandlimited.h"
48
49 /*****************************************************************************
50  * Local prototypes
51  *****************************************************************************/
52
53 /* audio filter */
54 static int  OpenFilter ( vlc_object_t * );
55 static void CloseFilter( filter_t * );
56 static block_t *Resample( filter_t *, block_t * );
57
58 static void ResampleFloat( filter_t *p_filter,
59                            block_t **pp_out_buf,  size_t *pi_out,
60                            float **pp_in,
61                            int i_in, int i_in_end,
62                            double d_factor, bool b_factor_old,
63                            int i_nb_channels, int i_bytes_per_frame );
64
65 /*****************************************************************************
66  * Local structures
67  *****************************************************************************/
68 typedef struct
69 {
70     int32_t *p_buf;                        /* this filter introduces a delay */
71     size_t i_buf_size;
72
73     double d_old_factor;
74     size_t i_old_wing;
75
76     unsigned int i_remainder;                /* remainder of previous sample */
77     bool b_first;
78
79     date_t end_date;
80 } filter_sys_t;
81
82 /*****************************************************************************
83  * Module descriptor
84  *****************************************************************************/
85 vlc_module_begin ()
86     set_category( CAT_AUDIO )
87     set_subcategory( SUBCAT_AUDIO_RESAMPLER )
88     set_description( N_("Audio filter for band-limited interpolation resampling") )
89     set_capability( "audio converter", 20 )
90     set_callback( OpenFilter )
91
92     add_submodule()
93     set_capability( "audio resampler", 20 )
94     set_callback( OpenFilter )
95 vlc_module_end ()
96
97 /*****************************************************************************
98  * Resample: convert a buffer
99  *****************************************************************************/
100 static block_t *Resample( filter_t * p_filter, block_t * p_in_buf )
101 {
102     if( !p_in_buf || !p_in_buf->i_nb_samples )
103     {
104         if( p_in_buf )
105             block_Release( p_in_buf );
106         return NULL;
107     }
108
109     filter_sys_t *p_sys = p_filter->p_sys;
110     unsigned int i_out_rate = p_filter->fmt_out.audio.i_rate;
111     int i_nb_channels = p_filter->fmt_in.audio.i_channels;
112
113     /* Check if we really need to run the resampler */
114     if( i_out_rate == p_filter->fmt_in.audio.i_rate )
115     {
116         if( !(p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY) &&
117             p_sys->i_old_wing )
118         {
119             /* output the whole thing with the samples from last time */
120             p_in_buf = block_Realloc( p_in_buf,
121                 p_sys->i_old_wing * p_filter->fmt_in.audio.i_bytes_per_frame,
122                 p_in_buf->i_buffer );
123             if( !p_in_buf )
124                 return NULL;
125             memcpy( p_in_buf->p_buffer, p_sys->p_buf +
126                     i_nb_channels * p_sys->i_old_wing,
127                     p_sys->i_old_wing *
128                     p_filter->fmt_in.audio.i_bytes_per_frame );
129
130             p_in_buf->i_nb_samples += p_sys->i_old_wing;
131
132             p_in_buf->i_pts = date_Get( &p_sys->end_date );
133             p_in_buf->i_length =
134                 date_Increment( &p_sys->end_date,
135                                 p_in_buf->i_nb_samples ) - p_in_buf->i_pts;
136         }
137         p_sys->i_old_wing = 0;
138         p_sys->b_first = true;
139         return p_in_buf;
140     }
141
142     unsigned i_bytes_per_frame = p_filter->fmt_out.audio.i_channels *
143                                  p_filter->fmt_out.audio.i_bitspersample / 8;
144     size_t i_out_size = i_bytes_per_frame * ( 1 + ( p_in_buf->i_nb_samples *
145               p_filter->fmt_out.audio.i_rate / p_filter->fmt_in.audio.i_rate) )
146             + p_filter->p_sys->i_buf_size;
147     block_t *p_out_buf = block_Alloc( i_out_size );
148     if( !p_out_buf )
149     {
150         block_Release( p_in_buf );
151         return NULL;
152     }
153
154     if( (p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY) || p_sys->b_first )
155     {
156         /* Continuity in sound samples has been broken, we'd better reset
157          * everything. */
158         p_out_buf->i_flags |= BLOCK_FLAG_DISCONTINUITY;
159         p_sys->i_remainder = 0;
160         date_Init( &p_sys->end_date, i_out_rate, 1 );
161         date_Set( &p_sys->end_date, p_in_buf->i_pts );
162         p_sys->d_old_factor = 1;
163         p_sys->i_old_wing   = 0;
164         p_sys->b_first = false;
165     }
166
167     size_t i_in_nb = p_in_buf->i_nb_samples;
168     size_t i_in, i_out = 0;
169     double d_factor, d_scale_factor, d_old_scale_factor;
170     size_t i_filter_wing;
171
172 #if 0
173     msg_Err( p_filter, "old rate: %i, old factor: %f, old wing: %i, i_in: %i",
174              p_sys->i_old_rate, p_sys->d_old_factor,
175              p_sys->i_old_wing, i_in_nb );
176 #endif
177
178     /* Same format in and out... */
179     assert( p_filter->fmt_in.audio.i_bytes_per_frame == i_bytes_per_frame );
180
181     /* Prepare the source buffer */
182     if( p_sys->i_old_wing )
183     {   /* Copy all our samples in p_in_buf */
184         /* Normally, there should be enough room for the old wing in the
185          * buffer head room. Otherwise, we need to copy memory anyway. */
186         p_in_buf = block_Realloc( p_in_buf,
187                                   p_sys->i_old_wing * 2 * i_bytes_per_frame,
188                                   p_in_buf->i_buffer );
189         if( unlikely(p_in_buf == NULL) )
190             return NULL;
191         memcpy( p_in_buf->p_buffer, p_sys->p_buf,
192                 p_sys->i_old_wing * 2 * i_bytes_per_frame );
193     }
194     i_in_nb += (p_sys->i_old_wing * 2);
195     float *p_in = (float *)p_in_buf->p_buffer;
196     const float *p_in_orig = p_in;
197
198     /* Make sure the output buffer is reset */
199     memset( p_out_buf->p_buffer, 0, p_out_buf->i_buffer );
200
201     /* Calculate the new length of the filter wing */
202     d_factor = (double)i_out_rate / p_filter->fmt_in.audio.i_rate;
203     i_filter_wing = ((SMALL_FILTER_NMULT+1)/2.0) * __MAX(1.0,1.0/d_factor) + 1;
204
205     /* Account for increased filter gain when using factors less than 1 */
206     d_old_scale_factor = SMALL_FILTER_SCALE *
207         p_sys->d_old_factor + 0.5;
208     d_scale_factor = SMALL_FILTER_SCALE * d_factor + 0.5;
209
210     /* Apply the old rate until we have enough samples for the new one */
211     i_in = p_sys->i_old_wing;
212     p_in += p_sys->i_old_wing * i_nb_channels;
213
214     size_t i_old_in_end = 0;
215     if( p_sys->i_old_wing <= i_in_nb )
216         i_old_in_end = __MIN( i_filter_wing, i_in_nb - p_sys->i_old_wing );
217
218     ResampleFloat( p_filter,
219                    &p_out_buf, &i_out, &p_in,
220                    i_in, i_old_in_end,
221                    p_sys->d_old_factor, true,
222                    i_nb_channels, i_bytes_per_frame );
223     i_in = __MAX( i_in, i_old_in_end );
224
225     /* Apply the new rate for the rest of the samples */
226     if( i_in < i_in_nb - i_filter_wing )
227     {
228         p_sys->d_old_factor = d_factor;
229         p_sys->i_old_wing   = i_filter_wing;
230     }
231     if( p_out_buf )
232     {
233         ResampleFloat( p_filter,
234                        &p_out_buf, &i_out, &p_in,
235                        i_in, i_in_nb - i_filter_wing,
236                        d_factor, false,
237                        i_nb_channels, i_bytes_per_frame );
238
239         /* Finalize aout buffer */
240         p_out_buf->i_nb_samples = i_out;
241         p_out_buf->i_dts =
242         p_out_buf->i_pts = date_Get( &p_sys->end_date );
243         p_out_buf->i_length = date_Increment( &p_sys->end_date,
244                                       p_out_buf->i_nb_samples ) - p_out_buf->i_pts;
245
246         p_out_buf->i_buffer = p_out_buf->i_nb_samples *
247             i_nb_channels * sizeof(int32_t);
248     }
249
250     /* Buffer i_filter_wing * 2 samples for next time */
251     if( p_sys->i_old_wing )
252     {
253         size_t newsize = p_sys->i_old_wing * 2 * i_bytes_per_frame;
254         if( newsize > p_sys->i_buf_size )
255         {
256             free( p_sys->p_buf );
257             p_sys->p_buf = malloc( newsize );
258             if( p_sys->p_buf != NULL )
259                 p_sys->i_buf_size = newsize;
260             else
261             {
262                 p_sys->i_buf_size = p_sys->i_old_wing = 0; /* oops! */
263                 block_Release( p_in_buf );
264                 return p_out_buf;
265             }
266         }
267         memcpy( p_sys->p_buf,
268                 p_in_orig + (i_in_nb - 2 * p_sys->i_old_wing) *
269                 i_nb_channels, (2 * p_sys->i_old_wing) *
270                 p_filter->fmt_in.audio.i_bytes_per_frame );
271     }
272
273 #if 0
274     msg_Err( p_filter, "p_out size: %i, nb bytes out: %i", p_out_buf->i_buffer,
275              i_out * p_filter->fmt_in.audio.i_bytes_per_frame );
276 #endif
277
278     block_Release( p_in_buf );
279     return p_out_buf;
280 }
281
282 static const struct vlc_filter_operations filter_ops = {
283     .filter_audio = Resample, .close = CloseFilter,
284 };
285
286 /*****************************************************************************
287  * OpenFilter:
288  *****************************************************************************/
289 static int OpenFilter( vlc_object_t *p_this )
290 {
291     filter_t *p_filter = (filter_t *)p_this;
292     filter_sys_t *p_sys;
293     unsigned int i_out_rate  = p_filter->fmt_out.audio.i_rate;
294
295     if ( p_filter->fmt_in.audio.i_rate == p_filter->fmt_out.audio.i_rate
296       || p_filter->fmt_in.audio.i_format != p_filter->fmt_out.audio.i_format
297       || p_filter->fmt_in.audio.i_channels != p_filter->fmt_out.audio.i_channels
298       || p_filter->fmt_in.audio.i_format != VLC_CODEC_FL32 )
299     {
300         return VLC_EGENERIC;
301     }
302
303     /* Allocate the memory needed to store the module's structure */
304     p_filter->p_sys = p_sys = malloc( sizeof(struct filter_sys_t) );
305     if( p_sys == NULL )
306         return VLC_ENOMEM;
307
308     p_sys->p_buf = NULL;
309     p_sys->i_buf_size = 0;
310
311     p_sys->i_old_wing = 0;
312     p_sys->b_first = true;
313     p_filter->ops = &filter_ops;
314
315     msg_Dbg( p_this, "%4.4s/%iKHz/%i->%4.4s/%iKHz/%i",
316              (char *)&p_filter->fmt_in.i_codec,
317              p_filter->fmt_in.audio.i_rate,
318              p_filter->fmt_in.audio.i_channels,
319              (char *)&p_filter->fmt_out.i_codec,
320              p_filter->fmt_out.audio.i_rate,
321              p_filter->fmt_out.audio.i_channels);
322
323     p_filter->fmt_out = p_filter->fmt_in;
324     p_filter->fmt_out.audio.i_rate = i_out_rate;
325
326     return 0;
327 }
328
329 /*****************************************************************************
330  * CloseFilter : deallocate data structures
331  *****************************************************************************/
332 static void CloseFilter( filter_t *p_filter )
333 {
334     free( p_filter->p_sys->p_buf );
335     free( p_filter->p_sys );
336 }
337
338 static void FilterFloatUP( const float Imp[], const float ImpD[], uint16_t Nwing, float *p_in,
339                             float *p_out, uint32_t ui_remainder,
340                             uint32_t ui_output_rate, int16_t Inc, int i_nb_channels )
341 {
342     const float *Hp, *Hdp, *End;
343     float t, temp;
344     uint32_t ui_linear_remainder;
345     int i;
346
347     Hp = &Imp[(ui_remainder<<Nhc)/ui_output_rate];
348     Hdp = &ImpD[(ui_remainder<<Nhc)/ui_output_rate];
349
350     End = &Imp[Nwing];
351
352     ui_linear_remainder = (ui_remainder<<Nhc) -
353                             (ui_remainder<<Nhc)/ui_output_rate*ui_output_rate;
354
355     if (Inc == 1)               /* If doing right wing...              */
356     {                           /* ...drop extra coeff, so when Ph is  */
357         End--;                  /*    0.5, we don't do too many mult's */
358         if (ui_remainder == 0)  /* If the phase is zero...           */
359         {                       /* ...then we've already skipped the */
360             Hp += Npc;          /*    first sample, so we must also  */
361             Hdp += Npc;         /*    skip ahead in Imp[] and ImpD[] */
362         }
363     }
364
365     while (Hp < End) {
366         t = *Hp;                /* Get filter coeff */
367                                 /* t is now interp'd filter coeff */
368         t += *Hdp * ui_linear_remainder / ui_output_rate / Npc;
369         for( i = 0; i < i_nb_channels; i++ )
370         {
371             temp = t;
372             temp *= *(p_in+i);  /* Mult coeff by input sample */
373             *(p_out+i) += temp; /* The filter output */
374         }
375         Hdp += Npc;             /* Filter coeff differences step */
376         Hp += Npc;              /* Filter coeff step */
377         p_in += (Inc * i_nb_channels); /* Input signal step */
378     }
379 }
380
381 static void FilterFloatUD( const float Imp[], const float ImpD[], uint16_t Nwing, float *p_in,
382                            float *p_out, uint32_t ui_remainder,
383                            uint32_t ui_output_rate, uint32_t ui_input_rate,
384                            int16_t Inc, int i_nb_channels )
385 {
386     const float *Hp, *Hdp, *End;
387     float t, temp;
388     uint32_t ui_linear_remainder;
389     int i, ui_counter = 0;
390
391     Hp = Imp + (ui_remainder<<Nhc) / ui_input_rate;
392     Hdp = ImpD  + (ui_remainder<<Nhc) / ui_input_rate;
393
394     End = &Imp[Nwing];
395
396     if (Inc == 1)               /* If doing right wing...              */
397     {                           /* ...drop extra coeff, so when Ph is  */
398         End--;                  /*    0.5, we don't do too many mult's */
399         if (ui_remainder == 0)  /* If the phase is zero...           */
400         {                       /* ...then we've already skipped the */
401             Hp = Imp +          /* first sample, so we must also  */
402                   (ui_output_rate << Nhc) / ui_input_rate;
403             Hdp = ImpD +        /* skip ahead in Imp[] and ImpD[] */
404                   (ui_output_rate << Nhc) / ui_input_rate;
405             ui_counter++;
406         }
407     }
408
409     while (Hp < End) {
410         t = *Hp;                /* Get filter coeff */
411                                 /* t is now interp'd filter coeff */
412         ui_linear_remainder =
413           ((ui_output_rate * ui_counter + ui_remainder)<< Nhc) -
414           ((ui_output_rate * ui_counter + ui_remainder)<< Nhc) /
415           ui_input_rate * ui_input_rate;
416         t += *Hdp * ui_linear_remainder / ui_input_rate / Npc;
417         for( i = 0; i < i_nb_channels; i++ )
418         {
419             temp = t;
420             temp *= *(p_in+i);  /* Mult coeff by input sample */
421             *(p_out+i) += temp; /* The filter output */
422         }
423
424         ui_counter++;
425
426         /* Filter coeff step */
427         Hp = Imp + ((ui_output_rate * ui_counter + ui_remainder)<< Nhc)
428                     / ui_input_rate;
429         /* Filter coeff differences step */
430         Hdp = ImpD + ((ui_output_rate * ui_counter + ui_remainder)<< Nhc)
431                      / ui_input_rate;
432
433         p_in += (Inc * i_nb_channels); /* Input signal step */
434     }
435 }
436
437 static int ReallocBuffer( block_t **pp_out_buf,
438                           float **pp_out, size_t i_out,
439                           int i_nb_channels, int i_bytes_per_frame )
440 {
441     if( i_out < (*pp_out_buf)->i_buffer/i_bytes_per_frame )
442         return VLC_SUCCESS;
443
444     /* It may happen when the wing size changes */
445     const unsigned i_extra_frame = 256;
446     *pp_out_buf = block_Realloc( *pp_out_buf, 0,
447                                  (*pp_out_buf)->i_buffer +
448                                     i_extra_frame * i_bytes_per_frame );
449     if( !*pp_out_buf )
450         return VLC_EGENERIC;
451
452     *pp_out = (float*)(*pp_out_buf)->p_buffer + i_out * i_nb_channels;
453     memset( *pp_out, 0, i_extra_frame * i_bytes_per_frame );
454     return VLC_SUCCESS;
455 }
456
457 static void ResampleFloat( filter_t *p_filter,
458                            block_t **pp_out_buf,  size_t *pi_out,
459                            float **pp_in,
460                            int i_in, int i_in_end,
461                            double d_factor, bool b_factor_old,
462                            int i_nb_channels, int i_bytes_per_frame )
463 {
464     filter_sys_t *p_sys = p_filter->p_sys;
465
466     float *p_in = *pp_in;
467     size_t i_out = *pi_out;
468     float *p_out = (float*)(*pp_out_buf)->p_buffer + i_out * i_nb_channels;
469
470     for( ; i_in < i_in_end; i_in++ )
471     {
472         if( b_factor_old && d_factor == 1 )
473         {
474             if( ReallocBuffer( pp_out_buf, &p_out,
475                                i_out, i_nb_channels, i_bytes_per_frame ) )
476                 return;
477             /* Just copy the samples */
478             memcpy( p_out, p_in, i_bytes_per_frame );
479             p_in += i_nb_channels;
480             p_out += i_nb_channels;
481             i_out++;
482             continue;
483         }
484
485         while( p_sys->i_remainder < p_filter->fmt_out.audio.i_rate )
486         {
487             if( ReallocBuffer( pp_out_buf, &p_out,
488                                i_out, i_nb_channels, i_bytes_per_frame ) )
489                 return;
490
491             if( d_factor >= 1 )
492             {
493                 /* FilterFloatUP() is faster if we can use it */
494
495                 /* Perform left-wing inner product */
496                 FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
497                                SMALL_FILTER_NWING, p_in, p_out,
498                                p_sys->i_remainder,
499                                p_filter->fmt_out.audio.i_rate,
500                                -1, i_nb_channels );
501                 /* Perform right-wing inner product */
502                 FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
503                                SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
504                                p_filter->fmt_out.audio.i_rate -
505                                p_sys->i_remainder,
506                                p_filter->fmt_out.audio.i_rate,
507                                1, i_nb_channels );
508
509 #if 0
510                 /* Normalize for unity filter gain */
511                 for( i = 0; i < i_nb_channels; i++ )
512                 {
513                     *(p_out+i) *= d_old_scale_factor;
514                 }
515 #endif
516             }
517             else
518             {
519                 /* Perform left-wing inner product */
520                 FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
521                                SMALL_FILTER_NWING, p_in, p_out,
522                                p_sys->i_remainder,
523                                p_filter->fmt_out.audio.i_rate, p_filter->fmt_in.audio.i_rate,
524                                -1, i_nb_channels );
525                 /* Perform right-wing inner product */
526                 FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
527                                SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
528                                p_filter->fmt_out.audio.i_rate -
529                                p_sys->i_remainder,
530                                p_filter->fmt_out.audio.i_rate, p_filter->fmt_in.audio.i_rate,
531                                1, i_nb_channels );
532             }
533
534             p_out += i_nb_channels;
535             i_out++;
536
537             p_sys->i_remainder += p_filter->fmt_in.audio.i_rate;
538         }
539
540         p_in += i_nb_channels;
541         p_sys->i_remainder -= p_filter->fmt_out.audio.i_rate;
542     }
543
544     *pp_in  = p_in;
545     *pi_out = i_out;
546 }
547
548