shithub: opus

Download patch

ref: 4a7027b27e2d962dedc63360a45db5ff74dc1131
parent: e6a0be8ee6a0675dc7c959a0c3cf9d3f7219b682
author: Jean-Marc Valin <[email protected]>
date: Thu Oct 27 09:51:21 EDT 2011

Allow wrap-around in silk_LPC_analysis_filter()

--- a/silk/LPC_analysis_filter.c
+++ b/silk/LPC_analysis_filter.c
@@ -58,18 +58,20 @@
         in_ptr = &in[ ix - 1 ];
 
         out32_Q12 = silk_SMULBB(            in_ptr[  0 ], B[ 0 ] );
-        out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -1 ], B[ 1 ] );
-        out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -2 ], B[ 2 ] );
-        out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -3 ], B[ 3 ] );
-        out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -4 ], B[ 4 ] );
-        out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -5 ], B[ 5 ] );
+        /* Allowing wrap around so that two wraps can cancel each other. The rare
+           cases where the result wraps around can only be triggered by invalid streams*/
+        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -1 ], B[ 1 ] );
+        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -2 ], B[ 2 ] );
+        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -3 ], B[ 3 ] );
+        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -4 ], B[ 4 ] );
+        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -5 ], B[ 5 ] );
         for( j = 6; j < d; j += 2 ) {
-            out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -j     ], B[ j     ] );
-            out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] );
+            out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j     ], B[ j     ] );
+            out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] );
         }
 
         /* Subtract prediction */
-        out32_Q12 = silk_SUB32( silk_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 );
+        out32_Q12 = silk_SUB32_ovflw( silk_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 );
 
         /* Scale to Q0 */
         out32 = silk_RSHIFT_ROUND( out32_Q12, 12 );
--- a/silk/SigProc_FIX.h
+++ b/silk/SigProc_FIX.h
@@ -421,6 +421,9 @@
    (just standard two's complement implementation-specific behaviour) */
 #define silk_SUB32_ovflw(a, b)              ((opus_int32)((opus_uint32)(a) - (opus_uint32)(b)))
 
+/* a32 + (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)) output have to be 32bit int */
+#define silk_SMLABB_ovflw(a32, b32, c32)       (silk_ADD32_ovflw((a32) , ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))))
+
 /* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode)*/
 #define silk_MLA_ovflw(a32, b32, c32)       silk_ADD32_ovflw((a32), (opus_uint32)(b32) * (opus_uint32)(c32))
 #ifndef silk_SMLABB_ovflw