History

src/src_sinc.c : Optimization. About a 5% improvement in throughput.

Erik de Castro Lopo committed 18 years ago

Commit 1b248f71 parent d86441d2 files · +215 −60Browse files

Unified · Split

2 files
  1. ChangeLog +5 −0
  2. src/src_sinc.c +210 −60
ChangeLog+5−0
@@ -1,3 +1,8 @@
12008-09-27 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
2
3 * src/src_sinc.c
4 Optimization. About a 5% improvement in throughput.
5
12008-09-26 Erik de Castro Lopo <erikd AT mega-nerd DOT com>62008-09-26 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
2 7
3 * tests/util.[ch]8 * tests/util.[ch]
src/src_sinc.c+210−60
@@ -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
71static int sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;71static int sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
72 72static int sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
73static double calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch) ;
74 73
75static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ;74static 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
254static inline double
255calc_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
306static inline double
307calc_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
358static int
359sinc_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
249static int451static int
250sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)452sinc_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
415static double
416calc_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

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t