Line data Source code
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 "resampler_private.h"
34 : #include "stack_alloc.h"
35 :
36 : #define ORDER_FIR 4
37 :
38 : /* Downsample by a factor 2/3, low quality */
39 0 : void silk_resampler_down2_3(
40 : opus_int32 *S, /* I/O State vector [ 6 ] */
41 : opus_int16 *out, /* O Output signal [ floor(2*inLen/3) ] */
42 : const opus_int16 *in, /* I Input signal [ inLen ] */
43 : opus_int32 inLen /* I Number of input samples */
44 : )
45 : {
46 : opus_int32 nSamplesIn, counter, res_Q6;
47 : VARDECL( opus_int32, buf );
48 : opus_int32 *buf_ptr;
49 : SAVE_STACK;
50 :
51 0 : ALLOC( buf, RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR, opus_int32 );
52 :
53 : /* Copy buffered samples to start of buffer */
54 0 : silk_memcpy( buf, S, ORDER_FIR * sizeof( opus_int32 ) );
55 :
56 : /* Iterate over blocks of frameSizeIn input samples */
57 : while( 1 ) {
58 0 : nSamplesIn = silk_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN );
59 :
60 : /* Second-order AR filter (output in Q8) */
61 0 : silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in,
62 : silk_Resampler_2_3_COEFS_LQ, nSamplesIn );
63 :
64 : /* Interpolate filtered signal */
65 0 : buf_ptr = buf;
66 0 : counter = nSamplesIn;
67 0 : while( counter > 2 ) {
68 : /* Inner product */
69 0 : res_Q6 = silk_SMULWB( buf_ptr[ 0 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] );
70 0 : res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] );
71 0 : res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] );
72 0 : res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] );
73 :
74 : /* Scale down, saturate and store in output array */
75 0 : *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
76 :
77 0 : res_Q6 = silk_SMULWB( buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] );
78 0 : res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] );
79 0 : res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] );
80 0 : res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] );
81 :
82 : /* Scale down, saturate and store in output array */
83 0 : *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
84 :
85 0 : buf_ptr += 3;
86 0 : counter -= 3;
87 : }
88 :
89 0 : in += nSamplesIn;
90 0 : inLen -= nSamplesIn;
91 :
92 0 : if( inLen > 0 ) {
93 : /* More iterations to do; copy last part of filtered signal to beginning of buffer */
94 0 : silk_memcpy( buf, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) );
95 : } else {
96 0 : break;
97 : }
98 : }
99 :
100 : /* Copy last part of filtered signal to the state for the next call */
101 0 : silk_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) );
102 : RESTORE_STACK;
103 0 : }
|