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
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
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)
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])
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)
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)
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
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]
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]
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)