1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libopus/silk/NLSF_stabilize.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,142 @@ 1.4 +/*********************************************************************** 1.5 +Copyright (c) 2006-2011, Skype Limited. All rights reserved. 1.6 +Redistribution and use in source and binary forms, with or without 1.7 +modification, are permitted provided that the following conditions 1.8 +are met: 1.9 +- Redistributions of source code must retain the above copyright notice, 1.10 +this list of conditions and the following disclaimer. 1.11 +- Redistributions in binary form must reproduce the above copyright 1.12 +notice, this list of conditions and the following disclaimer in the 1.13 +documentation and/or other materials provided with the distribution. 1.14 +- Neither the name of Internet Society, IETF or IETF Trust, nor the 1.15 +names of specific contributors, may be used to endorse or promote 1.16 +products derived from this software without specific prior written 1.17 +permission. 1.18 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1.19 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.20 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.21 +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 1.22 +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.23 +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.24 +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.25 +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.26 +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.27 +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1.28 +POSSIBILITY OF SUCH DAMAGE. 1.29 +***********************************************************************/ 1.30 + 1.31 +#ifdef HAVE_CONFIG_H 1.32 +#include "config.h" 1.33 +#endif 1.34 + 1.35 +/* NLSF stabilizer: */ 1.36 +/* */ 1.37 +/* - Moves NLSFs further apart if they are too close */ 1.38 +/* - Moves NLSFs away from borders if they are too close */ 1.39 +/* - High effort to achieve a modification with minimum */ 1.40 +/* Euclidean distance to input vector */ 1.41 +/* - Output are sorted NLSF coefficients */ 1.42 +/* */ 1.43 + 1.44 +#include "SigProc_FIX.h" 1.45 + 1.46 +/* Constant Definitions */ 1.47 +#define MAX_LOOPS 20 1.48 + 1.49 +/* NLSF stabilizer, for a single input data vector */ 1.50 +void silk_NLSF_stabilize( 1.51 + opus_int16 *NLSF_Q15, /* I/O Unstable/stabilized normalized LSF vector in Q15 [L] */ 1.52 + const opus_int16 *NDeltaMin_Q15, /* I Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1] */ 1.53 + const opus_int L /* I Number of NLSF parameters in the input vector */ 1.54 +) 1.55 +{ 1.56 + opus_int i, I=0, k, loops; 1.57 + opus_int16 center_freq_Q15; 1.58 + opus_int32 diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15; 1.59 + 1.60 + /* This is necessary to ensure an output within range of a opus_int16 */ 1.61 + silk_assert( NDeltaMin_Q15[L] >= 1 ); 1.62 + 1.63 + for( loops = 0; loops < MAX_LOOPS; loops++ ) { 1.64 + /**************************/ 1.65 + /* Find smallest distance */ 1.66 + /**************************/ 1.67 + /* First element */ 1.68 + min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0]; 1.69 + I = 0; 1.70 + /* Middle elements */ 1.71 + for( i = 1; i <= L-1; i++ ) { 1.72 + diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] ); 1.73 + if( diff_Q15 < min_diff_Q15 ) { 1.74 + min_diff_Q15 = diff_Q15; 1.75 + I = i; 1.76 + } 1.77 + } 1.78 + /* Last element */ 1.79 + diff_Q15 = ( 1 << 15 ) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] ); 1.80 + if( diff_Q15 < min_diff_Q15 ) { 1.81 + min_diff_Q15 = diff_Q15; 1.82 + I = L; 1.83 + } 1.84 + 1.85 + /***************************************************/ 1.86 + /* Now check if the smallest distance non-negative */ 1.87 + /***************************************************/ 1.88 + if( min_diff_Q15 >= 0 ) { 1.89 + return; 1.90 + } 1.91 + 1.92 + if( I == 0 ) { 1.93 + /* Move away from lower limit */ 1.94 + NLSF_Q15[0] = NDeltaMin_Q15[0]; 1.95 + 1.96 + } else if( I == L) { 1.97 + /* Move away from higher limit */ 1.98 + NLSF_Q15[L-1] = ( 1 << 15 ) - NDeltaMin_Q15[L]; 1.99 + 1.100 + } else { 1.101 + /* Find the lower extreme for the location of the current center frequency */ 1.102 + min_center_Q15 = 0; 1.103 + for( k = 0; k < I; k++ ) { 1.104 + min_center_Q15 += NDeltaMin_Q15[k]; 1.105 + } 1.106 + min_center_Q15 += silk_RSHIFT( NDeltaMin_Q15[I], 1 ); 1.107 + 1.108 + /* Find the upper extreme for the location of the current center frequency */ 1.109 + max_center_Q15 = 1 << 15; 1.110 + for( k = L; k > I; k-- ) { 1.111 + max_center_Q15 -= NDeltaMin_Q15[k]; 1.112 + } 1.113 + max_center_Q15 -= silk_RSHIFT( NDeltaMin_Q15[I], 1 ); 1.114 + 1.115 + /* Move apart, sorted by value, keeping the same center frequency */ 1.116 + center_freq_Q15 = (opus_int16)silk_LIMIT_32( silk_RSHIFT_ROUND( (opus_int32)NLSF_Q15[I-1] + (opus_int32)NLSF_Q15[I], 1 ), 1.117 + min_center_Q15, max_center_Q15 ); 1.118 + NLSF_Q15[I-1] = center_freq_Q15 - silk_RSHIFT( NDeltaMin_Q15[I], 1 ); 1.119 + NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I]; 1.120 + } 1.121 + } 1.122 + 1.123 + /* Safe and simple fall back method, which is less ideal than the above */ 1.124 + if( loops == MAX_LOOPS ) 1.125 + { 1.126 + /* Insertion sort (fast for already almost sorted arrays): */ 1.127 + /* Best case: O(n) for an already sorted array */ 1.128 + /* Worst case: O(n^2) for an inversely sorted array */ 1.129 + silk_insertion_sort_increasing_all_values_int16( &NLSF_Q15[0], L ); 1.130 + 1.131 + /* First NLSF should be no less than NDeltaMin[0] */ 1.132 + NLSF_Q15[0] = silk_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] ); 1.133 + 1.134 + /* Keep delta_min distance between the NLSFs */ 1.135 + for( i = 1; i < L; i++ ) 1.136 + NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], NLSF_Q15[i-1] + NDeltaMin_Q15[i] ); 1.137 + 1.138 + /* Last NLSF should be no higher than 1 - NDeltaMin[L] */ 1.139 + NLSF_Q15[L-1] = silk_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] ); 1.140 + 1.141 + /* Keep NDeltaMin distance between the NLSFs */ 1.142 + for( i = L-2; i >= 0; i-- ) 1.143 + NLSF_Q15[i] = silk_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] ); 1.144 + } 1.145 +}