14930cef6SMatthias Ringwald# 24930cef6SMatthias Ringwald# Copyright 2022 Google LLC 34930cef6SMatthias Ringwald# 44930cef6SMatthias Ringwald# Licensed under the Apache License, Version 2.0 (the "License"); 54930cef6SMatthias Ringwald# you may not use this file except in compliance with the License. 64930cef6SMatthias Ringwald# You may obtain a copy of the License at 74930cef6SMatthias Ringwald# 84930cef6SMatthias Ringwald# http://www.apache.org/licenses/LICENSE-2.0 94930cef6SMatthias Ringwald# 104930cef6SMatthias Ringwald# Unless required by applicable law or agreed to in writing, software 114930cef6SMatthias Ringwald# distributed under the License is distributed on an "AS IS" BASIS, 124930cef6SMatthias Ringwald# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134930cef6SMatthias Ringwald# See the License for the specific language governing permissions and 144930cef6SMatthias Ringwald# limitations under the License. 154930cef6SMatthias Ringwald# 164930cef6SMatthias Ringwald 174930cef6SMatthias Ringwaldimport numpy as np 184930cef6SMatthias Ringwald 194c4eb519SMatthias Ringwaldimport lc3 204930cef6SMatthias Ringwaldimport tables as T, appendix_c as C 214930cef6SMatthias Ringwald 224930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 234930cef6SMatthias Ringwald 244930cef6SMatthias Ringwaldclass Tns: 25*6897da5cSDirk Helbig SUB_LIM_2M5_NB = [ [ 3, 10, 20 ] ] 26*6897da5cSDirk Helbig SUB_LIM_2M5_WB = [ [ 3, 20, 40 ] ] 27*6897da5cSDirk Helbig SUB_LIM_2M5_SSWB = [ [ 3, 30, 60 ] ] 28*6897da5cSDirk Helbig SUB_LIM_2M5_SWB = [ [ 3, 40, 80 ] ] 29*6897da5cSDirk Helbig SUB_LIM_2M5_FB = [ [ 3, 51, 100 ] ] 304930cef6SMatthias Ringwald 31*6897da5cSDirk Helbig SUB_LIM_2M5 = [ 32*6897da5cSDirk Helbig SUB_LIM_2M5_NB , SUB_LIM_2M5_WB, SUB_LIM_2M5_SSWB, 33*6897da5cSDirk Helbig SUB_LIM_2M5_SWB, SUB_LIM_2M5_FB, SUB_LIM_2M5_FB, SUB_LIM_2M5_FB ] 344930cef6SMatthias Ringwald 35*6897da5cSDirk Helbig SUB_LIM_5M_NB = [ [ 6, 23, 40 ] ] 36*6897da5cSDirk Helbig SUB_LIM_5M_WB = [ [ 6, 43, 80 ] ] 37*6897da5cSDirk Helbig SUB_LIM_5M_SSWB = [ [ 6, 63, 120 ] ] 38*6897da5cSDirk Helbig SUB_LIM_5M_SWB = [ [ 6, 43, 80 ], [ 80, 120, 160 ] ] 39*6897da5cSDirk Helbig SUB_LIM_5M_FB = [ [ 6, 53, 100 ], [ 100, 150, 200 ] ] 40*6897da5cSDirk Helbig 41*6897da5cSDirk Helbig SUB_LIM_5M = [ 42*6897da5cSDirk Helbig SUB_LIM_5M_NB , SUB_LIM_5M_WB, SUB_LIM_5M_SSWB, 43*6897da5cSDirk Helbig SUB_LIM_5M_SWB, SUB_LIM_5M_FB, SUB_LIM_5M_FB, SUB_LIM_5M_FB ] 444930cef6SMatthias Ringwald 454930cef6SMatthias Ringwald SUB_LIM_7M5_NB = [ [ 9, 26, 43, 60 ] ] 464930cef6SMatthias Ringwald SUB_LIM_7M5_WB = [ [ 9, 46, 83, 120 ] ] 474930cef6SMatthias Ringwald SUB_LIM_7M5_SSWB = [ [ 9, 66, 123, 180 ] ] 484930cef6SMatthias Ringwald SUB_LIM_7M5_SWB = [ [ 9, 46, 82, 120 ], [ 120, 159, 200, 240 ] ] 494930cef6SMatthias Ringwald SUB_LIM_7M5_FB = [ [ 9, 56, 103, 150 ], [ 150, 200, 250, 300 ] ] 504930cef6SMatthias Ringwald 51*6897da5cSDirk Helbig SUB_LIM_7M5 = [ 52*6897da5cSDirk Helbig SUB_LIM_7M5_NB , SUB_LIM_7M5_WB, SUB_LIM_7M5_SSWB, 53*6897da5cSDirk Helbig SUB_LIM_7M5_SWB, SUB_LIM_7M5_FB, None, None ] 544930cef6SMatthias Ringwald 55*6897da5cSDirk Helbig SUB_LIM_10M_NB = [ [ 12, 34, 57, 80 ] ] 56*6897da5cSDirk Helbig SUB_LIM_10M_WB = [ [ 12, 61, 110, 160 ] ] 57*6897da5cSDirk Helbig SUB_LIM_10M_SSWB = [ [ 12, 88, 164, 240 ] ] 58*6897da5cSDirk Helbig SUB_LIM_10M_SWB = [ [ 12, 61, 110, 160 ], [ 160, 213, 266, 320 ] ] 59*6897da5cSDirk Helbig SUB_LIM_10M_FB = [ [ 12, 74, 137, 200 ], [ 200, 266, 333, 400 ] ] 604930cef6SMatthias Ringwald 61*6897da5cSDirk Helbig SUB_LIM_10M = [ 62*6897da5cSDirk Helbig SUB_LIM_10M_NB , SUB_LIM_10M_WB, SUB_LIM_10M_SSWB, 63*6897da5cSDirk Helbig SUB_LIM_10M_SWB, SUB_LIM_10M_FB, SUB_LIM_10M_FB, SUB_LIM_10M_FB ] 644930cef6SMatthias Ringwald 65*6897da5cSDirk Helbig SUB_LIM = [ SUB_LIM_2M5, SUB_LIM_5M, SUB_LIM_7M5, SUB_LIM_10M ] 66*6897da5cSDirk Helbig 67*6897da5cSDirk Helbig 68*6897da5cSDirk Helbig FREQ_LIM_2M5_NB = [ 3, 20 ] 69*6897da5cSDirk Helbig FREQ_LIM_2M5_WB = [ 3, 40 ] 70*6897da5cSDirk Helbig FREQ_LIM_2M5_SSWB = [ 3, 60 ] 71*6897da5cSDirk Helbig FREQ_LIM_2M5_SWB = [ 3, 80 ] 72*6897da5cSDirk Helbig FREQ_LIM_2M5_FB = [ 3, 100 ] 73*6897da5cSDirk Helbig 74*6897da5cSDirk Helbig FREQ_LIM_2M5 = [ 75*6897da5cSDirk Helbig FREQ_LIM_2M5_NB , FREQ_LIM_2M5_WB, FREQ_LIM_2M5_SSWB, 76*6897da5cSDirk Helbig FREQ_LIM_2M5_SWB, FREQ_LIM_2M5_FB, FREQ_LIM_2M5_FB, FREQ_LIM_2M5_FB ] 77*6897da5cSDirk Helbig 78*6897da5cSDirk Helbig FREQ_LIM_5M_NB = [ 6, 40 ] 79*6897da5cSDirk Helbig FREQ_LIM_5M_WB = [ 6, 80 ] 80*6897da5cSDirk Helbig FREQ_LIM_5M_SSWB = [ 6, 120 ] 81*6897da5cSDirk Helbig FREQ_LIM_5M_SWB = [ 6, 80, 160 ] 82*6897da5cSDirk Helbig FREQ_LIM_5M_FB = [ 6, 100, 200 ] 83*6897da5cSDirk Helbig 84*6897da5cSDirk Helbig FREQ_LIM_5M = [ 85*6897da5cSDirk Helbig FREQ_LIM_5M_NB , FREQ_LIM_5M_WB, FREQ_LIM_5M_SSWB, 86*6897da5cSDirk Helbig FREQ_LIM_5M_SWB, FREQ_LIM_5M_FB, FREQ_LIM_5M_FB, FREQ_LIM_5M_FB ] 874930cef6SMatthias Ringwald 884930cef6SMatthias Ringwald FREQ_LIM_7M5_NB = [ 9, 60 ] 894930cef6SMatthias Ringwald FREQ_LIM_7M5_WB = [ 9, 120 ] 904930cef6SMatthias Ringwald FREQ_LIM_7M5_SSWB = [ 9, 180 ] 914930cef6SMatthias Ringwald FREQ_LIM_7M5_SWB = [ 9, 120, 240 ] 924930cef6SMatthias Ringwald FREQ_LIM_7M5_FB = [ 9, 150, 300 ] 934930cef6SMatthias Ringwald 94*6897da5cSDirk Helbig FREQ_LIM_7M5 = [ 95*6897da5cSDirk Helbig FREQ_LIM_7M5_NB , FREQ_LIM_7M5_WB, FREQ_LIM_7M5_SSWB, 96*6897da5cSDirk Helbig FREQ_LIM_7M5_SWB, FREQ_LIM_7M5_FB, None, None ] 974930cef6SMatthias Ringwald 98*6897da5cSDirk Helbig FREQ_LIM_10M_NB = [ 12, 80 ] 99*6897da5cSDirk Helbig FREQ_LIM_10M_WB = [ 12, 160 ] 100*6897da5cSDirk Helbig FREQ_LIM_10M_SSWB = [ 12, 240 ] 101*6897da5cSDirk Helbig FREQ_LIM_10M_SWB = [ 12, 160, 320 ] 102*6897da5cSDirk Helbig FREQ_LIM_10M_FB = [ 12, 200, 400 ] 103*6897da5cSDirk Helbig 104*6897da5cSDirk Helbig FREQ_LIM_10M = [ 105*6897da5cSDirk Helbig FREQ_LIM_10M_NB , FREQ_LIM_10M_WB, FREQ_LIM_10M_SSWB, 106*6897da5cSDirk Helbig FREQ_LIM_10M_SWB, FREQ_LIM_10M_FB, FREQ_LIM_10M_FB, FREQ_LIM_10M_FB ] 107*6897da5cSDirk Helbig 108*6897da5cSDirk Helbig FREQ_LIM = [ FREQ_LIM_2M5, FREQ_LIM_5M, FREQ_LIM_7M5, FREQ_LIM_10M ] 109*6897da5cSDirk Helbig 1104930cef6SMatthias Ringwald 1114930cef6SMatthias Ringwald def __init__(self, dt): 1124930cef6SMatthias Ringwald 1134930cef6SMatthias Ringwald self.dt = dt 1144930cef6SMatthias Ringwald 1154930cef6SMatthias Ringwald (self.nfilters, self.lpc_weighting, self.rc_order, self.rc) = \ 1164c4eb519SMatthias Ringwald (0, False, np.array([ 0, 0 ]), np.array([ 0, 0 ])) 1174930cef6SMatthias Ringwald 1184930cef6SMatthias Ringwald def get_data(self): 1194930cef6SMatthias Ringwald 120*6897da5cSDirk Helbig rc = np.append(self.rc - 8, np.zeros((2, 8 - len(self.rc[0]))), axis=1) 121*6897da5cSDirk Helbig 1224930cef6SMatthias Ringwald return { 'nfilters' : self.nfilters, 1234930cef6SMatthias Ringwald 'lpc_weighting' : self.lpc_weighting, 124*6897da5cSDirk Helbig 'rc_order' : self.rc_order, 'rc' : rc } 1254930cef6SMatthias Ringwald 1264930cef6SMatthias Ringwald def get_nbits(self): 1274930cef6SMatthias Ringwald 1284930cef6SMatthias Ringwald lpc_weighting = self.lpc_weighting 1294930cef6SMatthias Ringwald nbits = 0 1304930cef6SMatthias Ringwald 1314930cef6SMatthias Ringwald for f in range(self.nfilters): 1324930cef6SMatthias Ringwald rc_order = self.rc_order[f] 1334930cef6SMatthias Ringwald rc = self.rc[f] 1344930cef6SMatthias Ringwald 1354930cef6SMatthias Ringwald nbits_order = T.TNS_ORDER_BITS[int(lpc_weighting)][rc_order] 1364930cef6SMatthias Ringwald nbits_coef = sum([ T.TNS_COEF_BITS[k][rc[k]] 1374930cef6SMatthias Ringwald for k in range(rc_order) ]) 1384930cef6SMatthias Ringwald 1394930cef6SMatthias Ringwald nbits += ((2048 + nbits_order + nbits_coef) + 2047) >> 11 1404930cef6SMatthias Ringwald 1414930cef6SMatthias Ringwald return nbits 1424930cef6SMatthias Ringwald 1434930cef6SMatthias Ringwald 1444930cef6SMatthias Ringwaldclass TnsAnalysis(Tns): 1454930cef6SMatthias Ringwald 1464930cef6SMatthias Ringwald def __init__(self, dt): 1474930cef6SMatthias Ringwald 1484930cef6SMatthias Ringwald super().__init__(dt) 1494930cef6SMatthias Ringwald 1504930cef6SMatthias Ringwald def compute_lpc_coeffs(self, bw, f, x): 1514930cef6SMatthias Ringwald 1524930cef6SMatthias Ringwald ### Normalized autocorrelation function 1534930cef6SMatthias Ringwald 1544930cef6SMatthias Ringwald S = Tns.SUB_LIM[self.dt][bw][f] 155*6897da5cSDirk Helbig maxorder = [ 4, 8 ][self.dt > T.DT_5M] 1564930cef6SMatthias Ringwald 157*6897da5cSDirk Helbig r = np.append([ 3 ], np.zeros(maxorder)) 158*6897da5cSDirk Helbig e = [ sum(x[S[s]:S[s+1]] ** 2) for s in range(len(S)-1) ] 1594930cef6SMatthias Ringwald 1604930cef6SMatthias Ringwald for k in range(len(r) if sum(e) > 0 else 0): 1614930cef6SMatthias Ringwald c = [ np.dot(x[S[s]:S[s+1]-k], x[S[s]+k:S[s+1]]) 162*6897da5cSDirk Helbig for s in range(len(S)-1) ] 1634930cef6SMatthias Ringwald 1644930cef6SMatthias Ringwald r[k] = np.sum( np.array(c) / np.array(e) ) 1654930cef6SMatthias Ringwald 166*6897da5cSDirk Helbig r *= np.exp(-0.5 * (0.02 * np.pi * np.arange(1+maxorder)) ** 2) 1674930cef6SMatthias Ringwald 1684930cef6SMatthias Ringwald ### Levinson-Durbin recursion 1694930cef6SMatthias Ringwald 1704930cef6SMatthias Ringwald err = r[0] 1714930cef6SMatthias Ringwald a = np.ones(len(r)) 1724930cef6SMatthias Ringwald 1734930cef6SMatthias Ringwald for k in range(1, len(a)): 1744930cef6SMatthias Ringwald 1754930cef6SMatthias Ringwald rc = -sum(a[:k] * r[k:0:-1]) / err 1764930cef6SMatthias Ringwald 1774930cef6SMatthias Ringwald a[1:k] += rc * a[k-1:0:-1] 1784930cef6SMatthias Ringwald a[k] = rc 1794930cef6SMatthias Ringwald 1804930cef6SMatthias Ringwald err *= 1 - rc ** 2 1814930cef6SMatthias Ringwald 1824930cef6SMatthias Ringwald return (r[0] / err, a) 1834930cef6SMatthias Ringwald 1844c4eb519SMatthias Ringwald def lpc_weight(self, pred_gain, a): 1854930cef6SMatthias Ringwald 1864930cef6SMatthias Ringwald gamma = 1 - (1 - 0.85) * (2 - pred_gain) / (2 - 1.5) 1874930cef6SMatthias Ringwald return a * np.power(gamma, np.arange(len(a))) 1884930cef6SMatthias Ringwald 1894930cef6SMatthias Ringwald def coeffs_reflexion(self, a): 1904930cef6SMatthias Ringwald 191*6897da5cSDirk Helbig rc = np.zeros(len(a)-1) 1924930cef6SMatthias Ringwald b = a.copy() 1934930cef6SMatthias Ringwald 194*6897da5cSDirk Helbig for k in range(len(rc), 0, -1): 1954930cef6SMatthias Ringwald rc[k-1] = b[k] 1964930cef6SMatthias Ringwald e = 1 - rc[k-1] ** 2 1974930cef6SMatthias Ringwald b[1:k] = (b[1:k] - rc[k-1] * b[k-1:0:-1]) / e 1984930cef6SMatthias Ringwald 1994930cef6SMatthias Ringwald return rc 2004930cef6SMatthias Ringwald 2014930cef6SMatthias Ringwald def quantization(self, rc, lpc_weighting): 2024930cef6SMatthias Ringwald 2034930cef6SMatthias Ringwald delta = np.pi / 17 2044930cef6SMatthias Ringwald rc_i = np.rint(np.arcsin(rc) / delta).astype(int) + 8 2054930cef6SMatthias Ringwald rc_q = np.sin(delta * (rc_i - 8)) 206*6897da5cSDirk Helbig rc_q = np.rint(rc_q * 2**15) / 2**15 2074930cef6SMatthias Ringwald 2084930cef6SMatthias Ringwald rc_order = len(rc_i) - np.argmin(rc_i[::-1] == 8) 2094930cef6SMatthias Ringwald 2104930cef6SMatthias Ringwald return (rc_order, rc_q, rc_i) 2114930cef6SMatthias Ringwald 2124930cef6SMatthias Ringwald def filtering(self, st, x, rc_order, rc): 2134930cef6SMatthias Ringwald 2144930cef6SMatthias Ringwald y = np.empty(len(x)) 2154930cef6SMatthias Ringwald 2164930cef6SMatthias Ringwald for i in range(len(x)): 2174930cef6SMatthias Ringwald 2184930cef6SMatthias Ringwald xi = x[i] 2194930cef6SMatthias Ringwald s1 = xi 2204930cef6SMatthias Ringwald 2214930cef6SMatthias Ringwald for k in range(rc_order): 2224930cef6SMatthias Ringwald s0 = st[k] 2234930cef6SMatthias Ringwald st[k] = s1 2244930cef6SMatthias Ringwald 2254930cef6SMatthias Ringwald s1 = rc[k] * xi + s0 2264930cef6SMatthias Ringwald xi += rc[k] * s0 2274930cef6SMatthias Ringwald 2284930cef6SMatthias Ringwald y[i] = xi 2294930cef6SMatthias Ringwald 2304930cef6SMatthias Ringwald return y 2314930cef6SMatthias Ringwald 2324930cef6SMatthias Ringwald def run(self, x, bw, nn_flag, nbytes): 2334930cef6SMatthias Ringwald 2344930cef6SMatthias Ringwald fstate = np.zeros(8) 2354930cef6SMatthias Ringwald y = x.copy() 2364930cef6SMatthias Ringwald 2374930cef6SMatthias Ringwald self.nfilters = len(Tns.SUB_LIM[self.dt][bw]) 238*6897da5cSDirk Helbig maxorder = [ 4, 8 ][self.dt > T.DT_5M] 239*6897da5cSDirk Helbig 240*6897da5cSDirk Helbig self.lpc_weighting = nbytes < 120 * (1 + self.dt) / 8 241*6897da5cSDirk Helbig 242*6897da5cSDirk Helbig self.rc_order = np.zeros(2, dtype=np.intc) 243*6897da5cSDirk Helbig self.rc = np.zeros((2, maxorder), dtype=np.intc) 2444930cef6SMatthias Ringwald 2454930cef6SMatthias Ringwald for f in range(self.nfilters): 2464930cef6SMatthias Ringwald 2474930cef6SMatthias Ringwald (pred_gain, a) = self.compute_lpc_coeffs(bw, f, x) 2484930cef6SMatthias Ringwald 2494930cef6SMatthias Ringwald tns_off = pred_gain <= 1.5 or nn_flag 2504930cef6SMatthias Ringwald if tns_off: 2514930cef6SMatthias Ringwald continue 2524930cef6SMatthias Ringwald 2534930cef6SMatthias Ringwald if self.lpc_weighting and pred_gain < 2: 2544c4eb519SMatthias Ringwald a = self.lpc_weight(pred_gain, a) 2554930cef6SMatthias Ringwald 2564930cef6SMatthias Ringwald rc = self.coeffs_reflexion(a) 2574930cef6SMatthias Ringwald 2584930cef6SMatthias Ringwald (rc_order, rc_q, rc_i) = \ 2594930cef6SMatthias Ringwald self.quantization(rc, self.lpc_weighting) 2604930cef6SMatthias Ringwald 2614930cef6SMatthias Ringwald self.rc_order[f] = rc_order 2624930cef6SMatthias Ringwald self.rc[f] = rc_i 2634930cef6SMatthias Ringwald 2644930cef6SMatthias Ringwald if rc_order > 0: 2654930cef6SMatthias Ringwald i0 = Tns.FREQ_LIM[self.dt][bw][f] 2664930cef6SMatthias Ringwald i1 = Tns.FREQ_LIM[self.dt][bw][f+1] 2674930cef6SMatthias Ringwald 2684930cef6SMatthias Ringwald y[i0:i1] = self.filtering( 2694930cef6SMatthias Ringwald fstate, x[i0:i1], rc_order, rc_q) 2704930cef6SMatthias Ringwald 2714930cef6SMatthias Ringwald return y 2724930cef6SMatthias Ringwald 2734930cef6SMatthias Ringwald def store(self, b): 2744930cef6SMatthias Ringwald 2754930cef6SMatthias Ringwald for f in range(self.nfilters): 2764c4eb519SMatthias Ringwald lpc_weighting = self.lpc_weighting 2774930cef6SMatthias Ringwald rc_order = self.rc_order[f] 2784930cef6SMatthias Ringwald rc = self.rc[f] 2794930cef6SMatthias Ringwald 2804930cef6SMatthias Ringwald b.write_bit(min(rc_order, 1)) 2814930cef6SMatthias Ringwald 2824930cef6SMatthias Ringwald if rc_order > 0: 2834930cef6SMatthias Ringwald b.ac_encode( 2844930cef6SMatthias Ringwald T.TNS_ORDER_CUMFREQ[int(lpc_weighting)][rc_order-1], 2854930cef6SMatthias Ringwald T.TNS_ORDER_FREQ[int(lpc_weighting)][rc_order-1] ) 2864930cef6SMatthias Ringwald 2874930cef6SMatthias Ringwald for k in range(rc_order): 2884930cef6SMatthias Ringwald b.ac_encode(T.TNS_COEF_CUMFREQ[k][rc[k]], 2894930cef6SMatthias Ringwald T.TNS_COEF_FREQ[k][rc[k]] ) 2904930cef6SMatthias Ringwald 2914930cef6SMatthias Ringwald 2924930cef6SMatthias Ringwaldclass TnsSynthesis(Tns): 2934930cef6SMatthias Ringwald 2944930cef6SMatthias Ringwald def filtering(self, st, x, rc_order, rc): 2954930cef6SMatthias Ringwald 2964930cef6SMatthias Ringwald y = x.copy() 2974930cef6SMatthias Ringwald 2984930cef6SMatthias Ringwald for i in range(len(x)): 2994930cef6SMatthias Ringwald 3004930cef6SMatthias Ringwald xi = x[i] - rc[rc_order-1] * st[rc_order-1] 3014930cef6SMatthias Ringwald for k in range(rc_order-2, -1, -1): 3024930cef6SMatthias Ringwald xi -= rc[k] * st[k] 3034930cef6SMatthias Ringwald st[k+1] = xi * rc[k] + st[k]; 3044930cef6SMatthias Ringwald st[0] = xi; 3054930cef6SMatthias Ringwald 3064930cef6SMatthias Ringwald y[i] = xi 3074930cef6SMatthias Ringwald 3084930cef6SMatthias Ringwald return y 3094930cef6SMatthias Ringwald 3104930cef6SMatthias Ringwald def load(self, b, bw, nbytes): 3114930cef6SMatthias Ringwald 3124930cef6SMatthias Ringwald self.nfilters = len(Tns.SUB_LIM[self.dt][bw]) 313*6897da5cSDirk Helbig self.lpc_weighting = nbytes < 120 * (1 + self.dt) / 8 314*6897da5cSDirk Helbig self.rc_order = np.zeros(2, dtype=np.intc) 315*6897da5cSDirk Helbig self.rc = 8 * np.ones((2, 8), dtype=np.intc) 3164930cef6SMatthias Ringwald 3174930cef6SMatthias Ringwald for f in range(self.nfilters): 3184930cef6SMatthias Ringwald 3194930cef6SMatthias Ringwald if not b.read_bit(): 3204930cef6SMatthias Ringwald continue 3214930cef6SMatthias Ringwald 3224930cef6SMatthias Ringwald rc_order = 1 + b.ac_decode( 3234930cef6SMatthias Ringwald T.TNS_ORDER_CUMFREQ[int(self.lpc_weighting)], 3244930cef6SMatthias Ringwald T.TNS_ORDER_FREQ[int(self.lpc_weighting)]) 3254930cef6SMatthias Ringwald 3264930cef6SMatthias Ringwald self.rc_order[f] = rc_order 3274930cef6SMatthias Ringwald 3284930cef6SMatthias Ringwald for k in range(rc_order): 3294930cef6SMatthias Ringwald rc = b.ac_decode(T.TNS_COEF_CUMFREQ[k], T.TNS_COEF_FREQ[k]) 3304930cef6SMatthias Ringwald self.rc[f][k] = rc 3314930cef6SMatthias Ringwald 3324930cef6SMatthias Ringwald def run(self, x, bw): 3334930cef6SMatthias Ringwald 3344930cef6SMatthias Ringwald fstate = np.zeros(8) 3354930cef6SMatthias Ringwald y = x.copy() 3364930cef6SMatthias Ringwald 3374930cef6SMatthias Ringwald for f in range(self.nfilters): 3384930cef6SMatthias Ringwald 3394930cef6SMatthias Ringwald rc_order = self.rc_order[f] 3404930cef6SMatthias Ringwald rc = np.sin((np.pi / 17) * (self.rc[f] - 8)) 341*6897da5cSDirk Helbig rc = np.rint(rc * 2**15) / 2**15 3424930cef6SMatthias Ringwald 3434930cef6SMatthias Ringwald if rc_order > 0: 3444930cef6SMatthias Ringwald i0 = Tns.FREQ_LIM[self.dt][bw][f] 3454930cef6SMatthias Ringwald i1 = Tns.FREQ_LIM[self.dt][bw][f+1] 3464930cef6SMatthias Ringwald 3474930cef6SMatthias Ringwald y[i0:i1] = self.filtering( 3484930cef6SMatthias Ringwald fstate, x[i0:i1], rc_order, rc) 3494930cef6SMatthias Ringwald 3504930cef6SMatthias Ringwald return y 3514930cef6SMatthias Ringwald 3524930cef6SMatthias Ringwald 3534930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 3544930cef6SMatthias Ringwald 3554930cef6SMatthias Ringwalddef check_analysis(rng, dt, bw): 3564930cef6SMatthias Ringwald 3574930cef6SMatthias Ringwald ok = True 3584930cef6SMatthias Ringwald 3594930cef6SMatthias Ringwald analysis = TnsAnalysis(dt) 3604930cef6SMatthias Ringwald nbytes_lim = int((48 * T.DT_MS[dt]) // 8) 3614930cef6SMatthias Ringwald 3624930cef6SMatthias Ringwald for i in range(10): 363*6897da5cSDirk Helbig ne = T.I[dt][bw][-1] 364*6897da5cSDirk Helbig x = rng.random(ne) * 1e2 3654930cef6SMatthias Ringwald x = pow(x, .5 + i/5) 3664930cef6SMatthias Ringwald 3674930cef6SMatthias Ringwald for nn_flag in (True, False): 3684930cef6SMatthias Ringwald for nbytes in (nbytes_lim, nbytes_lim + 1): 3694930cef6SMatthias Ringwald 3704930cef6SMatthias Ringwald y = analysis.run(x, bw, nn_flag, nbytes) 3714930cef6SMatthias Ringwald (y_c, data_c) = lc3.tns_analyze(dt, bw, nn_flag, nbytes, x) 3724930cef6SMatthias Ringwald 3734930cef6SMatthias Ringwald ok = ok and data_c['lpc_weighting'] == analysis.lpc_weighting 374*6897da5cSDirk Helbig ok = ok and data_c['nfilters'] == analysis.nfilters 3754930cef6SMatthias Ringwald for f in range(analysis.nfilters): 3764930cef6SMatthias Ringwald rc_order = analysis.rc_order[f] 3774930cef6SMatthias Ringwald rc_order_c = data_c['rc_order'][f] 3784930cef6SMatthias Ringwald rc_c = 8 + data_c['rc'][f] 3794930cef6SMatthias Ringwald ok = ok and rc_order_c == rc_order 380*6897da5cSDirk Helbig ok = ok and not np.any(rc_c[:rc_order] - analysis.rc[f][:rc_order]) 3814930cef6SMatthias Ringwald 3824930cef6SMatthias Ringwald ok = ok and lc3.tns_get_nbits(data_c) == analysis.get_nbits() 3834930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y_c - y)) < 1e-2 3844930cef6SMatthias Ringwald 3854930cef6SMatthias Ringwald return ok 3864930cef6SMatthias Ringwald 3874930cef6SMatthias Ringwalddef check_synthesis(rng, dt, bw): 3884930cef6SMatthias Ringwald 3894930cef6SMatthias Ringwald ok = True 3904930cef6SMatthias Ringwald synthesis = TnsSynthesis(dt) 3914930cef6SMatthias Ringwald 3924930cef6SMatthias Ringwald for i in range(100): 3934930cef6SMatthias Ringwald 394*6897da5cSDirk Helbig ne = T.I[dt][bw][-1] 395*6897da5cSDirk Helbig x = rng.random(ne) * 1e2 3964930cef6SMatthias Ringwald 397*6897da5cSDirk Helbig maxorder = [ 4, 8 ][dt > T.DT_5M] 398*6897da5cSDirk Helbig synthesis.nfilters = 1 + int(dt >= T.DT_5M and bw >= T.SRATE_32K) 399*6897da5cSDirk Helbig synthesis.rc_order = rng.integers(0, 1+maxorder, 2) 4004930cef6SMatthias Ringwald synthesis.rc = rng.integers(0, 17, 16).reshape(2, 8) 4014930cef6SMatthias Ringwald 4024930cef6SMatthias Ringwald y = synthesis.run(x, bw) 4034930cef6SMatthias Ringwald y_c = lc3.tns_synthesize(dt, bw, synthesis.get_data(), x) 4044930cef6SMatthias Ringwald 405*6897da5cSDirk Helbig ok = ok and np.amax(np.abs(y_c - y) < 1e-4) 4064930cef6SMatthias Ringwald 4074930cef6SMatthias Ringwald return ok 4084930cef6SMatthias Ringwald 4094930cef6SMatthias Ringwalddef check_analysis_appendix_c(dt): 4104930cef6SMatthias Ringwald 411*6897da5cSDirk Helbig i0 = dt - T.DT_7M5 4124930cef6SMatthias Ringwald sr = T.SRATE_16K 413*6897da5cSDirk Helbig 4144930cef6SMatthias Ringwald ok = True 4154930cef6SMatthias Ringwald 416*6897da5cSDirk Helbig fs = Tns.FREQ_LIM[i0][sr][0] 417*6897da5cSDirk Helbig fe = Tns.FREQ_LIM[i0][sr][1] 4184930cef6SMatthias Ringwald st = np.zeros(8) 4194930cef6SMatthias Ringwald 420*6897da5cSDirk Helbig for i in range(len(C.X_S[i0])): 4214930cef6SMatthias Ringwald 422*6897da5cSDirk Helbig (_, a) = lc3.tns_compute_lpc_coeffs(dt, sr, C.X_S[i0][i]) 423*6897da5cSDirk Helbig ok = ok and np.amax(np.abs(a[0] - C.TNS_LEV_A[i0][i])) < 1e-5 4244930cef6SMatthias Ringwald 425*6897da5cSDirk Helbig rc = lc3.tns_lpc_reflection(dt, a[0]) 426*6897da5cSDirk Helbig ok = ok and np.amax(np.abs(rc - C.TNS_LEV_RC[i0][i])) < 1e-5 4274930cef6SMatthias Ringwald 428*6897da5cSDirk Helbig (rc_order, rc_i) = lc3.tns_quantize_rc(dt, C.TNS_LEV_RC[i0][i]) 429*6897da5cSDirk Helbig ok = ok and rc_order == C.RC_ORDER[i0][i][0] 430*6897da5cSDirk Helbig ok = ok and np.any((rc_i + 8) - C.RC_I_1[i0][i] == 0) 4314930cef6SMatthias Ringwald 4324930cef6SMatthias Ringwald rc_q = lc3.tns_unquantize_rc(rc_i, rc_order) 433*6897da5cSDirk Helbig ok = ok and np.amax(np.abs(rc_q - C.RC_Q_1[i0][i])) < 1e-6 4344930cef6SMatthias Ringwald 435*6897da5cSDirk Helbig (x, side) = lc3.tns_analyze(dt, sr, False, C.NBYTES[i0], C.X_S[i0][i]) 4364930cef6SMatthias Ringwald ok = ok and side['nfilters'] == 1 437*6897da5cSDirk Helbig ok = ok and side['rc_order'][0] == C.RC_ORDER[i0][i][0] 438*6897da5cSDirk Helbig ok = ok and not np.any((side['rc'][0] + 8) - C.RC_I_1[i0][i]) 439*6897da5cSDirk Helbig ok = ok and lc3.tns_get_nbits(side) == C.NBITS_TNS[i0][i] 440*6897da5cSDirk Helbig ok = ok and np.amax(np.abs(x - C.X_F[i0][i])) < 1e-3 4414930cef6SMatthias Ringwald 4424930cef6SMatthias Ringwald return ok 4434930cef6SMatthias Ringwald 4444930cef6SMatthias Ringwalddef check_synthesis_appendix_c(dt): 4454930cef6SMatthias Ringwald 446*6897da5cSDirk Helbig i0 = dt - T.DT_7M5 4474930cef6SMatthias Ringwald sr = T.SRATE_16K 448*6897da5cSDirk Helbig 4494930cef6SMatthias Ringwald ok = True 4504930cef6SMatthias Ringwald 451*6897da5cSDirk Helbig for i in range(len(C.X_HAT_Q[i0])): 4524930cef6SMatthias Ringwald 4534930cef6SMatthias Ringwald side = { 4544930cef6SMatthias Ringwald 'nfilters' : 1, 455*6897da5cSDirk Helbig 'lpc_weighting' : C.NBYTES[i0] < 120 * (1 + dt) / 8, 456*6897da5cSDirk Helbig 'rc_order': C.RC_ORDER[i0][i], 457*6897da5cSDirk Helbig 'rc': [ C.RC_I_1[i0][i] - 8, C.RC_I_2[i0][i] - 8 ] 4584930cef6SMatthias Ringwald } 4594930cef6SMatthias Ringwald 460*6897da5cSDirk Helbig g_int = C.GG_IND_ADJ[i0][i] + C.GG_OFF[i0][i] 461*6897da5cSDirk Helbig x = C.X_HAT_Q[i0][i] * (10 ** (g_int / 28)) 4624930cef6SMatthias Ringwald 4634930cef6SMatthias Ringwald x = lc3.tns_synthesize(dt, sr, side, x) 464*6897da5cSDirk Helbig ok = ok and np.amax(np.abs(x - C.X_HAT_TNS[i0][i])) < 1e-3 4654930cef6SMatthias Ringwald 4664930cef6SMatthias Ringwald sr = T.SRATE_48K 467*6897da5cSDirk Helbig if dt != T.DT_10M: 468*6897da5cSDirk Helbig return ok 4694930cef6SMatthias Ringwald 4704930cef6SMatthias Ringwald side = { 4714930cef6SMatthias Ringwald 'nfilters' : 2, 4724930cef6SMatthias Ringwald 'lpc_weighting' : False, 4734930cef6SMatthias Ringwald 'rc_order': C.RC_ORDER_48K_10M, 4744930cef6SMatthias Ringwald 'rc': [ C.RC_I_1_48K_10M - 8, C.RC_I_2_48K_10M - 8 ] 4754930cef6SMatthias Ringwald } 4764930cef6SMatthias Ringwald 4774930cef6SMatthias Ringwald x = C.X_HAT_F_48K_10M 4784930cef6SMatthias Ringwald x = lc3.tns_synthesize(dt, sr, side, x) 4794930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(x - C.X_HAT_TNS_48K_10M)) < 1e-3 4804930cef6SMatthias Ringwald 4814930cef6SMatthias Ringwald return ok 4824930cef6SMatthias Ringwald 4834930cef6SMatthias Ringwalddef check(): 4844930cef6SMatthias Ringwald 4854930cef6SMatthias Ringwald rng = np.random.default_rng(1234) 4864930cef6SMatthias Ringwald ok = True 4874930cef6SMatthias Ringwald 4884930cef6SMatthias Ringwald for dt in range(T.NUM_DT): 489*6897da5cSDirk Helbig for sr in range(T.SRATE_8K, T.SRATE_48K + 1): 4904930cef6SMatthias Ringwald ok = ok and check_analysis(rng, dt, sr) 4914930cef6SMatthias Ringwald ok = ok and check_synthesis(rng, dt, sr) 4924930cef6SMatthias Ringwald 493*6897da5cSDirk Helbig for dt in ( T.DT_2M5, T.DT_5M, T.DT_10M ): 494*6897da5cSDirk Helbig for sr in ( T.SRATE_48K_HR, T.SRATE_96K_HR ): 495*6897da5cSDirk Helbig ok = ok and check_analysis(rng, dt, sr) 496*6897da5cSDirk Helbig 497*6897da5cSDirk Helbig for dt in ( T.DT_7M5, T.DT_10M ): 498*6897da5cSDirk Helbig check_analysis_appendix_c(dt) 499*6897da5cSDirk Helbig check_synthesis_appendix_c(dt) 5004930cef6SMatthias Ringwald 5014930cef6SMatthias Ringwald return ok 5024930cef6SMatthias Ringwald 5034930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 504