ref: 67a8c942dd86c9febb9168dde524977b3f3a6421
parent: a3cfc1510d8caa091bcfec5f9ab8892ae71638c3
author: Alexander Grund <alexander.grund@tu-dresden.de>
date: Tue Aug 27 09:09:01 EDT 2019
Move buffer-underflow handling out of hot loop The event `data_index < 0` can be handled once by a simple arithmetic operation instead of beeing checked once per loop in the computationally most expensive loop.
--- a/src/src_sinc.c
+++ b/src/src_sinc.c
@@ -94,6 +94,11 @@
{ return fp_fraction_part (x) * INV_FP_ONE ;
} /* fp_to_double */
+static inline int
+int_div_ceil (int divident, int divisor) /* == (int) ceil ((float) divident / divisor) */
+{ assert (divident >= 0 && divisor > 0) ; /* For positive numbers only */
+ return (divident + (divisor - 1)) / divisor ;
+}
/*----------------------------------------------------------------------------------------
*/
@@ -295,22 +300,26 @@
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - coeff_count ;
+ if (data_index < 0) /* Avoid underflow access to filter->buffer. */
+ { int steps = -data_index ;
+ /* If the assert triggers we would have to take care not to underflow/overflow */
+ assert (steps <= int_div_ceil (filter_index, increment)) ;
+ filter_index -= increment * steps ;
+ data_index += steps ;
+ }
left = 0.0 ;
- do
- { if (data_index >= 0) /* Avoid underflow access to filter->buffer. */
- { fraction = fp_to_double (filter_index) ;
- indx = fp_to_int (filter_index) ;
- assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ;
- icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
- assert (data_index >= 0 && data_index < filter->b_len) ;
- assert (data_index < filter->b_end) ;
- left += icoeff * filter->buffer [data_index] ;
- } ;
+ while (filter_index >= MAKE_INCREMENT_T (0))
+ { fraction = fp_to_double (filter_index) ;
+ indx = fp_to_int (filter_index) ;
+ assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ;
+ icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
+ assert (data_index >= 0 && data_index < filter->b_len) ;
+ assert (data_index < filter->b_end) ;
+ left += icoeff * filter->buffer [data_index] ;
filter_index -= increment ;
data_index = data_index + 1 ;
- }
- while (filter_index >= MAKE_INCREMENT_T (0)) ;
+ } ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
@@ -444,23 +453,27 @@
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - filter->channels * coeff_count ;
+ if (data_index < 0) /* Avoid underflow access to filter->buffer. */
+ { int steps = int_div_ceil (-data_index, 2) ;
+ /* If the assert triggers we would have to take care not to underflow/overflow */
+ assert (steps <= int_div_ceil (filter_index, increment)) ;
+ filter_index -= increment * steps ;
+ data_index += steps * 2;
+ }
left [0] = left [1] = 0.0 ;
- do
- { if (data_index >= 0) /* Avoid underflow access to filter->buffer. */
- { fraction = fp_to_double (filter_index) ;
- indx = fp_to_int (filter_index) ;
- assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ;
- icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
- assert (data_index >= 0 && data_index + 1 < filter->b_len) ;
- assert (data_index + 1 < filter->b_end) ;
- for (int ch = 0; ch < 2; ch++)
- left [ch] += icoeff * filter->buffer [data_index + ch] ;
- } ;
+ while (filter_index >= MAKE_INCREMENT_T (0))
+ { fraction = fp_to_double (filter_index) ;
+ indx = fp_to_int (filter_index) ;
+ assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ;
+ icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
+ assert (data_index >= 0 && data_index + 1 < filter->b_len) ;
+ assert (data_index + 1 < filter->b_end) ;
+ for (int ch = 0; ch < 2; ch++)
+ left [ch] += icoeff * filter->buffer [data_index + ch] ;
filter_index -= increment ;
data_index = data_index + 2 ;
- }
- while (filter_index >= MAKE_INCREMENT_T (0)) ;
+ } ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
@@ -595,23 +608,27 @@
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - filter->channels * coeff_count ;
+ if (data_index < 0) /* Avoid underflow access to filter->buffer. */
+ { int steps = int_div_ceil (-data_index, 4) ;
+ /* If the assert triggers we would have to take care not to underflow/overflow */
+ assert (steps <= int_div_ceil (filter_index, increment)) ;
+ filter_index -= increment * steps ;
+ data_index += steps * 4;
+ }
left [0] = left [1] = left [2] = left [3] = 0.0 ;
- do
- { if (data_index >= 0) /* Avoid underflow access to filter->buffer. */
- { fraction = fp_to_double (filter_index) ;
- indx = fp_to_int (filter_index) ;
- assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ;
- icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
- assert (data_index >= 0 && data_index + 3 < filter->b_len) ;
- assert (data_index + 3 < filter->b_end) ;
- for (int ch = 0; ch < 4; ch++)
- left [ch] += icoeff * filter->buffer [data_index + ch] ;
- } ;
+ while (filter_index >= MAKE_INCREMENT_T (0))
+ { fraction = fp_to_double (filter_index) ;
+ indx = fp_to_int (filter_index) ;
+ assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ;
+ icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
+ assert (data_index >= 0 && data_index + 3 < filter->b_len) ;
+ assert (data_index + 3 < filter->b_end) ;
+ for (int ch = 0; ch < 4; ch++)
+ left [ch] += icoeff * filter->buffer [data_index + ch] ;
filter_index -= increment ;
data_index = data_index + 4 ;
- }
- while (filter_index >= MAKE_INCREMENT_T (0)) ;
+ } ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
@@ -747,23 +764,27 @@
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - filter->channels * coeff_count ;
+ if (data_index < 0) /* Avoid underflow access to filter->buffer. */
+ { int steps = int_div_ceil (-data_index, 6) ;
+ /* If the assert triggers we would have to take care not to underflow/overflow */
+ assert (steps <= int_div_ceil (filter_index, increment)) ;
+ filter_index -= increment * steps ;
+ data_index += steps * 6;
+ }
left [0] = left [1] = left [2] = left [3] = left [4] = left [5] = 0.0 ;
- do
- { if (data_index >= 0) /* Avoid underflow access to filter->buffer. */
- { fraction = fp_to_double (filter_index) ;
- indx = fp_to_int (filter_index) ;
- assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ;
- icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
- assert (data_index >= 0 && data_index + 5 < filter->b_len) ;
- assert (data_index + 5 < filter->b_end) ;
- for (int ch = 0; ch < 6; ch++)
- left [ch] += icoeff * filter->buffer [data_index + ch] ;
- } ;
+ while (filter_index >= MAKE_INCREMENT_T (0))
+ { fraction = fp_to_double (filter_index) ;
+ indx = fp_to_int (filter_index) ;
+ assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ;
+ icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
+ assert (data_index >= 0 && data_index + 5 < filter->b_len) ;
+ assert (data_index + 5 < filter->b_end) ;
+ for (int ch = 0; ch < 6; ch++)
+ left [ch] += icoeff * filter->buffer [data_index + ch] ;
filter_index -= increment ;
data_index = data_index + 6 ;
- }
- while (filter_index >= MAKE_INCREMENT_T (0)) ;
+ } ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
@@ -903,25 +924,30 @@
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - channels * coeff_count ;
+ if (data_index < 0) /* Avoid underflow access to filter->buffer. */
+ { int steps = int_div_ceil (-data_index, channels) ;
+ /* If the assert triggers we would have to take care not to underflow/overflow */
+ assert (steps <= int_div_ceil (filter_index, increment)) ;
+ filter_index -= increment * steps ;
+ data_index += steps * channels ;
+ }
+
memset (left, 0, sizeof (left [0]) * channels) ;
- do
+ while (filter_index >= MAKE_INCREMENT_T (0))
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
- if (data_index >= 0) /* Avoid underflow access to filter->buffer. */
- { assert (data_index >= 0 && data_index + channels - 1 < filter->b_len) ;
- assert (data_index + channels - 1 < filter->b_end) ;
- for (int ch = 0; ch < channels; ch++)
- left [ch] += icoeff * filter->buffer [data_index + ch] ;
- } ;
+ assert (data_index >= 0 && data_index + channels - 1 < filter->b_len) ;
+ assert (data_index + channels - 1 < filter->b_end) ;
+ for (int ch = 0; ch < channels; ch++)
+ left [ch] += icoeff * filter->buffer [data_index + ch] ;
filter_index -= increment ;
data_index = data_index + channels ;
- }
- while (filter_index >= MAKE_INCREMENT_T (0)) ;
+ } ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;