shithub: opus

Download patch

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;