| @@ -68,9 +68,8 @@ typedef struct · 67 unmodified lines |
| 68 | float buffer [1] ; | 68 | float buffer [1] ; |
| 69 | } SINC_FILTER ; | 69 | } SINC_FILTER ; |
| 70 | | 70 | |
| 71 | static int sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ; | 71 | static int sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ; |
| 72 | | 72 | static int sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ; |
| 73 | static double calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch) ; | | |
| 74 | | 73 | |
| 75 | static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ; | 74 | static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ; |
| 76 | | 75 | |
| @@ -167,8 +166,14 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum) · 90 unmodified lines |
| 167 | temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ; | 166 | temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ; |
| 168 | temp_filter.channels = psrc->channels ; | 167 | temp_filter.channels = psrc->channels ; |
| 169 | | 168 | |
| 170 | psrc->const_process = sinc_vari_process ; | 169 | if (psrc->channels == 1) |
| 171 | psrc->vari_process = sinc_vari_process ; | 170 | { psrc->const_process = sinc_1chan_vari_process ; |
| | 171 | psrc->vari_process = sinc_1chan_vari_process ; |
| | 172 | } |
| | 173 | else |
| | 174 | { psrc->const_process = sinc_multichan_vari_process ; |
| | 175 | psrc->vari_process = sinc_multichan_vari_process ; |
| | 176 | } ; |
| 172 | psrc->reset = sinc_reset ; | 177 | psrc->reset = sinc_reset ; |
| 173 | | 178 | |
| 174 | switch (src_enum) | 179 | switch (src_enum) |
| @@ -246,8 +251,205 @@ sinc_reset (SRC_PRIVATE *psrc) · 71 unmodified lines |
| 246 | ** Beware all ye who dare pass this point. There be dragons here. | 251 | ** Beware all ye who dare pass this point. There be dragons here. |
| 247 | */ | 252 | */ |
| 248 | | 253 | |
| | 254 | static inline double |
| | 255 | calc_output_single (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index) |
| | 256 | { double fraction, left, right, icoeff ; |
| | 257 | increment_t filter_index, max_filter_index ; |
| | 258 | int data_index, coeff_count, indx ; |
| | 259 | |
| | 260 | /* Convert input parameters into fixed point. */ |
| | 261 | max_filter_index = int_to_fp (filter->coeff_half_len) ; |
| | 262 | |
| | 263 | /* First apply the left half of the filter. */ |
| | 264 | filter_index = start_filter_index ; |
| | 265 | coeff_count = (max_filter_index - filter_index) / increment ; |
| | 266 | filter_index = filter_index + coeff_count * increment ; |
| | 267 | data_index = filter->b_current - coeff_count ; |
| | 268 | |
| | 269 | left = 0.0 ; |
| | 270 | do |
| | 271 | { fraction = fp_to_double (filter_index) ; |
| | 272 | indx = fp_to_int (filter_index) ; |
| | 273 | |
| | 274 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; |
| | 275 | |
| | 276 | left += icoeff * filter->buffer [data_index] ; |
| | 277 | |
| | 278 | filter_index -= increment ; |
| | 279 | data_index = data_index + 1 ; |
| | 280 | } |
| | 281 | while (filter_index >= MAKE_INCREMENT_T (0)) ; |
| | 282 | |
| | 283 | /* Now apply the right half of the filter. */ |
| | 284 | filter_index = increment - start_filter_index ; |
| | 285 | coeff_count = (max_filter_index - filter_index) / increment ; |
| | 286 | filter_index = filter_index + coeff_count * increment ; |
| | 287 | data_index = filter->b_current + 1 + coeff_count ; |
| | 288 | |
| | 289 | right = 0.0 ; |
| | 290 | do |
| | 291 | { fraction = fp_to_double (filter_index) ; |
| | 292 | indx = fp_to_int (filter_index) ; |
| | 293 | |
| | 294 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; |
| | 295 | |
| | 296 | right += icoeff * filter->buffer [data_index] ; |
| | 297 | |
| | 298 | filter_index -= increment ; |
| | 299 | data_index = data_index - 1 ; |
| | 300 | } |
| | 301 | while (filter_index > MAKE_INCREMENT_T (0)) ; |
| | 302 | |
| | 303 | return (left + right) ; |
| | 304 | } /* calc_output_single */ |
| | 305 | |
| | 306 | static inline double |
| | 307 | calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch) |
| | 308 | { double fraction, left, right, icoeff ; |
| | 309 | increment_t filter_index, max_filter_index ; |
| | 310 | int data_index, coeff_count, indx ; |
| | 311 | |
| | 312 | /* Convert input parameters into fixed point. */ |
| | 313 | max_filter_index = int_to_fp (filter->coeff_half_len) ; |
| | 314 | |
| | 315 | /* First apply the left half of the filter. */ |
| | 316 | filter_index = start_filter_index ; |
| | 317 | coeff_count = (max_filter_index - filter_index) / increment ; |
| | 318 | filter_index = filter_index + coeff_count * increment ; |
| | 319 | data_index = filter->b_current - filter->channels * coeff_count + ch ; |
| | 320 | |
| | 321 | left = 0.0 ; |
| | 322 | do |
| | 323 | { fraction = fp_to_double (filter_index) ; |
| | 324 | indx = fp_to_int (filter_index) ; |
| | 325 | |
| | 326 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; |
| | 327 | |
| | 328 | left += icoeff * filter->buffer [data_index] ; |
| | 329 | |
| | 330 | filter_index -= increment ; |
| | 331 | data_index = data_index + filter->channels ; |
| | 332 | } |
| | 333 | while (filter_index >= MAKE_INCREMENT_T (0)) ; |
| | 334 | |
| | 335 | /* Now apply the right half of the filter. */ |
| | 336 | filter_index = increment - start_filter_index ; |
| | 337 | coeff_count = (max_filter_index - filter_index) / increment ; |
| | 338 | filter_index = filter_index + coeff_count * increment ; |
| | 339 | data_index = filter->b_current + filter->channels * (1 + coeff_count) + ch ; |
| | 340 | |
| | 341 | right = 0.0 ; |
| | 342 | do |
| | 343 | { fraction = fp_to_double (filter_index) ; |
| | 344 | indx = fp_to_int (filter_index) ; |
| | 345 | |
| | 346 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; |
| | 347 | |
| | 348 | right += icoeff * filter->buffer [data_index] ; |
| | 349 | |
| | 350 | filter_index -= increment ; |
| | 351 | data_index = data_index - filter->channels ; |
| | 352 | } |
| | 353 | while (filter_index > MAKE_INCREMENT_T (0)) ; |
| | 354 | |
| | 355 | return (left + right) ; |
| | 356 | } /* calc_output_multi */ |
| | 357 | |
| | 358 | static int |
| | 359 | sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) |
| | 360 | { SINC_FILTER *filter ; |
| | 361 | double input_index, src_ratio, count, float_increment, terminate, rem ; |
| | 362 | increment_t increment, start_filter_index ; |
| | 363 | int half_filter_chan_len, samples_in_hand ; |
| | 364 | |
| | 365 | if (psrc->private_data == NULL) |
| | 366 | return SRC_ERR_NO_PRIVATE ; |
| | 367 | |
| | 368 | filter = (SINC_FILTER*) psrc->private_data ; |
| | 369 | |
| | 370 | /* If there is not a problem, this will be optimised out. */ |
| | 371 | if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0])) |
| | 372 | return SRC_ERR_SIZE_INCOMPATIBILITY ; |
| | 373 | |
| | 374 | filter->in_count = data->input_frames * filter->channels ; |
| | 375 | filter->out_count = data->output_frames * filter->channels ; |
| | 376 | filter->in_used = filter->out_gen = 0 ; |
| | 377 | |
| | 378 | src_ratio = psrc->last_ratio ; |
| | 379 | |
| | 380 | /* Check the sample rate ratio wrt the buffer len. */ |
| | 381 | count = (filter->coeff_half_len + 2.0) / filter->index_inc ; |
| | 382 | if (MIN (psrc->last_ratio, data->src_ratio) < 1.0) |
| | 383 | count /= MIN (psrc->last_ratio, data->src_ratio) ; |
| | 384 | |
| | 385 | /* Maximum coefficientson either side of center point. */ |
| | 386 | half_filter_chan_len = filter->channels * (lrint (count) + 1) ; |
| | 387 | |
| | 388 | input_index = psrc->last_position ; |
| | 389 | float_increment = filter->index_inc ; |
| | 390 | |
| | 391 | rem = fmod_one (input_index) ; |
| | 392 | filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ; |
| | 393 | input_index = rem ; |
| | 394 | |
| | 395 | terminate = 1.0 / src_ratio + 1e-20 ; |
| | 396 | |
| | 397 | /* Main processing loop. */ |
| | 398 | while (filter->out_gen < filter->out_count) |
| | 399 | { |
| | 400 | /* Need to reload buffer? */ |
| | 401 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; |
| | 402 | |
| | 403 | if (samples_in_hand <= half_filter_chan_len) |
| | 404 | { prepare_data (filter, data, half_filter_chan_len) ; |
| | 405 | |
| | 406 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; |
| | 407 | if (samples_in_hand <= half_filter_chan_len) |
| | 408 | break ; |
| | 409 | } ; |
| | 410 | |
| | 411 | /* This is the termination condition. */ |
| | 412 | if (filter->b_real_end >= 0) |
| | 413 | { if (filter->b_current + input_index + terminate >= filter->b_real_end) |
| | 414 | break ; |
| | 415 | } ; |
| | 416 | |
| | 417 | if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10) |
| | 418 | src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ; |
| | 419 | |
| | 420 | float_increment = filter->index_inc * 1.0 ; |
| | 421 | if (src_ratio < 1.0) |
| | 422 | float_increment = filter->index_inc * src_ratio ; |
| | 423 | |
| | 424 | increment = double_to_fp (float_increment) ; |
| | 425 | |
| | 426 | start_filter_index = double_to_fp (input_index * float_increment) ; |
| | 427 | |
| | 428 | data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) * |
| | 429 | calc_output_single (filter, increment, start_filter_index)) ; |
| | 430 | filter->out_gen ++ ; |
| | 431 | |
| | 432 | /* Figure out the next index. */ |
| | 433 | input_index += 1.0 / src_ratio ; |
| | 434 | rem = fmod_one (input_index) ; |
| | 435 | |
| | 436 | filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ; |
| | 437 | input_index = rem ; |
| | 438 | } ; |
| | 439 | |
| | 440 | psrc->last_position = input_index ; |
| | 441 | |
| | 442 | /* Save current ratio rather then target ratio. */ |
| | 443 | psrc->last_ratio = src_ratio ; |
| | 444 | |
| | 445 | data->input_frames_used = filter->in_used / filter->channels ; |
| | 446 | data->output_frames_gen = filter->out_gen / filter->channels ; |
| | 447 | |
| | 448 | return SRC_ERR_NO_ERROR ; |
| | 449 | } /* sinc_1chan_vari_process */ |
| | 450 | |
| 249 | static int | 451 | static int |
| 250 | sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) | 452 | sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) |
| 251 | { SINC_FILTER *filter ; | 453 | { SINC_FILTER *filter ; |
| 252 | double input_index, src_ratio, count, float_increment, terminate, rem ; | 454 | double input_index, src_ratio, count, float_increment, terminate, rem ; |
| 253 | increment_t increment, start_filter_index ; | 455 | increment_t increment, start_filter_index ; |
| @@ -318,7 +520,7 @@ sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) · 64 unmodified lines |
| 318 | | 520 | |
| 319 | for (ch = 0 ; ch < filter->channels ; ch++) | 521 | for (ch = 0 ; ch < filter->channels ; ch++) |
| 320 | { data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) * | 522 | { data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) * |
| 321 | calc_output (filter, increment, start_filter_index, ch)) ; | 523 | calc_output_multi (filter, increment, start_filter_index, ch)) ; |
| 322 | filter->out_gen ++ ; | 524 | filter->out_gen ++ ; |
| 323 | } ; | 525 | } ; |
| 324 | | 526 | |
| @@ -339,7 +541,7 @@ sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) · 14 unmodified lines |
| 339 | data->output_frames_gen = filter->out_gen / filter->channels ; | 541 | data->output_frames_gen = filter->out_gen / filter->channels ; |
| 340 | | 542 | |
| 341 | return SRC_ERR_NO_ERROR ; | 543 | return SRC_ERR_NO_ERROR ; |
| 342 | } /* sinc_vari_process */ | 544 | } /* sinc_multichan_vari_process */ |
| 343 | | 545 | |
| 344 | /*---------------------------------------------------------------------------------------- | 546 | /*---------------------------------------------------------------------------------------- |
| 345 | */ | 547 | */ |
| @@ -412,55 +614,3 @@ prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) · 66 unmodified lines |
| 412 | } /* prepare_data */ | 614 | } /* prepare_data */ |
| 413 | | 615 | |
| 414 | | 616 | |
| 415 | static double | | |
| 416 | calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch) | | |
| 417 | { double fraction, left, right, icoeff ; | | |
| 418 | increment_t filter_index, max_filter_index ; | | |
| 419 | int data_index, coeff_count, indx ; | | |
| 420 | | | |
| 421 | /* Convert input parameters into fixed point. */ | | |
| 422 | max_filter_index = int_to_fp (filter->coeff_half_len) ; | | |
| 423 | | | |
| 424 | /* First apply the left half of the filter. */ | | |
| 425 | filter_index = start_filter_index ; | | |
| 426 | coeff_count = (max_filter_index - filter_index) / increment ; | | |
| 427 | filter_index = filter_index + coeff_count * increment ; | | |
| 428 | data_index = filter->b_current - filter->channels * coeff_count + ch ; | | |
| 429 | | | |
| 430 | left = 0.0 ; | | |
| 431 | do | | |
| 432 | { fraction = fp_to_double (filter_index) ; | | |
| 433 | indx = fp_to_int (filter_index) ; | | |
| 434 | | | |
| 435 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; | | |
| 436 | | | |
| 437 | left += icoeff * filter->buffer [data_index] ; | | |
| 438 | | | |
| 439 | filter_index -= increment ; | | |
| 440 | data_index = data_index + filter->channels ; | | |
| 441 | } | | |
| 442 | while (filter_index >= MAKE_INCREMENT_T (0)) ; | | |
| 443 | | | |
| 444 | /* Now apply the right half of the filter. */ | | |
| 445 | filter_index = increment - start_filter_index ; | | |
| 446 | coeff_count = (max_filter_index - filter_index) / increment ; | | |
| 447 | filter_index = filter_index + coeff_count * increment ; | | |
| 448 | data_index = filter->b_current + filter->channels * (1 + coeff_count) + ch ; | | |
| 449 | | | |
| 450 | right = 0.0 ; | | |
| 451 | do | | |
| 452 | { fraction = fp_to_double (filter_index) ; | | |
| 453 | indx = fp_to_int (filter_index) ; | | |
| 454 | | | |
| 455 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; | | |
| 456 | | | |
| 457 | right += icoeff * filter->buffer [data_index] ; | | |
| 458 | | | |
| 459 | filter_index -= increment ; | | |
| 460 | data_index = data_index - filter->channels ; | | |
| 461 | } | | |
| 462 | while (filter_index > MAKE_INCREMENT_T (0)) ; | | |
| 463 | | | |
| 464 | return (left + right) ; | | |
| 465 | } /* calc_output */ | | |
| 466 | | | |