Index: third_party/opus/src/silk/tests/test_unit_LPC_inv_pred_gain.c |
diff --git a/third_party/opus/src/silk/tests/test_unit_LPC_inv_pred_gain.c b/third_party/opus/src/silk/tests/test_unit_LPC_inv_pred_gain.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..67067cead70297fe77361ae555aa9bc304b87ff6 |
--- /dev/null |
+++ b/third_party/opus/src/silk/tests/test_unit_LPC_inv_pred_gain.c |
@@ -0,0 +1,129 @@ |
+/*********************************************************************** |
+Copyright (c) 2017 Google Inc., Jean-Marc Valin |
+Redistribution and use in source and binary forms, with or without |
+modification, are permitted provided that the following conditions |
+are met: |
+- Redistributions of source code must retain the above copyright notice, |
+this list of conditions and the following disclaimer. |
+- Redistributions in binary form must reproduce the above copyright |
+notice, this list of conditions and the following disclaimer in the |
+documentation and/or other materials provided with the distribution. |
+- Neither the name of Internet Society, IETF or IETF Trust, nor the |
+names of specific contributors, may be used to endorse or promote |
+products derived from this software without specific prior written |
+permission. |
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
+POSSIBILITY OF SUCH DAMAGE. |
+***********************************************************************/ |
+ |
+#ifdef HAVE_CONFIG_H |
+#include "config.h" |
+#endif |
+ |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include "celt/stack_alloc.h" |
+#include "cpu_support.h" |
+#include "SigProc_FIX.h" |
+ |
+/* Computes the impulse response of the filter so we |
+ can catch filters that are definitely unstable. Some |
+ unstable filters may be classified as stable, but not |
+ the other way around. */ |
+int check_stability(opus_int16 *A_Q12, int order) { |
+ int i; |
+ int j; |
+ int sum_a, sum_abs_a; |
+ sum_a = sum_abs_a = 0; |
+ for( j = 0; j < order; j++ ) { |
+ sum_a += A_Q12[ j ]; |
+ sum_abs_a += silk_abs( A_Q12[ j ] ); |
+ } |
+ /* Check DC stability. */ |
+ if( sum_a >= 4096 ) { |
+ return 0; |
+ } |
+ /* If the sum of absolute values is less than 1, the filter |
+ has to be stable. */ |
+ if( sum_abs_a < 4096 ) { |
+ return 1; |
+ } |
+ double y[SILK_MAX_ORDER_LPC] = {0}; |
+ y[0] = 1; |
+ for( i = 0; i < 10000; i++ ) { |
+ double sum = 0; |
+ for( j = 0; j < order; j++ ) { |
+ sum += y[ j ]*A_Q12[ j ]; |
+ } |
+ for( j = order - 1; j > 0; j-- ) { |
+ y[ j ] = y[ j - 1 ]; |
+ } |
+ y[ 0 ] = sum*(1./4096); |
+ /* If impulse response reaches +/- 10000, the filter |
+ is definitely unstable. */ |
+ if( !(y[ 0 ] < 10000 && y[ 0 ] > -10000) ) { |
+ return 0; |
+ } |
+ /* Test every 8 sample for low amplitude. */ |
+ if( ( i & 0x7 ) == 0 ) { |
+ double amp = 0; |
+ for( j = 0; j < order; j++ ) { |
+ amp += fabs(y[j]); |
+ } |
+ if( amp < 0.00001 ) { |
+ return 1; |
+ } |
+ } |
+ } |
+ return 1; |
+} |
+ |
+int main(void) { |
+ const int arch = opus_select_arch(); |
+ /* Set to 10000 so all branches in C function are triggered */ |
+ const int loop_num = 10000; |
+ int count = 0; |
+ ALLOC_STACK; |
+ |
+ /* FIXME: Make the seed random (with option to set it explicitly) |
+ so we get wider coverage. */ |
+ srand(0); |
+ |
+ printf("Testing silk_LPC_inverse_pred_gain() optimization ...\n"); |
+ for( count = 0; count < loop_num; count++ ) { |
+ unsigned int i; |
+ opus_int order; |
+ unsigned int shift; |
+ opus_int16 A_Q12[ SILK_MAX_ORDER_LPC ]; |
+ opus_int32 gain; |
+ |
+ for( order = 2; order <= SILK_MAX_ORDER_LPC; order += 2 ) { /* order must be even. */ |
+ for( shift = 0; shift < 16; shift++ ) { /* Different dynamic range. */ |
+ for( i = 0; i < SILK_MAX_ORDER_LPC; i++ ) { |
+ A_Q12[i] = ((opus_int16)rand()) >> shift; |
+ } |
+ gain = silk_LPC_inverse_pred_gain(A_Q12, order, arch); |
+ /* Look for filters that silk_LPC_inverse_pred_gain() thinks are |
+ stable but definitely aren't. */ |
+ if( gain != 0 && !check_stability(A_Q12, order) ) { |
+ fprintf(stderr, "**Loop %4d failed!**\n", count); |
+ return 1; |
+ } |
+ } |
+ } |
+ if( !(count % 500) ) { |
+ printf("Loop %4d passed\n", count); |
+ } |
+ } |
+ printf("silk_LPC_inverse_pred_gain() optimization passed\n"); |
+ return 0; |
+} |