ref: d5158a42d1010e3a2c4431dbada17314496b6ce3
parent: d84c8d1fd89ee138d8e496f54708eb080ee1ff0a
author: Jean-Marc Valin <[email protected]>
date: Wed Oct 12 08:58:52 EDT 2011
Fixes a numerical accuracy issue in the pitch search The energy "sliding window" was using double accumulation with float multiplications. This forces the multiplications to be double as well.
--- a/silk/float/energy_FLP.c
+++ b/silk/float/energy_FLP.c
@@ -41,18 +41,18 @@
double result;
/* 4x unrolled loop */
- result = 0.0f;
+ result = 0.0;
dataSize4 = dataSize & 0xFFFC;
for( i = 0; i < dataSize4; i += 4 ) {
- result += data[ i + 0 ] * data[ i + 0 ] +
- data[ i + 1 ] * data[ i + 1 ] +
- data[ i + 2 ] * data[ i + 2 ] +
- data[ i + 3 ] * data[ i + 3 ];
+ result += data[ i + 0 ] * (double)data[ i + 0 ] +
+ data[ i + 1 ] * (double)data[ i + 1 ] +
+ data[ i + 2 ] * (double)data[ i + 2 ] +
+ data[ i + 3 ] * (double)data[ i + 3 ];
}
/* add any remaining products */
for( ; i < dataSize; i++ ) {
- result += data[ i ] * data[ i ];
+ result += data[ i ] * (double)data[ i ];
}
silk_assert( result >= 0.0 );
--- a/silk/float/pitch_analysis_core_FLP.c
+++ b/silk/float/pitch_analysis_core_FLP.c
@@ -610,11 +610,11 @@
lag_diff = ( matrix_ptr( Lag_range_ptr, k, 1, 2 ) - matrix_ptr( Lag_range_ptr, k, 0, 2 ) + 1 );
for( i = 1; i < lag_diff; i++ ) {
/* remove part outside new window */
- energy -= basis_ptr[sf_length - i] * basis_ptr[sf_length - i];
+ energy -= basis_ptr[sf_length - i] * (double)basis_ptr[sf_length - i];
silk_assert( energy >= 0.0 );
/* add part that comes into window */
- energy += basis_ptr[ -i ] * basis_ptr[ -i ];
+ energy += basis_ptr[ -i ] * (double)basis_ptr[ -i ];
silk_assert( energy >= 0.0 );
silk_assert( lag_counter < SCRATCH_SIZE );
scratch_mem[lag_counter] = (silk_float)energy;