1*4930cef6SMatthias Ringwald# 2*4930cef6SMatthias Ringwald# Copyright 2022 Google LLC 3*4930cef6SMatthias Ringwald# 4*4930cef6SMatthias Ringwald# Licensed under the Apache License, Version 2.0 (the "License"); 5*4930cef6SMatthias Ringwald# you may not use this file except in compliance with the License. 6*4930cef6SMatthias Ringwald# You may obtain a copy of the License at 7*4930cef6SMatthias Ringwald# 8*4930cef6SMatthias Ringwald# http://www.apache.org/licenses/LICENSE-2.0 9*4930cef6SMatthias Ringwald# 10*4930cef6SMatthias Ringwald# Unless required by applicable law or agreed to in writing, software 11*4930cef6SMatthias Ringwald# distributed under the License is distributed on an "AS IS" BASIS, 12*4930cef6SMatthias Ringwald# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*4930cef6SMatthias Ringwald# See the License for the specific language governing permissions and 14*4930cef6SMatthias Ringwald# limitations under the License. 15*4930cef6SMatthias Ringwald# 16*4930cef6SMatthias Ringwald 17*4930cef6SMatthias Ringwaldimport numpy as np 18*4930cef6SMatthias Ringwald 19*4930cef6SMatthias Ringwaldimport build.lc3 as lc3 20*4930cef6SMatthias Ringwaldimport tables as T, appendix_c as C 21*4930cef6SMatthias Ringwald 22*4930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 23*4930cef6SMatthias Ringwald 24*4930cef6SMatthias Ringwaldclass Tns: 25*4930cef6SMatthias Ringwald 26*4930cef6SMatthias Ringwald SUB_LIM_10M_NB = [ [ 12, 34, 57, 80 ] ] 27*4930cef6SMatthias Ringwald SUB_LIM_10M_WB = [ [ 12, 61, 110, 160 ] ] 28*4930cef6SMatthias Ringwald SUB_LIM_10M_SSWB = [ [ 12, 88, 164, 240 ] ] 29*4930cef6SMatthias Ringwald SUB_LIM_10M_SWB = [ [ 12, 61, 110, 160 ], [ 160, 213, 266, 320 ] ] 30*4930cef6SMatthias Ringwald SUB_LIM_10M_FB = [ [ 12, 74, 137, 200 ], [ 200, 266, 333, 400 ] ] 31*4930cef6SMatthias Ringwald 32*4930cef6SMatthias Ringwald SUB_LIM_10M = [ SUB_LIM_10M_NB, SUB_LIM_10M_WB, 33*4930cef6SMatthias Ringwald SUB_LIM_10M_SSWB, SUB_LIM_10M_SWB, SUB_LIM_10M_FB ] 34*4930cef6SMatthias Ringwald 35*4930cef6SMatthias Ringwald SUB_LIM_7M5_NB = [ [ 9, 26, 43, 60 ] ] 36*4930cef6SMatthias Ringwald SUB_LIM_7M5_WB = [ [ 9, 46, 83, 120 ] ] 37*4930cef6SMatthias Ringwald SUB_LIM_7M5_SSWB = [ [ 9, 66, 123, 180 ] ] 38*4930cef6SMatthias Ringwald SUB_LIM_7M5_SWB = [ [ 9, 46, 82, 120 ], [ 120, 159, 200, 240 ] ] 39*4930cef6SMatthias Ringwald SUB_LIM_7M5_FB = [ [ 9, 56, 103, 150 ], [ 150, 200, 250, 300 ] ] 40*4930cef6SMatthias Ringwald 41*4930cef6SMatthias Ringwald SUB_LIM_7M5 = [ SUB_LIM_7M5_NB, SUB_LIM_7M5_WB, 42*4930cef6SMatthias Ringwald SUB_LIM_7M5_SSWB, SUB_LIM_7M5_SWB, SUB_LIM_7M5_FB ] 43*4930cef6SMatthias Ringwald 44*4930cef6SMatthias Ringwald SUB_LIM = [ SUB_LIM_7M5, SUB_LIM_10M ] 45*4930cef6SMatthias Ringwald 46*4930cef6SMatthias Ringwald FREQ_LIM_10M_NB = [ 12, 80 ] 47*4930cef6SMatthias Ringwald FREQ_LIM_10M_WB = [ 12, 160 ] 48*4930cef6SMatthias Ringwald FREQ_LIM_10M_SSWB = [ 12, 240 ] 49*4930cef6SMatthias Ringwald FREQ_LIM_10M_SWB = [ 12, 160, 320 ] 50*4930cef6SMatthias Ringwald FREQ_LIM_10M_FB = [ 12, 200, 400 ] 51*4930cef6SMatthias Ringwald 52*4930cef6SMatthias Ringwald FREQ_LIM_10M = [ FREQ_LIM_10M_NB, FREQ_LIM_10M_WB, 53*4930cef6SMatthias Ringwald FREQ_LIM_10M_SSWB, FREQ_LIM_10M_SWB, FREQ_LIM_10M_FB ] 54*4930cef6SMatthias Ringwald 55*4930cef6SMatthias Ringwald FREQ_LIM_7M5_NB = [ 9, 60 ] 56*4930cef6SMatthias Ringwald FREQ_LIM_7M5_WB = [ 9, 120 ] 57*4930cef6SMatthias Ringwald FREQ_LIM_7M5_SSWB = [ 9, 180 ] 58*4930cef6SMatthias Ringwald FREQ_LIM_7M5_SWB = [ 9, 120, 240 ] 59*4930cef6SMatthias Ringwald FREQ_LIM_7M5_FB = [ 9, 150, 300 ] 60*4930cef6SMatthias Ringwald 61*4930cef6SMatthias Ringwald FREQ_LIM_7M5 = [ FREQ_LIM_7M5_NB, FREQ_LIM_7M5_WB, 62*4930cef6SMatthias Ringwald FREQ_LIM_7M5_SSWB, FREQ_LIM_7M5_SWB, FREQ_LIM_7M5_FB ] 63*4930cef6SMatthias Ringwald 64*4930cef6SMatthias Ringwald FREQ_LIM = [ FREQ_LIM_7M5, FREQ_LIM_10M ] 65*4930cef6SMatthias Ringwald 66*4930cef6SMatthias Ringwald def __init__(self, dt): 67*4930cef6SMatthias Ringwald 68*4930cef6SMatthias Ringwald self.dt = dt 69*4930cef6SMatthias Ringwald 70*4930cef6SMatthias Ringwald (self.nfilters, self.lpc_weighting, self.rc_order, self.rc) = \ 71*4930cef6SMatthias Ringwald (None, None, None, None) 72*4930cef6SMatthias Ringwald 73*4930cef6SMatthias Ringwald def get_data(self): 74*4930cef6SMatthias Ringwald 75*4930cef6SMatthias Ringwald return { 'nfilters' : self.nfilters, 76*4930cef6SMatthias Ringwald 'lpc_weighting' : self.lpc_weighting, 77*4930cef6SMatthias Ringwald 'rc_order' : self.rc_order, 'rc' : self.rc - 8 } 78*4930cef6SMatthias Ringwald 79*4930cef6SMatthias Ringwald def get_nbits(self): 80*4930cef6SMatthias Ringwald 81*4930cef6SMatthias Ringwald lpc_weighting = self.lpc_weighting 82*4930cef6SMatthias Ringwald nbits = 0 83*4930cef6SMatthias Ringwald 84*4930cef6SMatthias Ringwald for f in range(self.nfilters): 85*4930cef6SMatthias Ringwald rc_order = self.rc_order[f] 86*4930cef6SMatthias Ringwald rc = self.rc[f] 87*4930cef6SMatthias Ringwald 88*4930cef6SMatthias Ringwald nbits_order = T.TNS_ORDER_BITS[int(lpc_weighting)][rc_order] 89*4930cef6SMatthias Ringwald nbits_coef = sum([ T.TNS_COEF_BITS[k][rc[k]] 90*4930cef6SMatthias Ringwald for k in range(rc_order) ]) 91*4930cef6SMatthias Ringwald 92*4930cef6SMatthias Ringwald nbits += ((2048 + nbits_order + nbits_coef) + 2047) >> 11 93*4930cef6SMatthias Ringwald 94*4930cef6SMatthias Ringwald return nbits 95*4930cef6SMatthias Ringwald 96*4930cef6SMatthias Ringwald 97*4930cef6SMatthias Ringwaldclass TnsAnalysis(Tns): 98*4930cef6SMatthias Ringwald 99*4930cef6SMatthias Ringwald def __init__(self, dt): 100*4930cef6SMatthias Ringwald 101*4930cef6SMatthias Ringwald super().__init__(dt) 102*4930cef6SMatthias Ringwald 103*4930cef6SMatthias Ringwald def compute_lpc_coeffs(self, bw, f, x): 104*4930cef6SMatthias Ringwald 105*4930cef6SMatthias Ringwald ### Normalized autocorrelation function 106*4930cef6SMatthias Ringwald 107*4930cef6SMatthias Ringwald S = Tns.SUB_LIM[self.dt][bw][f] 108*4930cef6SMatthias Ringwald 109*4930cef6SMatthias Ringwald r = np.append([ 3 ], np.zeros(8)) 110*4930cef6SMatthias Ringwald e = [ sum(x[S[s]:S[s+1]] ** 2) for s in range(3) ] 111*4930cef6SMatthias Ringwald 112*4930cef6SMatthias Ringwald for k in range(len(r) if sum(e) > 0 else 0): 113*4930cef6SMatthias Ringwald c = [ np.dot(x[S[s]:S[s+1]-k], x[S[s]+k:S[s+1]]) 114*4930cef6SMatthias Ringwald for s in range(3) ] 115*4930cef6SMatthias Ringwald 116*4930cef6SMatthias Ringwald r[k] = np.sum( np.array(c) / np.array(e) ) 117*4930cef6SMatthias Ringwald 118*4930cef6SMatthias Ringwald r *= np.exp(-0.5 * (0.02 * np.pi * np.arange(9)) ** 2) 119*4930cef6SMatthias Ringwald 120*4930cef6SMatthias Ringwald ### Levinson-Durbin recursion 121*4930cef6SMatthias Ringwald 122*4930cef6SMatthias Ringwald err = r[0] 123*4930cef6SMatthias Ringwald a = np.ones(len(r)) 124*4930cef6SMatthias Ringwald 125*4930cef6SMatthias Ringwald for k in range(1, len(a)): 126*4930cef6SMatthias Ringwald 127*4930cef6SMatthias Ringwald rc = -sum(a[:k] * r[k:0:-1]) / err 128*4930cef6SMatthias Ringwald 129*4930cef6SMatthias Ringwald a[1:k] += rc * a[k-1:0:-1] 130*4930cef6SMatthias Ringwald a[k] = rc 131*4930cef6SMatthias Ringwald 132*4930cef6SMatthias Ringwald err *= 1 - rc ** 2 133*4930cef6SMatthias Ringwald 134*4930cef6SMatthias Ringwald return (r[0] / err, a) 135*4930cef6SMatthias Ringwald 136*4930cef6SMatthias Ringwald def lpc_weighting(self, pred_gain, a): 137*4930cef6SMatthias Ringwald 138*4930cef6SMatthias Ringwald gamma = 1 - (1 - 0.85) * (2 - pred_gain) / (2 - 1.5) 139*4930cef6SMatthias Ringwald return a * np.power(gamma, np.arange(len(a))) 140*4930cef6SMatthias Ringwald 141*4930cef6SMatthias Ringwald def coeffs_reflexion(self, a): 142*4930cef6SMatthias Ringwald 143*4930cef6SMatthias Ringwald rc = np.zeros(8) 144*4930cef6SMatthias Ringwald b = a.copy() 145*4930cef6SMatthias Ringwald 146*4930cef6SMatthias Ringwald for k in range(8, 0, -1): 147*4930cef6SMatthias Ringwald rc[k-1] = b[k] 148*4930cef6SMatthias Ringwald e = 1 - rc[k-1] ** 2 149*4930cef6SMatthias Ringwald b[1:k] = (b[1:k] - rc[k-1] * b[k-1:0:-1]) / e 150*4930cef6SMatthias Ringwald 151*4930cef6SMatthias Ringwald return rc 152*4930cef6SMatthias Ringwald 153*4930cef6SMatthias Ringwald def quantization(self, rc, lpc_weighting): 154*4930cef6SMatthias Ringwald 155*4930cef6SMatthias Ringwald delta = np.pi / 17 156*4930cef6SMatthias Ringwald rc_i = np.rint(np.arcsin(rc) / delta).astype(int) + 8 157*4930cef6SMatthias Ringwald rc_q = np.sin(delta * (rc_i - 8)) 158*4930cef6SMatthias Ringwald 159*4930cef6SMatthias Ringwald rc_order = len(rc_i) - np.argmin(rc_i[::-1] == 8) 160*4930cef6SMatthias Ringwald 161*4930cef6SMatthias Ringwald return (rc_order, rc_q, rc_i) 162*4930cef6SMatthias Ringwald 163*4930cef6SMatthias Ringwald def filtering(self, st, x, rc_order, rc): 164*4930cef6SMatthias Ringwald 165*4930cef6SMatthias Ringwald y = np.empty(len(x)) 166*4930cef6SMatthias Ringwald 167*4930cef6SMatthias Ringwald for i in range(len(x)): 168*4930cef6SMatthias Ringwald 169*4930cef6SMatthias Ringwald xi = x[i] 170*4930cef6SMatthias Ringwald s1 = xi 171*4930cef6SMatthias Ringwald 172*4930cef6SMatthias Ringwald for k in range(rc_order): 173*4930cef6SMatthias Ringwald s0 = st[k] 174*4930cef6SMatthias Ringwald st[k] = s1 175*4930cef6SMatthias Ringwald 176*4930cef6SMatthias Ringwald s1 = rc[k] * xi + s0 177*4930cef6SMatthias Ringwald xi += rc[k] * s0 178*4930cef6SMatthias Ringwald 179*4930cef6SMatthias Ringwald y[i] = xi 180*4930cef6SMatthias Ringwald 181*4930cef6SMatthias Ringwald return y 182*4930cef6SMatthias Ringwald 183*4930cef6SMatthias Ringwald def run(self, x, bw, nn_flag, nbytes): 184*4930cef6SMatthias Ringwald 185*4930cef6SMatthias Ringwald fstate = np.zeros(8) 186*4930cef6SMatthias Ringwald y = x.copy() 187*4930cef6SMatthias Ringwald 188*4930cef6SMatthias Ringwald self.nfilters = len(Tns.SUB_LIM[self.dt][bw]) 189*4930cef6SMatthias Ringwald self.lpc_weighting = nbytes * 8 < 48 * T.DT_MS[self.dt] 190*4930cef6SMatthias Ringwald self.rc_order = np.zeros(2, dtype=np.int) 191*4930cef6SMatthias Ringwald self.rc = np.zeros((2, 8), dtype=np.int) 192*4930cef6SMatthias Ringwald 193*4930cef6SMatthias Ringwald for f in range(self.nfilters): 194*4930cef6SMatthias Ringwald 195*4930cef6SMatthias Ringwald (pred_gain, a) = self.compute_lpc_coeffs(bw, f, x) 196*4930cef6SMatthias Ringwald 197*4930cef6SMatthias Ringwald tns_off = pred_gain <= 1.5 or nn_flag 198*4930cef6SMatthias Ringwald if tns_off: 199*4930cef6SMatthias Ringwald continue 200*4930cef6SMatthias Ringwald 201*4930cef6SMatthias Ringwald if self.lpc_weighting and pred_gain < 2: 202*4930cef6SMatthias Ringwald a = self.lpc_weighting(pred_gain, a) 203*4930cef6SMatthias Ringwald 204*4930cef6SMatthias Ringwald rc = self.coeffs_reflexion(a) 205*4930cef6SMatthias Ringwald 206*4930cef6SMatthias Ringwald (rc_order, rc_q, rc_i) = \ 207*4930cef6SMatthias Ringwald self.quantization(rc, self.lpc_weighting) 208*4930cef6SMatthias Ringwald 209*4930cef6SMatthias Ringwald self.rc_order[f] = rc_order 210*4930cef6SMatthias Ringwald self.rc[f] = rc_i 211*4930cef6SMatthias Ringwald 212*4930cef6SMatthias Ringwald if rc_order > 0: 213*4930cef6SMatthias Ringwald i0 = Tns.FREQ_LIM[self.dt][bw][f] 214*4930cef6SMatthias Ringwald i1 = Tns.FREQ_LIM[self.dt][bw][f+1] 215*4930cef6SMatthias Ringwald 216*4930cef6SMatthias Ringwald y[i0:i1] = self.filtering( 217*4930cef6SMatthias Ringwald fstate, x[i0:i1], rc_order, rc_q) 218*4930cef6SMatthias Ringwald 219*4930cef6SMatthias Ringwald return y 220*4930cef6SMatthias Ringwald 221*4930cef6SMatthias Ringwald def store(self, b): 222*4930cef6SMatthias Ringwald 223*4930cef6SMatthias Ringwald for f in range(self.nfilters): 224*4930cef6SMatthias Ringwald lpc_weighting = self.lpc_weighting[f] 225*4930cef6SMatthias Ringwald rc_order = self.rc_order[f] 226*4930cef6SMatthias Ringwald rc = self.rc[f] 227*4930cef6SMatthias Ringwald 228*4930cef6SMatthias Ringwald b.write_bit(min(rc_order, 1)) 229*4930cef6SMatthias Ringwald 230*4930cef6SMatthias Ringwald if rc_order > 0: 231*4930cef6SMatthias Ringwald b.ac_encode( 232*4930cef6SMatthias Ringwald T.TNS_ORDER_CUMFREQ[int(lpc_weighting)][rc_order-1], 233*4930cef6SMatthias Ringwald T.TNS_ORDER_FREQ[int(lpc_weighting)][rc_order-1] ) 234*4930cef6SMatthias Ringwald 235*4930cef6SMatthias Ringwald for k in range(rc_order): 236*4930cef6SMatthias Ringwald b.ac_encode(T.TNS_COEF_CUMFREQ[k][rc[k]], 237*4930cef6SMatthias Ringwald T.TNS_COEF_FREQ[k][rc[k]] ) 238*4930cef6SMatthias Ringwald 239*4930cef6SMatthias Ringwald 240*4930cef6SMatthias Ringwaldclass TnsSynthesis(Tns): 241*4930cef6SMatthias Ringwald 242*4930cef6SMatthias Ringwald def filtering(self, st, x, rc_order, rc): 243*4930cef6SMatthias Ringwald 244*4930cef6SMatthias Ringwald y = x.copy() 245*4930cef6SMatthias Ringwald 246*4930cef6SMatthias Ringwald for i in range(len(x)): 247*4930cef6SMatthias Ringwald 248*4930cef6SMatthias Ringwald xi = x[i] - rc[rc_order-1] * st[rc_order-1] 249*4930cef6SMatthias Ringwald for k in range(rc_order-2, -1, -1): 250*4930cef6SMatthias Ringwald xi -= rc[k] * st[k] 251*4930cef6SMatthias Ringwald st[k+1] = xi * rc[k] + st[k]; 252*4930cef6SMatthias Ringwald st[0] = xi; 253*4930cef6SMatthias Ringwald 254*4930cef6SMatthias Ringwald y[i] = xi 255*4930cef6SMatthias Ringwald 256*4930cef6SMatthias Ringwald return y 257*4930cef6SMatthias Ringwald 258*4930cef6SMatthias Ringwald def load(self, b, bw, nbytes): 259*4930cef6SMatthias Ringwald 260*4930cef6SMatthias Ringwald self.nfilters = len(Tns.SUB_LIM[self.dt][bw]) 261*4930cef6SMatthias Ringwald self.lpc_weighting = nbytes * 8 < 48 * T.DT_MS[self.dt] 262*4930cef6SMatthias Ringwald self.rc_order = np.zeros(2, dtype=np.int) 263*4930cef6SMatthias Ringwald self.rc = 8 * np.ones((2, 8), dtype=np.int) 264*4930cef6SMatthias Ringwald 265*4930cef6SMatthias Ringwald for f in range(self.nfilters): 266*4930cef6SMatthias Ringwald 267*4930cef6SMatthias Ringwald if not b.read_bit(): 268*4930cef6SMatthias Ringwald continue 269*4930cef6SMatthias Ringwald 270*4930cef6SMatthias Ringwald rc_order = 1 + b.ac_decode( 271*4930cef6SMatthias Ringwald T.TNS_ORDER_CUMFREQ[int(self.lpc_weighting)], 272*4930cef6SMatthias Ringwald T.TNS_ORDER_FREQ[int(self.lpc_weighting)]) 273*4930cef6SMatthias Ringwald 274*4930cef6SMatthias Ringwald self.rc_order[f] = rc_order 275*4930cef6SMatthias Ringwald 276*4930cef6SMatthias Ringwald for k in range(rc_order): 277*4930cef6SMatthias Ringwald rc = b.ac_decode(T.TNS_COEF_CUMFREQ[k], T.TNS_COEF_FREQ[k]) 278*4930cef6SMatthias Ringwald self.rc[f][k] = rc 279*4930cef6SMatthias Ringwald 280*4930cef6SMatthias Ringwald def run(self, x, bw): 281*4930cef6SMatthias Ringwald 282*4930cef6SMatthias Ringwald fstate = np.zeros(8) 283*4930cef6SMatthias Ringwald y = x.copy() 284*4930cef6SMatthias Ringwald 285*4930cef6SMatthias Ringwald for f in range(self.nfilters): 286*4930cef6SMatthias Ringwald 287*4930cef6SMatthias Ringwald rc_order = self.rc_order[f] 288*4930cef6SMatthias Ringwald rc = np.sin((np.pi / 17) * (self.rc[f] - 8)) 289*4930cef6SMatthias Ringwald 290*4930cef6SMatthias Ringwald if rc_order > 0: 291*4930cef6SMatthias Ringwald i0 = Tns.FREQ_LIM[self.dt][bw][f] 292*4930cef6SMatthias Ringwald i1 = Tns.FREQ_LIM[self.dt][bw][f+1] 293*4930cef6SMatthias Ringwald 294*4930cef6SMatthias Ringwald y[i0:i1] = self.filtering( 295*4930cef6SMatthias Ringwald fstate, x[i0:i1], rc_order, rc) 296*4930cef6SMatthias Ringwald 297*4930cef6SMatthias Ringwald return y 298*4930cef6SMatthias Ringwald 299*4930cef6SMatthias Ringwald 300*4930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 301*4930cef6SMatthias Ringwald 302*4930cef6SMatthias Ringwalddef check_analysis(rng, dt, bw): 303*4930cef6SMatthias Ringwald 304*4930cef6SMatthias Ringwald ok = True 305*4930cef6SMatthias Ringwald 306*4930cef6SMatthias Ringwald analysis = TnsAnalysis(dt) 307*4930cef6SMatthias Ringwald nbytes_lim = int((48 * T.DT_MS[dt]) // 8) 308*4930cef6SMatthias Ringwald 309*4930cef6SMatthias Ringwald for i in range(10): 310*4930cef6SMatthias Ringwald x = rng.random(T.NE[dt][bw]) * 1e2 311*4930cef6SMatthias Ringwald x = pow(x, .5 + i/5) 312*4930cef6SMatthias Ringwald 313*4930cef6SMatthias Ringwald for nn_flag in (True, False): 314*4930cef6SMatthias Ringwald for nbytes in (nbytes_lim, nbytes_lim + 1): 315*4930cef6SMatthias Ringwald 316*4930cef6SMatthias Ringwald y = analysis.run(x, bw, nn_flag, nbytes) 317*4930cef6SMatthias Ringwald (y_c, data_c) = lc3.tns_analyze(dt, bw, nn_flag, nbytes, x) 318*4930cef6SMatthias Ringwald 319*4930cef6SMatthias Ringwald ok = ok and data_c['nfilters'] == analysis.nfilters 320*4930cef6SMatthias Ringwald ok = ok and data_c['lpc_weighting'] == analysis.lpc_weighting 321*4930cef6SMatthias Ringwald for f in range(analysis.nfilters): 322*4930cef6SMatthias Ringwald rc_order = analysis.rc_order[f] 323*4930cef6SMatthias Ringwald rc_order_c = data_c['rc_order'][f] 324*4930cef6SMatthias Ringwald rc_c = 8 + data_c['rc'][f] 325*4930cef6SMatthias Ringwald ok = ok and rc_order_c == rc_order 326*4930cef6SMatthias Ringwald ok = ok and not np.any((rc_c - analysis.rc[f])[:rc_order]) 327*4930cef6SMatthias Ringwald 328*4930cef6SMatthias Ringwald ok = ok and lc3.tns_get_nbits(data_c) == analysis.get_nbits() 329*4930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y_c - y)) < 1e-2 330*4930cef6SMatthias Ringwald 331*4930cef6SMatthias Ringwald return ok 332*4930cef6SMatthias Ringwald 333*4930cef6SMatthias Ringwalddef check_synthesis(rng, dt, bw): 334*4930cef6SMatthias Ringwald 335*4930cef6SMatthias Ringwald ok = True 336*4930cef6SMatthias Ringwald synthesis = TnsSynthesis(dt) 337*4930cef6SMatthias Ringwald 338*4930cef6SMatthias Ringwald for i in range(100): 339*4930cef6SMatthias Ringwald 340*4930cef6SMatthias Ringwald x = rng.random(T.NE[dt][bw]) * 1e2 341*4930cef6SMatthias Ringwald 342*4930cef6SMatthias Ringwald synthesis.nfilters = 1 + int(bw >= T.SRATE_32K) 343*4930cef6SMatthias Ringwald synthesis.rc_order = rng.integers(0, 9, 2) 344*4930cef6SMatthias Ringwald synthesis.rc = rng.integers(0, 17, 16).reshape(2, 8) 345*4930cef6SMatthias Ringwald 346*4930cef6SMatthias Ringwald y = synthesis.run(x, bw) 347*4930cef6SMatthias Ringwald y_c = lc3.tns_synthesize(dt, bw, synthesis.get_data(), x) 348*4930cef6SMatthias Ringwald 349*4930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y_c - y) < 1e-6) 350*4930cef6SMatthias Ringwald 351*4930cef6SMatthias Ringwald return ok 352*4930cef6SMatthias Ringwald 353*4930cef6SMatthias Ringwalddef check_analysis_appendix_c(dt): 354*4930cef6SMatthias Ringwald 355*4930cef6SMatthias Ringwald sr = T.SRATE_16K 356*4930cef6SMatthias Ringwald ok = True 357*4930cef6SMatthias Ringwald 358*4930cef6SMatthias Ringwald fs = Tns.FREQ_LIM[dt][sr][0] 359*4930cef6SMatthias Ringwald fe = Tns.FREQ_LIM[dt][sr][1] 360*4930cef6SMatthias Ringwald st = np.zeros(8) 361*4930cef6SMatthias Ringwald 362*4930cef6SMatthias Ringwald for i in range(len(C.X_S[dt])): 363*4930cef6SMatthias Ringwald 364*4930cef6SMatthias Ringwald (_, a) = lc3.tns_compute_lpc_coeffs(dt, sr, C.X_S[dt][i]) 365*4930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(a[0] - C.TNS_LEV_A[dt][i])) < 1e-5 366*4930cef6SMatthias Ringwald 367*4930cef6SMatthias Ringwald rc = lc3.tns_lpc_reflection(a[0]) 368*4930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(rc - C.TNS_LEV_RC[dt][i])) < 1e-5 369*4930cef6SMatthias Ringwald 370*4930cef6SMatthias Ringwald (rc_order, rc_i) = lc3.tns_quantize_rc(C.TNS_LEV_RC[dt][i]) 371*4930cef6SMatthias Ringwald ok = ok and rc_order == C.RC_ORDER[dt][i][0] 372*4930cef6SMatthias Ringwald ok = ok and np.any((rc_i + 8) - C.RC_I_1[dt][i] == 0) 373*4930cef6SMatthias Ringwald 374*4930cef6SMatthias Ringwald rc_q = lc3.tns_unquantize_rc(rc_i, rc_order) 375*4930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(rc_q - C.RC_Q_1[dt][i])) < 1e-6 376*4930cef6SMatthias Ringwald 377*4930cef6SMatthias Ringwald (x, side) = lc3.tns_analyze(dt, sr, False, C.NBYTES[dt], C.X_S[dt][i]) 378*4930cef6SMatthias Ringwald ok = ok and side['nfilters'] == 1 379*4930cef6SMatthias Ringwald ok = ok and side['rc_order'][0] == C.RC_ORDER[dt][i][0] 380*4930cef6SMatthias Ringwald ok = ok and not np.any((side['rc'][0] + 8) - C.RC_I_1[dt][i]) 381*4930cef6SMatthias Ringwald ok = ok and lc3.tns_get_nbits(side) == C.NBITS_TNS[dt][i] 382*4930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(x - C.X_F[dt][i])) < 1e-3 383*4930cef6SMatthias Ringwald 384*4930cef6SMatthias Ringwald return ok 385*4930cef6SMatthias Ringwald 386*4930cef6SMatthias Ringwalddef check_synthesis_appendix_c(dt): 387*4930cef6SMatthias Ringwald 388*4930cef6SMatthias Ringwald sr = T.SRATE_16K 389*4930cef6SMatthias Ringwald ok = True 390*4930cef6SMatthias Ringwald 391*4930cef6SMatthias Ringwald for i in range(len(C.X_HAT_Q[dt])): 392*4930cef6SMatthias Ringwald 393*4930cef6SMatthias Ringwald side = { 394*4930cef6SMatthias Ringwald 'nfilters' : 1, 395*4930cef6SMatthias Ringwald 'lpc_weighting' : C.NBYTES[dt] * 8 < 48 * T.DT_MS[dt], 396*4930cef6SMatthias Ringwald 'rc_order': C.RC_ORDER[dt][i], 397*4930cef6SMatthias Ringwald 'rc': [ C.RC_I_1[dt][i] - 8, C.RC_I_2[dt][i] - 8 ] 398*4930cef6SMatthias Ringwald } 399*4930cef6SMatthias Ringwald 400*4930cef6SMatthias Ringwald g_int = C.GG_IND_ADJ[dt][i] + C.GG_OFF[dt][i] 401*4930cef6SMatthias Ringwald x = C.X_HAT_Q[dt][i] * (10 ** (g_int / 28)) 402*4930cef6SMatthias Ringwald 403*4930cef6SMatthias Ringwald x = lc3.tns_synthesize(dt, sr, side, x) 404*4930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(x - C.X_HAT_TNS[dt][i])) < 1e-3 405*4930cef6SMatthias Ringwald 406*4930cef6SMatthias Ringwald if dt != T.DT_10M: 407*4930cef6SMatthias Ringwald return ok 408*4930cef6SMatthias Ringwald 409*4930cef6SMatthias Ringwald sr = T.SRATE_48K 410*4930cef6SMatthias Ringwald 411*4930cef6SMatthias Ringwald side = { 412*4930cef6SMatthias Ringwald 'nfilters' : 2, 413*4930cef6SMatthias Ringwald 'lpc_weighting' : False, 414*4930cef6SMatthias Ringwald 'rc_order': C.RC_ORDER_48K_10M, 415*4930cef6SMatthias Ringwald 'rc': [ C.RC_I_1_48K_10M - 8, C.RC_I_2_48K_10M - 8 ] 416*4930cef6SMatthias Ringwald } 417*4930cef6SMatthias Ringwald 418*4930cef6SMatthias Ringwald x = C.X_HAT_F_48K_10M 419*4930cef6SMatthias Ringwald x = lc3.tns_synthesize(dt, sr, side, x) 420*4930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(x - C.X_HAT_TNS_48K_10M)) < 1e-3 421*4930cef6SMatthias Ringwald 422*4930cef6SMatthias Ringwald return ok 423*4930cef6SMatthias Ringwald 424*4930cef6SMatthias Ringwalddef check(): 425*4930cef6SMatthias Ringwald 426*4930cef6SMatthias Ringwald rng = np.random.default_rng(1234) 427*4930cef6SMatthias Ringwald ok = True 428*4930cef6SMatthias Ringwald 429*4930cef6SMatthias Ringwald for dt in range(T.NUM_DT): 430*4930cef6SMatthias Ringwald for sr in range(T.NUM_SRATE): 431*4930cef6SMatthias Ringwald ok = ok and check_analysis(rng, dt, sr) 432*4930cef6SMatthias Ringwald ok = ok and check_synthesis(rng, dt, sr) 433*4930cef6SMatthias Ringwald 434*4930cef6SMatthias Ringwald for dt in range(T.NUM_DT): 435*4930cef6SMatthias Ringwald ok = ok and check_analysis_appendix_c(dt) 436*4930cef6SMatthias Ringwald ok = ok and check_synthesis_appendix_c(dt) 437*4930cef6SMatthias Ringwald 438*4930cef6SMatthias Ringwald return ok 439*4930cef6SMatthias Ringwald 440*4930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 441