예제 #1
0
def Chebps_10(x: int, f: List[int], n: int) -> int:
    # Note: All computation are done in Q23.

    b2_h = 128      # b2 = 1.0 in Q23 DPF
    b2_l = 0

    t0 = basic_op.L_mult(x, 256)            # 2*x in Q23          
    t0 = basic_op.L_mac(t0, f[1], 4096)     # + f[1] in Q23       
    b1_h, b1_l = oper_32b.L_Extract(t0)     # b1 = 2*x + f[1]     

    for i in range(2, n):
        t0 = oper_32b.Mpy_32_16(b1_h, b1_l, x)      # t0 = 2.0*x*b1              
        t0 = basic_op.L_shl(t0, 1)
        t0 = basic_op.L_mac(t0, b2_h, -32768)       # t0 = 2.0*x*b1 - b2         
        t0 = basic_op.L_msu(t0, b2_l, 1)
        t0 = basic_op.L_mac(t0, f[i], 4096)         # t0 = 2.0*x*b1 - b2 + f[i] 

        b0_h, b0_l = oper_32b.L_Extract(t0)         # b0 = 2.0*x*b1 - b2 + f[i] 

        b2_l = b1_l     # b2 = b1 
        b2_h = b1_h
        b1_l = b0_l     # b1 = b0 
        b1_h = b0_h

    t0 = oper_32b.Mpy_32_16(b1_h, b1_l, x)          # t0 = x*b1              
    t0 = basic_op.L_mac(t0, b2_h, -32768)           # t0 = x*b1 - b2          
    t0 = basic_op.L_msu(t0, b2_l, 1)
    t0 = basic_op.L_mac(t0, f[i], 2048)             # t0 = x*b1 - b2 + f[i]/2 

    t0 = basic_op.L_shl(t0, 7)                      # Q23 to Q30 with saturation 
    cheb = basic_op.extract_h(t0)

    return cheb
예제 #2
0
def Inv_sqrt(L_x) -> int:
    """
    # (o) Q30 : output value   (range: 0<=val<1)
    # (i) Q0  : input value    (range: 0<=val<=7fffffff)
    """

    if L_x <= 0:
        return basic_op.MAX_INT_30

    exp = basic_op.norm_l(L_x)
    L_x = basic_op.L_shl(L_x, exp)  # L_x is normalize

    exp = basic_op.sub(30, exp)
    if (exp & 1) == 0:  # If exponent even -> shift right
        L_x = basic_op.L_shr(L_x, 1)

    exp = basic_op.shr(exp, 1)
    exp = basic_op.add(exp, 1)

    L_x = basic_op.L_shr(L_x, 9)
    i = basic_op.extract_h(L_x)  # Extract b25-b31
    L_x = basic_op.L_shr(L_x, 1)
    a = basic_op.extract_l(L_x)  # Extract b10-b24
    a = a & 0x7fff

    i = basic_op.sub(i, 16)

    L_y = basic_op.L_deposit_h(tab_ld8a.tabsqr[i])  # tabsqr[i] << 16
    tmp = basic_op.sub(tab_ld8a.tabsqr[i],
                       tab_ld8a.tabsqr[i + 1])  # tabsqr[i] - tabsqr[i+1])
    L_y = basic_op.L_msu(L_y, tmp, a)  # L_y -=  tmp*a*2

    L_y = basic_op.L_shr(L_y, exp)  # denormalization

    return L_y
예제 #3
0
def Log2(L_x: int, exponent: int, fraction: int) -> Tuple[int, int]:
    """
    # (i) Q0 : input value 
    # (o) Q0 : Integer part of Log2.   (range: 0<=val<=30)
    # (o) Q15: Fractional  part of Log2. (range: 0<=val<1)
    """

    if L_x <= 0:
        return (0, 0)

    exp = basic_op.norm_l(L_x)
    L_x = basic_op.L_shl(L_x, exp)  # L_x is normalized

    exponent = basic_op.sub(30, exp)

    L_x = basic_op.L_shr(L_x, 9)
    i = basic_op.extract_h(L_x)  # Extract b25-b31
    L_x = basic_op.L_shr(L_x, 1)
    a = basic_op.extract_l(L_x)  # Extract b10-b24 of fraction
    a = a & 0x7fff

    i = basic_op.sub(i, 32)

    L_y = basic_op.L_deposit_h(tab_ld8a.tablog[i])  # tablog[i] << 16
    tmp = basic_op.sub(tab_ld8a.tablog[i],
                       tab_ld8a.tablog[i + 1])  # tablog[i] - tablog[i+1]
    L_y = basic_op.L_msu(L_y, tmp, a)  # L_y -= tmp*a*2

    fraction = basic_op.extract_h(L_y)

    return (exponent, fraction)
예제 #4
0
def Autocorr(x: List[int], m: int, r_h: List[int], r_l: List[int]) -> None:
    """
    # (i)    : Input signal
    # (i)    : LPC order
    # (o)    : Autocorrelations  (msb)
    # (o)    : Autocorrelations  (lsb)
    """

    y = [0] * ld8a.L_WINDOW

    # Windowing of signal

    for i in range(0, ld8a.L_WINDOW):
        y[i] = basic_op.mult_r(x[i], tab_ld8a.hamwindow[i])

    # Compute r[0] and test for overflow
    while(basic_op.getOverflow() != 0):
        basic_op.setOverflow(0)
        sum = 1

        # Avoid case of all zeros

        for i in range(0, ld8a.L_WINDOW):
            sum = basic_op.L_mac(sum, y[i], y[i])

        # If overflow divide y[] by 4

        if basic_op.getOverflow() != 0:
            for i in range(0, ld8a.L_WINDOW):
                y[i] = basic_op.shr(y[i], 2)

    # Normalization of r[0]
    norm = basic_op.norm_l(sum)
    sum = basic_op.L_shl(sum, norm)
    r_h[0], r_l[0] = oper_32b.L_Extract(sum, r_h[0], r_l[0])

    # Put in DPF format(see oper_32b)
    # r[1] to r[m]

    for i in range(1, m + 1):
        sum = 0

        for j in range(0, ld8a.L_WINDOW - i):
            sum = basic_op.L_mac(sum, y[j], y[j + i])

        sum = basic_op.L_shl(sum, norm)
        r_h[i], r_l[i] = oper_32b.L_Extract(sum, r_h[i], r_l[i])
예제 #5
0
def Convolve(x: List[int], h: List[int], y: List[int], L: int) -> None:
    """
    # (i)     : input vector
    # (i) Q12 : impulse response
    # (o)     : output vector
    # (i)     : vector size
    """

    for n in range(0, L):
        s = 0
        for i in range(0, n + 1):
            s = basic_op.L_mac(s, x[i], h[n-i])

        s    = basic_op.L_shl(s, 3)                   # h is in Q12 and saturation
        y[n] = basic_op.extract_h(s)
예제 #6
0
def Residu(a: List[int], x: List[int], y: List[int], lg: int) -> None:
    """
    # (i) Q12 : prediction coefficients 
    # (i)     : speech (values x[-m..-1] are needed
    # (o)     : residual signal 
    # (i)     : size of filtering
    """

    for i in range(0, lg):
        s = basic_op.L_mult(x[i], a[0])
        
        for j in range(1, ld8a.M + 1):
            s = basic_op.L_mac(s, a[j], x[i-j])

        s = basic_op.L_shl(s, 3)
        y[i] = basic_op.round(s)
예제 #7
0
def Gain_update(past_qua_en: List[int], L_gbk12: int) -> None:
    """
    # (io) Q10 :Past quantized energies
    # (i) Q13 : gbk1[indice1][1]+gbk2[indice2][1]
    """

    for i in range(3, 0, -1):
        past_qua_en[i] = past_qua_en[i - 1]  # Q10

    ##########
    # -- past_qua_en[0] = 20*log10(gbk1[index1][1]+gbk2[index2][1]) --
    #    2 * 10 log10( gbk1[index1][1]+gbk2[index2][1] )
    #  = 2 * 3.0103 log2( gbk1[index1][1]+gbk2[index2][1] )
    #  = 2 * 3.0103 log2( gbk1[index1][1]+gbk2[index2][1] )
    #                                                 24660:Q12(6.0205)
    ##########

    exp, frac = dsp_func.Log2(L_gbk12, exp, frac)  # L_gbk12:Q13
    L_acc = oper_32b.L_Comp(basic_op.sub(exp, 13), frac)  # L_acc:Q16
    tmp = basic_op.extract_h(basic_op.L_shl(L_acc, 13))  # tmp:Q13
    past_qua_en[0] = basic_op.mult(tmp, 24660)  # past_qua_en[]:Q10
예제 #8
0
def Syn_filt(a: List[int], x: List[int], y: List[int], lg: int, mem: List[int], update: int) -> None:
    """
    # (i) Q12 : a[m+1] prediction coefficients   (m=10)
    # (i)     : input signal
    # (o)     : output signal
    # (i)     : size of filtering
    # (i/o)   : memory associated with this filtering.
    # (i)     : 0=no update, 1=update of memory.
    """

    #Word16 i, j
    #Word32 s
    #Word16 tmp[100]     # This is usually done by memory allocation (lg+M) 
    #Word16 *yy

    tmp = [0] * 100

    # Copy mem[] to yy[] (yy points to tmp)
    for i in range(0, ld8a.M):
        tmp[i] = mem[i]

    # Do the filtering. 
    for i in range(0, lg):
        s = basic_op.L_mult(x[i], a[0])

        for j in range(1, ld8a.M + 1):
            # this negative index needs tested
            s = basic_op.L_msu(s, a[j], tmp[-j])

        s = basic_op.L_shl(s, 3)
        tmp[i] = basic_op.round(s)
    
    for i in range (0, lg):
        y[i] = tmp[i+M]

    # Update of memory if update==1 

    if update != 0:
        for i in range(0, ld8a.M):
            mem[i] = y[lg-M+i]
예제 #9
0
def Levinson(Rh: List[int], Rl: List[int], A: List[int], rc: List[int]) -> None:
    """
    # (i)     : Rh[M+1] Vector of autocorrelations (msb)
    # (i)     : Rl[M+1] Vector of autocorrelations (lsb)
    # (o) Q12 : A[M]    LPC coefficients  (m = 10)
    # (o) Q15 : rc[M]   Reflection coefficients.
    """

    # LPC coef. in double prec. 
    Ah = [0] * (M + 1)
    Al = [0] * (M + 1)

    # LPC coef.for next iteration in double prec.
    Anh = [0] * (M + 1)
    Anl = [0] * (M + 1)

    # K = A[1] = -R[1] / R[0] 

    t1 = oper_32b.L_Comp(Rh[1], Rl[1])          # R[1] in Q31      
    t2 = basic_op.L_abs(t1)                     # abs R[1]         
    t0 = oper_32b.Div_32(t2, Rh[0], Rl[0])      # R[1]/R[0] in Q31

    if t1 > 0:
        t0 = basic_op.L_negate(t0)              # -R[1]/R[0]

    Kh, Kl = oper_32b.L_Extract(t0)             # K in DPF         
    rc[0] = Kh
    t0 = basic_op.L_shr(t0, 4)                  # A[1] in Q27      
    Ah[1], Al[1] = oper_32b.L_Extract(t0)       # A[1] in DPF      

    #  Alpha = R[0] * (1-K**2) 

    t0 = oper_32b.Mpy_32(Kh, Kl, Kh, Kl)            # K*K      in Q31 
    t0 = basic_op.L_abs(t0)                         # Some case <0 !! 
    t0 = basic_op.L_sub(basic_op.MAX_INT_32, t0)    # 1 - K*K  in Q31 
    hi, lo = L_Extract(t0)                          # DPF format      
    t0 = oper_32b.Mpy_32(Rh[0], Rl[0], hi, lo)      # Alpha in Q31    

    # Normalize Alpha 

    alp_exp = basic_op.norm_l(t0)
    t0 = basic_op.L_shl(t0, alp_exp)
    alp_h, alp_l = L_Extract(t0)                    # DPF format    

    ########
    # ITERATIONS  I=2 to M
    ########

    for i in range(2, ld8a.M + 1):
        # t0 = SUM ( R[j]*A[i-j] ,j=1,i-1 ) +  R[i] 

        t0 = 0
        for j in range(1, i):
            t0 = basic_op.L_add(t0, oper_32b.Mpy_32(Rh[j], Rl[j], Ah[i - j], Al[i - j]))

        t0 = basic_op.L_shl(t0, 4)                  # result in Q27 -> convert to Q31 
                                                    # No overflow possible            
        t1 = oper_32b.L_Comp(Rh[i], Rl[i])
        t0 = basic_op.L_add(t0, t1)                 # add R[i] in Q31                 

        # K = -t0 / Alpha

        t1 = basic_op.L_abs(t0)
        t2 = oper_32b.Div_32(t1, alp_h, alp_l)      # abs(t0)/Alpha
        
        if t0 > 0:
            t2 = basic_op.L_negate(t2)              # K =-t0/Alpha                    
        t2 = basic_op.L_shl(t2, alp_exp)            # denormalize compare to Alpha   
        Kh, Kl = L_Extract(t2)                      # K in DPF                        
        rc[i - 1] = Kh

        # Test for unstable filter. If unstable keep old A(z) 

        if basic_op.sub(basic_op.abs_s(Kh), 32750) > 0:
            for j in range(0, ld8a.M + 1):
                A[j] = old_A[j]
            
            rc[0] = old_rc[0]       # only two rc coefficients are needed 
            rc[1] = old_rc[1]
            return
        

        ##########
        # Compute new LPC coeff. -> An[i]         *
        # An[j]= A[j] + K*A[i-j]     , j=1 to i-1 *
        # An[i]= K                                *
        ##########

        for j in range (1, i):
            t0 = oper_32b.Mpy_32(Kh, Kl, Ah[i - j], Al[i - j])
            t0 = basic_op.L_add(t0, oper_32b.L_Comp(Ah[j], Al[j]))
            Anh[j], Anl[j] = L_Extract(t0)
        
        t2 = basic_op.L_shr(t2, 4)              # t2 = K in Q31 ->convert to Q27  
        Anh[i], Anl[i] = L_Extract(t2)          # An[i] in Q27                    

        #  Alpha = Alpha * (1-K**2) 

        t0 = oper_32b.Mpy_32(Kh, Kl, Kh, Kl)            # K*K      in Q31 
        t0 = basic_op.L_abs(t0)                         # Some case <0 !! 
        t0 = basic_op.L_sub(basic_op.MAX_INT_32, t0)    # 1 - K*K  in Q31 
        hi, lo = L_Extract(t0)                          # DPF format      
        t0 = oper_32b.Mpy_32(alp_h, alp_l, hi, lo)      # Alpha in Q31    

        # Normalize Alpha 

        j = basic_op.norm_l(t0)
        t0 = basic_op.L_shl(t0, j)
        alp_h, alp_l = L_Extract(t0)            # DPF format    
        alp_exp = basic_op.add(alp_exp, j)      # Add normalization to alp_exp 

        # A[j] = An[j] 

        for j in range(1, i + 1):
            Ah[j] = Anh[j]
            Al[j] = Anl[j]

    # Truncate A[i] in Q27 to Q12 with rounding 

    A[0] = 4096

    for i in range(1, ld8a.M + 1):
        t0 = oper_32b.L_Comp(Ah[i], Al[i])
        old_A[i] = A[i] = basic_op.round(L_shl(t0, 1))
    
    old_rc[0] = rc[0]
    old_rc[1] = rc[1]
예제 #10
0
def Gain_predict(past_qua_en: List[int], code: List[int],
                 L_subfr: int) -> Tuple[int, int]:
    """
    # (i) Q10 :Past quantized energies
    # (i) Q13 :Innovative vector.
    # (i)     :Subframe length.
    # (o) Qxx :Predicted codebook gain      - omitted param
    # (o)     :Q-Format(gcode0)             - omitted param
    """

    #Word16  i, exp, frac
    #Word32  L_tmp

    ##########
    # Energy coming from code
    ##########

    L_tmp = 0
    for i in range(0, L_subfr):
        L_tmp = basic_op.L_mac(L_tmp, code[i], code[i])

    ##########
    #  Compute: means_ener - 10log10(ener_code/ L_sufr)
    #  Note: mean_ener change from 36 dB to 30 dB because input/2
    #
    # = 30.0 - 10 log10( ener_code / lcode)  + 10log10(2^27)
    #                                          !!ener_code in Q27!!
    # = 30.0 - 3.0103  log2(ener_code) + 10log10(40) + 10log10(2^27)
    # = 30.0 - 3.0103  log2(ener_code) + 16.02  + 81.278
    # = 127.298 - 3.0103  log2(ener_code)
    ##########

    exp, frac = dsp_func.Log2(L_tmp, exp, frac)  # Q27->Q0 ^Q0 ^Q15
    L_tmp = oper_32b.Mpy_32_16(exp, frac, -24660)  # Q0 Q15 Q13 -> ^Q14
    # hi:Q0+Q13+1
    # lo:Q15+Q13-15+1
    # -24660[Q13]=-3.0103
    L_tmp = basic_op.L_mac(basic_op.L_tmp, 32588, 32)  # 32588*32[Q14]=127.298

    ##########
    # Compute gcode0.                                                 *
    #  = Sum(i=0,3) pred[i]*past_qua_en[i] - ener_code + mean_ener    *
    ##########

    L_tmp = basic_op.L_shl(L_tmp, 10)  # From Q14 to Q24
    for i in range(0, 4):
        L_tmp = basic_op.L_mac(L_tmp, pred[i], past_qua_en[i])  # Q13*Q10 ->Q24

    gcode0 = basic_op.extract_h(L_tmp)  # From Q24 to Q8

    ##########
    # gcode0 = pow(10.0, gcode0/20)                                   *
    #        = pow(2, 3.3219*gcode0/20)                               *
    #        = pow(2, 0.166*gcode0)                                   *
    ##########

    L_tmp = basic_op.L_mult(gcode0, 5439)  # *0.166 in Q15, result in Q24
    L_tmp = basic_op.L_shr(L_tmp, 8)  # From Q24 to Q16
    exp, frac = oper_32b.L_Extract(L_tmp, exp,
                                   frac)  # Extract exponent of gcode0

    gcode0 = basic_op.extract_l(dsp_func.Pow2(
        14, frac))  # Put 14 as exponent so that
    # output of Pow2() will be:
    # 16768 < Pow2() <= 32767
    exp_gcode0 = basic_op.sub(14, exp)

    return (gcode0, exp_gcode0)