00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdlib.h>
00036 #include <string.h>
00037
00038 #include <vlc/vlc.h>
00039 #include "audio_output.h"
00040 #include "aout_internal.h"
00041 #include "bandlimited.h"
00042
00043
00044
00045
00046 static int Create ( vlc_object_t * );
00047 static void Close ( vlc_object_t * );
00048 static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
00049 aout_buffer_t * );
00050
00051 static void FilterFloatUP( float Imp[], float ImpD[], uint16_t Nwing,
00052 float *f_in, float *f_out, uint32_t ui_remainder,
00053 uint32_t ui_output_rate, int16_t Inc,
00054 int i_nb_channels );
00055
00056 static void FilterFloatUD( float Imp[], float ImpD[], uint16_t Nwing,
00057 float *f_in, float *f_out, uint32_t ui_remainder,
00058 uint32_t ui_output_rate, uint32_t ui_input_rate,
00059 int16_t Inc, int i_nb_channels );
00060
00061
00062
00063
00064 struct aout_filter_sys_t
00065 {
00066 int32_t *p_buf;
00067 int i_buf_size;
00068
00069 int i_old_rate;
00070 double d_old_factor;
00071 int i_old_wing;
00072
00073 unsigned int i_remainder;
00074
00075 audio_date_t end_date;
00076 };
00077
00078
00079
00080
00081 vlc_module_begin();
00082 set_category( CAT_AUDIO );
00083 set_subcategory( SUBCAT_AUDIO_MISC );
00084 set_description( _("audio filter for band-limited interpolation resampling") );
00085 set_capability( "audio filter", 20 );
00086 set_callbacks( Create, Close );
00087 vlc_module_end();
00088
00089
00090
00091
00092 static int Create( vlc_object_t *p_this )
00093 {
00094 aout_filter_t * p_filter = (aout_filter_t *)p_this;
00095 double d_factor;
00096 int i_filter_wing;
00097
00098 if ( p_filter->input.i_rate == p_filter->output.i_rate
00099 || p_filter->input.i_format != p_filter->output.i_format
00100 || p_filter->input.i_physical_channels
00101 != p_filter->output.i_physical_channels
00102 || p_filter->input.i_original_channels
00103 != p_filter->output.i_original_channels
00104 || p_filter->input.i_format != VLC_FOURCC('f','l','3','2') )
00105 {
00106 return VLC_EGENERIC;
00107 }
00108
00109 #if !defined( SYS_DARWIN )
00110 if( !config_GetInt( p_this, "hq-resampling" ) )
00111 {
00112 return VLC_EGENERIC;
00113 }
00114 #endif
00115
00116
00117 p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) );
00118 if( p_filter->p_sys == NULL )
00119 {
00120 msg_Err( p_filter, "out of memory" );
00121 return VLC_ENOMEM;
00122 }
00123
00124
00125 d_factor = (double)p_filter->output.i_rate
00126 / p_filter->input.i_rate;
00127 i_filter_wing = ((SMALL_FILTER_NMULT + 1)/2.0)
00128 * __MAX(1.0, 1.0/d_factor) + 10;
00129 p_filter->p_sys->i_buf_size = aout_FormatNbChannels( &p_filter->input ) *
00130 sizeof(int32_t) * 2 * i_filter_wing;
00131
00132
00133 p_filter->p_sys->p_buf = malloc( p_filter->p_sys->i_buf_size );
00134 if( p_filter->p_sys->p_buf == NULL )
00135 {
00136 msg_Err( p_filter, "out of memory" );
00137 return VLC_ENOMEM;
00138 }
00139
00140 p_filter->p_sys->i_old_wing = 0;
00141 p_filter->pf_do_work = DoWork;
00142
00143
00144
00145 p_filter->b_in_place = VLC_TRUE;
00146
00147 return VLC_SUCCESS;
00148 }
00149
00150
00151
00152
00153 static void Close( vlc_object_t * p_this )
00154 {
00155 aout_filter_t * p_filter = (aout_filter_t *)p_this;
00156 free( p_filter->p_sys->p_buf );
00157 free( p_filter->p_sys );
00158 }
00159
00160
00161
00162
00163 static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
00164 aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
00165 {
00166 float *p_in, *p_in_orig, *p_out = (float *)p_out_buf->p_buffer;
00167
00168 int i_nb_channels = aout_FormatNbChannels( &p_filter->input );
00169 int i_in_nb = p_in_buf->i_nb_samples;
00170 int i_in, i_out = 0;
00171 double d_factor, d_scale_factor, d_old_scale_factor;
00172 int i_filter_wing;
00173 #if 0
00174 int i;
00175 #endif
00176
00177
00178 if( p_aout->mixer.mixer.i_rate == p_filter->input.i_rate )
00179 {
00180 if(
00181 p_filter->p_sys->i_old_wing &&
00182 p_in_buf->i_size >=
00183 p_in_buf->i_nb_bytes + p_filter->p_sys->i_old_wing *
00184 p_filter->input.i_bytes_per_frame )
00185 {
00186
00187 memmove( ((float *)(p_in_buf->p_buffer)) +
00188 i_nb_channels * p_filter->p_sys->i_old_wing,
00189 p_in_buf->p_buffer, p_in_buf->i_nb_bytes );
00190 memcpy( p_in_buf->p_buffer, p_filter->p_sys->p_buf +
00191 i_nb_channels * p_filter->p_sys->i_old_wing,
00192 p_filter->p_sys->i_old_wing *
00193 p_filter->input.i_bytes_per_frame );
00194
00195 p_out_buf->i_nb_samples = p_in_buf->i_nb_samples +
00196 p_filter->p_sys->i_old_wing;
00197
00198 p_out_buf->start_date = aout_DateGet( &p_filter->p_sys->end_date );
00199 p_out_buf->end_date =
00200 aout_DateIncrement( &p_filter->p_sys->end_date,
00201 p_out_buf->i_nb_samples );
00202
00203 p_out_buf->i_nb_bytes = p_out_buf->i_nb_samples *
00204 p_filter->input.i_bytes_per_frame;
00205 }
00206 p_filter->b_continuity = VLC_FALSE;
00207 p_filter->p_sys->i_old_wing = 0;
00208 return;
00209 }
00210
00211 if( !p_filter->b_continuity )
00212 {
00213
00214
00215 p_filter->b_continuity = VLC_TRUE;
00216 p_filter->p_sys->i_remainder = 0;
00217 aout_DateInit( &p_filter->p_sys->end_date, p_filter->output.i_rate );
00218 aout_DateSet( &p_filter->p_sys->end_date, p_in_buf->start_date );
00219 p_filter->p_sys->i_old_rate = p_filter->input.i_rate;
00220 p_filter->p_sys->d_old_factor = 1;
00221 p_filter->p_sys->i_old_wing = 0;
00222 }
00223
00224 #if 0
00225 msg_Err( p_filter, "old rate: %i, old factor: %f, old wing: %i, i_in: %i",
00226 p_filter->p_sys->i_old_rate, p_filter->p_sys->d_old_factor,
00227 p_filter->p_sys->i_old_wing, i_in_nb );
00228 #endif
00229
00230
00231 i_in_nb += (p_filter->p_sys->i_old_wing * 2);
00232 #ifdef HAVE_ALLOCA
00233 p_in = p_in_orig = (float *)alloca( i_in_nb *
00234 p_filter->input.i_bytes_per_frame );
00235 #else
00236 p_in = p_in_orig = (float *)malloc( i_in_nb *
00237 p_filter->input.i_bytes_per_frame );
00238 #endif
00239 if( p_in == NULL )
00240 {
00241 return;
00242 }
00243
00244
00245 if( p_filter->p_sys->i_old_wing )
00246 {
00247 p_aout->p_vlc->pf_memcpy( p_in, p_filter->p_sys->p_buf,
00248 p_filter->p_sys->i_old_wing * 2 *
00249 p_filter->input.i_bytes_per_frame );
00250 }
00251 p_aout->p_vlc->pf_memcpy( p_in + p_filter->p_sys->i_old_wing * 2 *
00252 i_nb_channels, p_in_buf->p_buffer,
00253 p_in_buf->i_nb_samples *
00254 p_filter->input.i_bytes_per_frame );
00255
00256
00257 memset( p_out, 0, p_out_buf->i_size );
00258
00259
00260 d_factor = (double)p_aout->mixer.mixer.i_rate / p_filter->input.i_rate;
00261 i_filter_wing = ((SMALL_FILTER_NMULT+1)/2.0) * __MAX(1.0,1.0/d_factor) + 1;
00262
00263
00264 d_old_scale_factor = SMALL_FILTER_SCALE *
00265 p_filter->p_sys->d_old_factor + 0.5;
00266 d_scale_factor = SMALL_FILTER_SCALE * d_factor + 0.5;
00267
00268
00269 i_in = p_filter->p_sys->i_old_wing;
00270 p_in += p_filter->p_sys->i_old_wing * i_nb_channels;
00271 for( ; i_in < i_filter_wing &&
00272 (i_in + p_filter->p_sys->i_old_wing) < i_in_nb; i_in++ )
00273 {
00274 if( p_filter->p_sys->d_old_factor == 1 )
00275 {
00276
00277 memcpy( p_out, p_in,
00278 p_filter->input.i_bytes_per_frame );
00279 p_in += i_nb_channels;
00280 p_out += i_nb_channels;
00281 i_out++;
00282 continue;
00283 }
00284
00285 while( p_filter->p_sys->i_remainder < p_filter->output.i_rate )
00286 {
00287
00288 if( p_filter->p_sys->d_old_factor >= 1 )
00289 {
00290
00291
00292
00293 FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
00294 SMALL_FILTER_NWING, p_in, p_out,
00295 p_filter->p_sys->i_remainder,
00296 p_filter->output.i_rate,
00297 -1, i_nb_channels );
00298
00299 FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
00300 SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
00301 p_filter->output.i_rate -
00302 p_filter->p_sys->i_remainder,
00303 p_filter->output.i_rate,
00304 1, i_nb_channels );
00305
00306 #if 0
00307
00308 for( i = 0; i < i_nb_channels; i++ )
00309 {
00310 *(p_out+i) *= d_old_scale_factor;
00311 }
00312 #endif
00313
00314
00315 if( p_out_buf->i_size/p_filter->input.i_bytes_per_frame
00316 <= (unsigned int)i_out+1 )
00317 {
00318 p_out += i_nb_channels;
00319 i_out++;
00320 p_filter->p_sys->i_remainder += p_filter->input.i_rate;
00321 break;
00322 }
00323 }
00324 else
00325 {
00326
00327 FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
00328 SMALL_FILTER_NWING, p_in, p_out,
00329 p_filter->p_sys->i_remainder,
00330 p_filter->output.i_rate, p_filter->input.i_rate,
00331 -1, i_nb_channels );
00332
00333 FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
00334 SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
00335 p_filter->output.i_rate -
00336 p_filter->p_sys->i_remainder,
00337 p_filter->output.i_rate, p_filter->input.i_rate,
00338 1, i_nb_channels );
00339 }
00340
00341 p_out += i_nb_channels;
00342 i_out++;
00343
00344 p_filter->p_sys->i_remainder += p_filter->input.i_rate;
00345 }
00346
00347 p_in += i_nb_channels;
00348 p_filter->p_sys->i_remainder -= p_filter->output.i_rate;
00349 }
00350
00351
00352 if( i_in < i_in_nb - i_filter_wing )
00353 {
00354 p_filter->p_sys->i_old_rate = p_filter->input.i_rate;
00355 p_filter->p_sys->d_old_factor = d_factor;
00356 p_filter->p_sys->i_old_wing = i_filter_wing;
00357 }
00358 for( ; i_in < i_in_nb - i_filter_wing; i_in++ )
00359 {
00360 while( p_filter->p_sys->i_remainder < p_filter->output.i_rate )
00361 {
00362
00363 if( d_factor >= 1 )
00364 {
00365
00366
00367
00368 FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
00369 SMALL_FILTER_NWING, p_in, p_out,
00370 p_filter->p_sys->i_remainder,
00371 p_filter->output.i_rate,
00372 -1, i_nb_channels );
00373
00374
00375 FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
00376 SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
00377 p_filter->output.i_rate -
00378 p_filter->p_sys->i_remainder,
00379 p_filter->output.i_rate,
00380 1, i_nb_channels );
00381
00382 #if 0
00383
00384 for( i = 0; i < i_nb_channels; i++ )
00385 {
00386 *(p_out+i) *= d_old_scale_factor;
00387 }
00388 #endif
00389
00390 if( p_out_buf->i_size/p_filter->input.i_bytes_per_frame
00391 <= (unsigned int)i_out+1 )
00392 {
00393 p_out += i_nb_channels;
00394 i_out++;
00395 p_filter->p_sys->i_remainder += p_filter->input.i_rate;
00396 break;
00397 }
00398 }
00399 else
00400 {
00401
00402 FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
00403 SMALL_FILTER_NWING, p_in, p_out,
00404 p_filter->p_sys->i_remainder,
00405 p_filter->output.i_rate, p_filter->input.i_rate,
00406 -1, i_nb_channels );
00407
00408 FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
00409 SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
00410 p_filter->output.i_rate -
00411 p_filter->p_sys->i_remainder,
00412 p_filter->output.i_rate, p_filter->input.i_rate,
00413 1, i_nb_channels );
00414 }
00415
00416 p_out += i_nb_channels;
00417 i_out++;
00418
00419 p_filter->p_sys->i_remainder += p_filter->input.i_rate;
00420 }
00421
00422 p_in += i_nb_channels;
00423 p_filter->p_sys->i_remainder -= p_filter->output.i_rate;
00424 }
00425
00426
00427 if( p_filter->p_sys->i_old_wing )
00428 {
00429 memcpy( p_filter->p_sys->p_buf,
00430 p_in_orig + (i_in_nb - 2 * p_filter->p_sys->i_old_wing) *
00431 i_nb_channels, (2 * p_filter->p_sys->i_old_wing) *
00432 p_filter->input.i_bytes_per_frame );
00433 }
00434
00435 #if 0
00436 msg_Err( p_filter, "p_out size: %i, nb bytes out: %i", p_out_buf->i_size,
00437 i_out * p_filter->input.i_bytes_per_frame );
00438 #endif
00439
00440
00441 #ifndef HAVE_ALLOCA
00442 free( p_in_orig );
00443 #endif
00444
00445
00446 p_out_buf->i_nb_samples = i_out;
00447 p_out_buf->start_date = aout_DateGet( &p_filter->p_sys->end_date );
00448 p_out_buf->end_date = aout_DateIncrement( &p_filter->p_sys->end_date,
00449 p_out_buf->i_nb_samples );
00450
00451 p_out_buf->i_nb_bytes = p_out_buf->i_nb_samples *
00452 i_nb_channels * sizeof(int32_t);
00453
00454 }
00455
00456 void FilterFloatUP( float Imp[], float ImpD[], uint16_t Nwing, float *p_in,
00457 float *p_out, uint32_t ui_remainder,
00458 uint32_t ui_output_rate, int16_t Inc, int i_nb_channels )
00459 {
00460 float *Hp, *Hdp, *End;
00461 float t, temp;
00462 uint32_t ui_linear_remainder;
00463 int i;
00464
00465 Hp = &Imp[(ui_remainder<<Nhc)/ui_output_rate];
00466 Hdp = &ImpD[(ui_remainder<<Nhc)/ui_output_rate];
00467
00468 End = &Imp[Nwing];
00469
00470 ui_linear_remainder = (ui_remainder<<Nhc) -
00471 (ui_remainder<<Nhc)/ui_output_rate*ui_output_rate;
00472
00473 if (Inc == 1)
00474 {
00475 End--;
00476 if (ui_remainder == 0)
00477 {
00478 Hp += Npc;
00479 Hdp += Npc;
00480 }
00481 }
00482
00483 while (Hp < End) {
00484 t = *Hp;
00485
00486 t += *Hdp * ui_linear_remainder / ui_output_rate / Npc;
00487 for( i = 0; i < i_nb_channels; i++ )
00488 {
00489 temp = t;
00490 temp *= *(p_in+i);
00491 *(p_out+i) += temp;
00492 }
00493 Hdp += Npc;
00494 Hp += Npc;
00495 p_in += (Inc * i_nb_channels);
00496 }
00497 }
00498
00499 void FilterFloatUD( float Imp[], float ImpD[], uint16_t Nwing, float *p_in,
00500 float *p_out, uint32_t ui_remainder,
00501 uint32_t ui_output_rate, uint32_t ui_input_rate,
00502 int16_t Inc, int i_nb_channels )
00503 {
00504 float *Hp, *Hdp, *End;
00505 float t, temp;
00506 uint32_t ui_linear_remainder;
00507 int i, ui_counter = 0;
00508
00509 Hp = Imp + (ui_remainder<<Nhc) / ui_input_rate;
00510 Hdp = ImpD + (ui_remainder<<Nhc) / ui_input_rate;
00511
00512 End = &Imp[Nwing];
00513
00514 if (Inc == 1)
00515 {
00516 End--;
00517 if (ui_remainder == 0)
00518 {
00519 Hp = Imp +
00520 (ui_output_rate << Nhc) / ui_input_rate;
00521 Hdp = ImpD +
00522 (ui_output_rate << Nhc) / ui_input_rate;
00523 ui_counter++;
00524 }
00525 }
00526
00527 while (Hp < End) {
00528 t = *Hp;
00529
00530 ui_linear_remainder =
00531 ((ui_output_rate * ui_counter + ui_remainder)<< Nhc) -
00532 ((ui_output_rate * ui_counter + ui_remainder)<< Nhc) /
00533 ui_input_rate * ui_input_rate;
00534 t += *Hdp * ui_linear_remainder / ui_input_rate / Npc;
00535 for( i = 0; i < i_nb_channels; i++ )
00536 {
00537 temp = t;
00538 temp *= *(p_in+i);
00539 *(p_out+i) += temp;
00540 }
00541
00542 ui_counter++;
00543
00544
00545 Hp = Imp + ((ui_output_rate * ui_counter + ui_remainder)<< Nhc)
00546 / ui_input_rate;
00547
00548 Hdp = ImpD + ((ui_output_rate * ui_counter + ui_remainder)<< Nhc)
00549 / ui_input_rate;
00550
00551 p_in += (Inc * i_nb_channels);
00552 }
00553 }