Fixes a numerical accuracy issue in the pitch search
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Wed, 12 Oct 2011 16:58:52 +0000 (12:58 -0400)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Wed, 12 Oct 2011 16:58:52 +0000 (12:58 -0400)
The energy "sliding window" was using double accumulation with
float multiplications. This forces the multiplications to be
double as well.

silk/float/energy_FLP.c
silk/float/pitch_analysis_core_FLP.c

index 86767da..f43143d 100644 (file)
@@ -41,18 +41,18 @@ double silk_energy_FLP(
     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 );
index a90859b..8e66159 100644 (file)
@@ -610,11 +610,11 @@ calculated recursively.
         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;