1885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/***********************************************************************
2885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCopyright (c) 2006-2011, Skype Limited. All rights reserved.
3885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgRedistribution and use in source and binary forms, with or without
4885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgmodification, are permitted provided that the following conditions
5885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgare met:
6885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org- Redistributions of source code must retain the above copyright notice,
7885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgthis list of conditions and the following disclaimer.
8885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org- Redistributions in binary form must reproduce the above copyright
9885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgnotice, this list of conditions and the following disclaimer in the
10885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgdocumentation and/or other materials provided with the distribution.
11e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org- Neither the name of Internet Society, IETF or IETF Trust, nor the
12885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgnames of specific contributors, may be used to endorse or promote
13885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgproducts derived from this software without specific prior written
14885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgpermission.
15e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgPOSSIBILITY OF SUCH DAMAGE.
26885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org***********************************************************************/
27885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
28885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef HAVE_CONFIG_H
29885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "config.h"
30885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
31885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
32885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "main.h"
33885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
34885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Convert adaptive Mid/Side representation to Left/Right stereo signal */
35885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid silk_stereo_MS_to_LR(
36885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    stereo_dec_state            *state,                         /* I/O  State                                       */
37885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    opus_int16                  x1[],                           /* I/O  Left input signal, becomes mid signal       */
38885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    opus_int16                  x2[],                           /* I/O  Right input signal, becomes side signal     */
39885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    const opus_int32            pred_Q13[],                     /* I    Predictors                                  */
40885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    opus_int                    fs_kHz,                         /* I    Samples rate (kHz)                          */
41885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    opus_int                    frame_length                    /* I    Number of samples                           */
42885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org)
43885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{
44885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    opus_int   n, denom_Q16, delta0_Q13, delta1_Q13;
45885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    opus_int32 sum, diff, pred0_Q13, pred1_Q13;
46885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
47885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    /* Buffering */
48885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    silk_memcpy( x1, state->sMid,  2 * sizeof( opus_int16 ) );
49885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    silk_memcpy( x2, state->sSide, 2 * sizeof( opus_int16 ) );
50885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    silk_memcpy( state->sMid,  &x1[ frame_length ], 2 * sizeof( opus_int16 ) );
51885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    silk_memcpy( state->sSide, &x2[ frame_length ], 2 * sizeof( opus_int16 ) );
52885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
53885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    /* Interpolate predictors and add prediction to side channel */
54885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    pred0_Q13  = state->pred_prev_Q13[ 0 ];
55885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    pred1_Q13  = state->pred_prev_Q13[ 1 ];
56885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    denom_Q16  = silk_DIV32_16( (opus_int32)1 << 16, STEREO_INTERP_LEN_MS * fs_kHz );
57885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    delta0_Q13 = silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 );
58885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    delta1_Q13 = silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 );
59885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) {
60885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        pred0_Q13 += delta0_Q13;
61885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        pred1_Q13 += delta1_Q13;
62885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 );       /* Q11 */
63885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 );         /* Q8  */
64885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 );        /* Q8  */
65885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
66885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    }
67885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    pred0_Q13 = pred_Q13[ 0 ];
68885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    pred1_Q13 = pred_Q13[ 1 ];
69885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) {
70885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 );       /* Q11 */
71885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 );         /* Q8  */
72885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 );        /* Q8  */
73885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
74885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    }
75885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ];
76885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    state->pred_prev_Q13[ 1 ] = pred_Q13[ 1 ];
77885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
78885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    /* Convert to left/right signals */
79885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    for( n = 0; n < frame_length; n++ ) {
80885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        sum  = x1[ n + 1 ] + (opus_int32)x2[ n + 1 ];
81885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        diff = x1[ n + 1 ] - (opus_int32)x2[ n + 1 ];
82885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        x1[ n + 1 ] = (opus_int16)silk_SAT16( sum );
83885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org        x2[ n + 1 ] = (opus_int16)silk_SAT16( diff );
84885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    }
85885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}
86