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

Showing the changes to src (1 of 2 files). Show all

Unified · Split

src/src_sinc.c+210−60
@@ -68,9 +68,8 @@ typedef struct · 67 unmodified lines
6868 float buffer [1] ;
6969 } SINC_FILTER ;
7070
71−static int sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
72−
73−static double calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch) ;
71+static int sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
72+static int sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
7473
7574 static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ;
7675
@@ -167,8 +166,14 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum) · 90 unmodified lines
167166 temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ;
168167 temp_filter.channels = psrc->channels ;
169168
170− psrc->const_process = sinc_vari_process ;
171− psrc->vari_process = sinc_vari_process ;
169+ if (psrc->channels == 1)
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+ } ;
172177 psrc->reset = sinc_reset ;
173178
174179 switch (src_enum)
@@ -246,8 +251,205 @@ sinc_reset (SRC_PRIVATE *psrc) · 71 unmodified lines
246251 ** Beware all ye who dare pass this point. There be dragons here.
247252 */
248253
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+
249451 static int
250−sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
452+sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
251453 { SINC_FILTER *filter ;
252454 double input_index, src_ratio, count, float_increment, terminate, rem ;
253455 increment_t increment, start_filter_index ;
@@ -318,7 +520,7 @@ sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) · 64 unmodified lines
318520
319521 for (ch = 0 ; ch < filter->channels ; ch++)
320522 { 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)) ;
322524 filter->out_gen ++ ;
323525 } ;
324526
@@ -339,7 +541,7 @@ sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) · 14 unmodified lines
339541 data->output_frames_gen = filter->out_gen / filter->channels ;
340542
341543 return SRC_ERR_NO_ERROR ;
342−} /* sinc_vari_process */
544+} /* sinc_multichan_vari_process */
343545
344546 /*----------------------------------------------------------------------------------------
345547 */
@@ -412,55 +614,3 @@ prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) · 66 unmodified lines
412614 } /* prepare_data */
413615
414616
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−

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