diff options
Diffstat (limited to 'lib/rbcodec/codecs/libopus/silk/fixed')
33 files changed, 5700 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/LTP_analysis_filter_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/LTP_analysis_filter_FIX.c new file mode 100644 index 0000000000..5574e7069f --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/LTP_analysis_filter_FIX.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | |||
34 | void silk_LTP_analysis_filter_FIX( | ||
35 | opus_int16 *LTP_res, /* O LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */ | ||
36 | const opus_int16 *x, /* I Pointer to input signal with at least max( pitchL ) preceding samples */ | ||
37 | const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */ | ||
38 | const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag, one for each subframe */ | ||
39 | const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I Inverse quantization gains, one for each subframe */ | ||
40 | const opus_int subfr_length, /* I Length of each subframe */ | ||
41 | const opus_int nb_subfr, /* I Number of subframes */ | ||
42 | const opus_int pre_length /* I Length of the preceding samples starting at &x[0] for each subframe */ | ||
43 | ) | ||
44 | { | ||
45 | const opus_int16 *x_ptr, *x_lag_ptr; | ||
46 | opus_int16 Btmp_Q14[ LTP_ORDER ]; | ||
47 | opus_int16 *LTP_res_ptr; | ||
48 | opus_int k, i; | ||
49 | opus_int32 LTP_est; | ||
50 | |||
51 | x_ptr = x; | ||
52 | LTP_res_ptr = LTP_res; | ||
53 | for( k = 0; k < nb_subfr; k++ ) { | ||
54 | |||
55 | x_lag_ptr = x_ptr - pitchL[ k ]; | ||
56 | |||
57 | Btmp_Q14[ 0 ] = LTPCoef_Q14[ k * LTP_ORDER ]; | ||
58 | Btmp_Q14[ 1 ] = LTPCoef_Q14[ k * LTP_ORDER + 1 ]; | ||
59 | Btmp_Q14[ 2 ] = LTPCoef_Q14[ k * LTP_ORDER + 2 ]; | ||
60 | Btmp_Q14[ 3 ] = LTPCoef_Q14[ k * LTP_ORDER + 3 ]; | ||
61 | Btmp_Q14[ 4 ] = LTPCoef_Q14[ k * LTP_ORDER + 4 ]; | ||
62 | |||
63 | /* LTP analysis FIR filter */ | ||
64 | for( i = 0; i < subfr_length + pre_length; i++ ) { | ||
65 | LTP_res_ptr[ i ] = x_ptr[ i ]; | ||
66 | |||
67 | /* Long-term prediction */ | ||
68 | LTP_est = silk_SMULBB( x_lag_ptr[ LTP_ORDER / 2 ], Btmp_Q14[ 0 ] ); | ||
69 | LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ 1 ], Btmp_Q14[ 1 ] ); | ||
70 | LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ 0 ], Btmp_Q14[ 2 ] ); | ||
71 | LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ -1 ], Btmp_Q14[ 3 ] ); | ||
72 | LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ -2 ], Btmp_Q14[ 4 ] ); | ||
73 | |||
74 | LTP_est = silk_RSHIFT_ROUND( LTP_est, 14 ); /* round and -> Q0*/ | ||
75 | |||
76 | /* Subtract long-term prediction */ | ||
77 | LTP_res_ptr[ i ] = (opus_int16)silk_SAT16( (opus_int32)x_ptr[ i ] - LTP_est ); | ||
78 | |||
79 | /* Scale residual */ | ||
80 | LTP_res_ptr[ i ] = silk_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] ); | ||
81 | |||
82 | x_lag_ptr++; | ||
83 | } | ||
84 | |||
85 | /* Update pointers */ | ||
86 | LTP_res_ptr += subfr_length + pre_length; | ||
87 | x_ptr += subfr_length; | ||
88 | } | ||
89 | } | ||
90 | |||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/LTP_scale_ctrl_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/LTP_scale_ctrl_FIX.c new file mode 100644 index 0000000000..3dcedef891 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/LTP_scale_ctrl_FIX.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | |||
34 | /* Calculation of LTP state scaling */ | ||
35 | void silk_LTP_scale_ctrl_FIX( | ||
36 | silk_encoder_state_FIX *psEnc, /* I/O encoder state */ | ||
37 | silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ | ||
38 | opus_int condCoding /* I The type of conditional coding to use */ | ||
39 | ) | ||
40 | { | ||
41 | opus_int round_loss; | ||
42 | |||
43 | if( condCoding == CODE_INDEPENDENTLY ) { | ||
44 | /* Only scale if first frame in packet */ | ||
45 | round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; | ||
46 | psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( | ||
47 | silk_SMULWB( silk_SMULBB( round_loss, psEncCtrl->LTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 ); | ||
48 | } else { | ||
49 | /* Default is minimum scaling */ | ||
50 | psEnc->sCmn.indices.LTP_scaleIndex = 0; | ||
51 | } | ||
52 | psEncCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ]; | ||
53 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/apply_sine_window_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/apply_sine_window_FIX.c new file mode 100644 index 0000000000..03e088a6de --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/apply_sine_window_FIX.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "SigProc_FIX.h" | ||
33 | |||
34 | /* Apply sine window to signal vector. */ | ||
35 | /* Window types: */ | ||
36 | /* 1 -> sine window from 0 to pi/2 */ | ||
37 | /* 2 -> sine window from pi/2 to pi */ | ||
38 | /* Every other sample is linearly interpolated, for speed. */ | ||
39 | /* Window length must be between 16 and 120 (incl) and a multiple of 4. */ | ||
40 | |||
41 | /* Matlab code for table: | ||
42 | for k=16:9*4:16+2*9*4, fprintf(' %7.d,', -round(65536*pi ./ (k:4:k+8*4))); fprintf('\n'); end | ||
43 | */ | ||
44 | static const opus_int16 freq_table_Q16[ 27 ] = { | ||
45 | 12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202, | ||
46 | 3885, 3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422, | ||
47 | 2313, 2214, 2123, 2038, 1961, 1889, 1822, 1760, 1702, | ||
48 | }; | ||
49 | |||
50 | void silk_apply_sine_window( | ||
51 | opus_int16 px_win[], /* O Pointer to windowed signal */ | ||
52 | const opus_int16 px[], /* I Pointer to input signal */ | ||
53 | const opus_int win_type, /* I Selects a window type */ | ||
54 | const opus_int length /* I Window length, multiple of 4 */ | ||
55 | ) | ||
56 | { | ||
57 | opus_int k, f_Q16, c_Q16; | ||
58 | opus_int32 S0_Q16, S1_Q16; | ||
59 | |||
60 | celt_assert( win_type == 1 || win_type == 2 ); | ||
61 | |||
62 | /* Length must be in a range from 16 to 120 and a multiple of 4 */ | ||
63 | celt_assert( length >= 16 && length <= 120 ); | ||
64 | celt_assert( ( length & 3 ) == 0 ); | ||
65 | |||
66 | /* Frequency */ | ||
67 | k = ( length >> 2 ) - 4; | ||
68 | celt_assert( k >= 0 && k <= 26 ); | ||
69 | f_Q16 = (opus_int)freq_table_Q16[ k ]; | ||
70 | |||
71 | /* Factor used for cosine approximation */ | ||
72 | c_Q16 = silk_SMULWB( (opus_int32)f_Q16, -f_Q16 ); | ||
73 | silk_assert( c_Q16 >= -32768 ); | ||
74 | |||
75 | /* initialize state */ | ||
76 | if( win_type == 1 ) { | ||
77 | /* start from 0 */ | ||
78 | S0_Q16 = 0; | ||
79 | /* approximation of sin(f) */ | ||
80 | S1_Q16 = f_Q16 + silk_RSHIFT( length, 3 ); | ||
81 | } else { | ||
82 | /* start from 1 */ | ||
83 | S0_Q16 = ( (opus_int32)1 << 16 ); | ||
84 | /* approximation of cos(f) */ | ||
85 | S1_Q16 = ( (opus_int32)1 << 16 ) + silk_RSHIFT( c_Q16, 1 ) + silk_RSHIFT( length, 4 ); | ||
86 | } | ||
87 | |||
88 | /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */ | ||
89 | /* 4 samples at a time */ | ||
90 | for( k = 0; k < length; k += 4 ) { | ||
91 | px_win[ k ] = (opus_int16)silk_SMULWB( silk_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] ); | ||
92 | px_win[ k + 1 ] = (opus_int16)silk_SMULWB( S1_Q16, px[ k + 1] ); | ||
93 | S0_Q16 = silk_SMULWB( S1_Q16, c_Q16 ) + silk_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1; | ||
94 | S0_Q16 = silk_min( S0_Q16, ( (opus_int32)1 << 16 ) ); | ||
95 | |||
96 | px_win[ k + 2 ] = (opus_int16)silk_SMULWB( silk_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] ); | ||
97 | px_win[ k + 3 ] = (opus_int16)silk_SMULWB( S0_Q16, px[ k + 3 ] ); | ||
98 | S1_Q16 = silk_SMULWB( S0_Q16, c_Q16 ) + silk_LSHIFT( S0_Q16, 1 ) - S1_Q16; | ||
99 | S1_Q16 = silk_min( S1_Q16, ( (opus_int32)1 << 16 ) ); | ||
100 | } | ||
101 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h b/lib/rbcodec/codecs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h new file mode 100644 index 0000000000..1992e43288 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2017 Google Inc. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifndef SILK_WARPED_AUTOCORRELATION_FIX_ARM_H | ||
29 | # define SILK_WARPED_AUTOCORRELATION_FIX_ARM_H | ||
30 | |||
31 | # include "celt/arm/armcpu.h" | ||
32 | |||
33 | # if defined(FIXED_POINT) | ||
34 | |||
35 | # if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) | ||
36 | void silk_warped_autocorrelation_FIX_neon( | ||
37 | opus_int32 *corr, /* O Result [order + 1] */ | ||
38 | opus_int *scale, /* O Scaling of the correlation vector */ | ||
39 | const opus_int16 *input, /* I Input data to correlate */ | ||
40 | const opus_int warping_Q16, /* I Warping coefficient */ | ||
41 | const opus_int length, /* I Length of input */ | ||
42 | const opus_int order /* I Correlation order (even) */ | ||
43 | ); | ||
44 | |||
45 | # if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON) | ||
46 | # define OVERRIDE_silk_warped_autocorrelation_FIX (1) | ||
47 | # define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \ | ||
48 | ((void)(arch), PRESUME_NEON(silk_warped_autocorrelation_FIX)(corr, scale, input, warping_Q16, length, order)) | ||
49 | # endif | ||
50 | # endif | ||
51 | |||
52 | # if !defined(OVERRIDE_silk_warped_autocorrelation_FIX) | ||
53 | /*Is run-time CPU detection enabled on this platform?*/ | ||
54 | # if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)) | ||
55 | extern void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK+1])(opus_int32*, opus_int*, const opus_int16*, const opus_int, const opus_int, const opus_int); | ||
56 | # define OVERRIDE_silk_warped_autocorrelation_FIX (1) | ||
57 | # define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \ | ||
58 | ((*SILK_WARPED_AUTOCORRELATION_FIX_IMPL[(arch)&OPUS_ARCHMASK])(corr, scale, input, warping_Q16, length, order)) | ||
59 | # elif defined(OPUS_ARM_PRESUME_NEON_INTR) | ||
60 | # define OVERRIDE_silk_warped_autocorrelation_FIX (1) | ||
61 | # define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \ | ||
62 | ((void)(arch), silk_warped_autocorrelation_FIX_neon(corr, scale, input, warping_Q16, length, order)) | ||
63 | # endif | ||
64 | # endif | ||
65 | |||
66 | # endif /* end FIXED_POINT */ | ||
67 | |||
68 | #endif /* end SILK_WARPED_AUTOCORRELATION_FIX_ARM_H */ | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c b/lib/rbcodec/codecs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c new file mode 100644 index 0000000000..00a70cb51f --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c | |||
@@ -0,0 +1,260 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2017 Google Inc., Jean-Marc Valin | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include <arm_neon.h> | ||
33 | #ifdef OPUS_CHECK_ASM | ||
34 | # include <string.h> | ||
35 | #endif | ||
36 | #include "stack_alloc.h" | ||
37 | #include "main_FIX.h" | ||
38 | |||
39 | static OPUS_INLINE void calc_corr( const opus_int32 *const input_QS, opus_int64 *const corr_QC, const opus_int offset, const int32x4_t state_QS_s32x4 ) | ||
40 | { | ||
41 | int64x2_t corr_QC_s64x2[ 2 ], t_s64x2[ 2 ]; | ||
42 | const int32x4_t input_QS_s32x4 = vld1q_s32( input_QS + offset ); | ||
43 | corr_QC_s64x2[ 0 ] = vld1q_s64( corr_QC + offset + 0 ); | ||
44 | corr_QC_s64x2[ 1 ] = vld1q_s64( corr_QC + offset + 2 ); | ||
45 | t_s64x2[ 0 ] = vmull_s32( vget_low_s32( state_QS_s32x4 ), vget_low_s32( input_QS_s32x4 ) ); | ||
46 | t_s64x2[ 1 ] = vmull_s32( vget_high_s32( state_QS_s32x4 ), vget_high_s32( input_QS_s32x4 ) ); | ||
47 | corr_QC_s64x2[ 0 ] = vsraq_n_s64( corr_QC_s64x2[ 0 ], t_s64x2[ 0 ], 2 * QS - QC ); | ||
48 | corr_QC_s64x2[ 1 ] = vsraq_n_s64( corr_QC_s64x2[ 1 ], t_s64x2[ 1 ], 2 * QS - QC ); | ||
49 | vst1q_s64( corr_QC + offset + 0, corr_QC_s64x2[ 0 ] ); | ||
50 | vst1q_s64( corr_QC + offset + 2, corr_QC_s64x2[ 1 ] ); | ||
51 | } | ||
52 | |||
53 | static OPUS_INLINE int32x4_t calc_state( const int32x4_t state_QS0_s32x4, const int32x4_t state_QS0_1_s32x4, const int32x4_t state_QS1_1_s32x4, const int32x4_t warping_Q16_s32x4 ) | ||
54 | { | ||
55 | int32x4_t t_s32x4 = vsubq_s32( state_QS0_s32x4, state_QS0_1_s32x4 ); | ||
56 | t_s32x4 = vqdmulhq_s32( t_s32x4, warping_Q16_s32x4 ); | ||
57 | return vaddq_s32( state_QS1_1_s32x4, t_s32x4 ); | ||
58 | } | ||
59 | |||
60 | void silk_warped_autocorrelation_FIX_neon( | ||
61 | opus_int32 *corr, /* O Result [order + 1] */ | ||
62 | opus_int *scale, /* O Scaling of the correlation vector */ | ||
63 | const opus_int16 *input, /* I Input data to correlate */ | ||
64 | const opus_int warping_Q16, /* I Warping coefficient */ | ||
65 | const opus_int length, /* I Length of input */ | ||
66 | const opus_int order /* I Correlation order (even) */ | ||
67 | ) | ||
68 | { | ||
69 | if( ( MAX_SHAPE_LPC_ORDER > 24 ) || ( order < 6 ) ) { | ||
70 | silk_warped_autocorrelation_FIX_c( corr, scale, input, warping_Q16, length, order ); | ||
71 | } else { | ||
72 | opus_int n, i, lsh; | ||
73 | opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; /* In reverse order */ | ||
74 | opus_int64 corr_QC_orderT; | ||
75 | int64x2_t lsh_s64x2; | ||
76 | const opus_int orderT = ( order + 3 ) & ~3; | ||
77 | opus_int64 *corr_QCT; | ||
78 | opus_int32 *input_QS; | ||
79 | VARDECL( opus_int32, input_QST ); | ||
80 | VARDECL( opus_int32, state ); | ||
81 | SAVE_STACK; | ||
82 | |||
83 | /* Order must be even */ | ||
84 | silk_assert( ( order & 1 ) == 0 ); | ||
85 | silk_assert( 2 * QS - QC >= 0 ); | ||
86 | |||
87 | ALLOC( input_QST, length + 2 * MAX_SHAPE_LPC_ORDER, opus_int32 ); | ||
88 | |||
89 | input_QS = input_QST; | ||
90 | /* input_QS has zero paddings in the beginning and end. */ | ||
91 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
92 | input_QS += 4; | ||
93 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
94 | input_QS += 4; | ||
95 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
96 | input_QS += 4; | ||
97 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
98 | input_QS += 4; | ||
99 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
100 | input_QS += 4; | ||
101 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
102 | input_QS += 4; | ||
103 | |||
104 | /* Loop over samples */ | ||
105 | for( n = 0; n < length - 7; n += 8, input_QS += 8 ) { | ||
106 | const int16x8_t t0_s16x4 = vld1q_s16( input + n ); | ||
107 | vst1q_s32( input_QS + 0, vshll_n_s16( vget_low_s16( t0_s16x4 ), QS ) ); | ||
108 | vst1q_s32( input_QS + 4, vshll_n_s16( vget_high_s16( t0_s16x4 ), QS ) ); | ||
109 | } | ||
110 | for( ; n < length; n++, input_QS++ ) { | ||
111 | input_QS[ 0 ] = silk_LSHIFT32( (opus_int32)input[ n ], QS ); | ||
112 | } | ||
113 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
114 | input_QS += 4; | ||
115 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
116 | input_QS += 4; | ||
117 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
118 | input_QS += 4; | ||
119 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
120 | input_QS += 4; | ||
121 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
122 | input_QS += 4; | ||
123 | vst1q_s32( input_QS, vdupq_n_s32( 0 ) ); | ||
124 | input_QS = input_QST + MAX_SHAPE_LPC_ORDER - orderT; | ||
125 | |||
126 | /* The following loop runs ( length + order ) times, with ( order ) extra epilogues. */ | ||
127 | /* The zero paddings in input_QS guarantee corr_QC's correctness even with the extra epilogues. */ | ||
128 | /* The values of state_QS will be polluted by the extra epilogues, however they are temporary values. */ | ||
129 | |||
130 | /* Keep the C code here to help understand the intrinsics optimization. */ | ||
131 | /* | ||
132 | { | ||
133 | opus_int32 state_QS[ 2 ][ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; | ||
134 | opus_int32 *state_QST[ 3 ]; | ||
135 | state_QST[ 0 ] = state_QS[ 0 ]; | ||
136 | state_QST[ 1 ] = state_QS[ 1 ]; | ||
137 | for( n = 0; n < length + order; n++, input_QS++ ) { | ||
138 | state_QST[ 0 ][ orderT ] = input_QS[ orderT ]; | ||
139 | for( i = 0; i < orderT; i++ ) { | ||
140 | corr_QC[ i ] += silk_RSHIFT64( silk_SMULL( state_QST[ 0 ][ i ], input_QS[ i ] ), 2 * QS - QC ); | ||
141 | state_QST[ 1 ][ i ] = silk_SMLAWB( state_QST[ 1 ][ i + 1 ], state_QST[ 0 ][ i ] - state_QST[ 0 ][ i + 1 ], warping_Q16 ); | ||
142 | } | ||
143 | state_QST[ 2 ] = state_QST[ 0 ]; | ||
144 | state_QST[ 0 ] = state_QST[ 1 ]; | ||
145 | state_QST[ 1 ] = state_QST[ 2 ]; | ||
146 | } | ||
147 | } | ||
148 | */ | ||
149 | |||
150 | { | ||
151 | const int32x4_t warping_Q16_s32x4 = vdupq_n_s32( warping_Q16 << 15 ); | ||
152 | const opus_int32 *in = input_QS + orderT; | ||
153 | opus_int o = orderT; | ||
154 | int32x4_t state_QS_s32x4[ 3 ][ 2 ]; | ||
155 | |||
156 | ALLOC( state, length + orderT, opus_int32 ); | ||
157 | state_QS_s32x4[ 2 ][ 1 ] = vdupq_n_s32( 0 ); | ||
158 | |||
159 | /* Calculate 8 taps of all inputs in each loop. */ | ||
160 | do { | ||
161 | state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 0 ][ 1 ] = | ||
162 | state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 1 ][ 1 ] = vdupq_n_s32( 0 ); | ||
163 | n = 0; | ||
164 | do { | ||
165 | calc_corr( input_QS + n, corr_QC, o - 8, state_QS_s32x4[ 0 ][ 0 ] ); | ||
166 | calc_corr( input_QS + n, corr_QC, o - 4, state_QS_s32x4[ 0 ][ 1 ] ); | ||
167 | state_QS_s32x4[ 2 ][ 1 ] = vld1q_s32( in + n ); | ||
168 | vst1q_lane_s32( state + n, state_QS_s32x4[ 0 ][ 0 ], 0 ); | ||
169 | state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 0 ][ 1 ], 1 ); | ||
170 | state_QS_s32x4[ 2 ][ 1 ] = vextq_s32( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], 1 ); | ||
171 | state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 ); | ||
172 | state_QS_s32x4[ 0 ][ 1 ] = calc_state( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], state_QS_s32x4[ 1 ][ 1 ], warping_Q16_s32x4 ); | ||
173 | state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ]; | ||
174 | state_QS_s32x4[ 1 ][ 1 ] = state_QS_s32x4[ 2 ][ 1 ]; | ||
175 | } while( ++n < ( length + order ) ); | ||
176 | in = state; | ||
177 | o -= 8; | ||
178 | } while( o > 4 ); | ||
179 | |||
180 | if( o ) { | ||
181 | /* Calculate the last 4 taps of all inputs. */ | ||
182 | opus_int32 *stateT = state; | ||
183 | silk_assert( o == 4 ); | ||
184 | state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 1 ][ 0 ] = vdupq_n_s32( 0 ); | ||
185 | n = length + order; | ||
186 | do { | ||
187 | calc_corr( input_QS, corr_QC, 0, state_QS_s32x4[ 0 ][ 0 ] ); | ||
188 | state_QS_s32x4[ 2 ][ 0 ] = vld1q_s32( stateT ); | ||
189 | vst1q_lane_s32( stateT, state_QS_s32x4[ 0 ][ 0 ], 0 ); | ||
190 | state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], 1 ); | ||
191 | state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 ); | ||
192 | state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ]; | ||
193 | input_QS++; | ||
194 | stateT++; | ||
195 | } while( --n ); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | { | ||
200 | const opus_int16 *inputT = input; | ||
201 | int32x4_t t_s32x4; | ||
202 | int64x1_t t_s64x1; | ||
203 | int64x2_t t_s64x2 = vdupq_n_s64( 0 ); | ||
204 | for( n = 0; n <= length - 8; n += 8 ) { | ||
205 | int16x8_t input_s16x8 = vld1q_s16( inputT ); | ||
206 | t_s32x4 = vmull_s16( vget_low_s16( input_s16x8 ), vget_low_s16( input_s16x8 ) ); | ||
207 | t_s32x4 = vmlal_s16( t_s32x4, vget_high_s16( input_s16x8 ), vget_high_s16( input_s16x8 ) ); | ||
208 | t_s64x2 = vaddw_s32( t_s64x2, vget_low_s32( t_s32x4 ) ); | ||
209 | t_s64x2 = vaddw_s32( t_s64x2, vget_high_s32( t_s32x4 ) ); | ||
210 | inputT += 8; | ||
211 | } | ||
212 | t_s64x1 = vadd_s64( vget_low_s64( t_s64x2 ), vget_high_s64( t_s64x2 ) ); | ||
213 | corr_QC_orderT = vget_lane_s64( t_s64x1, 0 ); | ||
214 | for( ; n < length; n++ ) { | ||
215 | corr_QC_orderT += silk_SMULL( input[ n ], input[ n ] ); | ||
216 | } | ||
217 | corr_QC_orderT = silk_LSHIFT64( corr_QC_orderT, QC ); | ||
218 | corr_QC[ orderT ] = corr_QC_orderT; | ||
219 | } | ||
220 | |||
221 | corr_QCT = corr_QC + orderT - order; | ||
222 | lsh = silk_CLZ64( corr_QC_orderT ) - 35; | ||
223 | lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC ); | ||
224 | *scale = -( QC + lsh ); | ||
225 | silk_assert( *scale >= -30 && *scale <= 12 ); | ||
226 | lsh_s64x2 = vdupq_n_s64( lsh ); | ||
227 | for( i = 0; i <= order - 3; i += 4 ) { | ||
228 | int32x4_t corr_s32x4; | ||
229 | int64x2_t corr_QC0_s64x2, corr_QC1_s64x2; | ||
230 | corr_QC0_s64x2 = vld1q_s64( corr_QCT + i ); | ||
231 | corr_QC1_s64x2 = vld1q_s64( corr_QCT + i + 2 ); | ||
232 | corr_QC0_s64x2 = vshlq_s64( corr_QC0_s64x2, lsh_s64x2 ); | ||
233 | corr_QC1_s64x2 = vshlq_s64( corr_QC1_s64x2, lsh_s64x2 ); | ||
234 | corr_s32x4 = vcombine_s32( vmovn_s64( corr_QC1_s64x2 ), vmovn_s64( corr_QC0_s64x2 ) ); | ||
235 | corr_s32x4 = vrev64q_s32( corr_s32x4 ); | ||
236 | vst1q_s32( corr + order - i - 3, corr_s32x4 ); | ||
237 | } | ||
238 | if( lsh >= 0 ) { | ||
239 | for( ; i < order + 1; i++ ) { | ||
240 | corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QCT[ i ], lsh ) ); | ||
241 | } | ||
242 | } else { | ||
243 | for( ; i < order + 1; i++ ) { | ||
244 | corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QCT[ i ], -lsh ) ); | ||
245 | } | ||
246 | } | ||
247 | silk_assert( corr_QCT[ order ] >= 0 ); /* If breaking, decrease QC*/ | ||
248 | RESTORE_STACK; | ||
249 | } | ||
250 | |||
251 | #ifdef OPUS_CHECK_ASM | ||
252 | { | ||
253 | opus_int32 corr_c[ MAX_SHAPE_LPC_ORDER + 1 ]; | ||
254 | opus_int scale_c; | ||
255 | silk_warped_autocorrelation_FIX_c( corr_c, &scale_c, input, warping_Q16, length, order ); | ||
256 | silk_assert( !memcmp( corr_c, corr, sizeof( corr_c[ 0 ] ) * ( order + 1 ) ) ); | ||
257 | silk_assert( scale_c == *scale ); | ||
258 | } | ||
259 | #endif | ||
260 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/autocorr_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/autocorr_FIX.c new file mode 100644 index 0000000000..de95c98693 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/autocorr_FIX.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "SigProc_FIX.h" | ||
33 | #include "celt_lpc.h" | ||
34 | |||
35 | /* Compute autocorrelation */ | ||
36 | void silk_autocorr( | ||
37 | opus_int32 *results, /* O Result (length correlationCount) */ | ||
38 | opus_int *scale, /* O Scaling of the correlation vector */ | ||
39 | const opus_int16 *inputData, /* I Input data to correlate */ | ||
40 | const opus_int inputDataSize, /* I Length of input */ | ||
41 | const opus_int correlationCount, /* I Number of correlation taps to compute */ | ||
42 | int arch /* I Run-time architecture */ | ||
43 | ) | ||
44 | { | ||
45 | opus_int corrCount; | ||
46 | corrCount = silk_min_int( inputDataSize, correlationCount ); | ||
47 | *scale = _celt_autocorr(inputData, results, NULL, 0, corrCount-1, inputDataSize, arch); | ||
48 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/burg_modified_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/burg_modified_FIX.c new file mode 100644 index 0000000000..274d4b28e1 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/burg_modified_FIX.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "SigProc_FIX.h" | ||
33 | #include "define.h" | ||
34 | #include "tuning_parameters.h" | ||
35 | #include "pitch.h" | ||
36 | |||
37 | #define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */ | ||
38 | |||
39 | #define QA 25 | ||
40 | #define N_BITS_HEAD_ROOM 3 | ||
41 | #define MIN_RSHIFTS -16 | ||
42 | #define MAX_RSHIFTS (32 - QA) | ||
43 | |||
44 | /* Compute reflection coefficients from input signal */ | ||
45 | void silk_burg_modified_c( | ||
46 | opus_int32 *res_nrg, /* O Residual energy */ | ||
47 | opus_int *res_nrg_Q, /* O Residual energy Q value */ | ||
48 | opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ | ||
49 | const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ | ||
50 | const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */ | ||
51 | const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */ | ||
52 | const opus_int nb_subfr, /* I Number of subframes stacked in x */ | ||
53 | const opus_int D, /* I Order */ | ||
54 | int arch /* I Run-time architecture */ | ||
55 | ) | ||
56 | { | ||
57 | opus_int k, n, s, lz, rshifts, reached_max_gain; | ||
58 | opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; | ||
59 | const opus_int16 *x_ptr; | ||
60 | opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; | ||
61 | opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; | ||
62 | opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; | ||
63 | opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; | ||
64 | opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; | ||
65 | opus_int32 xcorr[ SILK_MAX_ORDER_LPC ]; | ||
66 | opus_int64 C0_64; | ||
67 | |||
68 | celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); | ||
69 | |||
70 | /* Compute autocorrelations, added over subframes */ | ||
71 | C0_64 = silk_inner_prod16_aligned_64( x, x, subfr_length*nb_subfr, arch ); | ||
72 | lz = silk_CLZ64(C0_64); | ||
73 | rshifts = 32 + 1 + N_BITS_HEAD_ROOM - lz; | ||
74 | if (rshifts > MAX_RSHIFTS) rshifts = MAX_RSHIFTS; | ||
75 | if (rshifts < MIN_RSHIFTS) rshifts = MIN_RSHIFTS; | ||
76 | |||
77 | if (rshifts > 0) { | ||
78 | C0 = (opus_int32)silk_RSHIFT64(C0_64, rshifts ); | ||
79 | } else { | ||
80 | C0 = silk_LSHIFT32((opus_int32)C0_64, -rshifts ); | ||
81 | } | ||
82 | |||
83 | CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ | ||
84 | silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); | ||
85 | if( rshifts > 0 ) { | ||
86 | for( s = 0; s < nb_subfr; s++ ) { | ||
87 | x_ptr = x + s * subfr_length; | ||
88 | for( n = 1; n < D + 1; n++ ) { | ||
89 | C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64( | ||
90 | silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts ); | ||
91 | } | ||
92 | } | ||
93 | } else { | ||
94 | for( s = 0; s < nb_subfr; s++ ) { | ||
95 | int i; | ||
96 | opus_int32 d; | ||
97 | x_ptr = x + s * subfr_length; | ||
98 | celt_pitch_xcorr(x_ptr, x_ptr + 1, xcorr, subfr_length - D, D, arch ); | ||
99 | for( n = 1; n < D + 1; n++ ) { | ||
100 | for ( i = n + subfr_length - D, d = 0; i < subfr_length; i++ ) | ||
101 | d = MAC16_16( d, x_ptr[ i ], x_ptr[ i - n ] ); | ||
102 | xcorr[ n - 1 ] += d; | ||
103 | } | ||
104 | for( n = 1; n < D + 1; n++ ) { | ||
105 | C_first_row[ n - 1 ] += silk_LSHIFT32( xcorr[ n - 1 ], -rshifts ); | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); | ||
110 | |||
111 | /* Initialize */ | ||
112 | CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ | ||
113 | |||
114 | invGain_Q30 = (opus_int32)1 << 30; | ||
115 | reached_max_gain = 0; | ||
116 | for( n = 0; n < D; n++ ) { | ||
117 | /* Update first row of correlation matrix (without first element) */ | ||
118 | /* Update last row of correlation matrix (without last element, stored in reversed order) */ | ||
119 | /* Update C * Af */ | ||
120 | /* Update C * flipud(Af) (stored in reversed order) */ | ||
121 | if( rshifts > -2 ) { | ||
122 | for( s = 0; s < nb_subfr; s++ ) { | ||
123 | x_ptr = x + s * subfr_length; | ||
124 | x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts) */ | ||
125 | x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts) */ | ||
126 | tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16) */ | ||
127 | tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16) */ | ||
128 | for( k = 0; k < n; k++ ) { | ||
129 | C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ | ||
130 | C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ | ||
131 | Atmp_QA = Af_QA[ k ]; | ||
132 | tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16) */ | ||
133 | tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16) */ | ||
134 | } | ||
135 | tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts) */ | ||
136 | tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts) */ | ||
137 | for( k = 0; k <= n; k++ ) { | ||
138 | CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift ) */ | ||
139 | CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift ) */ | ||
140 | } | ||
141 | } | ||
142 | } else { | ||
143 | for( s = 0; s < nb_subfr; s++ ) { | ||
144 | x_ptr = x + s * subfr_length; | ||
145 | x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts ) */ | ||
146 | x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts ) */ | ||
147 | tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17 */ | ||
148 | tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17 */ | ||
149 | for( k = 0; k < n; k++ ) { | ||
150 | C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ | ||
151 | C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ | ||
152 | Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */ | ||
153 | /* We sometimes have get overflows in the multiplications (even beyond +/- 2^32), | ||
154 | but they cancel each other and the real result seems to always fit in a 32-bit | ||
155 | signed integer. This was determined experimentally, not theoretically (unfortunately). */ | ||
156 | tmp1 = silk_MLA_ovflw( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */ | ||
157 | tmp2 = silk_MLA_ovflw( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */ | ||
158 | } | ||
159 | tmp1 = -tmp1; /* Q17 */ | ||
160 | tmp2 = -tmp2; /* Q17 */ | ||
161 | for( k = 0; k <= n; k++ ) { | ||
162 | CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, | ||
163 | silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift ) */ | ||
164 | CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2, | ||
165 | silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift ) */ | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | |||
170 | /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ | ||
171 | tmp1 = C_first_row[ n ]; /* Q( -rshifts ) */ | ||
172 | tmp2 = C_last_row[ n ]; /* Q( -rshifts ) */ | ||
173 | num = 0; /* Q( -rshifts ) */ | ||
174 | nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts ) */ | ||
175 | for( k = 0; k < n; k++ ) { | ||
176 | Atmp_QA = Af_QA[ k ]; | ||
177 | lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; | ||
178 | lz = silk_min( 32 - QA, lz ); | ||
179 | Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz ) */ | ||
180 | |||
181 | tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ | ||
182 | tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ | ||
183 | num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ | ||
184 | nrg = silk_ADD_LSHIFT32( nrg, silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), | ||
185 | Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts ) */ | ||
186 | } | ||
187 | CAf[ n + 1 ] = tmp1; /* Q( -rshifts ) */ | ||
188 | CAb[ n + 1 ] = tmp2; /* Q( -rshifts ) */ | ||
189 | num = silk_ADD32( num, tmp2 ); /* Q( -rshifts ) */ | ||
190 | num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts ) */ | ||
191 | |||
192 | /* Calculate the next order reflection (parcor) coefficient */ | ||
193 | if( silk_abs( num ) < nrg ) { | ||
194 | rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); | ||
195 | } else { | ||
196 | rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN; | ||
197 | } | ||
198 | |||
199 | /* Update inverse prediction gain */ | ||
200 | tmp1 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); | ||
201 | tmp1 = silk_LSHIFT( silk_SMMUL( invGain_Q30, tmp1 ), 2 ); | ||
202 | if( tmp1 <= minInvGain_Q30 ) { | ||
203 | /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ | ||
204 | tmp2 = ( (opus_int32)1 << 30 ) - silk_DIV32_varQ( minInvGain_Q30, invGain_Q30, 30 ); /* Q30 */ | ||
205 | rc_Q31 = silk_SQRT_APPROX( tmp2 ); /* Q15 */ | ||
206 | if( rc_Q31 > 0 ) { | ||
207 | /* Newton-Raphson iteration */ | ||
208 | rc_Q31 = silk_RSHIFT32( rc_Q31 + silk_DIV32( tmp2, rc_Q31 ), 1 ); /* Q15 */ | ||
209 | rc_Q31 = silk_LSHIFT32( rc_Q31, 16 ); /* Q31 */ | ||
210 | if( num < 0 ) { | ||
211 | /* Ensure adjusted reflection coefficients has the original sign */ | ||
212 | rc_Q31 = -rc_Q31; | ||
213 | } | ||
214 | } | ||
215 | invGain_Q30 = minInvGain_Q30; | ||
216 | reached_max_gain = 1; | ||
217 | } else { | ||
218 | invGain_Q30 = tmp1; | ||
219 | } | ||
220 | |||
221 | /* Update the AR coefficients */ | ||
222 | for( k = 0; k < (n + 1) >> 1; k++ ) { | ||
223 | tmp1 = Af_QA[ k ]; /* QA */ | ||
224 | tmp2 = Af_QA[ n - k - 1 ]; /* QA */ | ||
225 | Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA */ | ||
226 | Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA */ | ||
227 | } | ||
228 | Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA */ | ||
229 | |||
230 | if( reached_max_gain ) { | ||
231 | /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ | ||
232 | for( k = n + 1; k < D; k++ ) { | ||
233 | Af_QA[ k ] = 0; | ||
234 | } | ||
235 | break; | ||
236 | } | ||
237 | |||
238 | /* Update C * Af and C * Ab */ | ||
239 | for( k = 0; k <= n + 1; k++ ) { | ||
240 | tmp1 = CAf[ k ]; /* Q( -rshifts ) */ | ||
241 | tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts ) */ | ||
242 | CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts ) */ | ||
243 | CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts ) */ | ||
244 | } | ||
245 | } | ||
246 | |||
247 | if( reached_max_gain ) { | ||
248 | for( k = 0; k < D; k++ ) { | ||
249 | /* Scale coefficients */ | ||
250 | A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); | ||
251 | } | ||
252 | /* Subtract energy of preceding samples from C0 */ | ||
253 | if( rshifts > 0 ) { | ||
254 | for( s = 0; s < nb_subfr; s++ ) { | ||
255 | x_ptr = x + s * subfr_length; | ||
256 | C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D, arch ), rshifts ); | ||
257 | } | ||
258 | } else { | ||
259 | for( s = 0; s < nb_subfr; s++ ) { | ||
260 | x_ptr = x + s * subfr_length; | ||
261 | C0 -= silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr, D, arch), -rshifts); | ||
262 | } | ||
263 | } | ||
264 | /* Approximate residual energy */ | ||
265 | *res_nrg = silk_LSHIFT( silk_SMMUL( invGain_Q30, C0 ), 2 ); | ||
266 | *res_nrg_Q = -rshifts; | ||
267 | } else { | ||
268 | /* Return residual energy */ | ||
269 | nrg = CAf[ 0 ]; /* Q( -rshifts ) */ | ||
270 | tmp1 = (opus_int32)1 << 16; /* Q16 */ | ||
271 | for( k = 0; k < D; k++ ) { | ||
272 | Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16 */ | ||
273 | nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts ) */ | ||
274 | tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16 */ | ||
275 | A_Q16[ k ] = -Atmp1; | ||
276 | } | ||
277 | *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ), -tmp1 );/* Q( -rshifts ) */ | ||
278 | *res_nrg_Q = -rshifts; | ||
279 | } | ||
280 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/corrMatrix_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/corrMatrix_FIX.c new file mode 100644 index 0000000000..1b4a29c232 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/corrMatrix_FIX.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | /********************************************************************** | ||
33 | * Correlation Matrix Computations for LS estimate. | ||
34 | **********************************************************************/ | ||
35 | |||
36 | #include "main_FIX.h" | ||
37 | |||
38 | /* Calculates correlation vector X'*t */ | ||
39 | void silk_corrVector_FIX( | ||
40 | const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ | ||
41 | const opus_int16 *t, /* I Target vector [L] */ | ||
42 | const opus_int L, /* I Length of vectors */ | ||
43 | const opus_int order, /* I Max lag for correlation */ | ||
44 | opus_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */ | ||
45 | const opus_int rshifts, /* I Right shifts of correlations */ | ||
46 | int arch /* I Run-time architecture */ | ||
47 | ) | ||
48 | { | ||
49 | opus_int lag, i; | ||
50 | const opus_int16 *ptr1, *ptr2; | ||
51 | opus_int32 inner_prod; | ||
52 | |||
53 | ptr1 = &x[ order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */ | ||
54 | ptr2 = t; | ||
55 | /* Calculate X'*t */ | ||
56 | if( rshifts > 0 ) { | ||
57 | /* Right shifting used */ | ||
58 | for( lag = 0; lag < order; lag++ ) { | ||
59 | inner_prod = 0; | ||
60 | for( i = 0; i < L; i++ ) { | ||
61 | inner_prod = silk_ADD_RSHIFT32( inner_prod, silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts ); | ||
62 | } | ||
63 | Xt[ lag ] = inner_prod; /* X[:,lag]'*t */ | ||
64 | ptr1--; /* Go to next column of X */ | ||
65 | } | ||
66 | } else { | ||
67 | silk_assert( rshifts == 0 ); | ||
68 | for( lag = 0; lag < order; lag++ ) { | ||
69 | Xt[ lag ] = silk_inner_prod_aligned( ptr1, ptr2, L, arch ); /* X[:,lag]'*t */ | ||
70 | ptr1--; /* Go to next column of X */ | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | |||
75 | /* Calculates correlation matrix X'*X */ | ||
76 | void silk_corrMatrix_FIX( | ||
77 | const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ | ||
78 | const opus_int L, /* I Length of vectors */ | ||
79 | const opus_int order, /* I Max lag for correlation */ | ||
80 | opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */ | ||
81 | opus_int32 *nrg, /* O Energy of x vector */ | ||
82 | opus_int *rshifts, /* O Right shifts of correlations and energy */ | ||
83 | int arch /* I Run-time architecture */ | ||
84 | ) | ||
85 | { | ||
86 | opus_int i, j, lag; | ||
87 | opus_int32 energy; | ||
88 | const opus_int16 *ptr1, *ptr2; | ||
89 | |||
90 | /* Calculate energy to find shift used to fit in 32 bits */ | ||
91 | silk_sum_sqr_shift( nrg, rshifts, x, L + order - 1 ); | ||
92 | energy = *nrg; | ||
93 | |||
94 | /* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */ | ||
95 | /* Remove contribution of first order - 1 samples */ | ||
96 | for( i = 0; i < order - 1; i++ ) { | ||
97 | energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), *rshifts ); | ||
98 | } | ||
99 | |||
100 | /* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */ | ||
101 | /* Fill out the diagonal of the correlation matrix */ | ||
102 | matrix_ptr( XX, 0, 0, order ) = energy; | ||
103 | silk_assert( energy >= 0 ); | ||
104 | ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */ | ||
105 | for( j = 1; j < order; j++ ) { | ||
106 | energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), *rshifts ) ); | ||
107 | energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), *rshifts ) ); | ||
108 | matrix_ptr( XX, j, j, order ) = energy; | ||
109 | silk_assert( energy >= 0 ); | ||
110 | } | ||
111 | |||
112 | ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */ | ||
113 | /* Calculate the remaining elements of the correlation matrix */ | ||
114 | if( *rshifts > 0 ) { | ||
115 | /* Right shifting used */ | ||
116 | for( lag = 1; lag < order; lag++ ) { | ||
117 | /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ | ||
118 | energy = 0; | ||
119 | for( i = 0; i < L; i++ ) { | ||
120 | energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), *rshifts ); | ||
121 | } | ||
122 | /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ | ||
123 | matrix_ptr( XX, lag, 0, order ) = energy; | ||
124 | matrix_ptr( XX, 0, lag, order ) = energy; | ||
125 | for( j = 1; j < ( order - lag ); j++ ) { | ||
126 | energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), *rshifts ) ); | ||
127 | energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), *rshifts ) ); | ||
128 | matrix_ptr( XX, lag + j, j, order ) = energy; | ||
129 | matrix_ptr( XX, j, lag + j, order ) = energy; | ||
130 | } | ||
131 | ptr2--; /* Update pointer to first sample of next column (lag) in X */ | ||
132 | } | ||
133 | } else { | ||
134 | for( lag = 1; lag < order; lag++ ) { | ||
135 | /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ | ||
136 | energy = silk_inner_prod_aligned( ptr1, ptr2, L, arch ); | ||
137 | matrix_ptr( XX, lag, 0, order ) = energy; | ||
138 | matrix_ptr( XX, 0, lag, order ) = energy; | ||
139 | /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ | ||
140 | for( j = 1; j < ( order - lag ); j++ ) { | ||
141 | energy = silk_SUB32( energy, silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ) ); | ||
142 | energy = silk_SMLABB( energy, ptr1[ -j ], ptr2[ -j ] ); | ||
143 | matrix_ptr( XX, lag + j, j, order ) = energy; | ||
144 | matrix_ptr( XX, j, lag + j, order ) = energy; | ||
145 | } | ||
146 | ptr2--;/* Update pointer to first sample of next column (lag) in X */ | ||
147 | } | ||
148 | } | ||
149 | } | ||
150 | |||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/encode_frame_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/encode_frame_FIX.c new file mode 100644 index 0000000000..a02bf87dbb --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/encode_frame_FIX.c | |||
@@ -0,0 +1,448 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include <stdlib.h> | ||
33 | #include "main_FIX.h" | ||
34 | #include "stack_alloc.h" | ||
35 | #include "tuning_parameters.h" | ||
36 | |||
37 | /* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */ | ||
38 | static OPUS_INLINE void silk_LBRR_encode_FIX( | ||
39 | silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ | ||
40 | silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ | ||
41 | const opus_int16 x16[], /* I Input signal */ | ||
42 | opus_int condCoding /* I The type of conditional coding used so far for this frame */ | ||
43 | ); | ||
44 | |||
45 | void silk_encode_do_VAD_FIX( | ||
46 | silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ | ||
47 | opus_int activity /* I Decision of Opus voice activity detector */ | ||
48 | ) | ||
49 | { | ||
50 | const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ); | ||
51 | |||
52 | /****************************/ | ||
53 | /* Voice Activity Detection */ | ||
54 | /****************************/ | ||
55 | silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch ); | ||
56 | /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */ | ||
57 | if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) { | ||
58 | psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1; | ||
59 | } | ||
60 | |||
61 | /**************************************************/ | ||
62 | /* Convert speech activity into VAD and DTX flags */ | ||
63 | /**************************************************/ | ||
64 | if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) { | ||
65 | psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY; | ||
66 | psEnc->sCmn.noSpeechCounter++; | ||
67 | if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) { | ||
68 | psEnc->sCmn.inDTX = 0; | ||
69 | } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) { | ||
70 | psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX; | ||
71 | psEnc->sCmn.inDTX = 0; | ||
72 | } | ||
73 | psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0; | ||
74 | } else { | ||
75 | psEnc->sCmn.noSpeechCounter = 0; | ||
76 | psEnc->sCmn.inDTX = 0; | ||
77 | psEnc->sCmn.indices.signalType = TYPE_UNVOICED; | ||
78 | psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | /****************/ | ||
83 | /* Encode frame */ | ||
84 | /****************/ | ||
85 | opus_int silk_encode_frame_FIX( | ||
86 | silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ | ||
87 | opus_int32 *pnBytesOut, /* O Pointer to number of payload bytes; */ | ||
88 | ec_enc *psRangeEnc, /* I/O compressor data structure */ | ||
89 | opus_int condCoding, /* I The type of conditional coding to use */ | ||
90 | opus_int maxBits, /* I If > 0: maximum number of output bits */ | ||
91 | opus_int useCBR /* I Flag to force constant-bitrate operation */ | ||
92 | ) | ||
93 | { | ||
94 | silk_encoder_control_FIX sEncCtrl; | ||
95 | opus_int i, iter, maxIter, found_upper, found_lower, ret = 0; | ||
96 | opus_int16 *x_frame; | ||
97 | ec_enc sRangeEnc_copy, sRangeEnc_copy2; | ||
98 | silk_nsq_state sNSQ_copy, sNSQ_copy2; | ||
99 | opus_int32 seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper; | ||
100 | opus_int32 gainsID, gainsID_lower, gainsID_upper; | ||
101 | opus_int16 gainMult_Q8; | ||
102 | opus_int16 ec_prevLagIndex_copy; | ||
103 | opus_int ec_prevSignalType_copy; | ||
104 | opus_int8 LastGainIndex_copy2; | ||
105 | opus_int gain_lock[ MAX_NB_SUBFR ] = {0}; | ||
106 | opus_int16 best_gain_mult[ MAX_NB_SUBFR ]; | ||
107 | opus_int best_sum[ MAX_NB_SUBFR ]; | ||
108 | SAVE_STACK; | ||
109 | |||
110 | /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */ | ||
111 | LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0; | ||
112 | |||
113 | psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; | ||
114 | |||
115 | /**************************************************************/ | ||
116 | /* Set up Input Pointers, and insert frame in input buffer */ | ||
117 | /*************************************************************/ | ||
118 | /* start of frame to encode */ | ||
119 | x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; | ||
120 | |||
121 | /***************************************/ | ||
122 | /* Ensure smooth bandwidth transitions */ | ||
123 | /***************************************/ | ||
124 | silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length ); | ||
125 | |||
126 | /*******************************************/ | ||
127 | /* Copy new frame to front of input buffer */ | ||
128 | /*******************************************/ | ||
129 | silk_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); | ||
130 | |||
131 | if( !psEnc->sCmn.prefillFlag ) { | ||
132 | VARDECL( opus_int16, res_pitch ); | ||
133 | VARDECL( opus_uint8, ec_buf_copy ); | ||
134 | opus_int16 *res_pitch_frame; | ||
135 | |||
136 | ALLOC( res_pitch, | ||
137 | psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length | ||
138 | + psEnc->sCmn.ltp_mem_length, opus_int16 ); | ||
139 | /* start of pitch LPC residual frame */ | ||
140 | res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; | ||
141 | |||
142 | /*****************************************/ | ||
143 | /* Find pitch lags, initial LPC analysis */ | ||
144 | /*****************************************/ | ||
145 | silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame - psEnc->sCmn.ltp_mem_length, psEnc->sCmn.arch ); | ||
146 | |||
147 | /************************/ | ||
148 | /* Noise shape analysis */ | ||
149 | /************************/ | ||
150 | silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, psEnc->sCmn.arch ); | ||
151 | |||
152 | /***************************************************/ | ||
153 | /* Find linear prediction coefficients (LPC + LTP) */ | ||
154 | /***************************************************/ | ||
155 | silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding ); | ||
156 | |||
157 | /****************************************/ | ||
158 | /* Process gains */ | ||
159 | /****************************************/ | ||
160 | silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding ); | ||
161 | |||
162 | /****************************************/ | ||
163 | /* Low Bitrate Redundant Encoding */ | ||
164 | /****************************************/ | ||
165 | silk_LBRR_encode_FIX( psEnc, &sEncCtrl, x_frame, condCoding ); | ||
166 | |||
167 | /* Loop over quantizer and entropy coding to control bitrate */ | ||
168 | maxIter = 6; | ||
169 | gainMult_Q8 = SILK_FIX_CONST( 1, 8 ); | ||
170 | found_lower = 0; | ||
171 | found_upper = 0; | ||
172 | gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr ); | ||
173 | gainsID_lower = -1; | ||
174 | gainsID_upper = -1; | ||
175 | /* Copy part of the input state */ | ||
176 | silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) ); | ||
177 | silk_memcpy( &sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); | ||
178 | seed_copy = psEnc->sCmn.indices.Seed; | ||
179 | ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex; | ||
180 | ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType; | ||
181 | ALLOC( ec_buf_copy, 1275, opus_uint8 ); | ||
182 | for( iter = 0; ; iter++ ) { | ||
183 | if( gainsID == gainsID_lower ) { | ||
184 | nBits = nBits_lower; | ||
185 | } else if( gainsID == gainsID_upper ) { | ||
186 | nBits = nBits_upper; | ||
187 | } else { | ||
188 | /* Restore part of the input state */ | ||
189 | if( iter > 0 ) { | ||
190 | silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) ); | ||
191 | silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) ); | ||
192 | psEnc->sCmn.indices.Seed = seed_copy; | ||
193 | psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy; | ||
194 | psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy; | ||
195 | } | ||
196 | |||
197 | /*****************************************/ | ||
198 | /* Noise shaping quantization */ | ||
199 | /*****************************************/ | ||
200 | if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { | ||
201 | silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses, | ||
202 | sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14, | ||
203 | sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14, | ||
204 | psEnc->sCmn.arch ); | ||
205 | } else { | ||
206 | silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses, | ||
207 | sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14, | ||
208 | sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14, | ||
209 | psEnc->sCmn.arch); | ||
210 | } | ||
211 | |||
212 | if ( iter == maxIter && !found_lower ) { | ||
213 | silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) ); | ||
214 | } | ||
215 | |||
216 | /****************************************/ | ||
217 | /* Encode Parameters */ | ||
218 | /****************************************/ | ||
219 | silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding ); | ||
220 | |||
221 | /****************************************/ | ||
222 | /* Encode Excitation Signal */ | ||
223 | /****************************************/ | ||
224 | silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType, | ||
225 | psEnc->sCmn.pulses, psEnc->sCmn.frame_length ); | ||
226 | |||
227 | nBits = ec_tell( psRangeEnc ); | ||
228 | |||
229 | /* If we still bust after the last iteration, do some damage control. */ | ||
230 | if ( iter == maxIter && !found_lower && nBits > maxBits ) { | ||
231 | silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) ); | ||
232 | |||
233 | /* Keep gains the same as the last frame. */ | ||
234 | psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev; | ||
235 | for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { | ||
236 | psEnc->sCmn.indices.GainsIndices[ i ] = 4; | ||
237 | } | ||
238 | if (condCoding != CODE_CONDITIONALLY) { | ||
239 | psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev; | ||
240 | } | ||
241 | psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy; | ||
242 | psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy; | ||
243 | /* Clear all pulses. */ | ||
244 | for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) { | ||
245 | psEnc->sCmn.pulses[ i ] = 0; | ||
246 | } | ||
247 | |||
248 | silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding ); | ||
249 | |||
250 | silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType, | ||
251 | psEnc->sCmn.pulses, psEnc->sCmn.frame_length ); | ||
252 | |||
253 | nBits = ec_tell( psRangeEnc ); | ||
254 | } | ||
255 | |||
256 | if( useCBR == 0 && iter == 0 && nBits <= maxBits ) { | ||
257 | break; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | if( iter == maxIter ) { | ||
262 | if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) { | ||
263 | /* Restore output state from earlier iteration that did meet the bitrate budget */ | ||
264 | silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) ); | ||
265 | celt_assert( sRangeEnc_copy2.offs <= 1275 ); | ||
266 | silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs ); | ||
267 | silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) ); | ||
268 | psEnc->sShape.LastGainIndex = LastGainIndex_copy2; | ||
269 | } | ||
270 | break; | ||
271 | } | ||
272 | |||
273 | if( nBits > maxBits ) { | ||
274 | if( found_lower == 0 && iter >= 2 ) { | ||
275 | /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */ | ||
276 | sEncCtrl.Lambda_Q10 = silk_ADD_RSHIFT32( sEncCtrl.Lambda_Q10, sEncCtrl.Lambda_Q10, 1 ); | ||
277 | found_upper = 0; | ||
278 | gainsID_upper = -1; | ||
279 | } else { | ||
280 | found_upper = 1; | ||
281 | nBits_upper = nBits; | ||
282 | gainMult_upper = gainMult_Q8; | ||
283 | gainsID_upper = gainsID; | ||
284 | } | ||
285 | } else if( nBits < maxBits - 5 ) { | ||
286 | found_lower = 1; | ||
287 | nBits_lower = nBits; | ||
288 | gainMult_lower = gainMult_Q8; | ||
289 | if( gainsID != gainsID_lower ) { | ||
290 | gainsID_lower = gainsID; | ||
291 | /* Copy part of the output state */ | ||
292 | silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) ); | ||
293 | celt_assert( psRangeEnc->offs <= 1275 ); | ||
294 | silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs ); | ||
295 | silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); | ||
296 | LastGainIndex_copy2 = psEnc->sShape.LastGainIndex; | ||
297 | } | ||
298 | } else { | ||
299 | /* Within 5 bits of budget: close enough */ | ||
300 | break; | ||
301 | } | ||
302 | |||
303 | if ( !found_lower && nBits > maxBits ) { | ||
304 | int j; | ||
305 | for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { | ||
306 | int sum=0; | ||
307 | for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) { | ||
308 | sum += abs( psEnc->sCmn.pulses[j] ); | ||
309 | } | ||
310 | if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) { | ||
311 | best_sum[i] = sum; | ||
312 | best_gain_mult[i] = gainMult_Q8; | ||
313 | } else { | ||
314 | gain_lock[i] = 1; | ||
315 | } | ||
316 | } | ||
317 | } | ||
318 | if( ( found_lower & found_upper ) == 0 ) { | ||
319 | /* Adjust gain according to high-rate rate/distortion curve */ | ||
320 | if( nBits > maxBits ) { | ||
321 | if (gainMult_Q8 < 16384) { | ||
322 | gainMult_Q8 *= 2; | ||
323 | } else { | ||
324 | gainMult_Q8 = 32767; | ||
325 | } | ||
326 | } else { | ||
327 | opus_int32 gain_factor_Q16; | ||
328 | gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) ); | ||
329 | gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 ); | ||
330 | } | ||
331 | |||
332 | } else { | ||
333 | /* Adjust gain by interpolating */ | ||
334 | gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower ); | ||
335 | /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */ | ||
336 | if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) { | ||
337 | gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ); | ||
338 | } else | ||
339 | if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) { | ||
340 | gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ); | ||
341 | } | ||
342 | } | ||
343 | |||
344 | for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { | ||
345 | opus_int16 tmp; | ||
346 | if ( gain_lock[i] ) { | ||
347 | tmp = best_gain_mult[i]; | ||
348 | } else { | ||
349 | tmp = gainMult_Q8; | ||
350 | } | ||
351 | sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 ); | ||
352 | } | ||
353 | |||
354 | /* Quantize gains */ | ||
355 | psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev; | ||
356 | silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_Q16, | ||
357 | &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); | ||
358 | |||
359 | /* Unique identifier of gains vector */ | ||
360 | gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr ); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | /* Update input buffer */ | ||
365 | silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], | ||
366 | ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( opus_int16 ) ); | ||
367 | |||
368 | /* Exit without entropy coding */ | ||
369 | if( psEnc->sCmn.prefillFlag ) { | ||
370 | /* No payload */ | ||
371 | *pnBytesOut = 0; | ||
372 | RESTORE_STACK; | ||
373 | return ret; | ||
374 | } | ||
375 | |||
376 | /* Parameters needed for next frame */ | ||
377 | psEnc->sCmn.prevLag = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ]; | ||
378 | psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType; | ||
379 | |||
380 | /****************************************/ | ||
381 | /* Finalize payload */ | ||
382 | /****************************************/ | ||
383 | psEnc->sCmn.first_frame_after_reset = 0; | ||
384 | /* Payload size */ | ||
385 | *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); | ||
386 | |||
387 | RESTORE_STACK; | ||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | /* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */ | ||
392 | static OPUS_INLINE void silk_LBRR_encode_FIX( | ||
393 | silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ | ||
394 | silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ | ||
395 | const opus_int16 x16[], /* I Input signal */ | ||
396 | opus_int condCoding /* I The type of conditional coding used so far for this frame */ | ||
397 | ) | ||
398 | { | ||
399 | opus_int32 TempGains_Q16[ MAX_NB_SUBFR ]; | ||
400 | SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; | ||
401 | silk_nsq_state sNSQ_LBRR; | ||
402 | |||
403 | /*******************************************/ | ||
404 | /* Control use of inband LBRR */ | ||
405 | /*******************************************/ | ||
406 | if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { | ||
407 | psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; | ||
408 | |||
409 | /* Copy noise shaping quantizer state and quantization indices from regular encoding */ | ||
410 | silk_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); | ||
411 | silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); | ||
412 | |||
413 | /* Save original gains */ | ||
414 | silk_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); | ||
415 | |||
416 | if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) { | ||
417 | /* First frame in packet or previous frame not LBRR coded */ | ||
418 | psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; | ||
419 | |||
420 | /* Increase Gains to get target LBRR rate */ | ||
421 | psIndices_LBRR->GainsIndices[ 0 ] = psIndices_LBRR->GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases; | ||
422 | psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 ); | ||
423 | } | ||
424 | |||
425 | /* Decode to get gains in sync with decoder */ | ||
426 | /* Overwrite unquantized gains with quantized gains */ | ||
427 | silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices, | ||
428 | &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); | ||
429 | |||
430 | /*****************************************/ | ||
431 | /* Noise shaping quantization */ | ||
432 | /*****************************************/ | ||
433 | if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { | ||
434 | silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16, | ||
435 | psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, | ||
436 | psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, | ||
437 | psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch ); | ||
438 | } else { | ||
439 | silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16, | ||
440 | psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, | ||
441 | psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, | ||
442 | psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch ); | ||
443 | } | ||
444 | |||
445 | /* Restore original gains */ | ||
446 | silk_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); | ||
447 | } | ||
448 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/find_LPC_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/find_LPC_FIX.c new file mode 100644 index 0000000000..c762a0f2a2 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/find_LPC_FIX.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | #include "stack_alloc.h" | ||
34 | #include "tuning_parameters.h" | ||
35 | |||
36 | /* Finds LPC vector from correlations, and converts to NLSF */ | ||
37 | void silk_find_LPC_FIX( | ||
38 | silk_encoder_state *psEncC, /* I/O Encoder state */ | ||
39 | opus_int16 NLSF_Q15[], /* O NLSFs */ | ||
40 | const opus_int16 x[], /* I Input signal */ | ||
41 | const opus_int32 minInvGain_Q30 /* I Inverse of max prediction gain */ | ||
42 | ) | ||
43 | { | ||
44 | opus_int k, subfr_length; | ||
45 | opus_int32 a_Q16[ MAX_LPC_ORDER ]; | ||
46 | opus_int isInterpLower, shift; | ||
47 | opus_int32 res_nrg0, res_nrg1; | ||
48 | opus_int rshift0, rshift1; | ||
49 | |||
50 | /* Used only for LSF interpolation */ | ||
51 | opus_int32 a_tmp_Q16[ MAX_LPC_ORDER ], res_nrg_interp, res_nrg, res_tmp_nrg; | ||
52 | opus_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q; | ||
53 | opus_int16 a_tmp_Q12[ MAX_LPC_ORDER ]; | ||
54 | opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; | ||
55 | SAVE_STACK; | ||
56 | |||
57 | subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder; | ||
58 | |||
59 | /* Default: no interpolation */ | ||
60 | psEncC->indices.NLSFInterpCoef_Q2 = 4; | ||
61 | |||
62 | /* Burg AR analysis for the full frame */ | ||
63 | silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, minInvGain_Q30, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder, psEncC->arch ); | ||
64 | |||
65 | if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) { | ||
66 | VARDECL( opus_int16, LPC_res ); | ||
67 | |||
68 | /* Optimal solution for last 10 ms */ | ||
69 | silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + 2 * subfr_length, minInvGain_Q30, subfr_length, 2, psEncC->predictLPCOrder, psEncC->arch ); | ||
70 | |||
71 | /* subtract residual energy here, as that's easier than adding it to the */ | ||
72 | /* residual energy of the first 10 ms in each iteration of the search below */ | ||
73 | shift = res_tmp_nrg_Q - res_nrg_Q; | ||
74 | if( shift >= 0 ) { | ||
75 | if( shift < 32 ) { | ||
76 | res_nrg = res_nrg - silk_RSHIFT( res_tmp_nrg, shift ); | ||
77 | } | ||
78 | } else { | ||
79 | silk_assert( shift > -32 ); | ||
80 | res_nrg = silk_RSHIFT( res_nrg, -shift ) - res_tmp_nrg; | ||
81 | res_nrg_Q = res_tmp_nrg_Q; | ||
82 | } | ||
83 | |||
84 | /* Convert to NLSFs */ | ||
85 | silk_A2NLSF( NLSF_Q15, a_tmp_Q16, psEncC->predictLPCOrder ); | ||
86 | |||
87 | ALLOC( LPC_res, 2 * subfr_length, opus_int16 ); | ||
88 | |||
89 | /* Search over interpolation indices to find the one with lowest residual energy */ | ||
90 | for( k = 3; k >= 0; k-- ) { | ||
91 | /* Interpolate NLSFs for first half */ | ||
92 | silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder ); | ||
93 | |||
94 | /* Convert to LPC for residual energy evaluation */ | ||
95 | silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch ); | ||
96 | |||
97 | /* Calculate residual energy with NLSF interpolation */ | ||
98 | silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder, psEncC->arch ); | ||
99 | |||
100 | silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + psEncC->predictLPCOrder, subfr_length - psEncC->predictLPCOrder ); | ||
101 | silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ); | ||
102 | |||
103 | /* Add subframe energies from first half frame */ | ||
104 | shift = rshift0 - rshift1; | ||
105 | if( shift >= 0 ) { | ||
106 | res_nrg1 = silk_RSHIFT( res_nrg1, shift ); | ||
107 | res_nrg_interp_Q = -rshift0; | ||
108 | } else { | ||
109 | res_nrg0 = silk_RSHIFT( res_nrg0, -shift ); | ||
110 | res_nrg_interp_Q = -rshift1; | ||
111 | } | ||
112 | res_nrg_interp = silk_ADD32( res_nrg0, res_nrg1 ); | ||
113 | |||
114 | /* Compare with first half energy without NLSF interpolation, or best interpolated value so far */ | ||
115 | shift = res_nrg_interp_Q - res_nrg_Q; | ||
116 | if( shift >= 0 ) { | ||
117 | if( silk_RSHIFT( res_nrg_interp, shift ) < res_nrg ) { | ||
118 | isInterpLower = silk_TRUE; | ||
119 | } else { | ||
120 | isInterpLower = silk_FALSE; | ||
121 | } | ||
122 | } else { | ||
123 | if( -shift < 32 ) { | ||
124 | if( res_nrg_interp < silk_RSHIFT( res_nrg, -shift ) ) { | ||
125 | isInterpLower = silk_TRUE; | ||
126 | } else { | ||
127 | isInterpLower = silk_FALSE; | ||
128 | } | ||
129 | } else { | ||
130 | isInterpLower = silk_FALSE; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | /* Determine whether current interpolated NLSFs are best so far */ | ||
135 | if( isInterpLower == silk_TRUE ) { | ||
136 | /* Interpolation has lower residual energy */ | ||
137 | res_nrg = res_nrg_interp; | ||
138 | res_nrg_Q = res_nrg_interp_Q; | ||
139 | psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k; | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | |||
144 | if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) { | ||
145 | /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ | ||
146 | silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder ); | ||
147 | } | ||
148 | |||
149 | celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) ); | ||
150 | RESTORE_STACK; | ||
151 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/find_LTP_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/find_LTP_FIX.c new file mode 100644 index 0000000000..62d4afb250 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/find_LTP_FIX.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | #include "tuning_parameters.h" | ||
34 | |||
35 | void silk_find_LTP_FIX( | ||
36 | opus_int32 XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Correlation matrix */ | ||
37 | opus_int32 xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ], /* O Correlation vector */ | ||
38 | const opus_int16 r_ptr[], /* I Residual signal after LPC */ | ||
39 | const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ | ||
40 | const opus_int subfr_length, /* I Subframe length */ | ||
41 | const opus_int nb_subfr, /* I Number of subframes */ | ||
42 | int arch /* I Run-time architecture */ | ||
43 | ) | ||
44 | { | ||
45 | opus_int i, k, extra_shifts; | ||
46 | opus_int xx_shifts, xX_shifts, XX_shifts; | ||
47 | const opus_int16 *lag_ptr; | ||
48 | opus_int32 *XXLTP_Q17_ptr, *xXLTP_Q17_ptr; | ||
49 | opus_int32 xx, nrg, temp; | ||
50 | |||
51 | xXLTP_Q17_ptr = xXLTP_Q17; | ||
52 | XXLTP_Q17_ptr = XXLTP_Q17; | ||
53 | for( k = 0; k < nb_subfr; k++ ) { | ||
54 | lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 ); | ||
55 | |||
56 | silk_sum_sqr_shift( &xx, &xx_shifts, r_ptr, subfr_length + LTP_ORDER ); /* xx in Q( -xx_shifts ) */ | ||
57 | silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, XXLTP_Q17_ptr, &nrg, &XX_shifts, arch ); /* XXLTP_Q17_ptr and nrg in Q( -XX_shifts ) */ | ||
58 | extra_shifts = xx_shifts - XX_shifts; | ||
59 | if( extra_shifts > 0 ) { | ||
60 | /* Shift XX */ | ||
61 | xX_shifts = xx_shifts; | ||
62 | for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) { | ||
63 | XXLTP_Q17_ptr[ i ] = silk_RSHIFT32( XXLTP_Q17_ptr[ i ], extra_shifts ); /* Q( -xX_shifts ) */ | ||
64 | } | ||
65 | nrg = silk_RSHIFT32( nrg, extra_shifts ); /* Q( -xX_shifts ) */ | ||
66 | } else if( extra_shifts < 0 ) { | ||
67 | /* Shift xx */ | ||
68 | xX_shifts = XX_shifts; | ||
69 | xx = silk_RSHIFT32( xx, -extra_shifts ); /* Q( -xX_shifts ) */ | ||
70 | } else { | ||
71 | xX_shifts = xx_shifts; | ||
72 | } | ||
73 | silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xXLTP_Q17_ptr, xX_shifts, arch ); /* xXLTP_Q17_ptr in Q( -xX_shifts ) */ | ||
74 | |||
75 | /* At this point all correlations are in Q(-xX_shifts) */ | ||
76 | temp = silk_SMLAWB( 1, nrg, SILK_FIX_CONST( LTP_CORR_INV_MAX, 16 ) ); | ||
77 | temp = silk_max( temp, xx ); | ||
78 | TIC(div) | ||
79 | #if 0 | ||
80 | for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) { | ||
81 | XXLTP_Q17_ptr[ i ] = silk_DIV32_varQ( XXLTP_Q17_ptr[ i ], temp, 17 ); | ||
82 | } | ||
83 | for( i = 0; i < LTP_ORDER; i++ ) { | ||
84 | xXLTP_Q17_ptr[ i ] = silk_DIV32_varQ( xXLTP_Q17_ptr[ i ], temp, 17 ); | ||
85 | } | ||
86 | #else | ||
87 | for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) { | ||
88 | XXLTP_Q17_ptr[ i ] = (opus_int32)( silk_LSHIFT64( (opus_int64)XXLTP_Q17_ptr[ i ], 17 ) / temp ); | ||
89 | } | ||
90 | for( i = 0; i < LTP_ORDER; i++ ) { | ||
91 | xXLTP_Q17_ptr[ i ] = (opus_int32)( silk_LSHIFT64( (opus_int64)xXLTP_Q17_ptr[ i ], 17 ) / temp ); | ||
92 | } | ||
93 | #endif | ||
94 | TOC(div) | ||
95 | r_ptr += subfr_length; | ||
96 | XXLTP_Q17_ptr += LTP_ORDER * LTP_ORDER; | ||
97 | xXLTP_Q17_ptr += LTP_ORDER; | ||
98 | } | ||
99 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/find_pitch_lags_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/find_pitch_lags_FIX.c new file mode 100644 index 0000000000..6c3379f2bb --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/find_pitch_lags_FIX.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | #include "stack_alloc.h" | ||
34 | #include "tuning_parameters.h" | ||
35 | |||
36 | /* Find pitch lags */ | ||
37 | void silk_find_pitch_lags_FIX( | ||
38 | silk_encoder_state_FIX *psEnc, /* I/O encoder state */ | ||
39 | silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ | ||
40 | opus_int16 res[], /* O residual */ | ||
41 | const opus_int16 x[], /* I Speech signal */ | ||
42 | int arch /* I Run-time architecture */ | ||
43 | ) | ||
44 | { | ||
45 | opus_int buf_len, i, scale; | ||
46 | opus_int32 thrhld_Q13, res_nrg; | ||
47 | const opus_int16 *x_ptr; | ||
48 | VARDECL( opus_int16, Wsig ); | ||
49 | opus_int16 *Wsig_ptr; | ||
50 | opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; | ||
51 | opus_int16 rc_Q15[ MAX_FIND_PITCH_LPC_ORDER ]; | ||
52 | opus_int32 A_Q24[ MAX_FIND_PITCH_LPC_ORDER ]; | ||
53 | opus_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; | ||
54 | SAVE_STACK; | ||
55 | |||
56 | /******************************************/ | ||
57 | /* Set up buffer lengths etc based on Fs */ | ||
58 | /******************************************/ | ||
59 | buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; | ||
60 | |||
61 | /* Safety check */ | ||
62 | celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); | ||
63 | |||
64 | /*************************************/ | ||
65 | /* Estimate LPC AR coefficients */ | ||
66 | /*************************************/ | ||
67 | |||
68 | /* Calculate windowed signal */ | ||
69 | |||
70 | ALLOC( Wsig, psEnc->sCmn.pitch_LPC_win_length, opus_int16 ); | ||
71 | |||
72 | /* First LA_LTP samples */ | ||
73 | x_ptr = x + buf_len - psEnc->sCmn.pitch_LPC_win_length; | ||
74 | Wsig_ptr = Wsig; | ||
75 | silk_apply_sine_window( Wsig_ptr, x_ptr, 1, psEnc->sCmn.la_pitch ); | ||
76 | |||
77 | /* Middle un - windowed samples */ | ||
78 | Wsig_ptr += psEnc->sCmn.la_pitch; | ||
79 | x_ptr += psEnc->sCmn.la_pitch; | ||
80 | silk_memcpy( Wsig_ptr, x_ptr, ( psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) ); | ||
81 | |||
82 | /* Last LA_LTP samples */ | ||
83 | Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ); | ||
84 | x_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ); | ||
85 | silk_apply_sine_window( Wsig_ptr, x_ptr, 2, psEnc->sCmn.la_pitch ); | ||
86 | |||
87 | /* Calculate autocorrelation sequence */ | ||
88 | silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1, arch ); | ||
89 | |||
90 | /* Add white noise, as fraction of energy */ | ||
91 | auto_corr[ 0 ] = silk_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ) + 1; | ||
92 | |||
93 | /* Calculate the reflection coefficients using schur */ | ||
94 | res_nrg = silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); | ||
95 | |||
96 | /* Prediction gain */ | ||
97 | psEncCtrl->predGain_Q16 = silk_DIV32_varQ( auto_corr[ 0 ], silk_max_int( res_nrg, 1 ), 16 ); | ||
98 | |||
99 | /* Convert reflection coefficients to prediction coefficients */ | ||
100 | silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder ); | ||
101 | |||
102 | /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ | ||
103 | for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { | ||
104 | A_Q12[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT( A_Q24[ i ], 12 ) ); | ||
105 | } | ||
106 | |||
107 | /* Do BWE */ | ||
108 | silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWIDTH_EXPANSION, 16 ) ); | ||
109 | |||
110 | /*****************************************/ | ||
111 | /* LPC analysis filtering */ | ||
112 | /*****************************************/ | ||
113 | silk_LPC_analysis_filter( res, x, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch ); | ||
114 | |||
115 | if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) { | ||
116 | /* Threshold for pitch estimator */ | ||
117 | thrhld_Q13 = SILK_FIX_CONST( 0.6, 13 ); | ||
118 | thrhld_Q13 = silk_SMLABB( thrhld_Q13, SILK_FIX_CONST( -0.004, 13 ), psEnc->sCmn.pitchEstimationLPCOrder ); | ||
119 | thrhld_Q13 = silk_SMLAWB( thrhld_Q13, SILK_FIX_CONST( -0.1, 21 ), psEnc->sCmn.speech_activity_Q8 ); | ||
120 | thrhld_Q13 = silk_SMLABB( thrhld_Q13, SILK_FIX_CONST( -0.15, 13 ), silk_RSHIFT( psEnc->sCmn.prevSignalType, 1 ) ); | ||
121 | thrhld_Q13 = silk_SMLAWB( thrhld_Q13, SILK_FIX_CONST( -0.1, 14 ), psEnc->sCmn.input_tilt_Q15 ); | ||
122 | thrhld_Q13 = silk_SAT16( thrhld_Q13 ); | ||
123 | |||
124 | /*****************************************/ | ||
125 | /* Call pitch estimator */ | ||
126 | /*****************************************/ | ||
127 | if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, | ||
128 | &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16, | ||
129 | (opus_int)thrhld_Q13, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr, | ||
130 | psEnc->sCmn.arch) == 0 ) | ||
131 | { | ||
132 | psEnc->sCmn.indices.signalType = TYPE_VOICED; | ||
133 | } else { | ||
134 | psEnc->sCmn.indices.signalType = TYPE_UNVOICED; | ||
135 | } | ||
136 | } else { | ||
137 | silk_memset( psEncCtrl->pitchL, 0, sizeof( psEncCtrl->pitchL ) ); | ||
138 | psEnc->sCmn.indices.lagIndex = 0; | ||
139 | psEnc->sCmn.indices.contourIndex = 0; | ||
140 | psEnc->LTPCorr_Q15 = 0; | ||
141 | } | ||
142 | RESTORE_STACK; | ||
143 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/find_pred_coefs_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/find_pred_coefs_FIX.c new file mode 100644 index 0000000000..606d863347 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/find_pred_coefs_FIX.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | #include "stack_alloc.h" | ||
34 | |||
35 | void silk_find_pred_coefs_FIX( | ||
36 | silk_encoder_state_FIX *psEnc, /* I/O encoder state */ | ||
37 | silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ | ||
38 | const opus_int16 res_pitch[], /* I Residual from pitch analysis */ | ||
39 | const opus_int16 x[], /* I Speech signal */ | ||
40 | opus_int condCoding /* I The type of conditional coding to use */ | ||
41 | ) | ||
42 | { | ||
43 | opus_int i; | ||
44 | opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ]; | ||
45 | opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; | ||
46 | const opus_int16 *x_ptr; | ||
47 | opus_int16 *x_pre_ptr; | ||
48 | VARDECL( opus_int16, LPC_in_pre ); | ||
49 | opus_int32 min_gain_Q16, minInvGain_Q30; | ||
50 | SAVE_STACK; | ||
51 | |||
52 | /* weighting for weighted least squares */ | ||
53 | min_gain_Q16 = silk_int32_MAX >> 6; | ||
54 | for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { | ||
55 | min_gain_Q16 = silk_min( min_gain_Q16, psEncCtrl->Gains_Q16[ i ] ); | ||
56 | } | ||
57 | for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { | ||
58 | /* Divide to Q16 */ | ||
59 | silk_assert( psEncCtrl->Gains_Q16[ i ] > 0 ); | ||
60 | /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */ | ||
61 | invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 ); | ||
62 | |||
63 | /* Limit inverse */ | ||
64 | invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 100 ); | ||
65 | |||
66 | /* Square the inverted gains */ | ||
67 | silk_assert( invGains_Q16[ i ] == silk_SAT16( invGains_Q16[ i ] ) ); | ||
68 | |||
69 | /* Invert the inverted and normalized gains */ | ||
70 | local_gains[ i ] = silk_DIV32( ( (opus_int32)1 << 16 ), invGains_Q16[ i ] ); | ||
71 | } | ||
72 | |||
73 | ALLOC( LPC_in_pre, | ||
74 | psEnc->sCmn.nb_subfr * psEnc->sCmn.predictLPCOrder | ||
75 | + psEnc->sCmn.frame_length, opus_int16 ); | ||
76 | if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
77 | VARDECL( opus_int32, xXLTP_Q17 ); | ||
78 | VARDECL( opus_int32, XXLTP_Q17 ); | ||
79 | |||
80 | /**********/ | ||
81 | /* VOICED */ | ||
82 | /**********/ | ||
83 | celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); | ||
84 | |||
85 | ALLOC( xXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER, opus_int32 ); | ||
86 | ALLOC( XXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 ); | ||
87 | |||
88 | /* LTP analysis */ | ||
89 | silk_find_LTP_FIX( XXLTP_Q17, xXLTP_Q17, res_pitch, | ||
90 | psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch ); | ||
91 | |||
92 | /* Quantize LTP gain parameters */ | ||
93 | silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex, | ||
94 | &psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain_Q7, XXLTP_Q17, xXLTP_Q17, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch ); | ||
95 | |||
96 | /* Control LTP scaling */ | ||
97 | silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl, condCoding ); | ||
98 | |||
99 | /* Create LTP residual */ | ||
100 | silk_LTP_analysis_filter_FIX( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef_Q14, | ||
101 | psEncCtrl->pitchL, invGains_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); | ||
102 | |||
103 | } else { | ||
104 | /************/ | ||
105 | /* UNVOICED */ | ||
106 | /************/ | ||
107 | /* Create signal with prepended subframes, scaled by inverse gains */ | ||
108 | x_ptr = x - psEnc->sCmn.predictLPCOrder; | ||
109 | x_pre_ptr = LPC_in_pre; | ||
110 | for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { | ||
111 | silk_scale_copy_vector16( x_pre_ptr, x_ptr, invGains_Q16[ i ], | ||
112 | psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder ); | ||
113 | x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; | ||
114 | x_ptr += psEnc->sCmn.subfr_length; | ||
115 | } | ||
116 | |||
117 | silk_memset( psEncCtrl->LTPCoef_Q14, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( opus_int16 ) ); | ||
118 | psEncCtrl->LTPredCodGain_Q7 = 0; | ||
119 | psEnc->sCmn.sum_log_gain_Q7 = 0; | ||
120 | } | ||
121 | |||
122 | /* Limit on total predictive coding gain */ | ||
123 | if( psEnc->sCmn.first_frame_after_reset ) { | ||
124 | minInvGain_Q30 = SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET, 30 ); | ||
125 | } else { | ||
126 | minInvGain_Q30 = silk_log2lin( silk_SMLAWB( 16 << 7, (opus_int32)psEncCtrl->LTPredCodGain_Q7, SILK_FIX_CONST( 1.0 / 3, 16 ) ) ); /* Q16 */ | ||
127 | minInvGain_Q30 = silk_DIV32_varQ( minInvGain_Q30, | ||
128 | silk_SMULWW( SILK_FIX_CONST( MAX_PREDICTION_POWER_GAIN, 0 ), | ||
129 | silk_SMLAWB( SILK_FIX_CONST( 0.25, 18 ), SILK_FIX_CONST( 0.75, 18 ), psEncCtrl->coding_quality_Q14 ) ), 14 ); | ||
130 | } | ||
131 | |||
132 | /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ | ||
133 | silk_find_LPC_FIX( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain_Q30 ); | ||
134 | |||
135 | /* Quantize LSFs */ | ||
136 | silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); | ||
137 | |||
138 | /* Calculate residual energy using quantized LPC coefficients */ | ||
139 | silk_residual_energy_FIX( psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, psEncCtrl->PredCoef_Q12, local_gains, | ||
140 | psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder, psEnc->sCmn.arch ); | ||
141 | |||
142 | /* Copy to prediction struct for use in next frame for interpolation */ | ||
143 | silk_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); | ||
144 | RESTORE_STACK; | ||
145 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/k2a_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/k2a_FIX.c new file mode 100644 index 0000000000..549f6eadaa --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/k2a_FIX.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "SigProc_FIX.h" | ||
33 | |||
34 | /* Step up function, converts reflection coefficients to prediction coefficients */ | ||
35 | void silk_k2a( | ||
36 | opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */ | ||
37 | const opus_int16 *rc_Q15, /* I Reflection coefficients [order] Q15 */ | ||
38 | const opus_int32 order /* I Prediction order */ | ||
39 | ) | ||
40 | { | ||
41 | opus_int k, n; | ||
42 | opus_int32 rc, tmp1, tmp2; | ||
43 | |||
44 | for( k = 0; k < order; k++ ) { | ||
45 | rc = rc_Q15[ k ]; | ||
46 | for( n = 0; n < (k + 1) >> 1; n++ ) { | ||
47 | tmp1 = A_Q24[ n ]; | ||
48 | tmp2 = A_Q24[ k - n - 1 ]; | ||
49 | A_Q24[ n ] = silk_SMLAWB( tmp1, silk_LSHIFT( tmp2, 1 ), rc ); | ||
50 | A_Q24[ k - n - 1 ] = silk_SMLAWB( tmp2, silk_LSHIFT( tmp1, 1 ), rc ); | ||
51 | } | ||
52 | A_Q24[ k ] = -silk_LSHIFT( (opus_int32)rc_Q15[ k ], 9 ); | ||
53 | } | ||
54 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/k2a_Q16_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/k2a_Q16_FIX.c new file mode 100644 index 0000000000..1595aa6212 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/k2a_Q16_FIX.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "SigProc_FIX.h" | ||
33 | |||
34 | /* Step up function, converts reflection coefficients to prediction coefficients */ | ||
35 | void silk_k2a_Q16( | ||
36 | opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */ | ||
37 | const opus_int32 *rc_Q16, /* I Reflection coefficients [order] Q16 */ | ||
38 | const opus_int32 order /* I Prediction order */ | ||
39 | ) | ||
40 | { | ||
41 | opus_int k, n; | ||
42 | opus_int32 rc, tmp1, tmp2; | ||
43 | |||
44 | for( k = 0; k < order; k++ ) { | ||
45 | rc = rc_Q16[ k ]; | ||
46 | for( n = 0; n < (k + 1) >> 1; n++ ) { | ||
47 | tmp1 = A_Q24[ n ]; | ||
48 | tmp2 = A_Q24[ k - n - 1 ]; | ||
49 | A_Q24[ n ] = silk_SMLAWW( tmp1, tmp2, rc ); | ||
50 | A_Q24[ k - n - 1 ] = silk_SMLAWW( tmp2, tmp1, rc ); | ||
51 | } | ||
52 | A_Q24[ k ] = -silk_LSHIFT( rc, 8 ); | ||
53 | } | ||
54 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/main_FIX.h b/lib/rbcodec/codecs/libopus/silk/fixed/main_FIX.h new file mode 100644 index 0000000000..6d2112e511 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/main_FIX.h | |||
@@ -0,0 +1,244 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifndef SILK_MAIN_FIX_H | ||
29 | #define SILK_MAIN_FIX_H | ||
30 | |||
31 | #include "SigProc_FIX.h" | ||
32 | #include "structs_FIX.h" | ||
33 | #include "control.h" | ||
34 | #include "main.h" | ||
35 | #include "PLC.h" | ||
36 | #include "debug.h" | ||
37 | #include "entenc.h" | ||
38 | |||
39 | #if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \ | ||
40 | || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)) | ||
41 | #include "fixed/arm/warped_autocorrelation_FIX_arm.h" | ||
42 | #endif | ||
43 | |||
44 | #ifndef FORCE_CPP_BUILD | ||
45 | #ifdef __cplusplus | ||
46 | extern "C" | ||
47 | { | ||
48 | #endif | ||
49 | #endif | ||
50 | |||
51 | #define silk_encoder_state_Fxx silk_encoder_state_FIX | ||
52 | #define silk_encode_do_VAD_Fxx silk_encode_do_VAD_FIX | ||
53 | #define silk_encode_frame_Fxx silk_encode_frame_FIX | ||
54 | |||
55 | #define QC 10 | ||
56 | #define QS 13 | ||
57 | |||
58 | /*********************/ | ||
59 | /* Encoder Functions */ | ||
60 | /*********************/ | ||
61 | |||
62 | /* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ | ||
63 | void silk_HP_variable_cutoff( | ||
64 | silk_encoder_state_Fxx state_Fxx[] /* I/O Encoder states */ | ||
65 | ); | ||
66 | |||
67 | /* Encoder main function */ | ||
68 | void silk_encode_do_VAD_FIX( | ||
69 | silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ | ||
70 | opus_int activity /* I Decision of Opus voice activity detector */ | ||
71 | ); | ||
72 | |||
73 | /* Encoder main function */ | ||
74 | opus_int silk_encode_frame_FIX( | ||
75 | silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ | ||
76 | opus_int32 *pnBytesOut, /* O Pointer to number of payload bytes; */ | ||
77 | ec_enc *psRangeEnc, /* I/O compressor data structure */ | ||
78 | opus_int condCoding, /* I The type of conditional coding to use */ | ||
79 | opus_int maxBits, /* I If > 0: maximum number of output bits */ | ||
80 | opus_int useCBR /* I Flag to force constant-bitrate operation */ | ||
81 | ); | ||
82 | |||
83 | /* Initializes the Silk encoder state */ | ||
84 | opus_int silk_init_encoder( | ||
85 | silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk FIX encoder state */ | ||
86 | int arch /* I Run-time architecture */ | ||
87 | ); | ||
88 | |||
89 | /* Control the Silk encoder */ | ||
90 | opus_int silk_control_encoder( | ||
91 | silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */ | ||
92 | silk_EncControlStruct *encControl, /* I Control structure */ | ||
93 | const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */ | ||
94 | const opus_int channelNb, /* I Channel number */ | ||
95 | const opus_int force_fs_kHz | ||
96 | ); | ||
97 | |||
98 | /**************************/ | ||
99 | /* Noise shaping analysis */ | ||
100 | /**************************/ | ||
101 | /* Compute noise shaping coefficients and initial gain values */ | ||
102 | void silk_noise_shape_analysis_FIX( | ||
103 | silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ | ||
104 | silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ | ||
105 | const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ | ||
106 | const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */ | ||
107 | int arch /* I Run-time architecture */ | ||
108 | ); | ||
109 | |||
110 | /* Autocorrelations for a warped frequency axis */ | ||
111 | void silk_warped_autocorrelation_FIX_c( | ||
112 | opus_int32 *corr, /* O Result [order + 1] */ | ||
113 | opus_int *scale, /* O Scaling of the correlation vector */ | ||
114 | const opus_int16 *input, /* I Input data to correlate */ | ||
115 | const opus_int warping_Q16, /* I Warping coefficient */ | ||
116 | const opus_int length, /* I Length of input */ | ||
117 | const opus_int order /* I Correlation order (even) */ | ||
118 | ); | ||
119 | |||
120 | #if !defined(OVERRIDE_silk_warped_autocorrelation_FIX) | ||
121 | #define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \ | ||
122 | ((void)(arch), silk_warped_autocorrelation_FIX_c(corr, scale, input, warping_Q16, length, order)) | ||
123 | #endif | ||
124 | |||
125 | /* Calculation of LTP state scaling */ | ||
126 | void silk_LTP_scale_ctrl_FIX( | ||
127 | silk_encoder_state_FIX *psEnc, /* I/O encoder state */ | ||
128 | silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ | ||
129 | opus_int condCoding /* I The type of conditional coding to use */ | ||
130 | ); | ||
131 | |||
132 | /**********************************************/ | ||
133 | /* Prediction Analysis */ | ||
134 | /**********************************************/ | ||
135 | /* Find pitch lags */ | ||
136 | void silk_find_pitch_lags_FIX( | ||
137 | silk_encoder_state_FIX *psEnc, /* I/O encoder state */ | ||
138 | silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ | ||
139 | opus_int16 res[], /* O residual */ | ||
140 | const opus_int16 x[], /* I Speech signal */ | ||
141 | int arch /* I Run-time architecture */ | ||
142 | ); | ||
143 | |||
144 | /* Find LPC and LTP coefficients */ | ||
145 | void silk_find_pred_coefs_FIX( | ||
146 | silk_encoder_state_FIX *psEnc, /* I/O encoder state */ | ||
147 | silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ | ||
148 | const opus_int16 res_pitch[], /* I Residual from pitch analysis */ | ||
149 | const opus_int16 x[], /* I Speech signal */ | ||
150 | opus_int condCoding /* I The type of conditional coding to use */ | ||
151 | ); | ||
152 | |||
153 | /* LPC analysis */ | ||
154 | void silk_find_LPC_FIX( | ||
155 | silk_encoder_state *psEncC, /* I/O Encoder state */ | ||
156 | opus_int16 NLSF_Q15[], /* O NLSFs */ | ||
157 | const opus_int16 x[], /* I Input signal */ | ||
158 | const opus_int32 minInvGain_Q30 /* I Inverse of max prediction gain */ | ||
159 | ); | ||
160 | |||
161 | /* LTP analysis */ | ||
162 | void silk_find_LTP_FIX( | ||
163 | opus_int32 XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Correlation matrix */ | ||
164 | opus_int32 xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ], /* O Correlation vector */ | ||
165 | const opus_int16 r_lpc[], /* I Residual signal after LPC */ | ||
166 | const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ | ||
167 | const opus_int subfr_length, /* I Subframe length */ | ||
168 | const opus_int nb_subfr, /* I Number of subframes */ | ||
169 | int arch /* I Run-time architecture */ | ||
170 | ); | ||
171 | |||
172 | void silk_LTP_analysis_filter_FIX( | ||
173 | opus_int16 *LTP_res, /* O LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */ | ||
174 | const opus_int16 *x, /* I Pointer to input signal with at least max( pitchL ) preceding samples */ | ||
175 | const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */ | ||
176 | const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag, one for each subframe */ | ||
177 | const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I Inverse quantization gains, one for each subframe */ | ||
178 | const opus_int subfr_length, /* I Length of each subframe */ | ||
179 | const opus_int nb_subfr, /* I Number of subframes */ | ||
180 | const opus_int pre_length /* I Length of the preceding samples starting at &x[0] for each subframe */ | ||
181 | ); | ||
182 | |||
183 | /* Calculates residual energies of input subframes where all subframes have LPC_order */ | ||
184 | /* of preceding samples */ | ||
185 | void silk_residual_energy_FIX( | ||
186 | opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ | ||
187 | opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ | ||
188 | const opus_int16 x[], /* I Input signal */ | ||
189 | opus_int16 a_Q12[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ | ||
190 | const opus_int32 gains[ MAX_NB_SUBFR ], /* I Quantization gains */ | ||
191 | const opus_int subfr_length, /* I Subframe length */ | ||
192 | const opus_int nb_subfr, /* I Number of subframes */ | ||
193 | const opus_int LPC_order, /* I LPC order */ | ||
194 | int arch /* I Run-time architecture */ | ||
195 | ); | ||
196 | |||
197 | /* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ | ||
198 | opus_int32 silk_residual_energy16_covar_FIX( | ||
199 | const opus_int16 *c, /* I Prediction vector */ | ||
200 | const opus_int32 *wXX, /* I Correlation matrix */ | ||
201 | const opus_int32 *wXx, /* I Correlation vector */ | ||
202 | opus_int32 wxx, /* I Signal energy */ | ||
203 | opus_int D, /* I Dimension */ | ||
204 | opus_int cQ /* I Q value for c vector 0 - 15 */ | ||
205 | ); | ||
206 | |||
207 | /* Processing of gains */ | ||
208 | void silk_process_gains_FIX( | ||
209 | silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ | ||
210 | silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control */ | ||
211 | opus_int condCoding /* I The type of conditional coding to use */ | ||
212 | ); | ||
213 | |||
214 | /******************/ | ||
215 | /* Linear Algebra */ | ||
216 | /******************/ | ||
217 | /* Calculates correlation matrix X'*X */ | ||
218 | void silk_corrMatrix_FIX( | ||
219 | const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ | ||
220 | const opus_int L, /* I Length of vectors */ | ||
221 | const opus_int order, /* I Max lag for correlation */ | ||
222 | opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */ | ||
223 | opus_int32 *nrg, /* O Energy of x vector */ | ||
224 | opus_int *rshifts, /* O Right shifts of correlations */ | ||
225 | int arch /* I Run-time architecture */ | ||
226 | ); | ||
227 | |||
228 | /* Calculates correlation vector X'*t */ | ||
229 | void silk_corrVector_FIX( | ||
230 | const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ | ||
231 | const opus_int16 *t, /* I Target vector [L] */ | ||
232 | const opus_int L, /* I Length of vectors */ | ||
233 | const opus_int order, /* I Max lag for correlation */ | ||
234 | opus_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */ | ||
235 | const opus_int rshifts, /* I Right shifts of correlations */ | ||
236 | int arch /* I Run-time architecture */ | ||
237 | ); | ||
238 | |||
239 | #ifndef FORCE_CPP_BUILD | ||
240 | #ifdef __cplusplus | ||
241 | } | ||
242 | #endif /* __cplusplus */ | ||
243 | #endif /* FORCE_CPP_BUILD */ | ||
244 | #endif /* SILK_MAIN_FIX_H */ | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h b/lib/rbcodec/codecs/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h new file mode 100644 index 0000000000..3999b5bd09 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h | |||
@@ -0,0 +1,336 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | |||
29 | /**************************************************************/ | ||
30 | /* Compute noise shaping coefficients and initial gain values */ | ||
31 | /**************************************************************/ | ||
32 | #define OVERRIDE_silk_noise_shape_analysis_FIX | ||
33 | |||
34 | void silk_noise_shape_analysis_FIX( | ||
35 | silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ | ||
36 | silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ | ||
37 | const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ | ||
38 | const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */ | ||
39 | int arch /* I Run-time architecture */ | ||
40 | ) | ||
41 | { | ||
42 | silk_shape_state_FIX *psShapeSt = &psEnc->sShape; | ||
43 | opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; | ||
44 | opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; | ||
45 | opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; | ||
46 | opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; | ||
47 | opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; | ||
48 | opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; | ||
49 | opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; | ||
50 | opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; | ||
51 | VARDECL( opus_int16, x_windowed ); | ||
52 | const opus_int16 *x_ptr, *pitch_res_ptr; | ||
53 | SAVE_STACK; | ||
54 | |||
55 | /* Point to start of first LPC analysis block */ | ||
56 | x_ptr = x - psEnc->sCmn.la_shape; | ||
57 | |||
58 | /****************/ | ||
59 | /* GAIN CONTROL */ | ||
60 | /****************/ | ||
61 | SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; | ||
62 | |||
63 | /* Input quality is the average of the quality in the lowest two VAD bands */ | ||
64 | psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ] | ||
65 | + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); | ||
66 | |||
67 | /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ | ||
68 | psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 - | ||
69 | SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 ); | ||
70 | |||
71 | /* Reduce coding SNR during low speech activity */ | ||
72 | if( psEnc->sCmn.useCBR == 0 ) { | ||
73 | b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; | ||
74 | b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 ); | ||
75 | SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, | ||
76 | silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), /* Q11*/ | ||
77 | silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); /* Q12*/ | ||
78 | } | ||
79 | |||
80 | if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
81 | /* Reduce gains for periodic signals */ | ||
82 | SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 ); | ||
83 | } else { | ||
84 | /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ | ||
85 | SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, | ||
86 | silk_SMLAWB( SILK_FIX_CONST( 6.0, 9 ), -SILK_FIX_CONST( 0.4, 18 ), psEnc->sCmn.SNR_dB_Q7 ), | ||
87 | SILK_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 ); | ||
88 | } | ||
89 | |||
90 | /*************************/ | ||
91 | /* SPARSENESS PROCESSING */ | ||
92 | /*************************/ | ||
93 | /* Set quantizer offset */ | ||
94 | if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
95 | /* Initially set to 0; may be overruled in process_gains(..) */ | ||
96 | psEnc->sCmn.indices.quantOffsetType = 0; | ||
97 | psEncCtrl->sparseness_Q8 = 0; | ||
98 | } else { | ||
99 | /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ | ||
100 | nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); | ||
101 | energy_variation_Q7 = 0; | ||
102 | log_energy_prev_Q7 = 0; | ||
103 | pitch_res_ptr = pitch_res; | ||
104 | for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) { | ||
105 | silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); | ||
106 | nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/ | ||
107 | |||
108 | log_energy_Q7 = silk_lin2log( nrg ); | ||
109 | if( k > 0 ) { | ||
110 | energy_variation_Q7 += silk_abs( log_energy_Q7 - log_energy_prev_Q7 ); | ||
111 | } | ||
112 | log_energy_prev_Q7 = log_energy_Q7; | ||
113 | pitch_res_ptr += nSamples; | ||
114 | } | ||
115 | |||
116 | psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 - | ||
117 | SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 ); | ||
118 | |||
119 | /* Set quantization offset depending on sparseness measure */ | ||
120 | if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) { | ||
121 | psEnc->sCmn.indices.quantOffsetType = 0; | ||
122 | } else { | ||
123 | psEnc->sCmn.indices.quantOffsetType = 1; | ||
124 | } | ||
125 | |||
126 | /* Increase coding SNR for sparse signals */ | ||
127 | SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) ); | ||
128 | } | ||
129 | |||
130 | /*******************************/ | ||
131 | /* Control bandwidth expansion */ | ||
132 | /*******************************/ | ||
133 | /* More BWE for signals with high prediction gain */ | ||
134 | strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); | ||
135 | BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ), | ||
136 | silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 ); | ||
137 | delta_Q16 = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), | ||
138 | SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) ); | ||
139 | BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 ); | ||
140 | BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 ); | ||
141 | /* BWExp1 will be applied after BWExp2, so make it relative */ | ||
142 | BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) ); | ||
143 | |||
144 | if( psEnc->sCmn.warping_Q16 > 0 ) { | ||
145 | /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ | ||
146 | warping_Q16 = silk_SMLAWB( psEnc->sCmn.warping_Q16, (opus_int32)psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) ); | ||
147 | } else { | ||
148 | warping_Q16 = 0; | ||
149 | } | ||
150 | |||
151 | /********************************************/ | ||
152 | /* Compute noise shaping AR coefs and gains */ | ||
153 | /********************************************/ | ||
154 | ALLOC( x_windowed, psEnc->sCmn.shapeWinLength, opus_int16 ); | ||
155 | for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
156 | /* Apply window: sine slope followed by flat part followed by cosine slope */ | ||
157 | opus_int shift, slope_part, flat_part; | ||
158 | flat_part = psEnc->sCmn.fs_kHz * 3; | ||
159 | slope_part = silk_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 ); | ||
160 | |||
161 | silk_apply_sine_window( x_windowed, x_ptr, 1, slope_part ); | ||
162 | shift = slope_part; | ||
163 | silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(opus_int16) ); | ||
164 | shift += flat_part; | ||
165 | silk_apply_sine_window( x_windowed + shift, x_ptr + shift, 2, slope_part ); | ||
166 | |||
167 | /* Update pointer: next LPC analysis block */ | ||
168 | x_ptr += psEnc->sCmn.subfr_length; | ||
169 | |||
170 | if( psEnc->sCmn.warping_Q16 > 0 ) { | ||
171 | /* Calculate warped auto correlation */ | ||
172 | silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder, arch ); | ||
173 | } else { | ||
174 | /* Calculate regular auto correlation */ | ||
175 | silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch ); | ||
176 | } | ||
177 | |||
178 | /* Add white noise, as a fraction of energy */ | ||
179 | auto_corr[0] = silk_ADD32( auto_corr[0], silk_max_32( silk_SMULWB( silk_RSHIFT( auto_corr[ 0 ], 4 ), | ||
180 | SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) ); | ||
181 | |||
182 | /* Calculate the reflection coefficients using schur */ | ||
183 | nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); | ||
184 | silk_assert( nrg >= 0 ); | ||
185 | |||
186 | /* Convert reflection coefficients to prediction coefficients */ | ||
187 | silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); | ||
188 | |||
189 | Qnrg = -scale; /* range: -12...30*/ | ||
190 | silk_assert( Qnrg >= -12 ); | ||
191 | silk_assert( Qnrg <= 30 ); | ||
192 | |||
193 | /* Make sure that Qnrg is an even number */ | ||
194 | if( Qnrg & 1 ) { | ||
195 | Qnrg -= 1; | ||
196 | nrg >>= 1; | ||
197 | } | ||
198 | |||
199 | tmp32 = silk_SQRT_APPROX( nrg ); | ||
200 | Qnrg >>= 1; /* range: -6...15*/ | ||
201 | |||
202 | psEncCtrl->Gains_Q16[ k ] = (silk_LSHIFT32( silk_LIMIT( (tmp32), silk_RSHIFT32( silk_int32_MIN, (16 - Qnrg) ), \ | ||
203 | silk_RSHIFT32( silk_int32_MAX, (16 - Qnrg) ) ), (16 - Qnrg) )); | ||
204 | |||
205 | if( psEnc->sCmn.warping_Q16 > 0 ) { | ||
206 | /* Adjust gain for warping */ | ||
207 | gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder ); | ||
208 | silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); | ||
209 | if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) { | ||
210 | psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX; | ||
211 | } else { | ||
212 | psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | /* Bandwidth expansion for synthesis filter shaping */ | ||
217 | silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 ); | ||
218 | |||
219 | /* Compute noise shaping filter coefficients */ | ||
220 | silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) ); | ||
221 | |||
222 | /* Bandwidth expansion for analysis filter shaping */ | ||
223 | silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) ); | ||
224 | silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); | ||
225 | |||
226 | /* Ratio of prediction gains, in energy domain */ | ||
227 | pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder, arch ); | ||
228 | nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder, arch ); | ||
229 | |||
230 | /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/ | ||
231 | pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 ); | ||
232 | psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 ); | ||
233 | |||
234 | /* Convert to monic warped prediction coefficients and limit absolute values */ | ||
235 | limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder ); | ||
236 | |||
237 | /* Convert from Q24 to Q13 and store in int16 */ | ||
238 | for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) { | ||
239 | psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) ); | ||
240 | psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) ); | ||
241 | } | ||
242 | } | ||
243 | |||
244 | /*****************/ | ||
245 | /* Gain tweaking */ | ||
246 | /*****************/ | ||
247 | /* Increase gains during low speech activity and put lower limit on gains */ | ||
248 | gain_mult_Q16 = silk_log2lin( -silk_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) ); | ||
249 | gain_add_Q16 = silk_log2lin( silk_SMLAWB( SILK_FIX_CONST( 16.0, 7 ), SILK_FIX_CONST( MIN_QGAIN_DB, 7 ), SILK_FIX_CONST( 0.16, 16 ) ) ); | ||
250 | silk_assert( gain_mult_Q16 > 0 ); | ||
251 | for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
252 | psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); | ||
253 | silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); | ||
254 | psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 ); | ||
255 | } | ||
256 | |||
257 | gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ), | ||
258 | psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 ); | ||
259 | for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
260 | psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] ); | ||
261 | } | ||
262 | |||
263 | /************************************************/ | ||
264 | /* Control low-frequency shaping and noise tilt */ | ||
265 | /************************************************/ | ||
266 | /* Less low frequency shaping for noisy inputs */ | ||
267 | strength_Q16 = silk_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), silk_SMLAWB( SILK_FIX_CONST( 1.0, 12 ), | ||
268 | SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) ); | ||
269 | strength_Q16 = silk_RSHIFT( silk_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 ); | ||
270 | if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
271 | /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */ | ||
272 | /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/ | ||
273 | opus_int fs_kHz_inv = silk_DIV32_16( SILK_FIX_CONST( 0.2, 14 ), psEnc->sCmn.fs_kHz ); | ||
274 | for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
275 | b_Q14 = fs_kHz_inv + silk_DIV32_16( SILK_FIX_CONST( 3.0, 14 ), psEncCtrl->pitchL[ k ] ); | ||
276 | /* Pack two coefficients in one int32 */ | ||
277 | psEncCtrl->LF_shp_Q14[ k ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - silk_SMULWB( strength_Q16, b_Q14 ), 16 ); | ||
278 | psEncCtrl->LF_shp_Q14[ k ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); | ||
279 | } | ||
280 | silk_assert( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ) < SILK_FIX_CONST( 0.5, 24 ) ); /* Guarantees that second argument to SMULWB() is within range of an opus_int16*/ | ||
281 | Tilt_Q16 = - SILK_FIX_CONST( HP_NOISE_COEF, 16 ) - | ||
282 | silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SILK_FIX_CONST( HP_NOISE_COEF, 16 ), | ||
283 | silk_SMULWB( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ), psEnc->sCmn.speech_activity_Q8 ) ); | ||
284 | } else { | ||
285 | b_Q14 = silk_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); /* 1.3_Q0 = 21299_Q14*/ | ||
286 | /* Pack two coefficients in one int32 */ | ||
287 | psEncCtrl->LF_shp_Q14[ 0 ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - | ||
288 | silk_SMULWB( strength_Q16, silk_SMULWB( SILK_FIX_CONST( 0.6, 16 ), b_Q14 ) ), 16 ); | ||
289 | psEncCtrl->LF_shp_Q14[ 0 ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); | ||
290 | for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
291 | psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ]; | ||
292 | } | ||
293 | Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 ); | ||
294 | } | ||
295 | |||
296 | /****************************/ | ||
297 | /* HARMONIC SHAPING CONTROL */ | ||
298 | /****************************/ | ||
299 | /* Control boosting of harmonic frequencies */ | ||
300 | HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ), | ||
301 | psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) ); | ||
302 | |||
303 | /* More harmonic boost for noisy input signals */ | ||
304 | HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16, | ||
305 | SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) ); | ||
306 | |||
307 | if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
308 | /* More harmonic noise shaping for high bitrates or noisy input */ | ||
309 | HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ), | ||
310 | SILK_FIX_CONST( 1.0, 16 ) - silk_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ), | ||
311 | psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) ); | ||
312 | |||
313 | /* Less harmonic noise shaping for less periodic signals */ | ||
314 | HarmShapeGain_Q16 = silk_SMULWB( silk_LSHIFT( HarmShapeGain_Q16, 1 ), | ||
315 | silk_SQRT_APPROX( silk_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) ); | ||
316 | } else { | ||
317 | HarmShapeGain_Q16 = 0; | ||
318 | } | ||
319 | |||
320 | /*************************/ | ||
321 | /* Smooth over subframes */ | ||
322 | /*************************/ | ||
323 | for( k = 0; k < MAX_NB_SUBFR; k++ ) { | ||
324 | psShapeSt->HarmBoost_smth_Q16 = | ||
325 | silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); | ||
326 | psShapeSt->HarmShapeGain_smth_Q16 = | ||
327 | silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); | ||
328 | psShapeSt->Tilt_smth_Q16 = | ||
329 | silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); | ||
330 | |||
331 | psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 ); | ||
332 | psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 ); | ||
333 | psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 ); | ||
334 | } | ||
335 | RESTORE_STACK; | ||
336 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/mips/prefilter_FIX_mipsr1.h b/lib/rbcodec/codecs/libopus/silk/fixed/mips/prefilter_FIX_mipsr1.h new file mode 100644 index 0000000000..21b256885f --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/mips/prefilter_FIX_mipsr1.h | |||
@@ -0,0 +1,184 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | #ifndef __PREFILTER_FIX_MIPSR1_H__ | ||
28 | #define __PREFILTER_FIX_MIPSR1_H__ | ||
29 | |||
30 | #ifdef HAVE_CONFIG_H | ||
31 | #include "config.h" | ||
32 | #endif | ||
33 | |||
34 | #include "main_FIX.h" | ||
35 | #include "stack_alloc.h" | ||
36 | #include "tuning_parameters.h" | ||
37 | |||
38 | #define OVERRIDE_silk_warped_LPC_analysis_filter_FIX | ||
39 | void silk_warped_LPC_analysis_filter_FIX( | ||
40 | opus_int32 state[], /* I/O State [order + 1] */ | ||
41 | opus_int32 res_Q2[], /* O Residual signal [length] */ | ||
42 | const opus_int16 coef_Q13[], /* I Coefficients [order] */ | ||
43 | const opus_int16 input[], /* I Input signal [length] */ | ||
44 | const opus_int16 lambda_Q16, /* I Warping factor */ | ||
45 | const opus_int length, /* I Length of input signal */ | ||
46 | const opus_int order, /* I Filter order (even) */ | ||
47 | int arch | ||
48 | ) | ||
49 | { | ||
50 | opus_int n, i; | ||
51 | opus_int32 acc_Q11, acc_Q22, tmp1, tmp2, tmp3, tmp4; | ||
52 | opus_int32 state_cur, state_next; | ||
53 | |||
54 | (void)arch; | ||
55 | |||
56 | /* Order must be even */ | ||
57 | /* Length must be even */ | ||
58 | |||
59 | silk_assert( ( order & 1 ) == 0 ); | ||
60 | silk_assert( ( length & 1 ) == 0 ); | ||
61 | |||
62 | for( n = 0; n < length; n+=2 ) { | ||
63 | /* Output of lowpass section */ | ||
64 | tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); | ||
65 | state_cur = silk_LSHIFT( input[ n ], 14 ); | ||
66 | /* Output of allpass section */ | ||
67 | tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); | ||
68 | state_next = tmp2; | ||
69 | acc_Q11 = silk_RSHIFT( order, 1 ); | ||
70 | acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] ); | ||
71 | |||
72 | |||
73 | /* Output of lowpass section */ | ||
74 | tmp4 = silk_SMLAWB( state_cur, state_next, lambda_Q16 ); | ||
75 | state[ 0 ] = silk_LSHIFT( input[ n+1 ], 14 ); | ||
76 | /* Output of allpass section */ | ||
77 | tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 ); | ||
78 | state[ 1 ] = tmp4; | ||
79 | acc_Q22 = silk_RSHIFT( order, 1 ); | ||
80 | acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ 0 ] ); | ||
81 | |||
82 | /* Loop over allpass sections */ | ||
83 | for( i = 2; i < order; i += 2 ) { | ||
84 | /* Output of allpass section */ | ||
85 | tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); | ||
86 | state_cur = tmp1; | ||
87 | acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); | ||
88 | /* Output of allpass section */ | ||
89 | tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); | ||
90 | state_next = tmp2; | ||
91 | acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); | ||
92 | |||
93 | |||
94 | /* Output of allpass section */ | ||
95 | tmp4 = silk_SMLAWB( state_cur, state_next - tmp3, lambda_Q16 ); | ||
96 | state[ i ] = tmp3; | ||
97 | acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ i - 1 ] ); | ||
98 | /* Output of allpass section */ | ||
99 | tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 ); | ||
100 | state[ i + 1 ] = tmp4; | ||
101 | acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ i ] ); | ||
102 | } | ||
103 | acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); | ||
104 | res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 ); | ||
105 | |||
106 | state[ order ] = tmp3; | ||
107 | acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ order - 1 ] ); | ||
108 | res_Q2[ n+1 ] = silk_LSHIFT( (opus_int32)input[ n+1 ], 2 ) - silk_RSHIFT_ROUND( acc_Q22, 9 ); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | |||
113 | |||
114 | /* Prefilter for finding Quantizer input signal */ | ||
115 | #define OVERRIDE_silk_prefilt_FIX | ||
116 | static inline void silk_prefilt_FIX( | ||
117 | silk_prefilter_state_FIX *P, /* I/O state */ | ||
118 | opus_int32 st_res_Q12[], /* I short term residual signal */ | ||
119 | opus_int32 xw_Q3[], /* O prefiltered signal */ | ||
120 | opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ | ||
121 | opus_int Tilt_Q14, /* I Tilt shaping coeficient */ | ||
122 | opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ | ||
123 | opus_int lag, /* I Lag for harmonic shaping */ | ||
124 | opus_int length /* I Length of signals */ | ||
125 | ) | ||
126 | { | ||
127 | opus_int i, idx, LTP_shp_buf_idx; | ||
128 | opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; | ||
129 | opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; | ||
130 | opus_int16 *LTP_shp_buf; | ||
131 | |||
132 | /* To speed up use temp variables instead of using the struct */ | ||
133 | LTP_shp_buf = P->sLTP_shp; | ||
134 | LTP_shp_buf_idx = P->sLTP_shp_buf_idx; | ||
135 | sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; | ||
136 | sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; | ||
137 | |||
138 | if( lag > 0 ) { | ||
139 | for( i = 0; i < length; i++ ) { | ||
140 | /* unrolled loop */ | ||
141 | silk_assert( HARM_SHAPE_FIR_TAPS == 3 ); | ||
142 | idx = lag + LTP_shp_buf_idx; | ||
143 | n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); | ||
144 | n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); | ||
145 | n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); | ||
146 | |||
147 | n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); | ||
148 | n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); | ||
149 | |||
150 | sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) ); | ||
151 | sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) ); | ||
152 | |||
153 | LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; | ||
154 | LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); | ||
155 | |||
156 | xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 ); | ||
157 | } | ||
158 | } | ||
159 | else | ||
160 | { | ||
161 | for( i = 0; i < length; i++ ) { | ||
162 | |||
163 | n_LTP_Q12 = 0; | ||
164 | |||
165 | n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); | ||
166 | n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); | ||
167 | |||
168 | sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) ); | ||
169 | sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) ); | ||
170 | |||
171 | LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; | ||
172 | LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); | ||
173 | |||
174 | xw_Q3[i] = silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 9 ); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /* Copy temp variable back to state */ | ||
179 | P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; | ||
180 | P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; | ||
181 | P->sLTP_shp_buf_idx = LTP_shp_buf_idx; | ||
182 | } | ||
183 | |||
184 | #endif /* __PREFILTER_FIX_MIPSR1_H__ */ | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h b/lib/rbcodec/codecs/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h new file mode 100644 index 0000000000..fcbd96c88d --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h | |||
@@ -0,0 +1,166 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifndef __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__ | ||
29 | #define __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__ | ||
30 | |||
31 | #ifdef HAVE_CONFIG_H | ||
32 | #include "config.h" | ||
33 | #endif | ||
34 | |||
35 | #include "main_FIX.h" | ||
36 | |||
37 | #undef QC | ||
38 | #define QC 10 | ||
39 | |||
40 | #undef QS | ||
41 | #define QS 14 | ||
42 | |||
43 | /* Autocorrelations for a warped frequency axis */ | ||
44 | #define OVERRIDE_silk_warped_autocorrelation_FIX | ||
45 | void silk_warped_autocorrelation_FIX( | ||
46 | opus_int32 *corr, /* O Result [order + 1] */ | ||
47 | opus_int *scale, /* O Scaling of the correlation vector */ | ||
48 | const opus_int16 *input, /* I Input data to correlate */ | ||
49 | const opus_int warping_Q16, /* I Warping coefficient */ | ||
50 | const opus_int length, /* I Length of input */ | ||
51 | const opus_int order, /* I Correlation order (even) */ | ||
52 | int arch /* I Run-time architecture */ | ||
53 | ) | ||
54 | { | ||
55 | opus_int n, i, lsh; | ||
56 | opus_int32 tmp1_QS=0, tmp2_QS=0, tmp3_QS=0, tmp4_QS=0, tmp5_QS=0, tmp6_QS=0, tmp7_QS=0, tmp8_QS=0, start_1=0, start_2=0, start_3=0; | ||
57 | opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; | ||
58 | opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; | ||
59 | opus_int64 temp64; | ||
60 | |||
61 | opus_int32 val; | ||
62 | val = 2 * QS - QC; | ||
63 | |||
64 | /* Order must be even */ | ||
65 | silk_assert( ( order & 1 ) == 0 ); | ||
66 | silk_assert( 2 * QS - QC >= 0 ); | ||
67 | |||
68 | /* Loop over samples */ | ||
69 | for( n = 0; n < length; n=n+4 ) { | ||
70 | |||
71 | tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS ); | ||
72 | start_1 = tmp1_QS; | ||
73 | tmp3_QS = silk_LSHIFT32( (opus_int32)input[ n+1], QS ); | ||
74 | start_2 = tmp3_QS; | ||
75 | tmp5_QS = silk_LSHIFT32( (opus_int32)input[ n+2], QS ); | ||
76 | start_3 = tmp5_QS; | ||
77 | tmp7_QS = silk_LSHIFT32( (opus_int32)input[ n+3], QS ); | ||
78 | |||
79 | /* Loop over allpass sections */ | ||
80 | for( i = 0; i < order; i += 2 ) { | ||
81 | /* Output of allpass section */ | ||
82 | tmp2_QS = silk_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 ); | ||
83 | corr_QC[ i ] = __builtin_mips_madd( corr_QC[ i ], tmp1_QS, start_1); | ||
84 | |||
85 | tmp4_QS = silk_SMLAWB( tmp1_QS, tmp2_QS - tmp3_QS, warping_Q16 ); | ||
86 | corr_QC[ i ] = __builtin_mips_madd( corr_QC[ i ], tmp3_QS, start_2); | ||
87 | |||
88 | tmp6_QS = silk_SMLAWB( tmp3_QS, tmp4_QS - tmp5_QS, warping_Q16 ); | ||
89 | corr_QC[ i ] = __builtin_mips_madd( corr_QC[ i ], tmp5_QS, start_3); | ||
90 | |||
91 | tmp8_QS = silk_SMLAWB( tmp5_QS, tmp6_QS - tmp7_QS, warping_Q16 ); | ||
92 | state_QS[ i ] = tmp7_QS; | ||
93 | corr_QC[ i ] = __builtin_mips_madd( corr_QC[ i ], tmp7_QS, state_QS[0]); | ||
94 | |||
95 | /* Output of allpass section */ | ||
96 | tmp1_QS = silk_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 ); | ||
97 | corr_QC[ i+1 ] = __builtin_mips_madd( corr_QC[ i+1 ], tmp2_QS, start_1); | ||
98 | |||
99 | tmp3_QS = silk_SMLAWB( tmp2_QS, tmp1_QS - tmp4_QS, warping_Q16 ); | ||
100 | corr_QC[ i+1 ] = __builtin_mips_madd( corr_QC[ i+1 ], tmp4_QS, start_2); | ||
101 | |||
102 | tmp5_QS = silk_SMLAWB( tmp4_QS, tmp3_QS - tmp6_QS, warping_Q16 ); | ||
103 | corr_QC[ i+1 ] = __builtin_mips_madd( corr_QC[ i+1 ], tmp6_QS, start_3); | ||
104 | |||
105 | tmp7_QS = silk_SMLAWB( tmp6_QS, tmp5_QS - tmp8_QS, warping_Q16 ); | ||
106 | state_QS[ i + 1 ] = tmp8_QS; | ||
107 | corr_QC[ i+1 ] = __builtin_mips_madd( corr_QC[ i+1 ], tmp8_QS, state_QS[ 0 ]); | ||
108 | |||
109 | } | ||
110 | state_QS[ order ] = tmp7_QS; | ||
111 | |||
112 | corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp1_QS, start_1); | ||
113 | corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp3_QS, start_2); | ||
114 | corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp5_QS, start_3); | ||
115 | corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp7_QS, state_QS[ 0 ]); | ||
116 | } | ||
117 | |||
118 | for(;n< length; n++ ) { | ||
119 | |||
120 | tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS ); | ||
121 | |||
122 | /* Loop over allpass sections */ | ||
123 | for( i = 0; i < order; i += 2 ) { | ||
124 | |||
125 | /* Output of allpass section */ | ||
126 | tmp2_QS = silk_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 ); | ||
127 | state_QS[ i ] = tmp1_QS; | ||
128 | corr_QC[ i ] = __builtin_mips_madd( corr_QC[ i ], tmp1_QS, state_QS[ 0 ]); | ||
129 | |||
130 | /* Output of allpass section */ | ||
131 | tmp1_QS = silk_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 ); | ||
132 | state_QS[ i + 1 ] = tmp2_QS; | ||
133 | corr_QC[ i+1 ] = __builtin_mips_madd( corr_QC[ i+1 ], tmp2_QS, state_QS[ 0 ]); | ||
134 | } | ||
135 | state_QS[ order ] = tmp1_QS; | ||
136 | corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp1_QS, state_QS[ 0 ]); | ||
137 | } | ||
138 | |||
139 | temp64 = corr_QC[ 0 ]; | ||
140 | temp64 = __builtin_mips_shilo(temp64, val); | ||
141 | |||
142 | lsh = silk_CLZ64( temp64 ) - 35; | ||
143 | lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC ); | ||
144 | *scale = -( QC + lsh ); | ||
145 | silk_assert( *scale >= -30 && *scale <= 12 ); | ||
146 | if( lsh >= 0 ) { | ||
147 | for( i = 0; i < order + 1; i++ ) { | ||
148 | temp64 = corr_QC[ i ]; | ||
149 | //temp64 = __builtin_mips_shilo(temp64, val); | ||
150 | temp64 = (val >= 0) ? (temp64 >> val) : (temp64 << -val); | ||
151 | corr[ i ] = (opus_int32)silk_CHECK_FIT32( __builtin_mips_shilo( temp64, -lsh ) ); | ||
152 | } | ||
153 | } else { | ||
154 | for( i = 0; i < order + 1; i++ ) { | ||
155 | temp64 = corr_QC[ i ]; | ||
156 | //temp64 = __builtin_mips_shilo(temp64, val); | ||
157 | temp64 = (val >= 0) ? (temp64 >> val) : (temp64 << -val); | ||
158 | corr[ i ] = (opus_int32)silk_CHECK_FIT32( __builtin_mips_shilo( temp64, -lsh ) ); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | corr_QC[ 0 ] = __builtin_mips_shilo(corr_QC[ 0 ], val); | ||
163 | |||
164 | silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/ | ||
165 | } | ||
166 | #endif /* __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__ */ | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/noise_shape_analysis_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/noise_shape_analysis_FIX.c new file mode 100644 index 0000000000..85fea0bf09 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/noise_shape_analysis_FIX.c | |||
@@ -0,0 +1,407 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | #include "stack_alloc.h" | ||
34 | #include "tuning_parameters.h" | ||
35 | |||
36 | /* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */ | ||
37 | /* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */ | ||
38 | /* Note: A monic filter is one with the first coefficient equal to 1.0. In Silk we omit the first */ | ||
39 | /* coefficient in an array of coefficients, for monic filters. */ | ||
40 | static OPUS_INLINE opus_int32 warped_gain( /* gain in Q16*/ | ||
41 | const opus_int32 *coefs_Q24, | ||
42 | opus_int lambda_Q16, | ||
43 | opus_int order | ||
44 | ) { | ||
45 | opus_int i; | ||
46 | opus_int32 gain_Q24; | ||
47 | |||
48 | lambda_Q16 = -lambda_Q16; | ||
49 | gain_Q24 = coefs_Q24[ order - 1 ]; | ||
50 | for( i = order - 2; i >= 0; i-- ) { | ||
51 | gain_Q24 = silk_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 ); | ||
52 | } | ||
53 | gain_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 ); | ||
54 | return silk_INVERSE32_varQ( gain_Q24, 40 ); | ||
55 | } | ||
56 | |||
57 | /* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */ | ||
58 | /* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */ | ||
59 | static OPUS_INLINE void limit_warped_coefs( | ||
60 | opus_int32 *coefs_Q24, | ||
61 | opus_int lambda_Q16, | ||
62 | opus_int32 limit_Q24, | ||
63 | opus_int order | ||
64 | ) { | ||
65 | opus_int i, iter, ind = 0; | ||
66 | opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_Q16; | ||
67 | opus_int32 nom_Q16, den_Q24; | ||
68 | opus_int32 limit_Q20, maxabs_Q20; | ||
69 | |||
70 | /* Convert to monic coefficients */ | ||
71 | lambda_Q16 = -lambda_Q16; | ||
72 | for( i = order - 1; i > 0; i-- ) { | ||
73 | coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 ); | ||
74 | } | ||
75 | lambda_Q16 = -lambda_Q16; | ||
76 | nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 ); | ||
77 | den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_Q24[ 0 ], lambda_Q16 ); | ||
78 | gain_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); | ||
79 | for( i = 0; i < order; i++ ) { | ||
80 | coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] ); | ||
81 | } | ||
82 | limit_Q20 = silk_RSHIFT(limit_Q24, 4); | ||
83 | for( iter = 0; iter < 10; iter++ ) { | ||
84 | /* Find maximum absolute value */ | ||
85 | maxabs_Q24 = -1; | ||
86 | for( i = 0; i < order; i++ ) { | ||
87 | tmp = silk_abs_int32( coefs_Q24[ i ] ); | ||
88 | if( tmp > maxabs_Q24 ) { | ||
89 | maxabs_Q24 = tmp; | ||
90 | ind = i; | ||
91 | } | ||
92 | } | ||
93 | /* Use Q20 to avoid any overflow when multiplying by (ind + 1) later. */ | ||
94 | maxabs_Q20 = silk_RSHIFT(maxabs_Q24, 4); | ||
95 | if( maxabs_Q20 <= limit_Q20 ) { | ||
96 | /* Coefficients are within range - done */ | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | /* Convert back to true warped coefficients */ | ||
101 | for( i = 1; i < order; i++ ) { | ||
102 | coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 ); | ||
103 | } | ||
104 | gain_Q16 = silk_INVERSE32_varQ( gain_Q16, 32 ); | ||
105 | for( i = 0; i < order; i++ ) { | ||
106 | coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] ); | ||
107 | } | ||
108 | |||
109 | /* Apply bandwidth expansion */ | ||
110 | chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ( | ||
111 | silk_SMULWB( maxabs_Q20 - limit_Q20, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ), | ||
112 | silk_MUL( maxabs_Q20, ind + 1 ), 22 ); | ||
113 | silk_bwexpander_32( coefs_Q24, order, chirp_Q16 ); | ||
114 | |||
115 | /* Convert to monic warped coefficients */ | ||
116 | lambda_Q16 = -lambda_Q16; | ||
117 | for( i = order - 1; i > 0; i-- ) { | ||
118 | coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 ); | ||
119 | } | ||
120 | lambda_Q16 = -lambda_Q16; | ||
121 | nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 ); | ||
122 | den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_Q24[ 0 ], lambda_Q16 ); | ||
123 | gain_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); | ||
124 | for( i = 0; i < order; i++ ) { | ||
125 | coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] ); | ||
126 | } | ||
127 | } | ||
128 | silk_assert( 0 ); | ||
129 | } | ||
130 | |||
131 | /* Disable MIPS version until it's updated. */ | ||
132 | #if 0 && defined(MIPSr1_ASM) | ||
133 | #include "mips/noise_shape_analysis_FIX_mipsr1.h" | ||
134 | #endif | ||
135 | |||
136 | /**************************************************************/ | ||
137 | /* Compute noise shaping coefficients and initial gain values */ | ||
138 | /**************************************************************/ | ||
139 | #ifndef OVERRIDE_silk_noise_shape_analysis_FIX | ||
140 | void silk_noise_shape_analysis_FIX( | ||
141 | silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ | ||
142 | silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ | ||
143 | const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ | ||
144 | const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */ | ||
145 | int arch /* I Run-time architecture */ | ||
146 | ) | ||
147 | { | ||
148 | silk_shape_state_FIX *psShapeSt = &psEnc->sShape; | ||
149 | opus_int k, i, nSamples, nSegs, Qnrg, b_Q14, warping_Q16, scale = 0; | ||
150 | opus_int32 SNR_adj_dB_Q7, HarmShapeGain_Q16, Tilt_Q16, tmp32; | ||
151 | opus_int32 nrg, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; | ||
152 | opus_int32 BWExp_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; | ||
153 | opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; | ||
154 | opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; | ||
155 | opus_int32 AR_Q24[ MAX_SHAPE_LPC_ORDER ]; | ||
156 | VARDECL( opus_int16, x_windowed ); | ||
157 | const opus_int16 *x_ptr, *pitch_res_ptr; | ||
158 | SAVE_STACK; | ||
159 | |||
160 | /* Point to start of first LPC analysis block */ | ||
161 | x_ptr = x - psEnc->sCmn.la_shape; | ||
162 | |||
163 | /****************/ | ||
164 | /* GAIN CONTROL */ | ||
165 | /****************/ | ||
166 | SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; | ||
167 | |||
168 | /* Input quality is the average of the quality in the lowest two VAD bands */ | ||
169 | psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ] | ||
170 | + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); | ||
171 | |||
172 | /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ | ||
173 | psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 - | ||
174 | SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 ); | ||
175 | |||
176 | /* Reduce coding SNR during low speech activity */ | ||
177 | if( psEnc->sCmn.useCBR == 0 ) { | ||
178 | b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; | ||
179 | b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 ); | ||
180 | SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, | ||
181 | silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), /* Q11*/ | ||
182 | silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); /* Q12*/ | ||
183 | } | ||
184 | |||
185 | if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
186 | /* Reduce gains for periodic signals */ | ||
187 | SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 ); | ||
188 | } else { | ||
189 | /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ | ||
190 | SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, | ||
191 | silk_SMLAWB( SILK_FIX_CONST( 6.0, 9 ), -SILK_FIX_CONST( 0.4, 18 ), psEnc->sCmn.SNR_dB_Q7 ), | ||
192 | SILK_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 ); | ||
193 | } | ||
194 | |||
195 | /*************************/ | ||
196 | /* SPARSENESS PROCESSING */ | ||
197 | /*************************/ | ||
198 | /* Set quantizer offset */ | ||
199 | if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
200 | /* Initially set to 0; may be overruled in process_gains(..) */ | ||
201 | psEnc->sCmn.indices.quantOffsetType = 0; | ||
202 | } else { | ||
203 | /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ | ||
204 | nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); | ||
205 | energy_variation_Q7 = 0; | ||
206 | log_energy_prev_Q7 = 0; | ||
207 | pitch_res_ptr = pitch_res; | ||
208 | nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; | ||
209 | for( k = 0; k < nSegs; k++ ) { | ||
210 | silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); | ||
211 | nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/ | ||
212 | |||
213 | log_energy_Q7 = silk_lin2log( nrg ); | ||
214 | if( k > 0 ) { | ||
215 | energy_variation_Q7 += silk_abs( log_energy_Q7 - log_energy_prev_Q7 ); | ||
216 | } | ||
217 | log_energy_prev_Q7 = log_energy_Q7; | ||
218 | pitch_res_ptr += nSamples; | ||
219 | } | ||
220 | |||
221 | /* Set quantization offset depending on sparseness measure */ | ||
222 | if( energy_variation_Q7 > SILK_FIX_CONST( ENERGY_VARIATION_THRESHOLD_QNT_OFFSET, 7 ) * (nSegs-1) ) { | ||
223 | psEnc->sCmn.indices.quantOffsetType = 0; | ||
224 | } else { | ||
225 | psEnc->sCmn.indices.quantOffsetType = 1; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | /*******************************/ | ||
230 | /* Control bandwidth expansion */ | ||
231 | /*******************************/ | ||
232 | /* More BWE for signals with high prediction gain */ | ||
233 | strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); | ||
234 | BWExp_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ), | ||
235 | silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 ); | ||
236 | |||
237 | if( psEnc->sCmn.warping_Q16 > 0 ) { | ||
238 | /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ | ||
239 | warping_Q16 = silk_SMLAWB( psEnc->sCmn.warping_Q16, (opus_int32)psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) ); | ||
240 | } else { | ||
241 | warping_Q16 = 0; | ||
242 | } | ||
243 | |||
244 | /********************************************/ | ||
245 | /* Compute noise shaping AR coefs and gains */ | ||
246 | /********************************************/ | ||
247 | ALLOC( x_windowed, psEnc->sCmn.shapeWinLength, opus_int16 ); | ||
248 | for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
249 | /* Apply window: sine slope followed by flat part followed by cosine slope */ | ||
250 | opus_int shift, slope_part, flat_part; | ||
251 | flat_part = psEnc->sCmn.fs_kHz * 3; | ||
252 | slope_part = silk_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 ); | ||
253 | |||
254 | silk_apply_sine_window( x_windowed, x_ptr, 1, slope_part ); | ||
255 | shift = slope_part; | ||
256 | silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(opus_int16) ); | ||
257 | shift += flat_part; | ||
258 | silk_apply_sine_window( x_windowed + shift, x_ptr + shift, 2, slope_part ); | ||
259 | |||
260 | /* Update pointer: next LPC analysis block */ | ||
261 | x_ptr += psEnc->sCmn.subfr_length; | ||
262 | |||
263 | if( psEnc->sCmn.warping_Q16 > 0 ) { | ||
264 | /* Calculate warped auto correlation */ | ||
265 | silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder, arch ); | ||
266 | } else { | ||
267 | /* Calculate regular auto correlation */ | ||
268 | silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch ); | ||
269 | } | ||
270 | |||
271 | /* Add white noise, as a fraction of energy */ | ||
272 | auto_corr[0] = silk_ADD32( auto_corr[0], silk_max_32( silk_SMULWB( silk_RSHIFT( auto_corr[ 0 ], 4 ), | ||
273 | SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) ); | ||
274 | |||
275 | /* Calculate the reflection coefficients using schur */ | ||
276 | nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); | ||
277 | silk_assert( nrg >= 0 ); | ||
278 | |||
279 | /* Convert reflection coefficients to prediction coefficients */ | ||
280 | silk_k2a_Q16( AR_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); | ||
281 | |||
282 | Qnrg = -scale; /* range: -12...30*/ | ||
283 | silk_assert( Qnrg >= -12 ); | ||
284 | silk_assert( Qnrg <= 30 ); | ||
285 | |||
286 | /* Make sure that Qnrg is an even number */ | ||
287 | if( Qnrg & 1 ) { | ||
288 | Qnrg -= 1; | ||
289 | nrg >>= 1; | ||
290 | } | ||
291 | |||
292 | tmp32 = silk_SQRT_APPROX( nrg ); | ||
293 | Qnrg >>= 1; /* range: -6...15*/ | ||
294 | |||
295 | psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( tmp32, 16 - Qnrg ); | ||
296 | |||
297 | if( psEnc->sCmn.warping_Q16 > 0 ) { | ||
298 | /* Adjust gain for warping */ | ||
299 | gain_mult_Q16 = warped_gain( AR_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder ); | ||
300 | silk_assert( psEncCtrl->Gains_Q16[ k ] > 0 ); | ||
301 | if( psEncCtrl->Gains_Q16[ k ] < SILK_FIX_CONST( 0.25, 16 ) ) { | ||
302 | psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); | ||
303 | } else { | ||
304 | psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ); | ||
305 | if ( psEncCtrl->Gains_Q16[ k ] >= ( silk_int32_MAX >> 1 ) ) { | ||
306 | psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX; | ||
307 | } else { | ||
308 | psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT32( psEncCtrl->Gains_Q16[ k ], 1 ); | ||
309 | } | ||
310 | } | ||
311 | silk_assert( psEncCtrl->Gains_Q16[ k ] > 0 ); | ||
312 | } | ||
313 | |||
314 | /* Bandwidth expansion */ | ||
315 | silk_bwexpander_32( AR_Q24, psEnc->sCmn.shapingLPCOrder, BWExp_Q16 ); | ||
316 | |||
317 | if( psEnc->sCmn.warping_Q16 > 0 ) { | ||
318 | /* Convert to monic warped prediction coefficients and limit absolute values */ | ||
319 | limit_warped_coefs( AR_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder ); | ||
320 | |||
321 | /* Convert from Q24 to Q13 and store in int16 */ | ||
322 | for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) { | ||
323 | psEncCtrl->AR_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR_Q24[ i ], 11 ) ); | ||
324 | } | ||
325 | } else { | ||
326 | silk_LPC_fit( &psEncCtrl->AR_Q13[ k * MAX_SHAPE_LPC_ORDER ], AR_Q24, 13, 24, psEnc->sCmn.shapingLPCOrder ); | ||
327 | } | ||
328 | } | ||
329 | |||
330 | /*****************/ | ||
331 | /* Gain tweaking */ | ||
332 | /*****************/ | ||
333 | /* Increase gains during low speech activity and put lower limit on gains */ | ||
334 | gain_mult_Q16 = silk_log2lin( -silk_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) ); | ||
335 | gain_add_Q16 = silk_log2lin( silk_SMLAWB( SILK_FIX_CONST( 16.0, 7 ), SILK_FIX_CONST( MIN_QGAIN_DB, 7 ), SILK_FIX_CONST( 0.16, 16 ) ) ); | ||
336 | silk_assert( gain_mult_Q16 > 0 ); | ||
337 | for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
338 | psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); | ||
339 | silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); | ||
340 | psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 ); | ||
341 | } | ||
342 | |||
343 | |||
344 | /************************************************/ | ||
345 | /* Control low-frequency shaping and noise tilt */ | ||
346 | /************************************************/ | ||
347 | /* Less low frequency shaping for noisy inputs */ | ||
348 | strength_Q16 = silk_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), silk_SMLAWB( SILK_FIX_CONST( 1.0, 12 ), | ||
349 | SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) ); | ||
350 | strength_Q16 = silk_RSHIFT( silk_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 ); | ||
351 | if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
352 | /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */ | ||
353 | /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/ | ||
354 | opus_int fs_kHz_inv = silk_DIV32_16( SILK_FIX_CONST( 0.2, 14 ), psEnc->sCmn.fs_kHz ); | ||
355 | for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
356 | b_Q14 = fs_kHz_inv + silk_DIV32_16( SILK_FIX_CONST( 3.0, 14 ), psEncCtrl->pitchL[ k ] ); | ||
357 | /* Pack two coefficients in one int32 */ | ||
358 | psEncCtrl->LF_shp_Q14[ k ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - silk_SMULWB( strength_Q16, b_Q14 ), 16 ); | ||
359 | psEncCtrl->LF_shp_Q14[ k ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); | ||
360 | } | ||
361 | silk_assert( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ) < SILK_FIX_CONST( 0.5, 24 ) ); /* Guarantees that second argument to SMULWB() is within range of an opus_int16*/ | ||
362 | Tilt_Q16 = - SILK_FIX_CONST( HP_NOISE_COEF, 16 ) - | ||
363 | silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SILK_FIX_CONST( HP_NOISE_COEF, 16 ), | ||
364 | silk_SMULWB( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ), psEnc->sCmn.speech_activity_Q8 ) ); | ||
365 | } else { | ||
366 | b_Q14 = silk_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); /* 1.3_Q0 = 21299_Q14*/ | ||
367 | /* Pack two coefficients in one int32 */ | ||
368 | psEncCtrl->LF_shp_Q14[ 0 ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - | ||
369 | silk_SMULWB( strength_Q16, silk_SMULWB( SILK_FIX_CONST( 0.6, 16 ), b_Q14 ) ), 16 ); | ||
370 | psEncCtrl->LF_shp_Q14[ 0 ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); | ||
371 | for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
372 | psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ]; | ||
373 | } | ||
374 | Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 ); | ||
375 | } | ||
376 | |||
377 | /****************************/ | ||
378 | /* HARMONIC SHAPING CONTROL */ | ||
379 | /****************************/ | ||
380 | if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
381 | /* More harmonic noise shaping for high bitrates or noisy input */ | ||
382 | HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ), | ||
383 | SILK_FIX_CONST( 1.0, 16 ) - silk_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ), | ||
384 | psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) ); | ||
385 | |||
386 | /* Less harmonic noise shaping for less periodic signals */ | ||
387 | HarmShapeGain_Q16 = silk_SMULWB( silk_LSHIFT( HarmShapeGain_Q16, 1 ), | ||
388 | silk_SQRT_APPROX( silk_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) ); | ||
389 | } else { | ||
390 | HarmShapeGain_Q16 = 0; | ||
391 | } | ||
392 | |||
393 | /*************************/ | ||
394 | /* Smooth over subframes */ | ||
395 | /*************************/ | ||
396 | for( k = 0; k < MAX_NB_SUBFR; k++ ) { | ||
397 | psShapeSt->HarmShapeGain_smth_Q16 = | ||
398 | silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); | ||
399 | psShapeSt->Tilt_smth_Q16 = | ||
400 | silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); | ||
401 | |||
402 | psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 ); | ||
403 | psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 ); | ||
404 | } | ||
405 | RESTORE_STACK; | ||
406 | } | ||
407 | #endif /* OVERRIDE_silk_noise_shape_analysis_FIX */ | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/pitch_analysis_core_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/pitch_analysis_core_FIX.c new file mode 100644 index 0000000000..14729046d2 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/pitch_analysis_core_FIX.c | |||
@@ -0,0 +1,721 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | /*********************************************************** | ||
33 | * Pitch analyser function | ||
34 | ********************************************************** */ | ||
35 | #include "SigProc_FIX.h" | ||
36 | #include "pitch_est_defines.h" | ||
37 | #include "stack_alloc.h" | ||
38 | #include "debug.h" | ||
39 | #include "pitch.h" | ||
40 | |||
41 | #define SCRATCH_SIZE 22 | ||
42 | #define SF_LENGTH_4KHZ ( PE_SUBFR_LENGTH_MS * 4 ) | ||
43 | #define SF_LENGTH_8KHZ ( PE_SUBFR_LENGTH_MS * 8 ) | ||
44 | #define MIN_LAG_4KHZ ( PE_MIN_LAG_MS * 4 ) | ||
45 | #define MIN_LAG_8KHZ ( PE_MIN_LAG_MS * 8 ) | ||
46 | #define MAX_LAG_4KHZ ( PE_MAX_LAG_MS * 4 ) | ||
47 | #define MAX_LAG_8KHZ ( PE_MAX_LAG_MS * 8 - 1 ) | ||
48 | #define CSTRIDE_4KHZ ( MAX_LAG_4KHZ + 1 - MIN_LAG_4KHZ ) | ||
49 | #define CSTRIDE_8KHZ ( MAX_LAG_8KHZ + 3 - ( MIN_LAG_8KHZ - 2 ) ) | ||
50 | #define D_COMP_MIN ( MIN_LAG_8KHZ - 3 ) | ||
51 | #define D_COMP_MAX ( MAX_LAG_8KHZ + 4 ) | ||
52 | #define D_COMP_STRIDE ( D_COMP_MAX - D_COMP_MIN ) | ||
53 | |||
54 | typedef opus_int32 silk_pe_stage3_vals[ PE_NB_STAGE3_LAGS ]; | ||
55 | |||
56 | /************************************************************/ | ||
57 | /* Internally used functions */ | ||
58 | /************************************************************/ | ||
59 | static void silk_P_Ana_calc_corr_st3( | ||
60 | silk_pe_stage3_vals cross_corr_st3[], /* O 3 DIM correlation array */ | ||
61 | const opus_int16 frame[], /* I vector to correlate */ | ||
62 | opus_int start_lag, /* I lag offset to search around */ | ||
63 | opus_int sf_length, /* I length of a 5 ms subframe */ | ||
64 | opus_int nb_subfr, /* I number of subframes */ | ||
65 | opus_int complexity, /* I Complexity setting */ | ||
66 | int arch /* I Run-time architecture */ | ||
67 | ); | ||
68 | |||
69 | static void silk_P_Ana_calc_energy_st3( | ||
70 | silk_pe_stage3_vals energies_st3[], /* O 3 DIM energy array */ | ||
71 | const opus_int16 frame[], /* I vector to calc energy in */ | ||
72 | opus_int start_lag, /* I lag offset to search around */ | ||
73 | opus_int sf_length, /* I length of one 5 ms subframe */ | ||
74 | opus_int nb_subfr, /* I number of subframes */ | ||
75 | opus_int complexity, /* I Complexity setting */ | ||
76 | int arch /* I Run-time architecture */ | ||
77 | ); | ||
78 | |||
79 | /*************************************************************/ | ||
80 | /* FIXED POINT CORE PITCH ANALYSIS FUNCTION */ | ||
81 | /*************************************************************/ | ||
82 | opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */ | ||
83 | const opus_int16 *frame_unscaled, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ | ||
84 | opus_int *pitch_out, /* O 4 pitch lag values */ | ||
85 | opus_int16 *lagIndex, /* O Lag Index */ | ||
86 | opus_int8 *contourIndex, /* O Pitch contour Index */ | ||
87 | opus_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */ | ||
88 | opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */ | ||
89 | const opus_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */ | ||
90 | const opus_int search_thres2_Q13, /* I Final threshold for lag candidates 0 - 1 */ | ||
91 | const opus_int Fs_kHz, /* I Sample frequency (kHz) */ | ||
92 | const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ | ||
93 | const opus_int nb_subfr, /* I number of 5 ms subframes */ | ||
94 | int arch /* I Run-time architecture */ | ||
95 | ) | ||
96 | { | ||
97 | VARDECL( opus_int16, frame_8kHz_buf ); | ||
98 | VARDECL( opus_int16, frame_4kHz ); | ||
99 | VARDECL( opus_int16, frame_scaled ); | ||
100 | opus_int32 filt_state[ 6 ]; | ||
101 | const opus_int16 *frame, *frame_8kHz; | ||
102 | opus_int i, k, d, j; | ||
103 | VARDECL( opus_int16, C ); | ||
104 | VARDECL( opus_int32, xcorr32 ); | ||
105 | const opus_int16 *target_ptr, *basis_ptr; | ||
106 | opus_int32 cross_corr, normalizer, energy, energy_basis, energy_target; | ||
107 | opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp, shift; | ||
108 | VARDECL( opus_int16, d_comp ); | ||
109 | opus_int32 sum, threshold, lag_counter; | ||
110 | opus_int CBimax, CBimax_new, CBimax_old, lag, start_lag, end_lag, lag_new; | ||
111 | opus_int32 CC[ PE_NB_CBKS_STAGE2_EXT ], CCmax, CCmax_b, CCmax_new_b, CCmax_new; | ||
112 | VARDECL( silk_pe_stage3_vals, energies_st3 ); | ||
113 | VARDECL( silk_pe_stage3_vals, cross_corr_st3 ); | ||
114 | opus_int frame_length, frame_length_8kHz, frame_length_4kHz; | ||
115 | opus_int sf_length; | ||
116 | opus_int min_lag; | ||
117 | opus_int max_lag; | ||
118 | opus_int32 contour_bias_Q15, diff; | ||
119 | opus_int nb_cbk_search, cbk_size; | ||
120 | opus_int32 delta_lag_log2_sqr_Q7, lag_log2_Q7, prevLag_log2_Q7, prev_lag_bias_Q13; | ||
121 | const opus_int8 *Lag_CB_ptr; | ||
122 | SAVE_STACK; | ||
123 | |||
124 | /* Check for valid sampling frequency */ | ||
125 | celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 ); | ||
126 | |||
127 | /* Check for valid complexity setting */ | ||
128 | celt_assert( complexity >= SILK_PE_MIN_COMPLEX ); | ||
129 | celt_assert( complexity <= SILK_PE_MAX_COMPLEX ); | ||
130 | |||
131 | silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) ); | ||
132 | silk_assert( search_thres2_Q13 >= 0 && search_thres2_Q13 <= (1<<13) ); | ||
133 | |||
134 | /* Set up frame lengths max / min lag for the sampling frequency */ | ||
135 | frame_length = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz; | ||
136 | frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4; | ||
137 | frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8; | ||
138 | sf_length = PE_SUBFR_LENGTH_MS * Fs_kHz; | ||
139 | min_lag = PE_MIN_LAG_MS * Fs_kHz; | ||
140 | max_lag = PE_MAX_LAG_MS * Fs_kHz - 1; | ||
141 | |||
142 | /* Downscale input if necessary */ | ||
143 | silk_sum_sqr_shift( &energy, &shift, frame_unscaled, frame_length ); | ||
144 | shift += 3 - silk_CLZ32( energy ); /* at least two bits headroom */ | ||
145 | ALLOC( frame_scaled, frame_length, opus_int16 ); | ||
146 | if( shift > 0 ) { | ||
147 | shift = silk_RSHIFT( shift + 1, 1 ); | ||
148 | for( i = 0; i < frame_length; i++ ) { | ||
149 | frame_scaled[ i ] = silk_RSHIFT( frame_unscaled[ i ], shift ); | ||
150 | } | ||
151 | frame = frame_scaled; | ||
152 | } else { | ||
153 | frame = frame_unscaled; | ||
154 | } | ||
155 | |||
156 | ALLOC( frame_8kHz_buf, ( Fs_kHz == 8 ) ? 1 : frame_length_8kHz, opus_int16 ); | ||
157 | /* Resample from input sampled at Fs_kHz to 8 kHz */ | ||
158 | if( Fs_kHz == 16 ) { | ||
159 | silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) ); | ||
160 | silk_resampler_down2( filt_state, frame_8kHz_buf, frame, frame_length ); | ||
161 | frame_8kHz = frame_8kHz_buf; | ||
162 | } else if( Fs_kHz == 12 ) { | ||
163 | silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) ); | ||
164 | silk_resampler_down2_3( filt_state, frame_8kHz_buf, frame, frame_length ); | ||
165 | frame_8kHz = frame_8kHz_buf; | ||
166 | } else { | ||
167 | celt_assert( Fs_kHz == 8 ); | ||
168 | frame_8kHz = frame; | ||
169 | } | ||
170 | |||
171 | /* Decimate again to 4 kHz */ | ||
172 | silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );/* Set state to zero */ | ||
173 | ALLOC( frame_4kHz, frame_length_4kHz, opus_int16 ); | ||
174 | silk_resampler_down2( filt_state, frame_4kHz, frame_8kHz, frame_length_8kHz ); | ||
175 | |||
176 | /* Low-pass filter */ | ||
177 | for( i = frame_length_4kHz - 1; i > 0; i-- ) { | ||
178 | frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] ); | ||
179 | } | ||
180 | |||
181 | |||
182 | /****************************************************************************** | ||
183 | * FIRST STAGE, operating in 4 khz | ||
184 | ******************************************************************************/ | ||
185 | ALLOC( C, nb_subfr * CSTRIDE_8KHZ, opus_int16 ); | ||
186 | ALLOC( xcorr32, MAX_LAG_4KHZ-MIN_LAG_4KHZ+1, opus_int32 ); | ||
187 | silk_memset( C, 0, (nb_subfr >> 1) * CSTRIDE_4KHZ * sizeof( opus_int16 ) ); | ||
188 | target_ptr = &frame_4kHz[ silk_LSHIFT( SF_LENGTH_4KHZ, 2 ) ]; | ||
189 | for( k = 0; k < nb_subfr >> 1; k++ ) { | ||
190 | /* Check that we are within range of the array */ | ||
191 | celt_assert( target_ptr >= frame_4kHz ); | ||
192 | celt_assert( target_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz ); | ||
193 | |||
194 | basis_ptr = target_ptr - MIN_LAG_4KHZ; | ||
195 | |||
196 | /* Check that we are within range of the array */ | ||
197 | celt_assert( basis_ptr >= frame_4kHz ); | ||
198 | celt_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz ); | ||
199 | |||
200 | celt_pitch_xcorr( target_ptr, target_ptr - MAX_LAG_4KHZ, xcorr32, SF_LENGTH_8KHZ, MAX_LAG_4KHZ - MIN_LAG_4KHZ + 1, arch ); | ||
201 | |||
202 | /* Calculate first vector products before loop */ | ||
203 | cross_corr = xcorr32[ MAX_LAG_4KHZ - MIN_LAG_4KHZ ]; | ||
204 | normalizer = silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ, arch ); | ||
205 | normalizer = silk_ADD32( normalizer, silk_inner_prod_aligned( basis_ptr, basis_ptr, SF_LENGTH_8KHZ, arch ) ); | ||
206 | normalizer = silk_ADD32( normalizer, silk_SMULBB( SF_LENGTH_8KHZ, 4000 ) ); | ||
207 | |||
208 | matrix_ptr( C, k, 0, CSTRIDE_4KHZ ) = | ||
209 | (opus_int16)silk_DIV32_varQ( cross_corr, normalizer, 13 + 1 ); /* Q13 */ | ||
210 | |||
211 | /* From now on normalizer is computed recursively */ | ||
212 | for( d = MIN_LAG_4KHZ + 1; d <= MAX_LAG_4KHZ; d++ ) { | ||
213 | basis_ptr--; | ||
214 | |||
215 | /* Check that we are within range of the array */ | ||
216 | silk_assert( basis_ptr >= frame_4kHz ); | ||
217 | silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz ); | ||
218 | |||
219 | cross_corr = xcorr32[ MAX_LAG_4KHZ - d ]; | ||
220 | |||
221 | /* Add contribution of new sample and remove contribution from oldest sample */ | ||
222 | normalizer = silk_ADD32( normalizer, | ||
223 | silk_SMULBB( basis_ptr[ 0 ], basis_ptr[ 0 ] ) - | ||
224 | silk_SMULBB( basis_ptr[ SF_LENGTH_8KHZ ], basis_ptr[ SF_LENGTH_8KHZ ] ) ); | ||
225 | |||
226 | matrix_ptr( C, k, d - MIN_LAG_4KHZ, CSTRIDE_4KHZ) = | ||
227 | (opus_int16)silk_DIV32_varQ( cross_corr, normalizer, 13 + 1 ); /* Q13 */ | ||
228 | } | ||
229 | /* Update target pointer */ | ||
230 | target_ptr += SF_LENGTH_8KHZ; | ||
231 | } | ||
232 | |||
233 | /* Combine two subframes into single correlation measure and apply short-lag bias */ | ||
234 | if( nb_subfr == PE_MAX_NB_SUBFR ) { | ||
235 | for( i = MAX_LAG_4KHZ; i >= MIN_LAG_4KHZ; i-- ) { | ||
236 | sum = (opus_int32)matrix_ptr( C, 0, i - MIN_LAG_4KHZ, CSTRIDE_4KHZ ) | ||
237 | + (opus_int32)matrix_ptr( C, 1, i - MIN_LAG_4KHZ, CSTRIDE_4KHZ ); /* Q14 */ | ||
238 | sum = silk_SMLAWB( sum, sum, silk_LSHIFT( -i, 4 ) ); /* Q14 */ | ||
239 | C[ i - MIN_LAG_4KHZ ] = (opus_int16)sum; /* Q14 */ | ||
240 | } | ||
241 | } else { | ||
242 | /* Only short-lag bias */ | ||
243 | for( i = MAX_LAG_4KHZ; i >= MIN_LAG_4KHZ; i-- ) { | ||
244 | sum = silk_LSHIFT( (opus_int32)C[ i - MIN_LAG_4KHZ ], 1 ); /* Q14 */ | ||
245 | sum = silk_SMLAWB( sum, sum, silk_LSHIFT( -i, 4 ) ); /* Q14 */ | ||
246 | C[ i - MIN_LAG_4KHZ ] = (opus_int16)sum; /* Q14 */ | ||
247 | } | ||
248 | } | ||
249 | |||
250 | /* Sort */ | ||
251 | length_d_srch = silk_ADD_LSHIFT32( 4, complexity, 1 ); | ||
252 | celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH ); | ||
253 | silk_insertion_sort_decreasing_int16( C, d_srch, CSTRIDE_4KHZ, | ||
254 | length_d_srch ); | ||
255 | |||
256 | /* Escape if correlation is very low already here */ | ||
257 | Cmax = (opus_int)C[ 0 ]; /* Q14 */ | ||
258 | if( Cmax < SILK_FIX_CONST( 0.2, 14 ) ) { | ||
259 | silk_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); | ||
260 | *LTPCorr_Q15 = 0; | ||
261 | *lagIndex = 0; | ||
262 | *contourIndex = 0; | ||
263 | RESTORE_STACK; | ||
264 | return 1; | ||
265 | } | ||
266 | |||
267 | threshold = silk_SMULWB( search_thres1_Q16, Cmax ); | ||
268 | for( i = 0; i < length_d_srch; i++ ) { | ||
269 | /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */ | ||
270 | if( C[ i ] > threshold ) { | ||
271 | d_srch[ i ] = silk_LSHIFT( d_srch[ i ] + MIN_LAG_4KHZ, 1 ); | ||
272 | } else { | ||
273 | length_d_srch = i; | ||
274 | break; | ||
275 | } | ||
276 | } | ||
277 | celt_assert( length_d_srch > 0 ); | ||
278 | |||
279 | ALLOC( d_comp, D_COMP_STRIDE, opus_int16 ); | ||
280 | for( i = D_COMP_MIN; i < D_COMP_MAX; i++ ) { | ||
281 | d_comp[ i - D_COMP_MIN ] = 0; | ||
282 | } | ||
283 | for( i = 0; i < length_d_srch; i++ ) { | ||
284 | d_comp[ d_srch[ i ] - D_COMP_MIN ] = 1; | ||
285 | } | ||
286 | |||
287 | /* Convolution */ | ||
288 | for( i = D_COMP_MAX - 1; i >= MIN_LAG_8KHZ; i-- ) { | ||
289 | d_comp[ i - D_COMP_MIN ] += | ||
290 | d_comp[ i - 1 - D_COMP_MIN ] + d_comp[ i - 2 - D_COMP_MIN ]; | ||
291 | } | ||
292 | |||
293 | length_d_srch = 0; | ||
294 | for( i = MIN_LAG_8KHZ; i < MAX_LAG_8KHZ + 1; i++ ) { | ||
295 | if( d_comp[ i + 1 - D_COMP_MIN ] > 0 ) { | ||
296 | d_srch[ length_d_srch ] = i; | ||
297 | length_d_srch++; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | /* Convolution */ | ||
302 | for( i = D_COMP_MAX - 1; i >= MIN_LAG_8KHZ; i-- ) { | ||
303 | d_comp[ i - D_COMP_MIN ] += d_comp[ i - 1 - D_COMP_MIN ] | ||
304 | + d_comp[ i - 2 - D_COMP_MIN ] + d_comp[ i - 3 - D_COMP_MIN ]; | ||
305 | } | ||
306 | |||
307 | length_d_comp = 0; | ||
308 | for( i = MIN_LAG_8KHZ; i < D_COMP_MAX; i++ ) { | ||
309 | if( d_comp[ i - D_COMP_MIN ] > 0 ) { | ||
310 | d_comp[ length_d_comp ] = i - 2; | ||
311 | length_d_comp++; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | /********************************************************************************** | ||
316 | ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation | ||
317 | *************************************************************************************/ | ||
318 | |||
319 | /********************************************************************************* | ||
320 | * Find energy of each subframe projected onto its history, for a range of delays | ||
321 | *********************************************************************************/ | ||
322 | silk_memset( C, 0, nb_subfr * CSTRIDE_8KHZ * sizeof( opus_int16 ) ); | ||
323 | |||
324 | target_ptr = &frame_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ]; | ||
325 | for( k = 0; k < nb_subfr; k++ ) { | ||
326 | |||
327 | /* Check that we are within range of the array */ | ||
328 | celt_assert( target_ptr >= frame_8kHz ); | ||
329 | celt_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz ); | ||
330 | |||
331 | energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ, arch ), 1 ); | ||
332 | for( j = 0; j < length_d_comp; j++ ) { | ||
333 | d = d_comp[ j ]; | ||
334 | basis_ptr = target_ptr - d; | ||
335 | |||
336 | /* Check that we are within range of the array */ | ||
337 | silk_assert( basis_ptr >= frame_8kHz ); | ||
338 | silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz ); | ||
339 | |||
340 | cross_corr = silk_inner_prod_aligned( target_ptr, basis_ptr, SF_LENGTH_8KHZ, arch ); | ||
341 | if( cross_corr > 0 ) { | ||
342 | energy_basis = silk_inner_prod_aligned( basis_ptr, basis_ptr, SF_LENGTH_8KHZ, arch ); | ||
343 | matrix_ptr( C, k, d - ( MIN_LAG_8KHZ - 2 ), CSTRIDE_8KHZ ) = | ||
344 | (opus_int16)silk_DIV32_varQ( cross_corr, | ||
345 | silk_ADD32( energy_target, | ||
346 | energy_basis ), | ||
347 | 13 + 1 ); /* Q13 */ | ||
348 | } else { | ||
349 | matrix_ptr( C, k, d - ( MIN_LAG_8KHZ - 2 ), CSTRIDE_8KHZ ) = 0; | ||
350 | } | ||
351 | } | ||
352 | target_ptr += SF_LENGTH_8KHZ; | ||
353 | } | ||
354 | |||
355 | /* search over lag range and lags codebook */ | ||
356 | /* scale factor for lag codebook, as a function of center lag */ | ||
357 | |||
358 | CCmax = silk_int32_MIN; | ||
359 | CCmax_b = silk_int32_MIN; | ||
360 | |||
361 | CBimax = 0; /* To avoid returning undefined lag values */ | ||
362 | lag = -1; /* To check if lag with strong enough correlation has been found */ | ||
363 | |||
364 | if( prevLag > 0 ) { | ||
365 | if( Fs_kHz == 12 ) { | ||
366 | prevLag = silk_DIV32_16( silk_LSHIFT( prevLag, 1 ), 3 ); | ||
367 | } else if( Fs_kHz == 16 ) { | ||
368 | prevLag = silk_RSHIFT( prevLag, 1 ); | ||
369 | } | ||
370 | prevLag_log2_Q7 = silk_lin2log( (opus_int32)prevLag ); | ||
371 | } else { | ||
372 | prevLag_log2_Q7 = 0; | ||
373 | } | ||
374 | silk_assert( search_thres2_Q13 == silk_SAT16( search_thres2_Q13 ) ); | ||
375 | /* Set up stage 2 codebook based on number of subframes */ | ||
376 | if( nb_subfr == PE_MAX_NB_SUBFR ) { | ||
377 | cbk_size = PE_NB_CBKS_STAGE2_EXT; | ||
378 | Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ]; | ||
379 | if( Fs_kHz == 8 && complexity > SILK_PE_MIN_COMPLEX ) { | ||
380 | /* If input is 8 khz use a larger codebook here because it is last stage */ | ||
381 | nb_cbk_search = PE_NB_CBKS_STAGE2_EXT; | ||
382 | } else { | ||
383 | nb_cbk_search = PE_NB_CBKS_STAGE2; | ||
384 | } | ||
385 | } else { | ||
386 | cbk_size = PE_NB_CBKS_STAGE2_10MS; | ||
387 | Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ]; | ||
388 | nb_cbk_search = PE_NB_CBKS_STAGE2_10MS; | ||
389 | } | ||
390 | |||
391 | for( k = 0; k < length_d_srch; k++ ) { | ||
392 | d = d_srch[ k ]; | ||
393 | for( j = 0; j < nb_cbk_search; j++ ) { | ||
394 | CC[ j ] = 0; | ||
395 | for( i = 0; i < nb_subfr; i++ ) { | ||
396 | opus_int d_subfr; | ||
397 | /* Try all codebooks */ | ||
398 | d_subfr = d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size ); | ||
399 | CC[ j ] = CC[ j ] | ||
400 | + (opus_int32)matrix_ptr( C, i, | ||
401 | d_subfr - ( MIN_LAG_8KHZ - 2 ), | ||
402 | CSTRIDE_8KHZ ); | ||
403 | } | ||
404 | } | ||
405 | /* Find best codebook */ | ||
406 | CCmax_new = silk_int32_MIN; | ||
407 | CBimax_new = 0; | ||
408 | for( i = 0; i < nb_cbk_search; i++ ) { | ||
409 | if( CC[ i ] > CCmax_new ) { | ||
410 | CCmax_new = CC[ i ]; | ||
411 | CBimax_new = i; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | /* Bias towards shorter lags */ | ||
416 | lag_log2_Q7 = silk_lin2log( d ); /* Q7 */ | ||
417 | silk_assert( lag_log2_Q7 == silk_SAT16( lag_log2_Q7 ) ); | ||
418 | silk_assert( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ) == silk_SAT16( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ) ) ); | ||
419 | CCmax_new_b = CCmax_new - silk_RSHIFT( silk_SMULBB( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ), lag_log2_Q7 ), 7 ); /* Q13 */ | ||
420 | |||
421 | /* Bias towards previous lag */ | ||
422 | silk_assert( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ) == silk_SAT16( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ) ) ); | ||
423 | if( prevLag > 0 ) { | ||
424 | delta_lag_log2_sqr_Q7 = lag_log2_Q7 - prevLag_log2_Q7; | ||
425 | silk_assert( delta_lag_log2_sqr_Q7 == silk_SAT16( delta_lag_log2_sqr_Q7 ) ); | ||
426 | delta_lag_log2_sqr_Q7 = silk_RSHIFT( silk_SMULBB( delta_lag_log2_sqr_Q7, delta_lag_log2_sqr_Q7 ), 7 ); | ||
427 | prev_lag_bias_Q13 = silk_RSHIFT( silk_SMULBB( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ), *LTPCorr_Q15 ), 15 ); /* Q13 */ | ||
428 | prev_lag_bias_Q13 = silk_DIV32( silk_MUL( prev_lag_bias_Q13, delta_lag_log2_sqr_Q7 ), delta_lag_log2_sqr_Q7 + SILK_FIX_CONST( 0.5, 7 ) ); | ||
429 | CCmax_new_b -= prev_lag_bias_Q13; /* Q13 */ | ||
430 | } | ||
431 | |||
432 | if( CCmax_new_b > CCmax_b && /* Find maximum biased correlation */ | ||
433 | CCmax_new > silk_SMULBB( nb_subfr, search_thres2_Q13 ) && /* Correlation needs to be high enough to be voiced */ | ||
434 | silk_CB_lags_stage2[ 0 ][ CBimax_new ] <= MIN_LAG_8KHZ /* Lag must be in range */ | ||
435 | ) { | ||
436 | CCmax_b = CCmax_new_b; | ||
437 | CCmax = CCmax_new; | ||
438 | lag = d; | ||
439 | CBimax = CBimax_new; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | if( lag == -1 ) { | ||
444 | /* No suitable candidate found */ | ||
445 | silk_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); | ||
446 | *LTPCorr_Q15 = 0; | ||
447 | *lagIndex = 0; | ||
448 | *contourIndex = 0; | ||
449 | RESTORE_STACK; | ||
450 | return 1; | ||
451 | } | ||
452 | |||
453 | /* Output normalized correlation */ | ||
454 | *LTPCorr_Q15 = (opus_int)silk_LSHIFT( silk_DIV32_16( CCmax, nb_subfr ), 2 ); | ||
455 | silk_assert( *LTPCorr_Q15 >= 0 ); | ||
456 | |||
457 | if( Fs_kHz > 8 ) { | ||
458 | /* Search in original signal */ | ||
459 | |||
460 | CBimax_old = CBimax; | ||
461 | /* Compensate for decimation */ | ||
462 | silk_assert( lag == silk_SAT16( lag ) ); | ||
463 | if( Fs_kHz == 12 ) { | ||
464 | lag = silk_RSHIFT( silk_SMULBB( lag, 3 ), 1 ); | ||
465 | } else if( Fs_kHz == 16 ) { | ||
466 | lag = silk_LSHIFT( lag, 1 ); | ||
467 | } else { | ||
468 | lag = silk_SMULBB( lag, 3 ); | ||
469 | } | ||
470 | |||
471 | lag = silk_LIMIT_int( lag, min_lag, max_lag ); | ||
472 | start_lag = silk_max_int( lag - 2, min_lag ); | ||
473 | end_lag = silk_min_int( lag + 2, max_lag ); | ||
474 | lag_new = lag; /* to avoid undefined lag */ | ||
475 | CBimax = 0; /* to avoid undefined lag */ | ||
476 | |||
477 | CCmax = silk_int32_MIN; | ||
478 | /* pitch lags according to second stage */ | ||
479 | for( k = 0; k < nb_subfr; k++ ) { | ||
480 | pitch_out[ k ] = lag + 2 * silk_CB_lags_stage2[ k ][ CBimax_old ]; | ||
481 | } | ||
482 | |||
483 | /* Set up codebook parameters according to complexity setting and frame length */ | ||
484 | if( nb_subfr == PE_MAX_NB_SUBFR ) { | ||
485 | nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ]; | ||
486 | cbk_size = PE_NB_CBKS_STAGE3_MAX; | ||
487 | Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; | ||
488 | } else { | ||
489 | nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; | ||
490 | cbk_size = PE_NB_CBKS_STAGE3_10MS; | ||
491 | Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; | ||
492 | } | ||
493 | |||
494 | /* Calculate the correlations and energies needed in stage 3 */ | ||
495 | ALLOC( energies_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals ); | ||
496 | ALLOC( cross_corr_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals ); | ||
497 | silk_P_Ana_calc_corr_st3( cross_corr_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch ); | ||
498 | silk_P_Ana_calc_energy_st3( energies_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch ); | ||
499 | |||
500 | lag_counter = 0; | ||
501 | silk_assert( lag == silk_SAT16( lag ) ); | ||
502 | contour_bias_Q15 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 15 ), lag ); | ||
503 | |||
504 | target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ]; | ||
505 | energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, nb_subfr * sf_length, arch ), 1 ); | ||
506 | for( d = start_lag; d <= end_lag; d++ ) { | ||
507 | for( j = 0; j < nb_cbk_search; j++ ) { | ||
508 | cross_corr = 0; | ||
509 | energy = energy_target; | ||
510 | for( k = 0; k < nb_subfr; k++ ) { | ||
511 | cross_corr = silk_ADD32( cross_corr, | ||
512 | matrix_ptr( cross_corr_st3, k, j, | ||
513 | nb_cbk_search )[ lag_counter ] ); | ||
514 | energy = silk_ADD32( energy, | ||
515 | matrix_ptr( energies_st3, k, j, | ||
516 | nb_cbk_search )[ lag_counter ] ); | ||
517 | silk_assert( energy >= 0 ); | ||
518 | } | ||
519 | if( cross_corr > 0 ) { | ||
520 | CCmax_new = silk_DIV32_varQ( cross_corr, energy, 13 + 1 ); /* Q13 */ | ||
521 | /* Reduce depending on flatness of contour */ | ||
522 | diff = silk_int16_MAX - silk_MUL( contour_bias_Q15, j ); /* Q15 */ | ||
523 | silk_assert( diff == silk_SAT16( diff ) ); | ||
524 | CCmax_new = silk_SMULWB( CCmax_new, diff ); /* Q14 */ | ||
525 | } else { | ||
526 | CCmax_new = 0; | ||
527 | } | ||
528 | |||
529 | if( CCmax_new > CCmax && ( d + silk_CB_lags_stage3[ 0 ][ j ] ) <= max_lag ) { | ||
530 | CCmax = CCmax_new; | ||
531 | lag_new = d; | ||
532 | CBimax = j; | ||
533 | } | ||
534 | } | ||
535 | lag_counter++; | ||
536 | } | ||
537 | |||
538 | for( k = 0; k < nb_subfr; k++ ) { | ||
539 | pitch_out[ k ] = lag_new + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); | ||
540 | pitch_out[ k ] = silk_LIMIT( pitch_out[ k ], min_lag, PE_MAX_LAG_MS * Fs_kHz ); | ||
541 | } | ||
542 | *lagIndex = (opus_int16)( lag_new - min_lag); | ||
543 | *contourIndex = (opus_int8)CBimax; | ||
544 | } else { /* Fs_kHz == 8 */ | ||
545 | /* Save Lags */ | ||
546 | for( k = 0; k < nb_subfr; k++ ) { | ||
547 | pitch_out[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); | ||
548 | pitch_out[ k ] = silk_LIMIT( pitch_out[ k ], MIN_LAG_8KHZ, PE_MAX_LAG_MS * 8 ); | ||
549 | } | ||
550 | *lagIndex = (opus_int16)( lag - MIN_LAG_8KHZ ); | ||
551 | *contourIndex = (opus_int8)CBimax; | ||
552 | } | ||
553 | celt_assert( *lagIndex >= 0 ); | ||
554 | /* return as voiced */ | ||
555 | RESTORE_STACK; | ||
556 | return 0; | ||
557 | } | ||
558 | |||
559 | /*********************************************************************** | ||
560 | * Calculates the correlations used in stage 3 search. In order to cover | ||
561 | * the whole lag codebook for all the searched offset lags (lag +- 2), | ||
562 | * the following correlations are needed in each sub frame: | ||
563 | * | ||
564 | * sf1: lag range [-8,...,7] total 16 correlations | ||
565 | * sf2: lag range [-4,...,4] total 9 correlations | ||
566 | * sf3: lag range [-3,....4] total 8 correltions | ||
567 | * sf4: lag range [-6,....8] total 15 correlations | ||
568 | * | ||
569 | * In total 48 correlations. The direct implementation computed in worst | ||
570 | * case 4*12*5 = 240 correlations, but more likely around 120. | ||
571 | ***********************************************************************/ | ||
572 | static void silk_P_Ana_calc_corr_st3( | ||
573 | silk_pe_stage3_vals cross_corr_st3[], /* O 3 DIM correlation array */ | ||
574 | const opus_int16 frame[], /* I vector to correlate */ | ||
575 | opus_int start_lag, /* I lag offset to search around */ | ||
576 | opus_int sf_length, /* I length of a 5 ms subframe */ | ||
577 | opus_int nb_subfr, /* I number of subframes */ | ||
578 | opus_int complexity, /* I Complexity setting */ | ||
579 | int arch /* I Run-time architecture */ | ||
580 | ) | ||
581 | { | ||
582 | const opus_int16 *target_ptr; | ||
583 | opus_int i, j, k, lag_counter, lag_low, lag_high; | ||
584 | opus_int nb_cbk_search, delta, idx, cbk_size; | ||
585 | VARDECL( opus_int32, scratch_mem ); | ||
586 | VARDECL( opus_int32, xcorr32 ); | ||
587 | const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; | ||
588 | SAVE_STACK; | ||
589 | |||
590 | celt_assert( complexity >= SILK_PE_MIN_COMPLEX ); | ||
591 | celt_assert( complexity <= SILK_PE_MAX_COMPLEX ); | ||
592 | |||
593 | if( nb_subfr == PE_MAX_NB_SUBFR ) { | ||
594 | Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; | ||
595 | Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; | ||
596 | nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; | ||
597 | cbk_size = PE_NB_CBKS_STAGE3_MAX; | ||
598 | } else { | ||
599 | celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); | ||
600 | Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; | ||
601 | Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; | ||
602 | nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; | ||
603 | cbk_size = PE_NB_CBKS_STAGE3_10MS; | ||
604 | } | ||
605 | ALLOC( scratch_mem, SCRATCH_SIZE, opus_int32 ); | ||
606 | ALLOC( xcorr32, SCRATCH_SIZE, opus_int32 ); | ||
607 | |||
608 | target_ptr = &frame[ silk_LSHIFT( sf_length, 2 ) ]; /* Pointer to middle of frame */ | ||
609 | for( k = 0; k < nb_subfr; k++ ) { | ||
610 | lag_counter = 0; | ||
611 | |||
612 | /* Calculate the correlations for each subframe */ | ||
613 | lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 ); | ||
614 | lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 ); | ||
615 | celt_assert(lag_high-lag_low+1 <= SCRATCH_SIZE); | ||
616 | celt_pitch_xcorr( target_ptr, target_ptr - start_lag - lag_high, xcorr32, sf_length, lag_high - lag_low + 1, arch ); | ||
617 | for( j = lag_low; j <= lag_high; j++ ) { | ||
618 | silk_assert( lag_counter < SCRATCH_SIZE ); | ||
619 | scratch_mem[ lag_counter ] = xcorr32[ lag_high - j ]; | ||
620 | lag_counter++; | ||
621 | } | ||
622 | |||
623 | delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); | ||
624 | for( i = 0; i < nb_cbk_search; i++ ) { | ||
625 | /* Fill out the 3 dim array that stores the correlations for */ | ||
626 | /* each code_book vector for each start lag */ | ||
627 | idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; | ||
628 | for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { | ||
629 | silk_assert( idx + j < SCRATCH_SIZE ); | ||
630 | silk_assert( idx + j < lag_counter ); | ||
631 | matrix_ptr( cross_corr_st3, k, i, nb_cbk_search )[ j ] = | ||
632 | scratch_mem[ idx + j ]; | ||
633 | } | ||
634 | } | ||
635 | target_ptr += sf_length; | ||
636 | } | ||
637 | RESTORE_STACK; | ||
638 | } | ||
639 | |||
640 | /********************************************************************/ | ||
641 | /* Calculate the energies for first two subframes. The energies are */ | ||
642 | /* calculated recursively. */ | ||
643 | /********************************************************************/ | ||
644 | static void silk_P_Ana_calc_energy_st3( | ||
645 | silk_pe_stage3_vals energies_st3[], /* O 3 DIM energy array */ | ||
646 | const opus_int16 frame[], /* I vector to calc energy in */ | ||
647 | opus_int start_lag, /* I lag offset to search around */ | ||
648 | opus_int sf_length, /* I length of one 5 ms subframe */ | ||
649 | opus_int nb_subfr, /* I number of subframes */ | ||
650 | opus_int complexity, /* I Complexity setting */ | ||
651 | int arch /* I Run-time architecture */ | ||
652 | ) | ||
653 | { | ||
654 | const opus_int16 *target_ptr, *basis_ptr; | ||
655 | opus_int32 energy; | ||
656 | opus_int k, i, j, lag_counter; | ||
657 | opus_int nb_cbk_search, delta, idx, cbk_size, lag_diff; | ||
658 | VARDECL( opus_int32, scratch_mem ); | ||
659 | const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; | ||
660 | SAVE_STACK; | ||
661 | |||
662 | celt_assert( complexity >= SILK_PE_MIN_COMPLEX ); | ||
663 | celt_assert( complexity <= SILK_PE_MAX_COMPLEX ); | ||
664 | |||
665 | if( nb_subfr == PE_MAX_NB_SUBFR ) { | ||
666 | Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; | ||
667 | Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; | ||
668 | nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; | ||
669 | cbk_size = PE_NB_CBKS_STAGE3_MAX; | ||
670 | } else { | ||
671 | celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); | ||
672 | Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; | ||
673 | Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; | ||
674 | nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; | ||
675 | cbk_size = PE_NB_CBKS_STAGE3_10MS; | ||
676 | } | ||
677 | ALLOC( scratch_mem, SCRATCH_SIZE, opus_int32 ); | ||
678 | |||
679 | target_ptr = &frame[ silk_LSHIFT( sf_length, 2 ) ]; | ||
680 | for( k = 0; k < nb_subfr; k++ ) { | ||
681 | lag_counter = 0; | ||
682 | |||
683 | /* Calculate the energy for first lag */ | ||
684 | basis_ptr = target_ptr - ( start_lag + matrix_ptr( Lag_range_ptr, k, 0, 2 ) ); | ||
685 | energy = silk_inner_prod_aligned( basis_ptr, basis_ptr, sf_length, arch ); | ||
686 | silk_assert( energy >= 0 ); | ||
687 | scratch_mem[ lag_counter ] = energy; | ||
688 | lag_counter++; | ||
689 | |||
690 | lag_diff = ( matrix_ptr( Lag_range_ptr, k, 1, 2 ) - matrix_ptr( Lag_range_ptr, k, 0, 2 ) + 1 ); | ||
691 | for( i = 1; i < lag_diff; i++ ) { | ||
692 | /* remove part outside new window */ | ||
693 | energy -= silk_SMULBB( basis_ptr[ sf_length - i ], basis_ptr[ sf_length - i ] ); | ||
694 | silk_assert( energy >= 0 ); | ||
695 | |||
696 | /* add part that comes into window */ | ||
697 | energy = silk_ADD_SAT32( energy, silk_SMULBB( basis_ptr[ -i ], basis_ptr[ -i ] ) ); | ||
698 | silk_assert( energy >= 0 ); | ||
699 | silk_assert( lag_counter < SCRATCH_SIZE ); | ||
700 | scratch_mem[ lag_counter ] = energy; | ||
701 | lag_counter++; | ||
702 | } | ||
703 | |||
704 | delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); | ||
705 | for( i = 0; i < nb_cbk_search; i++ ) { | ||
706 | /* Fill out the 3 dim array that stores the correlations for */ | ||
707 | /* each code_book vector for each start lag */ | ||
708 | idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; | ||
709 | for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { | ||
710 | silk_assert( idx + j < SCRATCH_SIZE ); | ||
711 | silk_assert( idx + j < lag_counter ); | ||
712 | matrix_ptr( energies_st3, k, i, nb_cbk_search )[ j ] = | ||
713 | scratch_mem[ idx + j ]; | ||
714 | silk_assert( | ||
715 | matrix_ptr( energies_st3, k, i, nb_cbk_search )[ j ] >= 0 ); | ||
716 | } | ||
717 | } | ||
718 | target_ptr += sf_length; | ||
719 | } | ||
720 | RESTORE_STACK; | ||
721 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/process_gains_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/process_gains_FIX.c new file mode 100644 index 0000000000..05aba31788 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/process_gains_FIX.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | #include "tuning_parameters.h" | ||
34 | |||
35 | /* Processing of gains */ | ||
36 | void silk_process_gains_FIX( | ||
37 | silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ | ||
38 | silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control */ | ||
39 | opus_int condCoding /* I The type of conditional coding to use */ | ||
40 | ) | ||
41 | { | ||
42 | silk_shape_state_FIX *psShapeSt = &psEnc->sShape; | ||
43 | opus_int k; | ||
44 | opus_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart, quant_offset_Q10; | ||
45 | |||
46 | /* Gain reduction when LTP coding gain is high */ | ||
47 | if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
48 | /*s = -0.5f * silk_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ | ||
49 | s_Q16 = -silk_sigm_Q15( silk_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - SILK_FIX_CONST( 12.0, 7 ), 4 ) ); | ||
50 | for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
51 | psEncCtrl->Gains_Q16[ k ] = silk_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | /* Limit the quantized signal */ | ||
56 | /* InvMaxSqrVal = pow( 2.0f, 0.33f * ( 21.0f - SNR_dB ) ) / subfr_length; */ | ||
57 | InvMaxSqrVal_Q16 = silk_DIV32_16( silk_log2lin( | ||
58 | silk_SMULWB( SILK_FIX_CONST( 21 + 16 / 0.33, 7 ) - psEnc->sCmn.SNR_dB_Q7, SILK_FIX_CONST( 0.33, 16 ) ) ), psEnc->sCmn.subfr_length ); | ||
59 | |||
60 | for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { | ||
61 | /* Soft limit on ratio residual energy and squared gains */ | ||
62 | ResNrg = psEncCtrl->ResNrg[ k ]; | ||
63 | ResNrgPart = silk_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); | ||
64 | if( psEncCtrl->ResNrgQ[ k ] > 0 ) { | ||
65 | ResNrgPart = silk_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); | ||
66 | } else { | ||
67 | if( ResNrgPart >= silk_RSHIFT( silk_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { | ||
68 | ResNrgPart = silk_int32_MAX; | ||
69 | } else { | ||
70 | ResNrgPart = silk_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); | ||
71 | } | ||
72 | } | ||
73 | gain = psEncCtrl->Gains_Q16[ k ]; | ||
74 | gain_squared = silk_ADD_SAT32( ResNrgPart, silk_SMMUL( gain, gain ) ); | ||
75 | if( gain_squared < silk_int16_MAX ) { | ||
76 | /* recalculate with higher precision */ | ||
77 | gain_squared = silk_SMLAWW( silk_LSHIFT( ResNrgPart, 16 ), gain, gain ); | ||
78 | silk_assert( gain_squared > 0 ); | ||
79 | gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ | ||
80 | gain = silk_min( gain, silk_int32_MAX >> 8 ); | ||
81 | psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( gain, 8 ); /* Q16 */ | ||
82 | } else { | ||
83 | gain = silk_SQRT_APPROX( gain_squared ); /* Q0 */ | ||
84 | gain = silk_min( gain, silk_int32_MAX >> 16 ); | ||
85 | psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( gain, 16 ); /* Q16 */ | ||
86 | } | ||
87 | } | ||
88 | |||
89 | /* Save unquantized gains and gain Index */ | ||
90 | silk_memcpy( psEncCtrl->GainsUnq_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); | ||
91 | psEncCtrl->lastGainIndexPrev = psShapeSt->LastGainIndex; | ||
92 | |||
93 | /* Quantize gains */ | ||
94 | silk_gains_quant( psEnc->sCmn.indices.GainsIndices, psEncCtrl->Gains_Q16, | ||
95 | &psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); | ||
96 | |||
97 | /* Set quantizer offset for voiced signals. Larger offset when LTP coding gain is low or tilt is high (ie low-pass) */ | ||
98 | if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { | ||
99 | if( psEncCtrl->LTPredCodGain_Q7 + silk_RSHIFT( psEnc->sCmn.input_tilt_Q15, 8 ) > SILK_FIX_CONST( 1.0, 7 ) ) { | ||
100 | psEnc->sCmn.indices.quantOffsetType = 0; | ||
101 | } else { | ||
102 | psEnc->sCmn.indices.quantOffsetType = 1; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | /* Quantizer boundary adjustment */ | ||
107 | quant_offset_Q10 = silk_Quantization_Offsets_Q10[ psEnc->sCmn.indices.signalType >> 1 ][ psEnc->sCmn.indices.quantOffsetType ]; | ||
108 | psEncCtrl->Lambda_Q10 = SILK_FIX_CONST( LAMBDA_OFFSET, 10 ) | ||
109 | + silk_SMULBB( SILK_FIX_CONST( LAMBDA_DELAYED_DECISIONS, 10 ), psEnc->sCmn.nStatesDelayedDecision ) | ||
110 | + silk_SMULWB( SILK_FIX_CONST( LAMBDA_SPEECH_ACT, 18 ), psEnc->sCmn.speech_activity_Q8 ) | ||
111 | + silk_SMULWB( SILK_FIX_CONST( LAMBDA_INPUT_QUALITY, 12 ), psEncCtrl->input_quality_Q14 ) | ||
112 | + silk_SMULWB( SILK_FIX_CONST( LAMBDA_CODING_QUALITY, 12 ), psEncCtrl->coding_quality_Q14 ) | ||
113 | + silk_SMULWB( SILK_FIX_CONST( LAMBDA_QUANT_OFFSET, 16 ), quant_offset_Q10 ); | ||
114 | |||
115 | silk_assert( psEncCtrl->Lambda_Q10 > 0 ); | ||
116 | silk_assert( psEncCtrl->Lambda_Q10 < SILK_FIX_CONST( 2, 10 ) ); | ||
117 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/regularize_correlations_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/regularize_correlations_FIX.c new file mode 100644 index 0000000000..a2836b05f4 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/regularize_correlations_FIX.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | |||
34 | /* Add noise to matrix diagonal */ | ||
35 | void silk_regularize_correlations_FIX( | ||
36 | opus_int32 *XX, /* I/O Correlation matrices */ | ||
37 | opus_int32 *xx, /* I/O Correlation values */ | ||
38 | opus_int32 noise, /* I Noise to add */ | ||
39 | opus_int D /* I Dimension of XX */ | ||
40 | ) | ||
41 | { | ||
42 | opus_int i; | ||
43 | for( i = 0; i < D; i++ ) { | ||
44 | matrix_ptr( &XX[ 0 ], i, i, D ) = silk_ADD32( matrix_ptr( &XX[ 0 ], i, i, D ), noise ); | ||
45 | } | ||
46 | xx[ 0 ] += noise; | ||
47 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/residual_energy16_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/residual_energy16_FIX.c new file mode 100644 index 0000000000..7f130f3d3d --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/residual_energy16_FIX.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | |||
34 | /* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ | ||
35 | opus_int32 silk_residual_energy16_covar_FIX( | ||
36 | const opus_int16 *c, /* I Prediction vector */ | ||
37 | const opus_int32 *wXX, /* I Correlation matrix */ | ||
38 | const opus_int32 *wXx, /* I Correlation vector */ | ||
39 | opus_int32 wxx, /* I Signal energy */ | ||
40 | opus_int D, /* I Dimension */ | ||
41 | opus_int cQ /* I Q value for c vector 0 - 15 */ | ||
42 | ) | ||
43 | { | ||
44 | opus_int i, j, lshifts, Qxtra; | ||
45 | opus_int32 c_max, w_max, tmp, tmp2, nrg; | ||
46 | opus_int cn[ MAX_MATRIX_SIZE ]; | ||
47 | const opus_int32 *pRow; | ||
48 | |||
49 | /* Safety checks */ | ||
50 | celt_assert( D >= 0 ); | ||
51 | celt_assert( D <= 16 ); | ||
52 | celt_assert( cQ > 0 ); | ||
53 | celt_assert( cQ < 16 ); | ||
54 | |||
55 | lshifts = 16 - cQ; | ||
56 | Qxtra = lshifts; | ||
57 | |||
58 | c_max = 0; | ||
59 | for( i = 0; i < D; i++ ) { | ||
60 | c_max = silk_max_32( c_max, silk_abs( (opus_int32)c[ i ] ) ); | ||
61 | } | ||
62 | Qxtra = silk_min_int( Qxtra, silk_CLZ32( c_max ) - 17 ); | ||
63 | |||
64 | w_max = silk_max_32( wXX[ 0 ], wXX[ D * D - 1 ] ); | ||
65 | Qxtra = silk_min_int( Qxtra, silk_CLZ32( silk_MUL( D, silk_RSHIFT( silk_SMULWB( w_max, c_max ), 4 ) ) ) - 5 ); | ||
66 | Qxtra = silk_max_int( Qxtra, 0 ); | ||
67 | for( i = 0; i < D; i++ ) { | ||
68 | cn[ i ] = silk_LSHIFT( ( opus_int )c[ i ], Qxtra ); | ||
69 | silk_assert( silk_abs(cn[i]) <= ( silk_int16_MAX + 1 ) ); /* Check that silk_SMLAWB can be used */ | ||
70 | } | ||
71 | lshifts -= Qxtra; | ||
72 | |||
73 | /* Compute wxx - 2 * wXx * c */ | ||
74 | tmp = 0; | ||
75 | for( i = 0; i < D; i++ ) { | ||
76 | tmp = silk_SMLAWB( tmp, wXx[ i ], cn[ i ] ); | ||
77 | } | ||
78 | nrg = silk_RSHIFT( wxx, 1 + lshifts ) - tmp; /* Q: -lshifts - 1 */ | ||
79 | |||
80 | /* Add c' * wXX * c, assuming wXX is symmetric */ | ||
81 | tmp2 = 0; | ||
82 | for( i = 0; i < D; i++ ) { | ||
83 | tmp = 0; | ||
84 | pRow = &wXX[ i * D ]; | ||
85 | for( j = i + 1; j < D; j++ ) { | ||
86 | tmp = silk_SMLAWB( tmp, pRow[ j ], cn[ j ] ); | ||
87 | } | ||
88 | tmp = silk_SMLAWB( tmp, silk_RSHIFT( pRow[ i ], 1 ), cn[ i ] ); | ||
89 | tmp2 = silk_SMLAWB( tmp2, tmp, cn[ i ] ); | ||
90 | } | ||
91 | nrg = silk_ADD_LSHIFT32( nrg, tmp2, lshifts ); /* Q: -lshifts - 1 */ | ||
92 | |||
93 | /* Keep one bit free always, because we add them for LSF interpolation */ | ||
94 | if( nrg < 1 ) { | ||
95 | nrg = 1; | ||
96 | } else if( nrg > silk_RSHIFT( silk_int32_MAX, lshifts + 2 ) ) { | ||
97 | nrg = silk_int32_MAX >> 1; | ||
98 | } else { | ||
99 | nrg = silk_LSHIFT( nrg, lshifts + 1 ); /* Q0 */ | ||
100 | } | ||
101 | return nrg; | ||
102 | |||
103 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/residual_energy_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/residual_energy_FIX.c new file mode 100644 index 0000000000..6c7cade9a0 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/residual_energy_FIX.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | #include "stack_alloc.h" | ||
34 | |||
35 | /* Calculates residual energies of input subframes where all subframes have LPC_order */ | ||
36 | /* of preceding samples */ | ||
37 | void silk_residual_energy_FIX( | ||
38 | opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ | ||
39 | opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ | ||
40 | const opus_int16 x[], /* I Input signal */ | ||
41 | opus_int16 a_Q12[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ | ||
42 | const opus_int32 gains[ MAX_NB_SUBFR ], /* I Quantization gains */ | ||
43 | const opus_int subfr_length, /* I Subframe length */ | ||
44 | const opus_int nb_subfr, /* I Number of subframes */ | ||
45 | const opus_int LPC_order, /* I LPC order */ | ||
46 | int arch /* I Run-time architecture */ | ||
47 | ) | ||
48 | { | ||
49 | opus_int offset, i, j, rshift, lz1, lz2; | ||
50 | opus_int16 *LPC_res_ptr; | ||
51 | VARDECL( opus_int16, LPC_res ); | ||
52 | const opus_int16 *x_ptr; | ||
53 | opus_int32 tmp32; | ||
54 | SAVE_STACK; | ||
55 | |||
56 | x_ptr = x; | ||
57 | offset = LPC_order + subfr_length; | ||
58 | |||
59 | /* Filter input to create the LPC residual for each frame half, and measure subframe energies */ | ||
60 | ALLOC( LPC_res, ( MAX_NB_SUBFR >> 1 ) * offset, opus_int16 ); | ||
61 | celt_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr ); | ||
62 | for( i = 0; i < nb_subfr >> 1; i++ ) { | ||
63 | /* Calculate half frame LPC residual signal including preceding samples */ | ||
64 | silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order, arch ); | ||
65 | |||
66 | /* Point to first subframe of the just calculated LPC residual signal */ | ||
67 | LPC_res_ptr = LPC_res + LPC_order; | ||
68 | for( j = 0; j < ( MAX_NB_SUBFR >> 1 ); j++ ) { | ||
69 | /* Measure subframe energy */ | ||
70 | silk_sum_sqr_shift( &nrgs[ i * ( MAX_NB_SUBFR >> 1 ) + j ], &rshift, LPC_res_ptr, subfr_length ); | ||
71 | |||
72 | /* Set Q values for the measured energy */ | ||
73 | nrgsQ[ i * ( MAX_NB_SUBFR >> 1 ) + j ] = -rshift; | ||
74 | |||
75 | /* Move to next subframe */ | ||
76 | LPC_res_ptr += offset; | ||
77 | } | ||
78 | /* Move to next frame half */ | ||
79 | x_ptr += ( MAX_NB_SUBFR >> 1 ) * offset; | ||
80 | } | ||
81 | |||
82 | /* Apply the squared subframe gains */ | ||
83 | for( i = 0; i < nb_subfr; i++ ) { | ||
84 | /* Fully upscale gains and energies */ | ||
85 | lz1 = silk_CLZ32( nrgs[ i ] ) - 1; | ||
86 | lz2 = silk_CLZ32( gains[ i ] ) - 1; | ||
87 | |||
88 | tmp32 = silk_LSHIFT32( gains[ i ], lz2 ); | ||
89 | |||
90 | /* Find squared gains */ | ||
91 | tmp32 = silk_SMMUL( tmp32, tmp32 ); /* Q( 2 * lz2 - 32 )*/ | ||
92 | |||
93 | /* Scale energies */ | ||
94 | nrgs[ i ] = silk_SMMUL( tmp32, silk_LSHIFT32( nrgs[ i ], lz1 ) ); /* Q( nrgsQ[ i ] + lz1 + 2 * lz2 - 32 - 32 )*/ | ||
95 | nrgsQ[ i ] += lz1 + 2 * lz2 - 32 - 32; | ||
96 | } | ||
97 | RESTORE_STACK; | ||
98 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/schur64_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/schur64_FIX.c new file mode 100644 index 0000000000..4b7e19ea59 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/schur64_FIX.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "SigProc_FIX.h" | ||
33 | |||
34 | /* Slower than schur(), but more accurate. */ | ||
35 | /* Uses SMULL(), available on armv4 */ | ||
36 | opus_int32 silk_schur64( /* O returns residual energy */ | ||
37 | opus_int32 rc_Q16[], /* O Reflection coefficients [order] Q16 */ | ||
38 | const opus_int32 c[], /* I Correlations [order+1] */ | ||
39 | opus_int32 order /* I Prediction order */ | ||
40 | ) | ||
41 | { | ||
42 | opus_int k, n; | ||
43 | opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; | ||
44 | opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31; | ||
45 | |||
46 | celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC ); | ||
47 | |||
48 | /* Check for invalid input */ | ||
49 | if( c[ 0 ] <= 0 ) { | ||
50 | silk_memset( rc_Q16, 0, order * sizeof( opus_int32 ) ); | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | k = 0; | ||
55 | do { | ||
56 | C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; | ||
57 | } while( ++k <= order ); | ||
58 | |||
59 | for( k = 0; k < order; k++ ) { | ||
60 | /* Check that we won't be getting an unstable rc, otherwise stop here. */ | ||
61 | if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { | ||
62 | if ( C[ k + 1 ][ 0 ] > 0 ) { | ||
63 | rc_Q16[ k ] = -SILK_FIX_CONST( .99f, 16 ); | ||
64 | } else { | ||
65 | rc_Q16[ k ] = SILK_FIX_CONST( .99f, 16 ); | ||
66 | } | ||
67 | k++; | ||
68 | break; | ||
69 | } | ||
70 | |||
71 | /* Get reflection coefficient: divide two Q30 values and get result in Q31 */ | ||
72 | rc_tmp_Q31 = silk_DIV32_varQ( -C[ k + 1 ][ 0 ], C[ 0 ][ 1 ], 31 ); | ||
73 | |||
74 | /* Save the output */ | ||
75 | rc_Q16[ k ] = silk_RSHIFT_ROUND( rc_tmp_Q31, 15 ); | ||
76 | |||
77 | /* Update correlations */ | ||
78 | for( n = 0; n < order - k; n++ ) { | ||
79 | Ctmp1_Q30 = C[ n + k + 1 ][ 0 ]; | ||
80 | Ctmp2_Q30 = C[ n ][ 1 ]; | ||
81 | |||
82 | /* Multiply and add the highest int32 */ | ||
83 | C[ n + k + 1 ][ 0 ] = Ctmp1_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp2_Q30, 1 ), rc_tmp_Q31 ); | ||
84 | C[ n ][ 1 ] = Ctmp2_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp1_Q30, 1 ), rc_tmp_Q31 ); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | for(; k < order; k++ ) { | ||
89 | rc_Q16[ k ] = 0; | ||
90 | } | ||
91 | |||
92 | return silk_max_32( 1, C[ 0 ][ 1 ] ); | ||
93 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/schur_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/schur_FIX.c new file mode 100644 index 0000000000..2840f6b1aa --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/schur_FIX.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "SigProc_FIX.h" | ||
33 | |||
34 | /* Faster than schur64(), but much less accurate. */ | ||
35 | /* uses SMLAWB(), requiring armv5E and higher. */ | ||
36 | opus_int32 silk_schur( /* O Returns residual energy */ | ||
37 | opus_int16 *rc_Q15, /* O reflection coefficients [order] Q15 */ | ||
38 | const opus_int32 *c, /* I correlations [order+1] */ | ||
39 | const opus_int32 order /* I prediction order */ | ||
40 | ) | ||
41 | { | ||
42 | opus_int k, n, lz; | ||
43 | opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; | ||
44 | opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15; | ||
45 | |||
46 | celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC ); | ||
47 | |||
48 | /* Get number of leading zeros */ | ||
49 | lz = silk_CLZ32( c[ 0 ] ); | ||
50 | |||
51 | /* Copy correlations and adjust level to Q30 */ | ||
52 | k = 0; | ||
53 | if( lz < 2 ) { | ||
54 | /* lz must be 1, so shift one to the right */ | ||
55 | do { | ||
56 | C[ k ][ 0 ] = C[ k ][ 1 ] = silk_RSHIFT( c[ k ], 1 ); | ||
57 | } while( ++k <= order ); | ||
58 | } else if( lz > 2 ) { | ||
59 | /* Shift to the left */ | ||
60 | lz -= 2; | ||
61 | do { | ||
62 | C[ k ][ 0 ] = C[ k ][ 1 ] = silk_LSHIFT( c[ k ], lz ); | ||
63 | } while( ++k <= order ); | ||
64 | } else { | ||
65 | /* No need to shift */ | ||
66 | do { | ||
67 | C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; | ||
68 | } while( ++k <= order ); | ||
69 | } | ||
70 | |||
71 | for( k = 0; k < order; k++ ) { | ||
72 | /* Check that we won't be getting an unstable rc, otherwise stop here. */ | ||
73 | if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { | ||
74 | if ( C[ k + 1 ][ 0 ] > 0 ) { | ||
75 | rc_Q15[ k ] = -SILK_FIX_CONST( .99f, 15 ); | ||
76 | } else { | ||
77 | rc_Q15[ k ] = SILK_FIX_CONST( .99f, 15 ); | ||
78 | } | ||
79 | k++; | ||
80 | break; | ||
81 | } | ||
82 | |||
83 | /* Get reflection coefficient */ | ||
84 | rc_tmp_Q15 = -silk_DIV32_16( C[ k + 1 ][ 0 ], silk_max_32( silk_RSHIFT( C[ 0 ][ 1 ], 15 ), 1 ) ); | ||
85 | |||
86 | /* Clip (shouldn't happen for properly conditioned inputs) */ | ||
87 | rc_tmp_Q15 = silk_SAT16( rc_tmp_Q15 ); | ||
88 | |||
89 | /* Store */ | ||
90 | rc_Q15[ k ] = (opus_int16)rc_tmp_Q15; | ||
91 | |||
92 | /* Update correlations */ | ||
93 | for( n = 0; n < order - k; n++ ) { | ||
94 | Ctmp1 = C[ n + k + 1 ][ 0 ]; | ||
95 | Ctmp2 = C[ n ][ 1 ]; | ||
96 | C[ n + k + 1 ][ 0 ] = silk_SMLAWB( Ctmp1, silk_LSHIFT( Ctmp2, 1 ), rc_tmp_Q15 ); | ||
97 | C[ n ][ 1 ] = silk_SMLAWB( Ctmp2, silk_LSHIFT( Ctmp1, 1 ), rc_tmp_Q15 ); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | for(; k < order; k++ ) { | ||
102 | rc_Q15[ k ] = 0; | ||
103 | } | ||
104 | |||
105 | /* return residual energy */ | ||
106 | return silk_max_32( 1, C[ 0 ][ 1 ] ); | ||
107 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/structs_FIX.h b/lib/rbcodec/codecs/libopus/silk/fixed/structs_FIX.h new file mode 100644 index 0000000000..2774a97b24 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/structs_FIX.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifndef SILK_STRUCTS_FIX_H | ||
29 | #define SILK_STRUCTS_FIX_H | ||
30 | |||
31 | #include "typedef.h" | ||
32 | #include "main.h" | ||
33 | #include "structs.h" | ||
34 | |||
35 | #ifdef __cplusplus | ||
36 | extern "C" | ||
37 | { | ||
38 | #endif | ||
39 | |||
40 | /********************************/ | ||
41 | /* Noise shaping analysis state */ | ||
42 | /********************************/ | ||
43 | typedef struct { | ||
44 | opus_int8 LastGainIndex; | ||
45 | opus_int32 HarmBoost_smth_Q16; | ||
46 | opus_int32 HarmShapeGain_smth_Q16; | ||
47 | opus_int32 Tilt_smth_Q16; | ||
48 | } silk_shape_state_FIX; | ||
49 | |||
50 | /********************************/ | ||
51 | /* Encoder state FIX */ | ||
52 | /********************************/ | ||
53 | typedef struct { | ||
54 | silk_encoder_state sCmn; /* Common struct, shared with floating-point code */ | ||
55 | silk_shape_state_FIX sShape; /* Shape state */ | ||
56 | |||
57 | /* Buffer for find pitch and noise shape analysis */ | ||
58 | silk_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */ | ||
59 | opus_int LTPCorr_Q15; /* Normalized correlation from pitch lag estimator */ | ||
60 | opus_int32 resNrgSmth; | ||
61 | } silk_encoder_state_FIX; | ||
62 | |||
63 | /************************/ | ||
64 | /* Encoder control FIX */ | ||
65 | /************************/ | ||
66 | typedef struct { | ||
67 | /* Prediction and coding parameters */ | ||
68 | opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; | ||
69 | silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; | ||
70 | opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; | ||
71 | opus_int LTP_scale_Q14; | ||
72 | opus_int pitchL[ MAX_NB_SUBFR ]; | ||
73 | |||
74 | /* Noise shaping parameters */ | ||
75 | /* Testing */ | ||
76 | silk_DWORD_ALIGN opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; | ||
77 | opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */ | ||
78 | opus_int Tilt_Q14[ MAX_NB_SUBFR ]; | ||
79 | opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ]; | ||
80 | opus_int Lambda_Q10; | ||
81 | opus_int input_quality_Q14; | ||
82 | opus_int coding_quality_Q14; | ||
83 | |||
84 | /* measures */ | ||
85 | opus_int32 predGain_Q16; | ||
86 | opus_int LTPredCodGain_Q7; | ||
87 | opus_int32 ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */ | ||
88 | opus_int ResNrgQ[ MAX_NB_SUBFR ]; /* Q domain for the residual energy > 0 */ | ||
89 | |||
90 | /* Parameters for CBR mode */ | ||
91 | opus_int32 GainsUnq_Q16[ MAX_NB_SUBFR ]; | ||
92 | opus_int8 lastGainIndexPrev; | ||
93 | } silk_encoder_control_FIX; | ||
94 | |||
95 | /************************/ | ||
96 | /* Encoder Super Struct */ | ||
97 | /************************/ | ||
98 | typedef struct { | ||
99 | silk_encoder_state_FIX state_Fxx[ ENCODER_NUM_CHANNELS ]; | ||
100 | stereo_enc_state sStereo; | ||
101 | opus_int32 nBitsUsedLBRR; | ||
102 | opus_int32 nBitsExceeded; | ||
103 | opus_int nChannelsAPI; | ||
104 | opus_int nChannelsInternal; | ||
105 | opus_int nPrevChannelsInternal; | ||
106 | opus_int timeSinceSwitchAllowed_ms; | ||
107 | opus_int allowBandwidthSwitch; | ||
108 | opus_int prev_decode_only_middle; | ||
109 | } silk_encoder; | ||
110 | |||
111 | |||
112 | #ifdef __cplusplus | ||
113 | } | ||
114 | #endif | ||
115 | |||
116 | #endif | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/vector_ops_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/vector_ops_FIX.c new file mode 100644 index 0000000000..d94980014f --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/vector_ops_FIX.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "SigProc_FIX.h" | ||
33 | #include "pitch.h" | ||
34 | |||
35 | /* Copy and multiply a vector by a constant */ | ||
36 | void silk_scale_copy_vector16( | ||
37 | opus_int16 *data_out, | ||
38 | const opus_int16 *data_in, | ||
39 | opus_int32 gain_Q16, /* I Gain in Q16 */ | ||
40 | const opus_int dataSize /* I Length */ | ||
41 | ) | ||
42 | { | ||
43 | opus_int i; | ||
44 | opus_int32 tmp32; | ||
45 | |||
46 | for( i = 0; i < dataSize; i++ ) { | ||
47 | tmp32 = silk_SMULWB( gain_Q16, data_in[ i ] ); | ||
48 | data_out[ i ] = (opus_int16)silk_CHECK_FIT16( tmp32 ); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | /* Multiply a vector by a constant */ | ||
53 | void silk_scale_vector32_Q26_lshift_18( | ||
54 | opus_int32 *data1, /* I/O Q0/Q18 */ | ||
55 | opus_int32 gain_Q26, /* I Q26 */ | ||
56 | opus_int dataSize /* I length */ | ||
57 | ) | ||
58 | { | ||
59 | opus_int i; | ||
60 | |||
61 | for( i = 0; i < dataSize; i++ ) { | ||
62 | data1[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( silk_SMULL( data1[ i ], gain_Q26 ), 8 ) ); /* OUTPUT: Q18 */ | ||
63 | } | ||
64 | } | ||
65 | |||
66 | /* sum = for(i=0;i<len;i++)inVec1[i]*inVec2[i]; --- inner product */ | ||
67 | /* Note for ARM asm: */ | ||
68 | /* * inVec1 and inVec2 should be at least 2 byte aligned. */ | ||
69 | /* * len should be positive 16bit integer. */ | ||
70 | /* * only when len>6, memory access can be reduced by half. */ | ||
71 | opus_int32 silk_inner_prod_aligned( | ||
72 | const opus_int16 *const inVec1, /* I input vector 1 */ | ||
73 | const opus_int16 *const inVec2, /* I input vector 2 */ | ||
74 | const opus_int len, /* I vector lengths */ | ||
75 | int arch /* I Run-time architecture */ | ||
76 | ) | ||
77 | { | ||
78 | #ifdef FIXED_POINT | ||
79 | return celt_inner_prod(inVec1, inVec2, len, arch); | ||
80 | #else | ||
81 | opus_int i; | ||
82 | opus_int32 sum = 0; | ||
83 | for( i = 0; i < len; i++ ) { | ||
84 | sum = silk_SMLABB( sum, inVec1[ i ], inVec2[ i ] ); | ||
85 | } | ||
86 | return sum; | ||
87 | #endif | ||
88 | } | ||
89 | |||
90 | opus_int64 silk_inner_prod16_aligned_64_c( | ||
91 | const opus_int16 *inVec1, /* I input vector 1 */ | ||
92 | const opus_int16 *inVec2, /* I input vector 2 */ | ||
93 | const opus_int len /* I vector lengths */ | ||
94 | ) | ||
95 | { | ||
96 | opus_int i; | ||
97 | opus_int64 sum = 0; | ||
98 | for( i = 0; i < len; i++ ) { | ||
99 | sum = silk_SMLALBB( sum, inVec1[ i ], inVec2[ i ] ); | ||
100 | } | ||
101 | return sum; | ||
102 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/warped_autocorrelation_FIX.c b/lib/rbcodec/codecs/libopus/silk/fixed/warped_autocorrelation_FIX.c new file mode 100644 index 0000000000..52002a1118 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/warped_autocorrelation_FIX.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /*********************************************************************** | ||
2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions | ||
5 | are met: | ||
6 | - Redistributions of source code must retain the above copyright notice, | ||
7 | this list of conditions and the following disclaimer. | ||
8 | - Redistributions in binary form must reproduce the above copyright | ||
9 | notice, this list of conditions and the following disclaimer in the | ||
10 | documentation and/or other materials provided with the distribution. | ||
11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the | ||
12 | names of specific contributors, may be used to endorse or promote | ||
13 | products derived from this software without specific prior written | ||
14 | permission. | ||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
25 | POSSIBILITY OF SUCH DAMAGE. | ||
26 | ***********************************************************************/ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include "main_FIX.h" | ||
33 | |||
34 | #if defined(MIPSr1_ASM) | ||
35 | #include "mips/warped_autocorrelation_FIX_mipsr1.h" | ||
36 | #endif | ||
37 | |||
38 | |||
39 | /* Autocorrelations for a warped frequency axis */ | ||
40 | void silk_warped_autocorrelation_FIX_c( | ||
41 | opus_int32 *corr, /* O Result [order + 1] */ | ||
42 | opus_int *scale, /* O Scaling of the correlation vector */ | ||
43 | const opus_int16 *input, /* I Input data to correlate */ | ||
44 | const opus_int warping_Q16, /* I Warping coefficient */ | ||
45 | const opus_int length, /* I Length of input */ | ||
46 | const opus_int order /* I Correlation order (even) */ | ||
47 | ) | ||
48 | { | ||
49 | opus_int n, i, lsh; | ||
50 | opus_int32 tmp1_QS, tmp2_QS; | ||
51 | opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; | ||
52 | opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; | ||
53 | |||
54 | /* Order must be even */ | ||
55 | celt_assert( ( order & 1 ) == 0 ); | ||
56 | silk_assert( 2 * QS - QC >= 0 ); | ||
57 | |||
58 | /* Loop over samples */ | ||
59 | for( n = 0; n < length; n++ ) { | ||
60 | tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS ); | ||
61 | /* Loop over allpass sections */ | ||
62 | for( i = 0; i < order; i += 2 ) { | ||
63 | /* Output of allpass section */ | ||
64 | tmp2_QS = silk_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 ); | ||
65 | state_QS[ i ] = tmp1_QS; | ||
66 | corr_QC[ i ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); | ||
67 | /* Output of allpass section */ | ||
68 | tmp1_QS = silk_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 ); | ||
69 | state_QS[ i + 1 ] = tmp2_QS; | ||
70 | corr_QC[ i + 1 ] += silk_RSHIFT64( silk_SMULL( tmp2_QS, state_QS[ 0 ] ), 2 * QS - QC ); | ||
71 | } | ||
72 | state_QS[ order ] = tmp1_QS; | ||
73 | corr_QC[ order ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); | ||
74 | } | ||
75 | |||
76 | lsh = silk_CLZ64( corr_QC[ 0 ] ) - 35; | ||
77 | lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC ); | ||
78 | *scale = -( QC + lsh ); | ||
79 | silk_assert( *scale >= -30 && *scale <= 12 ); | ||
80 | if( lsh >= 0 ) { | ||
81 | for( i = 0; i < order + 1; i++ ) { | ||
82 | corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QC[ i ], lsh ) ); | ||
83 | } | ||
84 | } else { | ||
85 | for( i = 0; i < order + 1; i++ ) { | ||
86 | corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) ); | ||
87 | } | ||
88 | } | ||
89 | silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/ | ||
90 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/x86/burg_modified_FIX_sse4_1.c b/lib/rbcodec/codecs/libopus/silk/fixed/x86/burg_modified_FIX_sse4_1.c new file mode 100644 index 0000000000..bbb1ce0fcc --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/x86/burg_modified_FIX_sse4_1.c | |||
@@ -0,0 +1,377 @@ | |||
1 | /* Copyright (c) 2014, Cisco Systems, INC | ||
2 | Written by XiangMingZhu WeiZhou MinPeng YanWang | ||
3 | |||
4 | Redistribution and use in source and binary forms, with or without | ||
5 | modification, are permitted provided that the following conditions | ||
6 | are met: | ||
7 | |||
8 | - Redistributions of source code must retain the above copyright | ||
9 | notice, this list of conditions and the following disclaimer. | ||
10 | |||
11 | - Redistributions in binary form must reproduce the above copyright | ||
12 | notice, this list of conditions and the following disclaimer in the | ||
13 | documentation and/or other materials provided with the distribution. | ||
14 | |||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
16 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||
19 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include <xmmintrin.h> | ||
33 | #include <emmintrin.h> | ||
34 | #include <smmintrin.h> | ||
35 | |||
36 | #include "SigProc_FIX.h" | ||
37 | #include "define.h" | ||
38 | #include "tuning_parameters.h" | ||
39 | #include "pitch.h" | ||
40 | #include "celt/x86/x86cpu.h" | ||
41 | |||
42 | #define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */ | ||
43 | |||
44 | #define QA 25 | ||
45 | #define N_BITS_HEAD_ROOM 2 | ||
46 | #define MIN_RSHIFTS -16 | ||
47 | #define MAX_RSHIFTS (32 - QA) | ||
48 | |||
49 | /* Compute reflection coefficients from input signal */ | ||
50 | void silk_burg_modified_sse4_1( | ||
51 | opus_int32 *res_nrg, /* O Residual energy */ | ||
52 | opus_int *res_nrg_Q, /* O Residual energy Q value */ | ||
53 | opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ | ||
54 | const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ | ||
55 | const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */ | ||
56 | const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */ | ||
57 | const opus_int nb_subfr, /* I Number of subframes stacked in x */ | ||
58 | const opus_int D, /* I Order */ | ||
59 | int arch /* I Run-time architecture */ | ||
60 | ) | ||
61 | { | ||
62 | opus_int k, n, s, lz, rshifts, rshifts_extra, reached_max_gain; | ||
63 | opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; | ||
64 | const opus_int16 *x_ptr; | ||
65 | opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; | ||
66 | opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; | ||
67 | opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; | ||
68 | opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; | ||
69 | opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; | ||
70 | opus_int32 xcorr[ SILK_MAX_ORDER_LPC ]; | ||
71 | |||
72 | __m128i FIRST_3210, LAST_3210, ATMP_3210, TMP1_3210, TMP2_3210, T1_3210, T2_3210, PTR_3210, SUBFR_3210, X1_3210, X2_3210; | ||
73 | __m128i CONST1 = _mm_set1_epi32(1); | ||
74 | |||
75 | celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); | ||
76 | |||
77 | /* Compute autocorrelations, added over subframes */ | ||
78 | silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length ); | ||
79 | if( rshifts > MAX_RSHIFTS ) { | ||
80 | C0 = silk_LSHIFT32( C0, rshifts - MAX_RSHIFTS ); | ||
81 | silk_assert( C0 > 0 ); | ||
82 | rshifts = MAX_RSHIFTS; | ||
83 | } else { | ||
84 | lz = silk_CLZ32( C0 ) - 1; | ||
85 | rshifts_extra = N_BITS_HEAD_ROOM - lz; | ||
86 | if( rshifts_extra > 0 ) { | ||
87 | rshifts_extra = silk_min( rshifts_extra, MAX_RSHIFTS - rshifts ); | ||
88 | C0 = silk_RSHIFT32( C0, rshifts_extra ); | ||
89 | } else { | ||
90 | rshifts_extra = silk_max( rshifts_extra, MIN_RSHIFTS - rshifts ); | ||
91 | C0 = silk_LSHIFT32( C0, -rshifts_extra ); | ||
92 | } | ||
93 | rshifts += rshifts_extra; | ||
94 | } | ||
95 | CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ | ||
96 | silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); | ||
97 | if( rshifts > 0 ) { | ||
98 | for( s = 0; s < nb_subfr; s++ ) { | ||
99 | x_ptr = x + s * subfr_length; | ||
100 | for( n = 1; n < D + 1; n++ ) { | ||
101 | C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64( | ||
102 | silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts ); | ||
103 | } | ||
104 | } | ||
105 | } else { | ||
106 | for( s = 0; s < nb_subfr; s++ ) { | ||
107 | int i; | ||
108 | opus_int32 d; | ||
109 | x_ptr = x + s * subfr_length; | ||
110 | celt_pitch_xcorr(x_ptr, x_ptr + 1, xcorr, subfr_length - D, D, arch ); | ||
111 | for( n = 1; n < D + 1; n++ ) { | ||
112 | for ( i = n + subfr_length - D, d = 0; i < subfr_length; i++ ) | ||
113 | d = MAC16_16( d, x_ptr[ i ], x_ptr[ i - n ] ); | ||
114 | xcorr[ n - 1 ] += d; | ||
115 | } | ||
116 | for( n = 1; n < D + 1; n++ ) { | ||
117 | C_first_row[ n - 1 ] += silk_LSHIFT32( xcorr[ n - 1 ], -rshifts ); | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); | ||
122 | |||
123 | /* Initialize */ | ||
124 | CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ | ||
125 | |||
126 | invGain_Q30 = (opus_int32)1 << 30; | ||
127 | reached_max_gain = 0; | ||
128 | for( n = 0; n < D; n++ ) { | ||
129 | /* Update first row of correlation matrix (without first element) */ | ||
130 | /* Update last row of correlation matrix (without last element, stored in reversed order) */ | ||
131 | /* Update C * Af */ | ||
132 | /* Update C * flipud(Af) (stored in reversed order) */ | ||
133 | if( rshifts > -2 ) { | ||
134 | for( s = 0; s < nb_subfr; s++ ) { | ||
135 | x_ptr = x + s * subfr_length; | ||
136 | x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts) */ | ||
137 | x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts) */ | ||
138 | tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16) */ | ||
139 | tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16) */ | ||
140 | for( k = 0; k < n; k++ ) { | ||
141 | C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ | ||
142 | C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ | ||
143 | Atmp_QA = Af_QA[ k ]; | ||
144 | tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16) */ | ||
145 | tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16) */ | ||
146 | } | ||
147 | tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts) */ | ||
148 | tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts) */ | ||
149 | for( k = 0; k <= n; k++ ) { | ||
150 | CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift ) */ | ||
151 | CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift ) */ | ||
152 | } | ||
153 | } | ||
154 | } else { | ||
155 | for( s = 0; s < nb_subfr; s++ ) { | ||
156 | x_ptr = x + s * subfr_length; | ||
157 | x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts ) */ | ||
158 | x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts ) */ | ||
159 | tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17 */ | ||
160 | tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17 */ | ||
161 | |||
162 | X1_3210 = _mm_set1_epi32( x1 ); | ||
163 | X2_3210 = _mm_set1_epi32( x2 ); | ||
164 | TMP1_3210 = _mm_setzero_si128(); | ||
165 | TMP2_3210 = _mm_setzero_si128(); | ||
166 | for( k = 0; k < n - 3; k += 4 ) { | ||
167 | PTR_3210 = OP_CVTEPI16_EPI32_M64( &x_ptr[ n - k - 1 - 3 ] ); | ||
168 | SUBFR_3210 = OP_CVTEPI16_EPI32_M64( &x_ptr[ subfr_length - n + k ] ); | ||
169 | FIRST_3210 = _mm_loadu_si128( (__m128i *)&C_first_row[ k ] ); | ||
170 | PTR_3210 = _mm_shuffle_epi32( PTR_3210, _MM_SHUFFLE( 0, 1, 2, 3 ) ); | ||
171 | LAST_3210 = _mm_loadu_si128( (__m128i *)&C_last_row[ k ] ); | ||
172 | ATMP_3210 = _mm_loadu_si128( (__m128i *)&Af_QA[ k ] ); | ||
173 | |||
174 | T1_3210 = _mm_mullo_epi32( PTR_3210, X1_3210 ); | ||
175 | T2_3210 = _mm_mullo_epi32( SUBFR_3210, X2_3210 ); | ||
176 | |||
177 | ATMP_3210 = _mm_srai_epi32( ATMP_3210, 7 ); | ||
178 | ATMP_3210 = _mm_add_epi32( ATMP_3210, CONST1 ); | ||
179 | ATMP_3210 = _mm_srai_epi32( ATMP_3210, 1 ); | ||
180 | |||
181 | FIRST_3210 = _mm_add_epi32( FIRST_3210, T1_3210 ); | ||
182 | LAST_3210 = _mm_add_epi32( LAST_3210, T2_3210 ); | ||
183 | |||
184 | PTR_3210 = _mm_mullo_epi32( ATMP_3210, PTR_3210 ); | ||
185 | SUBFR_3210 = _mm_mullo_epi32( ATMP_3210, SUBFR_3210 ); | ||
186 | |||
187 | _mm_storeu_si128( (__m128i *)&C_first_row[ k ], FIRST_3210 ); | ||
188 | _mm_storeu_si128( (__m128i *)&C_last_row[ k ], LAST_3210 ); | ||
189 | |||
190 | TMP1_3210 = _mm_add_epi32( TMP1_3210, PTR_3210 ); | ||
191 | TMP2_3210 = _mm_add_epi32( TMP2_3210, SUBFR_3210 ); | ||
192 | } | ||
193 | |||
194 | TMP1_3210 = _mm_add_epi32( TMP1_3210, _mm_unpackhi_epi64(TMP1_3210, TMP1_3210 ) ); | ||
195 | TMP2_3210 = _mm_add_epi32( TMP2_3210, _mm_unpackhi_epi64(TMP2_3210, TMP2_3210 ) ); | ||
196 | TMP1_3210 = _mm_add_epi32( TMP1_3210, _mm_shufflelo_epi16(TMP1_3210, 0x0E ) ); | ||
197 | TMP2_3210 = _mm_add_epi32( TMP2_3210, _mm_shufflelo_epi16(TMP2_3210, 0x0E ) ); | ||
198 | |||
199 | tmp1 += _mm_cvtsi128_si32( TMP1_3210 ); | ||
200 | tmp2 += _mm_cvtsi128_si32( TMP2_3210 ); | ||
201 | |||
202 | for( ; k < n; k++ ) { | ||
203 | C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ | ||
204 | C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ | ||
205 | Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */ | ||
206 | tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */ | ||
207 | tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */ | ||
208 | } | ||
209 | |||
210 | tmp1 = -tmp1; /* Q17 */ | ||
211 | tmp2 = -tmp2; /* Q17 */ | ||
212 | |||
213 | { | ||
214 | __m128i xmm_tmp1, xmm_tmp2; | ||
215 | __m128i xmm_x_ptr_n_k_x2x0, xmm_x_ptr_n_k_x3x1; | ||
216 | __m128i xmm_x_ptr_sub_x2x0, xmm_x_ptr_sub_x3x1; | ||
217 | |||
218 | xmm_tmp1 = _mm_set1_epi32( tmp1 ); | ||
219 | xmm_tmp2 = _mm_set1_epi32( tmp2 ); | ||
220 | |||
221 | for( k = 0; k <= n - 3; k += 4 ) { | ||
222 | xmm_x_ptr_n_k_x2x0 = OP_CVTEPI16_EPI32_M64( &x_ptr[ n - k - 3 ] ); | ||
223 | xmm_x_ptr_sub_x2x0 = OP_CVTEPI16_EPI32_M64( &x_ptr[ subfr_length - n + k - 1 ] ); | ||
224 | |||
225 | xmm_x_ptr_n_k_x2x0 = _mm_shuffle_epi32( xmm_x_ptr_n_k_x2x0, _MM_SHUFFLE( 0, 1, 2, 3 ) ); | ||
226 | |||
227 | xmm_x_ptr_n_k_x2x0 = _mm_slli_epi32( xmm_x_ptr_n_k_x2x0, -rshifts - 1 ); | ||
228 | xmm_x_ptr_sub_x2x0 = _mm_slli_epi32( xmm_x_ptr_sub_x2x0, -rshifts - 1 ); | ||
229 | |||
230 | /* equal shift right 4 bytes, xmm_x_ptr_n_k_x3x1 = _mm_srli_si128(xmm_x_ptr_n_k_x2x0, 4)*/ | ||
231 | xmm_x_ptr_n_k_x3x1 = _mm_shuffle_epi32( xmm_x_ptr_n_k_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); | ||
232 | xmm_x_ptr_sub_x3x1 = _mm_shuffle_epi32( xmm_x_ptr_sub_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); | ||
233 | |||
234 | xmm_x_ptr_n_k_x2x0 = _mm_mul_epi32( xmm_x_ptr_n_k_x2x0, xmm_tmp1 ); | ||
235 | xmm_x_ptr_n_k_x3x1 = _mm_mul_epi32( xmm_x_ptr_n_k_x3x1, xmm_tmp1 ); | ||
236 | xmm_x_ptr_sub_x2x0 = _mm_mul_epi32( xmm_x_ptr_sub_x2x0, xmm_tmp2 ); | ||
237 | xmm_x_ptr_sub_x3x1 = _mm_mul_epi32( xmm_x_ptr_sub_x3x1, xmm_tmp2 ); | ||
238 | |||
239 | xmm_x_ptr_n_k_x2x0 = _mm_srli_epi64( xmm_x_ptr_n_k_x2x0, 16 ); | ||
240 | xmm_x_ptr_n_k_x3x1 = _mm_slli_epi64( xmm_x_ptr_n_k_x3x1, 16 ); | ||
241 | xmm_x_ptr_sub_x2x0 = _mm_srli_epi64( xmm_x_ptr_sub_x2x0, 16 ); | ||
242 | xmm_x_ptr_sub_x3x1 = _mm_slli_epi64( xmm_x_ptr_sub_x3x1, 16 ); | ||
243 | |||
244 | xmm_x_ptr_n_k_x2x0 = _mm_blend_epi16( xmm_x_ptr_n_k_x2x0, xmm_x_ptr_n_k_x3x1, 0xCC ); | ||
245 | xmm_x_ptr_sub_x2x0 = _mm_blend_epi16( xmm_x_ptr_sub_x2x0, xmm_x_ptr_sub_x3x1, 0xCC ); | ||
246 | |||
247 | X1_3210 = _mm_loadu_si128( (__m128i *)&CAf[ k ] ); | ||
248 | PTR_3210 = _mm_loadu_si128( (__m128i *)&CAb[ k ] ); | ||
249 | |||
250 | X1_3210 = _mm_add_epi32( X1_3210, xmm_x_ptr_n_k_x2x0 ); | ||
251 | PTR_3210 = _mm_add_epi32( PTR_3210, xmm_x_ptr_sub_x2x0 ); | ||
252 | |||
253 | _mm_storeu_si128( (__m128i *)&CAf[ k ], X1_3210 ); | ||
254 | _mm_storeu_si128( (__m128i *)&CAb[ k ], PTR_3210 ); | ||
255 | } | ||
256 | |||
257 | for( ; k <= n; k++ ) { | ||
258 | CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, | ||
259 | silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift ) */ | ||
260 | CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2, | ||
261 | silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift ) */ | ||
262 | } | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | |||
267 | /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ | ||
268 | tmp1 = C_first_row[ n ]; /* Q( -rshifts ) */ | ||
269 | tmp2 = C_last_row[ n ]; /* Q( -rshifts ) */ | ||
270 | num = 0; /* Q( -rshifts ) */ | ||
271 | nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts ) */ | ||
272 | for( k = 0; k < n; k++ ) { | ||
273 | Atmp_QA = Af_QA[ k ]; | ||
274 | lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; | ||
275 | lz = silk_min( 32 - QA, lz ); | ||
276 | Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz ) */ | ||
277 | |||
278 | tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ | ||
279 | tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ | ||
280 | num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ | ||
281 | nrg = silk_ADD_LSHIFT32( nrg, silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), | ||
282 | Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts ) */ | ||
283 | } | ||
284 | CAf[ n + 1 ] = tmp1; /* Q( -rshifts ) */ | ||
285 | CAb[ n + 1 ] = tmp2; /* Q( -rshifts ) */ | ||
286 | num = silk_ADD32( num, tmp2 ); /* Q( -rshifts ) */ | ||
287 | num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts ) */ | ||
288 | |||
289 | /* Calculate the next order reflection (parcor) coefficient */ | ||
290 | if( silk_abs( num ) < nrg ) { | ||
291 | rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); | ||
292 | } else { | ||
293 | rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN; | ||
294 | } | ||
295 | |||
296 | /* Update inverse prediction gain */ | ||
297 | tmp1 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); | ||
298 | tmp1 = silk_LSHIFT( silk_SMMUL( invGain_Q30, tmp1 ), 2 ); | ||
299 | if( tmp1 <= minInvGain_Q30 ) { | ||
300 | /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ | ||
301 | tmp2 = ( (opus_int32)1 << 30 ) - silk_DIV32_varQ( minInvGain_Q30, invGain_Q30, 30 ); /* Q30 */ | ||
302 | rc_Q31 = silk_SQRT_APPROX( tmp2 ); /* Q15 */ | ||
303 | if( rc_Q31 > 0 ) { | ||
304 | /* Newton-Raphson iteration */ | ||
305 | rc_Q31 = silk_RSHIFT32( rc_Q31 + silk_DIV32( tmp2, rc_Q31 ), 1 ); /* Q15 */ | ||
306 | rc_Q31 = silk_LSHIFT32( rc_Q31, 16 ); /* Q31 */ | ||
307 | if( num < 0 ) { | ||
308 | /* Ensure adjusted reflection coefficients has the original sign */ | ||
309 | rc_Q31 = -rc_Q31; | ||
310 | } | ||
311 | } | ||
312 | invGain_Q30 = minInvGain_Q30; | ||
313 | reached_max_gain = 1; | ||
314 | } else { | ||
315 | invGain_Q30 = tmp1; | ||
316 | } | ||
317 | |||
318 | /* Update the AR coefficients */ | ||
319 | for( k = 0; k < (n + 1) >> 1; k++ ) { | ||
320 | tmp1 = Af_QA[ k ]; /* QA */ | ||
321 | tmp2 = Af_QA[ n - k - 1 ]; /* QA */ | ||
322 | Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA */ | ||
323 | Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA */ | ||
324 | } | ||
325 | Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA */ | ||
326 | |||
327 | if( reached_max_gain ) { | ||
328 | /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ | ||
329 | for( k = n + 1; k < D; k++ ) { | ||
330 | Af_QA[ k ] = 0; | ||
331 | } | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | /* Update C * Af and C * Ab */ | ||
336 | for( k = 0; k <= n + 1; k++ ) { | ||
337 | tmp1 = CAf[ k ]; /* Q( -rshifts ) */ | ||
338 | tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts ) */ | ||
339 | CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts ) */ | ||
340 | CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts ) */ | ||
341 | } | ||
342 | } | ||
343 | |||
344 | if( reached_max_gain ) { | ||
345 | for( k = 0; k < D; k++ ) { | ||
346 | /* Scale coefficients */ | ||
347 | A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); | ||
348 | } | ||
349 | /* Subtract energy of preceding samples from C0 */ | ||
350 | if( rshifts > 0 ) { | ||
351 | for( s = 0; s < nb_subfr; s++ ) { | ||
352 | x_ptr = x + s * subfr_length; | ||
353 | C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D, arch ), rshifts ); | ||
354 | } | ||
355 | } else { | ||
356 | for( s = 0; s < nb_subfr; s++ ) { | ||
357 | x_ptr = x + s * subfr_length; | ||
358 | C0 -= silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr, D, arch ), -rshifts ); | ||
359 | } | ||
360 | } | ||
361 | /* Approximate residual energy */ | ||
362 | *res_nrg = silk_LSHIFT( silk_SMMUL( invGain_Q30, C0 ), 2 ); | ||
363 | *res_nrg_Q = -rshifts; | ||
364 | } else { | ||
365 | /* Return residual energy */ | ||
366 | nrg = CAf[ 0 ]; /* Q( -rshifts ) */ | ||
367 | tmp1 = (opus_int32)1 << 16; /* Q16 */ | ||
368 | for( k = 0; k < D; k++ ) { | ||
369 | Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16 */ | ||
370 | nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts ) */ | ||
371 | tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16 */ | ||
372 | A_Q16[ k ] = -Atmp1; | ||
373 | } | ||
374 | *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ), -tmp1 );/* Q( -rshifts ) */ | ||
375 | *res_nrg_Q = -rshifts; | ||
376 | } | ||
377 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/x86/prefilter_FIX_sse.c b/lib/rbcodec/codecs/libopus/silk/fixed/x86/prefilter_FIX_sse.c new file mode 100644 index 0000000000..555432cd96 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/x86/prefilter_FIX_sse.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* Copyright (c) 2014, Cisco Systems, INC | ||
2 | Written by XiangMingZhu WeiZhou MinPeng YanWang | ||
3 | |||
4 | Redistribution and use in source and binary forms, with or without | ||
5 | modification, are permitted provided that the following conditions | ||
6 | are met: | ||
7 | |||
8 | - Redistributions of source code must retain the above copyright | ||
9 | notice, this list of conditions and the following disclaimer. | ||
10 | |||
11 | - Redistributions in binary form must reproduce the above copyright | ||
12 | notice, this list of conditions and the following disclaimer in the | ||
13 | documentation and/or other materials provided with the distribution. | ||
14 | |||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
16 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||
19 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include <xmmintrin.h> | ||
33 | #include <emmintrin.h> | ||
34 | #include <smmintrin.h> | ||
35 | #include "main.h" | ||
36 | #include "celt/x86/x86cpu.h" | ||
37 | |||
38 | void silk_warped_LPC_analysis_filter_FIX_sse4_1( | ||
39 | opus_int32 state[], /* I/O State [order + 1] */ | ||
40 | opus_int32 res_Q2[], /* O Residual signal [length] */ | ||
41 | const opus_int16 coef_Q13[], /* I Coefficients [order] */ | ||
42 | const opus_int16 input[], /* I Input signal [length] */ | ||
43 | const opus_int16 lambda_Q16, /* I Warping factor */ | ||
44 | const opus_int length, /* I Length of input signal */ | ||
45 | const opus_int order /* I Filter order (even) */ | ||
46 | ) | ||
47 | { | ||
48 | opus_int n, i; | ||
49 | opus_int32 acc_Q11, tmp1, tmp2; | ||
50 | |||
51 | /* Order must be even */ | ||
52 | celt_assert( ( order & 1 ) == 0 ); | ||
53 | |||
54 | if (order == 10) | ||
55 | { | ||
56 | if (0 == lambda_Q16) | ||
57 | { | ||
58 | __m128i coef_Q13_3210, coef_Q13_7654; | ||
59 | __m128i coef_Q13_0123, coef_Q13_4567; | ||
60 | __m128i state_0123, state_4567; | ||
61 | __m128i xmm_product1, xmm_product2; | ||
62 | __m128i xmm_tempa, xmm_tempb; | ||
63 | |||
64 | register opus_int32 sum; | ||
65 | register opus_int32 state_8, state_9, state_a; | ||
66 | register opus_int64 coef_Q13_8, coef_Q13_9; | ||
67 | |||
68 | celt_assert( length > 0 ); | ||
69 | |||
70 | coef_Q13_3210 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 0 ] ); | ||
71 | coef_Q13_7654 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 4 ] ); | ||
72 | |||
73 | coef_Q13_0123 = _mm_shuffle_epi32( coef_Q13_3210, _MM_SHUFFLE( 0, 1, 2, 3 ) ); | ||
74 | coef_Q13_4567 = _mm_shuffle_epi32( coef_Q13_7654, _MM_SHUFFLE( 0, 1, 2, 3 ) ); | ||
75 | |||
76 | coef_Q13_8 = (opus_int64) coef_Q13[ 8 ]; | ||
77 | coef_Q13_9 = (opus_int64) coef_Q13[ 9 ]; | ||
78 | |||
79 | state_0123 = _mm_loadu_si128( (__m128i *)(&state[ 0 ] ) ); | ||
80 | state_4567 = _mm_loadu_si128( (__m128i *)(&state[ 4 ] ) ); | ||
81 | |||
82 | state_0123 = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ); | ||
83 | state_4567 = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ); | ||
84 | |||
85 | state_8 = state[ 8 ]; | ||
86 | state_9 = state[ 9 ]; | ||
87 | state_a = 0; | ||
88 | |||
89 | for( n = 0; n < length; n++ ) | ||
90 | { | ||
91 | xmm_product1 = _mm_mul_epi32( coef_Q13_0123, state_0123 ); /* 64-bit multiply, only 2 pairs */ | ||
92 | xmm_product2 = _mm_mul_epi32( coef_Q13_4567, state_4567 ); | ||
93 | |||
94 | xmm_tempa = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ); | ||
95 | xmm_tempb = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ); | ||
96 | |||
97 | xmm_product1 = _mm_srli_epi64( xmm_product1, 16 ); /* >> 16, zero extending works */ | ||
98 | xmm_product2 = _mm_srli_epi64( xmm_product2, 16 ); | ||
99 | |||
100 | xmm_tempa = _mm_mul_epi32( coef_Q13_3210, xmm_tempa ); | ||
101 | xmm_tempb = _mm_mul_epi32( coef_Q13_7654, xmm_tempb ); | ||
102 | |||
103 | xmm_tempa = _mm_srli_epi64( xmm_tempa, 16 ); | ||
104 | xmm_tempb = _mm_srli_epi64( xmm_tempb, 16 ); | ||
105 | |||
106 | xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_product1 ); | ||
107 | xmm_tempb = _mm_add_epi32( xmm_tempb, xmm_product2 ); | ||
108 | xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_tempb ); | ||
109 | |||
110 | sum = (opus_int32)((coef_Q13_8 * state_8) >> 16); | ||
111 | sum += (opus_int32)((coef_Q13_9 * state_9) >> 16); | ||
112 | |||
113 | xmm_tempa = _mm_add_epi32( xmm_tempa, _mm_shuffle_epi32( xmm_tempa, _MM_SHUFFLE( 0, 0, 0, 2 ) ) ); | ||
114 | sum += _mm_cvtsi128_si32( xmm_tempa); | ||
115 | res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( ( 5 + sum ), 9); | ||
116 | |||
117 | /* move right */ | ||
118 | state_a = state_9; | ||
119 | state_9 = state_8; | ||
120 | state_8 = _mm_cvtsi128_si32( state_4567 ); | ||
121 | state_4567 = _mm_alignr_epi8( state_0123, state_4567, 4 ); | ||
122 | |||
123 | state_0123 = _mm_alignr_epi8( _mm_cvtsi32_si128( silk_LSHIFT( input[ n ], 14 ) ), state_0123, 4 ); | ||
124 | } | ||
125 | |||
126 | _mm_storeu_si128( (__m128i *)( &state[ 0 ] ), _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ) ); | ||
127 | _mm_storeu_si128( (__m128i *)( &state[ 4 ] ), _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ) ); | ||
128 | state[ 8 ] = state_8; | ||
129 | state[ 9 ] = state_9; | ||
130 | state[ 10 ] = state_a; | ||
131 | |||
132 | return; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | for( n = 0; n < length; n++ ) { | ||
137 | /* Output of lowpass section */ | ||
138 | tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); | ||
139 | state[ 0 ] = silk_LSHIFT( input[ n ], 14 ); | ||
140 | /* Output of allpass section */ | ||
141 | tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); | ||
142 | state[ 1 ] = tmp2; | ||
143 | acc_Q11 = silk_RSHIFT( order, 1 ); | ||
144 | acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] ); | ||
145 | /* Loop over allpass sections */ | ||
146 | for( i = 2; i < order; i += 2 ) { | ||
147 | /* Output of allpass section */ | ||
148 | tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); | ||
149 | state[ i ] = tmp1; | ||
150 | acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); | ||
151 | /* Output of allpass section */ | ||
152 | tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); | ||
153 | state[ i + 1 ] = tmp2; | ||
154 | acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); | ||
155 | } | ||
156 | state[ order ] = tmp1; | ||
157 | acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); | ||
158 | res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 ); | ||
159 | } | ||
160 | } | ||
diff --git a/lib/rbcodec/codecs/libopus/silk/fixed/x86/vector_ops_FIX_sse4_1.c b/lib/rbcodec/codecs/libopus/silk/fixed/x86/vector_ops_FIX_sse4_1.c new file mode 100644 index 0000000000..c1e90564d0 --- /dev/null +++ b/lib/rbcodec/codecs/libopus/silk/fixed/x86/vector_ops_FIX_sse4_1.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /* Copyright (c) 2014, Cisco Systems, INC | ||
2 | Written by XiangMingZhu WeiZhou MinPeng YanWang | ||
3 | |||
4 | Redistribution and use in source and binary forms, with or without | ||
5 | modification, are permitted provided that the following conditions | ||
6 | are met: | ||
7 | |||
8 | - Redistributions of source code must retain the above copyright | ||
9 | notice, this list of conditions and the following disclaimer. | ||
10 | |||
11 | - Redistributions in binary form must reproduce the above copyright | ||
12 | notice, this list of conditions and the following disclaimer in the | ||
13 | documentation and/or other materials provided with the distribution. | ||
14 | |||
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
16 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||
19 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include <xmmintrin.h> | ||
33 | #include <emmintrin.h> | ||
34 | #include <smmintrin.h> | ||
35 | #include "main.h" | ||
36 | |||
37 | #include "SigProc_FIX.h" | ||
38 | #include "pitch.h" | ||
39 | |||
40 | opus_int64 silk_inner_prod16_aligned_64_sse4_1( | ||
41 | const opus_int16 *inVec1, /* I input vector 1 */ | ||
42 | const opus_int16 *inVec2, /* I input vector 2 */ | ||
43 | const opus_int len /* I vector lengths */ | ||
44 | ) | ||
45 | { | ||
46 | opus_int i, dataSize8; | ||
47 | opus_int64 sum; | ||
48 | |||
49 | __m128i xmm_tempa; | ||
50 | __m128i inVec1_76543210, acc1; | ||
51 | __m128i inVec2_76543210, acc2; | ||
52 | |||
53 | sum = 0; | ||
54 | dataSize8 = len & ~7; | ||
55 | |||
56 | acc1 = _mm_setzero_si128(); | ||
57 | acc2 = _mm_setzero_si128(); | ||
58 | |||
59 | for( i = 0; i < dataSize8; i += 8 ) { | ||
60 | inVec1_76543210 = _mm_loadu_si128( (__m128i *)(&inVec1[i + 0] ) ); | ||
61 | inVec2_76543210 = _mm_loadu_si128( (__m128i *)(&inVec2[i + 0] ) ); | ||
62 | |||
63 | /* only when all 4 operands are -32768 (0x8000), this results in wrap around */ | ||
64 | inVec1_76543210 = _mm_madd_epi16( inVec1_76543210, inVec2_76543210 ); | ||
65 | |||
66 | xmm_tempa = _mm_cvtepi32_epi64( inVec1_76543210 ); | ||
67 | /* equal shift right 8 bytes */ | ||
68 | inVec1_76543210 = _mm_shuffle_epi32( inVec1_76543210, _MM_SHUFFLE( 0, 0, 3, 2 ) ); | ||
69 | inVec1_76543210 = _mm_cvtepi32_epi64( inVec1_76543210 ); | ||
70 | |||
71 | acc1 = _mm_add_epi64( acc1, xmm_tempa ); | ||
72 | acc2 = _mm_add_epi64( acc2, inVec1_76543210 ); | ||
73 | } | ||
74 | |||
75 | acc1 = _mm_add_epi64( acc1, acc2 ); | ||
76 | |||
77 | /* equal shift right 8 bytes */ | ||
78 | acc2 = _mm_shuffle_epi32( acc1, _MM_SHUFFLE( 0, 0, 3, 2 ) ); | ||
79 | acc1 = _mm_add_epi64( acc1, acc2 ); | ||
80 | |||
81 | _mm_storel_epi64( (__m128i *)&sum, acc1 ); | ||
82 | |||
83 | for( ; i < len; i++ ) { | ||
84 | sum = silk_SMLABB( sum, inVec1[ i ], inVec2[ i ] ); | ||
85 | } | ||
86 | |||
87 | return sum; | ||
88 | } | ||