1*49fe348cSAndroid Build Coastguard Worker# 2*49fe348cSAndroid Build Coastguard Worker# Copyright 2022 Google LLC 3*49fe348cSAndroid Build Coastguard Worker# 4*49fe348cSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*49fe348cSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*49fe348cSAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*49fe348cSAndroid Build Coastguard Worker# 8*49fe348cSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*49fe348cSAndroid Build Coastguard Worker# 10*49fe348cSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*49fe348cSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*49fe348cSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*49fe348cSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*49fe348cSAndroid Build Coastguard Worker# limitations under the License. 15*49fe348cSAndroid Build Coastguard Worker# 16*49fe348cSAndroid Build Coastguard Worker 17*49fe348cSAndroid Build Coastguard Workerimport numpy as np 18*49fe348cSAndroid Build Coastguard Workerimport scipy.signal as signal 19*49fe348cSAndroid Build Coastguard Worker 20*49fe348cSAndroid Build Coastguard Workerimport lc3 21*49fe348cSAndroid Build Coastguard Workerimport tables as T, appendix_c as C 22*49fe348cSAndroid Build Coastguard Worker 23*49fe348cSAndroid Build Coastguard Worker### ------------------------------------------------------------------------ ### 24*49fe348cSAndroid Build Coastguard Worker 25*49fe348cSAndroid Build Coastguard Workerclass Resampler_12k8: 26*49fe348cSAndroid Build Coastguard Worker 27*49fe348cSAndroid Build Coastguard Worker def __init__(self, dt, sr, history = 0): 28*49fe348cSAndroid Build Coastguard Worker 29*49fe348cSAndroid Build Coastguard Worker self.sr = sr 30*49fe348cSAndroid Build Coastguard Worker self.p = 192 // T.SRATE_KHZ[sr] 31*49fe348cSAndroid Build Coastguard Worker self.w = 240 // self.p 32*49fe348cSAndroid Build Coastguard Worker 33*49fe348cSAndroid Build Coastguard Worker self.n = ((T.DT_MS[dt] * 128) / 10).astype(int) 34*49fe348cSAndroid Build Coastguard Worker self.d = [ 24, 44 ][dt == T.DT_7M5] 35*49fe348cSAndroid Build Coastguard Worker 36*49fe348cSAndroid Build Coastguard Worker self.x = np.zeros(self.w + T.NS[dt][sr]) 37*49fe348cSAndroid Build Coastguard Worker self.u = np.zeros(self.n + 2) 38*49fe348cSAndroid Build Coastguard Worker self.y = np.zeros(self.n + self.d + history) 39*49fe348cSAndroid Build Coastguard Worker 40*49fe348cSAndroid Build Coastguard Worker def resample(self, x): 41*49fe348cSAndroid Build Coastguard Worker 42*49fe348cSAndroid Build Coastguard Worker p = self.p 43*49fe348cSAndroid Build Coastguard Worker w = self.w 44*49fe348cSAndroid Build Coastguard Worker d = self.d 45*49fe348cSAndroid Build Coastguard Worker n = self.n 46*49fe348cSAndroid Build Coastguard Worker 47*49fe348cSAndroid Build Coastguard Worker ### Sliding window 48*49fe348cSAndroid Build Coastguard Worker 49*49fe348cSAndroid Build Coastguard Worker self.x[:w] = self.x[-w:] 50*49fe348cSAndroid Build Coastguard Worker self.x[w:] = x 51*49fe348cSAndroid Build Coastguard Worker self.u[:2] = self.u[-2:] 52*49fe348cSAndroid Build Coastguard Worker 53*49fe348cSAndroid Build Coastguard Worker if len(self.y) > 2*n + d: 54*49fe348cSAndroid Build Coastguard Worker self.y[n+d:-n] = self.y[d+2*n:] 55*49fe348cSAndroid Build Coastguard Worker if len(self.y) > n + d: 56*49fe348cSAndroid Build Coastguard Worker self.y[-n:] = self.y[:n] 57*49fe348cSAndroid Build Coastguard Worker self.y[:d] = self.y[n:d+n] 58*49fe348cSAndroid Build Coastguard Worker 59*49fe348cSAndroid Build Coastguard Worker x = self.x 60*49fe348cSAndroid Build Coastguard Worker u = self.u 61*49fe348cSAndroid Build Coastguard Worker 62*49fe348cSAndroid Build Coastguard Worker ### Resampling 63*49fe348cSAndroid Build Coastguard Worker 64*49fe348cSAndroid Build Coastguard Worker h = np.zeros(240 + p) 65*49fe348cSAndroid Build Coastguard Worker h[-119:] = T.LTPF_H12K8[:119] 66*49fe348cSAndroid Build Coastguard Worker h[ :120] = T.LTPF_H12K8[119:] 67*49fe348cSAndroid Build Coastguard Worker 68*49fe348cSAndroid Build Coastguard Worker for i in range(n): 69*49fe348cSAndroid Build Coastguard Worker e = (15 * i) // p 70*49fe348cSAndroid Build Coastguard Worker f = (15 * i) % p 71*49fe348cSAndroid Build Coastguard Worker k = np.arange(-120, 120 + p, p) - f 72*49fe348cSAndroid Build Coastguard Worker u[2+i] = p * np.dot( x[e:e+w+1], np.take(h, k) ) 73*49fe348cSAndroid Build Coastguard Worker 74*49fe348cSAndroid Build Coastguard Worker if self.sr == T.SRATE_8K: 75*49fe348cSAndroid Build Coastguard Worker u = 0.5 * u 76*49fe348cSAndroid Build Coastguard Worker 77*49fe348cSAndroid Build Coastguard Worker ### High-pass filtering 78*49fe348cSAndroid Build Coastguard Worker 79*49fe348cSAndroid Build Coastguard Worker b = [ 0.9827947082978771, -1.9655894165957540, 0.9827947082978771 ] 80*49fe348cSAndroid Build Coastguard Worker a = [ 1 , -1.9652933726226904, 0.9658854605688177 ] 81*49fe348cSAndroid Build Coastguard Worker 82*49fe348cSAndroid Build Coastguard Worker self.y[d:d+n] = b[0] * u[2:] + b[1] * u[1:-1] + b[2] * u[:-2] 83*49fe348cSAndroid Build Coastguard Worker for i in range(n): 84*49fe348cSAndroid Build Coastguard Worker self.y[d+i] -= a[1] * self.y[d+i-1] + a[2] * self.y[d+i-2] 85*49fe348cSAndroid Build Coastguard Worker 86*49fe348cSAndroid Build Coastguard Worker return self.y 87*49fe348cSAndroid Build Coastguard Worker 88*49fe348cSAndroid Build Coastguard Worker 89*49fe348cSAndroid Build Coastguard Workerclass Resampler_6k4: 90*49fe348cSAndroid Build Coastguard Worker 91*49fe348cSAndroid Build Coastguard Worker def __init__(self, n, history = 0): 92*49fe348cSAndroid Build Coastguard Worker 93*49fe348cSAndroid Build Coastguard Worker self.x = np.zeros(n + 5) 94*49fe348cSAndroid Build Coastguard Worker self.n = n // 2 95*49fe348cSAndroid Build Coastguard Worker 96*49fe348cSAndroid Build Coastguard Worker self.y = np.zeros(self.n + history) 97*49fe348cSAndroid Build Coastguard Worker 98*49fe348cSAndroid Build Coastguard Worker def resample(self, x): 99*49fe348cSAndroid Build Coastguard Worker 100*49fe348cSAndroid Build Coastguard Worker n = self.n 101*49fe348cSAndroid Build Coastguard Worker 102*49fe348cSAndroid Build Coastguard Worker ### Sliding window 103*49fe348cSAndroid Build Coastguard Worker 104*49fe348cSAndroid Build Coastguard Worker self.x[:3] = self.x[-5:-2] 105*49fe348cSAndroid Build Coastguard Worker self.x[3:] = x[:2*n+2] 106*49fe348cSAndroid Build Coastguard Worker x = self.x 107*49fe348cSAndroid Build Coastguard Worker 108*49fe348cSAndroid Build Coastguard Worker if len(self.y) > 2*n: 109*49fe348cSAndroid Build Coastguard Worker self.y[n:-n] = self.y[2*n:] 110*49fe348cSAndroid Build Coastguard Worker if len(self.y) > n: 111*49fe348cSAndroid Build Coastguard Worker self.y[-n:] = self.y[:n] 112*49fe348cSAndroid Build Coastguard Worker 113*49fe348cSAndroid Build Coastguard Worker ### Downsampling to 6.4 KHz 114*49fe348cSAndroid Build Coastguard Worker 115*49fe348cSAndroid Build Coastguard Worker h = [ 0.1236796411180537, 0.2353512128364889, 0.2819382920909148, 116*49fe348cSAndroid Build Coastguard Worker 0.2353512128364889, 0.1236796411180537 ] 117*49fe348cSAndroid Build Coastguard Worker 118*49fe348cSAndroid Build Coastguard Worker self.y[:n] = [ np.dot(x[2*i:2*i+5], h) for i in range(self.n) ] 119*49fe348cSAndroid Build Coastguard Worker return self.y 120*49fe348cSAndroid Build Coastguard Worker 121*49fe348cSAndroid Build Coastguard Worker 122*49fe348cSAndroid Build Coastguard Workerdef initial_hp50_state(): 123*49fe348cSAndroid Build Coastguard Worker return { 's1': 0, 's2': 0 } 124*49fe348cSAndroid Build Coastguard Worker 125*49fe348cSAndroid Build Coastguard Worker### ------------------------------------------------------------------------ ### 126*49fe348cSAndroid Build Coastguard Worker 127*49fe348cSAndroid Build Coastguard Workerclass Ltpf: 128*49fe348cSAndroid Build Coastguard Worker 129*49fe348cSAndroid Build Coastguard Worker def __init__(self, dt, sr): 130*49fe348cSAndroid Build Coastguard Worker 131*49fe348cSAndroid Build Coastguard Worker self.dt = dt 132*49fe348cSAndroid Build Coastguard Worker self.sr = sr 133*49fe348cSAndroid Build Coastguard Worker 134*49fe348cSAndroid Build Coastguard Worker (self.pitch_present, self.pitch_index) = (None, None) 135*49fe348cSAndroid Build Coastguard Worker 136*49fe348cSAndroid Build Coastguard Worker 137*49fe348cSAndroid Build Coastguard Workerclass LtpfAnalysis(Ltpf): 138*49fe348cSAndroid Build Coastguard Worker 139*49fe348cSAndroid Build Coastguard Worker def __init__(self, dt, sr): 140*49fe348cSAndroid Build Coastguard Worker 141*49fe348cSAndroid Build Coastguard Worker super().__init__(dt, sr) 142*49fe348cSAndroid Build Coastguard Worker 143*49fe348cSAndroid Build Coastguard Worker self.resampler_12k8 = Resampler_12k8(dt, sr, 144*49fe348cSAndroid Build Coastguard Worker history = 232 + (32 if dt == T.DT_2M5 else 0)) 145*49fe348cSAndroid Build Coastguard Worker 146*49fe348cSAndroid Build Coastguard Worker self.resampler_6k4 = Resampler_6k4(self.resampler_12k8.n, 147*49fe348cSAndroid Build Coastguard Worker history = 114 + (16 if dt == T.DT_2M5 else 0)) 148*49fe348cSAndroid Build Coastguard Worker 149*49fe348cSAndroid Build Coastguard Worker self.active = False 150*49fe348cSAndroid Build Coastguard Worker self.tc = 0 151*49fe348cSAndroid Build Coastguard Worker self.pitch = 0 152*49fe348cSAndroid Build Coastguard Worker self.nc = np.zeros(2) 153*49fe348cSAndroid Build Coastguard Worker 154*49fe348cSAndroid Build Coastguard Worker def get_data(self): 155*49fe348cSAndroid Build Coastguard Worker 156*49fe348cSAndroid Build Coastguard Worker return { 'active' : self.active, 157*49fe348cSAndroid Build Coastguard Worker 'pitch_index' : self.pitch_index } 158*49fe348cSAndroid Build Coastguard Worker 159*49fe348cSAndroid Build Coastguard Worker def get_nbits(self): 160*49fe348cSAndroid Build Coastguard Worker 161*49fe348cSAndroid Build Coastguard Worker return 1 + 10 * int(self.pitch_present) 162*49fe348cSAndroid Build Coastguard Worker 163*49fe348cSAndroid Build Coastguard Worker def correlate(self, x, i0, n, k0, k1): 164*49fe348cSAndroid Build Coastguard Worker 165*49fe348cSAndroid Build Coastguard Worker return np.array([ np.dot( 166*49fe348cSAndroid Build Coastguard Worker np.take(x, np.arange(i0, n)), 167*49fe348cSAndroid Build Coastguard Worker np.take(x, np.arange(i0, n) - k)) for k in range(k0, 1+k1) ]) 168*49fe348cSAndroid Build Coastguard Worker 169*49fe348cSAndroid Build Coastguard Worker def norm_corr(self, x, i0, n, k): 170*49fe348cSAndroid Build Coastguard Worker 171*49fe348cSAndroid Build Coastguard Worker u = np.take(x, np.arange(i0, n)) 172*49fe348cSAndroid Build Coastguard Worker v = np.take(x, np.arange(i0, n) - k) 173*49fe348cSAndroid Build Coastguard Worker uv = np.dot(u, v) 174*49fe348cSAndroid Build Coastguard Worker return uv / np.sqrt(np.dot(u, u) * np.dot(v, v)) if uv > 0 else 0 175*49fe348cSAndroid Build Coastguard Worker 176*49fe348cSAndroid Build Coastguard Worker def run(self, x): 177*49fe348cSAndroid Build Coastguard Worker 178*49fe348cSAndroid Build Coastguard Worker ### Resampling 179*49fe348cSAndroid Build Coastguard Worker 180*49fe348cSAndroid Build Coastguard Worker x_12k8 = self.resampler_12k8.resample(x) 181*49fe348cSAndroid Build Coastguard Worker 182*49fe348cSAndroid Build Coastguard Worker ### Pitch detection algorithm 183*49fe348cSAndroid Build Coastguard Worker 184*49fe348cSAndroid Build Coastguard Worker x = self.resampler_6k4.resample(x_12k8) 185*49fe348cSAndroid Build Coastguard Worker i0 = [-16, 0][self.dt > T.DT_2M5] 186*49fe348cSAndroid Build Coastguard Worker n = self.resampler_6k4.n 187*49fe348cSAndroid Build Coastguard Worker 188*49fe348cSAndroid Build Coastguard Worker r = self.correlate(x, i0, n, 17, 114) 189*49fe348cSAndroid Build Coastguard Worker rw = r * (1 - 0.5 * np.arange(len(r)) / (len(r) - 1)) 190*49fe348cSAndroid Build Coastguard Worker 191*49fe348cSAndroid Build Coastguard Worker tc = self.tc 192*49fe348cSAndroid Build Coastguard Worker k0 = max(0, tc-4) 193*49fe348cSAndroid Build Coastguard Worker k1 = min(len(r)-1, tc+4) 194*49fe348cSAndroid Build Coastguard Worker t = [ 17 + np.argmax(rw), 17 + k0 + np.argmax(r[k0:1+k1]) ] 195*49fe348cSAndroid Build Coastguard Worker 196*49fe348cSAndroid Build Coastguard Worker nc = [ self.norm_corr(x, i0, n, t[i]) for i in range(2) ] 197*49fe348cSAndroid Build Coastguard Worker ti = int(nc[1] > 0.85 * nc[0]) 198*49fe348cSAndroid Build Coastguard Worker self.tc = t[ti] - 17 199*49fe348cSAndroid Build Coastguard Worker 200*49fe348cSAndroid Build Coastguard Worker self.pitch_present = bool(nc[ti] > 0.6) 201*49fe348cSAndroid Build Coastguard Worker 202*49fe348cSAndroid Build Coastguard Worker ### Pitch-lag parameter 203*49fe348cSAndroid Build Coastguard Worker 204*49fe348cSAndroid Build Coastguard Worker if self.pitch_present: 205*49fe348cSAndroid Build Coastguard Worker tc = self.tc + 17 206*49fe348cSAndroid Build Coastguard Worker 207*49fe348cSAndroid Build Coastguard Worker x = x_12k8 208*49fe348cSAndroid Build Coastguard Worker i0 = [-32, 0][self.dt > T.DT_2M5] 209*49fe348cSAndroid Build Coastguard Worker n = self.resampler_12k8.n 210*49fe348cSAndroid Build Coastguard Worker 211*49fe348cSAndroid Build Coastguard Worker k0 = max( 32, 2*tc-4) 212*49fe348cSAndroid Build Coastguard Worker k1 = min(228, 2*tc+4) 213*49fe348cSAndroid Build Coastguard Worker r = self.correlate(x, i0, n, k0-4, k1+4) 214*49fe348cSAndroid Build Coastguard Worker e = k0 + np.argmax(r[4:-4]) 215*49fe348cSAndroid Build Coastguard Worker 216*49fe348cSAndroid Build Coastguard Worker h = np.zeros(42) 217*49fe348cSAndroid Build Coastguard Worker h[-15:] = T.LTPF_H4[:15] 218*49fe348cSAndroid Build Coastguard Worker h[ :16] = T.LTPF_H4[15:] 219*49fe348cSAndroid Build Coastguard Worker 220*49fe348cSAndroid Build Coastguard Worker m = np.arange(-4, 5) 221*49fe348cSAndroid Build Coastguard Worker s = [ np.dot( np.take(r, e-k0+4 + m), np.take(h, 4*m-d) ) \ 222*49fe348cSAndroid Build Coastguard Worker for d in range(-3, 4) ] 223*49fe348cSAndroid Build Coastguard Worker 224*49fe348cSAndroid Build Coastguard Worker f = np.argmax(s[3:]) if e <= 32 else \ 225*49fe348cSAndroid Build Coastguard Worker -3 + np.argmax(s) if e < 127 else \ 226*49fe348cSAndroid Build Coastguard Worker -2 + 2*np.argmax(s[1:-1:2]) if e < 157 else 0 227*49fe348cSAndroid Build Coastguard Worker 228*49fe348cSAndroid Build Coastguard Worker e -= (f < 0) 229*49fe348cSAndroid Build Coastguard Worker f += 4*(f < 0) 230*49fe348cSAndroid Build Coastguard Worker 231*49fe348cSAndroid Build Coastguard Worker self.pitch_index = 4*e + f - 128 if e < 127 else \ 232*49fe348cSAndroid Build Coastguard Worker 2*e + f//2 + 126 if e < 157 else e + 283 233*49fe348cSAndroid Build Coastguard Worker 234*49fe348cSAndroid Build Coastguard Worker else: 235*49fe348cSAndroid Build Coastguard Worker e = f = 0 236*49fe348cSAndroid Build Coastguard Worker self.pitch_index = 0 237*49fe348cSAndroid Build Coastguard Worker 238*49fe348cSAndroid Build Coastguard Worker ### Activation bit 239*49fe348cSAndroid Build Coastguard Worker 240*49fe348cSAndroid Build Coastguard Worker h = np.zeros(24) 241*49fe348cSAndroid Build Coastguard Worker h[-7:] = T.LTPF_HI[:7] 242*49fe348cSAndroid Build Coastguard Worker h[ :8] = T.LTPF_HI[7:] 243*49fe348cSAndroid Build Coastguard Worker 244*49fe348cSAndroid Build Coastguard Worker x = x_12k8 245*49fe348cSAndroid Build Coastguard Worker i0 = [-32, 0][self.dt > T.DT_2M5] 246*49fe348cSAndroid Build Coastguard Worker n = self.resampler_12k8.n 247*49fe348cSAndroid Build Coastguard Worker 248*49fe348cSAndroid Build Coastguard Worker k = np.arange(-2, 3) 249*49fe348cSAndroid Build Coastguard Worker u = [ np.dot( np.take(x, i-k), np.take(h, 4*k) ) \ 250*49fe348cSAndroid Build Coastguard Worker for i in range(i0, n) ] 251*49fe348cSAndroid Build Coastguard Worker v = [ np.dot( np.take(x, i-k), np.take(h, 4*k-f) ) \ 252*49fe348cSAndroid Build Coastguard Worker for i in range(i0-e, n-e) ] 253*49fe348cSAndroid Build Coastguard Worker 254*49fe348cSAndroid Build Coastguard Worker nc = max(0, np.dot(u, v)) / np.sqrt(np.dot(u, u) * np.dot(v, v)) \ 255*49fe348cSAndroid Build Coastguard Worker if self.pitch_present else 0 256*49fe348cSAndroid Build Coastguard Worker 257*49fe348cSAndroid Build Coastguard Worker pitch = e + f/4 258*49fe348cSAndroid Build Coastguard Worker 259*49fe348cSAndroid Build Coastguard Worker if not self.active: 260*49fe348cSAndroid Build Coastguard Worker active = (self.dt == T.DT_10M or self.nc[1] > 0.94) \ 261*49fe348cSAndroid Build Coastguard Worker and self.nc[0] > 0.94 and nc > 0.94 262*49fe348cSAndroid Build Coastguard Worker 263*49fe348cSAndroid Build Coastguard Worker else: 264*49fe348cSAndroid Build Coastguard Worker dp = abs(pitch - self.pitch) 265*49fe348cSAndroid Build Coastguard Worker dc = nc - self.nc[0] 266*49fe348cSAndroid Build Coastguard Worker active = nc > 0.9 or (dp < 2 and dc > -0.1 and nc > 0.84) 267*49fe348cSAndroid Build Coastguard Worker 268*49fe348cSAndroid Build Coastguard Worker if not self.pitch_present: 269*49fe348cSAndroid Build Coastguard Worker active = False 270*49fe348cSAndroid Build Coastguard Worker pitch = 0 271*49fe348cSAndroid Build Coastguard Worker nc = 0 272*49fe348cSAndroid Build Coastguard Worker 273*49fe348cSAndroid Build Coastguard Worker self.active = active 274*49fe348cSAndroid Build Coastguard Worker self.pitch = pitch 275*49fe348cSAndroid Build Coastguard Worker self.nc[1] = self.nc[0] 276*49fe348cSAndroid Build Coastguard Worker self.nc[0] = nc 277*49fe348cSAndroid Build Coastguard Worker 278*49fe348cSAndroid Build Coastguard Worker return self.pitch_present 279*49fe348cSAndroid Build Coastguard Worker 280*49fe348cSAndroid Build Coastguard Worker def disable(self): 281*49fe348cSAndroid Build Coastguard Worker 282*49fe348cSAndroid Build Coastguard Worker self.active = False 283*49fe348cSAndroid Build Coastguard Worker 284*49fe348cSAndroid Build Coastguard Worker def store(self, b): 285*49fe348cSAndroid Build Coastguard Worker 286*49fe348cSAndroid Build Coastguard Worker b.write_uint(self.active, 1) 287*49fe348cSAndroid Build Coastguard Worker b.write_uint(self.pitch_index, 9) 288*49fe348cSAndroid Build Coastguard Worker 289*49fe348cSAndroid Build Coastguard Worker 290*49fe348cSAndroid Build Coastguard Workerclass LtpfSynthesis(Ltpf): 291*49fe348cSAndroid Build Coastguard Worker 292*49fe348cSAndroid Build Coastguard Worker C_N = [ T.LTPF_N_8K , T.LTPF_N_16K, 293*49fe348cSAndroid Build Coastguard Worker T.LTPF_N_24K, T.LTPF_N_32K, T.LTPF_N_48K ] 294*49fe348cSAndroid Build Coastguard Worker 295*49fe348cSAndroid Build Coastguard Worker C_D = [ T.LTPF_D_8K , T.LTPF_D_16K, 296*49fe348cSAndroid Build Coastguard Worker T.LTPF_D_24K, T.LTPF_D_32K, T.LTPF_D_48K ] 297*49fe348cSAndroid Build Coastguard Worker 298*49fe348cSAndroid Build Coastguard Worker def __init__(self, dt, sr): 299*49fe348cSAndroid Build Coastguard Worker 300*49fe348cSAndroid Build Coastguard Worker super().__init__(dt, sr) 301*49fe348cSAndroid Build Coastguard Worker 302*49fe348cSAndroid Build Coastguard Worker self.C_N = LtpfSynthesis.C_N[sr] 303*49fe348cSAndroid Build Coastguard Worker self.C_D = LtpfSynthesis.C_D[sr] 304*49fe348cSAndroid Build Coastguard Worker 305*49fe348cSAndroid Build Coastguard Worker ns = T.NS[dt][sr] 306*49fe348cSAndroid Build Coastguard Worker 307*49fe348cSAndroid Build Coastguard Worker self.active = [ False, False ] 308*49fe348cSAndroid Build Coastguard Worker self.pitch_index = 0 309*49fe348cSAndroid Build Coastguard Worker 310*49fe348cSAndroid Build Coastguard Worker max_pitch_12k8 = 228 311*49fe348cSAndroid Build Coastguard Worker max_pitch = max_pitch_12k8 * T.SRATE_KHZ[self.sr] / 12.8 312*49fe348cSAndroid Build Coastguard Worker max_pitch = np.ceil(max_pitch).astype(int) 313*49fe348cSAndroid Build Coastguard Worker 314*49fe348cSAndroid Build Coastguard Worker self.x = np.zeros(ns) 315*49fe348cSAndroid Build Coastguard Worker self.y = np.zeros(max_pitch + len(self.C_D[0])) 316*49fe348cSAndroid Build Coastguard Worker 317*49fe348cSAndroid Build Coastguard Worker self.p_e = [ 0, 0 ] 318*49fe348cSAndroid Build Coastguard Worker self.p_f = [ 0, 0 ] 319*49fe348cSAndroid Build Coastguard Worker self.c_n = [ None, None ] 320*49fe348cSAndroid Build Coastguard Worker self.c_d = [ None, None ] 321*49fe348cSAndroid Build Coastguard Worker 322*49fe348cSAndroid Build Coastguard Worker def load(self, b): 323*49fe348cSAndroid Build Coastguard Worker 324*49fe348cSAndroid Build Coastguard Worker self.active[0] = bool(b.read_uint(1)) 325*49fe348cSAndroid Build Coastguard Worker self.pitch_index = b.read_uint(9) 326*49fe348cSAndroid Build Coastguard Worker 327*49fe348cSAndroid Build Coastguard Worker def disable(self): 328*49fe348cSAndroid Build Coastguard Worker 329*49fe348cSAndroid Build Coastguard Worker self.active[0] = False 330*49fe348cSAndroid Build Coastguard Worker self.pitch_index = 0 331*49fe348cSAndroid Build Coastguard Worker 332*49fe348cSAndroid Build Coastguard Worker def run(self, x, nbytes): 333*49fe348cSAndroid Build Coastguard Worker 334*49fe348cSAndroid Build Coastguard Worker sr = self.sr 335*49fe348cSAndroid Build Coastguard Worker dt = self.dt 336*49fe348cSAndroid Build Coastguard Worker 337*49fe348cSAndroid Build Coastguard Worker ### Filter parameters 338*49fe348cSAndroid Build Coastguard Worker 339*49fe348cSAndroid Build Coastguard Worker pitch_index = self.pitch_index 340*49fe348cSAndroid Build Coastguard Worker 341*49fe348cSAndroid Build Coastguard Worker if pitch_index >= 440: 342*49fe348cSAndroid Build Coastguard Worker p_e = pitch_index - 283 343*49fe348cSAndroid Build Coastguard Worker p_f = 0 344*49fe348cSAndroid Build Coastguard Worker elif pitch_index >= 380: 345*49fe348cSAndroid Build Coastguard Worker p_e = pitch_index // 2 - 63 346*49fe348cSAndroid Build Coastguard Worker p_f = 2*(pitch_index - 2*(p_e + 63)) 347*49fe348cSAndroid Build Coastguard Worker else: 348*49fe348cSAndroid Build Coastguard Worker p_e = pitch_index // 4 + 32 349*49fe348cSAndroid Build Coastguard Worker p_f = pitch_index - 4*(p_e - 32) 350*49fe348cSAndroid Build Coastguard Worker 351*49fe348cSAndroid Build Coastguard Worker p = (p_e + p_f / 4) * T.SRATE_KHZ[self.sr] / 12.8 352*49fe348cSAndroid Build Coastguard Worker 353*49fe348cSAndroid Build Coastguard Worker self.p_e[0] = int(p * 4 + 0.5) // 4 354*49fe348cSAndroid Build Coastguard Worker self.p_f[0] = int(p * 4 + 0.5) - 4*self.p_e[0] 355*49fe348cSAndroid Build Coastguard Worker 356*49fe348cSAndroid Build Coastguard Worker nbits = round(nbytes*8 * 10 / T.DT_MS[dt]) 357*49fe348cSAndroid Build Coastguard Worker if dt == T.DT_2M5: 358*49fe348cSAndroid Build Coastguard Worker nbits = int(nbits * (1 - 0.4)) 359*49fe348cSAndroid Build Coastguard Worker elif dt == T.DT_5M: 360*49fe348cSAndroid Build Coastguard Worker nbits = nbits - 160 361*49fe348cSAndroid Build Coastguard Worker 362*49fe348cSAndroid Build Coastguard Worker g_idx = max(nbits // 80, 3+sr) - (3+sr) 363*49fe348cSAndroid Build Coastguard Worker 364*49fe348cSAndroid Build Coastguard Worker g = [ 0.4, 0.35, 0.3, 0.25 ][g_idx] if g_idx < 4 else 0 365*49fe348cSAndroid Build Coastguard Worker g_idx = min(g_idx, 3) 366*49fe348cSAndroid Build Coastguard Worker 367*49fe348cSAndroid Build Coastguard Worker self.c_n[0] = 0.85 * g * LtpfSynthesis.C_N[sr][g_idx] 368*49fe348cSAndroid Build Coastguard Worker self.c_d[0] = g * LtpfSynthesis.C_D[sr][self.p_f[0]] 369*49fe348cSAndroid Build Coastguard Worker 370*49fe348cSAndroid Build Coastguard Worker ### Transition handling 371*49fe348cSAndroid Build Coastguard Worker 372*49fe348cSAndroid Build Coastguard Worker n0 = (T.SRATE_KHZ[sr] * 1000) // 400 373*49fe348cSAndroid Build Coastguard Worker ns = T.NS[dt][sr] 374*49fe348cSAndroid Build Coastguard Worker 375*49fe348cSAndroid Build Coastguard Worker x = np.append(x, self.x) 376*49fe348cSAndroid Build Coastguard Worker y = np.append(np.zeros(ns), self.y) 377*49fe348cSAndroid Build Coastguard Worker yc = y.copy() 378*49fe348cSAndroid Build Coastguard Worker 379*49fe348cSAndroid Build Coastguard Worker c_n = self.c_n 380*49fe348cSAndroid Build Coastguard Worker c_d = self.c_d 381*49fe348cSAndroid Build Coastguard Worker 382*49fe348cSAndroid Build Coastguard Worker l_n = len(c_n[0]) 383*49fe348cSAndroid Build Coastguard Worker l_d = len(c_d[0]) 384*49fe348cSAndroid Build Coastguard Worker 385*49fe348cSAndroid Build Coastguard Worker d = [ self.p_e[0] - (l_d - 1) // 2, 386*49fe348cSAndroid Build Coastguard Worker self.p_e[1] - (l_d - 1) // 2 ] 387*49fe348cSAndroid Build Coastguard Worker 388*49fe348cSAndroid Build Coastguard Worker for k in range(n0): 389*49fe348cSAndroid Build Coastguard Worker 390*49fe348cSAndroid Build Coastguard Worker if not self.active[0] and not self.active[1]: 391*49fe348cSAndroid Build Coastguard Worker y[k] = x[k] 392*49fe348cSAndroid Build Coastguard Worker 393*49fe348cSAndroid Build Coastguard Worker elif self.active[0] and not self.active[1]: 394*49fe348cSAndroid Build Coastguard Worker u = np.dot(c_n[0], np.take(x, k - np.arange(l_n))) - \ 395*49fe348cSAndroid Build Coastguard Worker np.dot(c_d[0], np.take(y, k - d[0] - np.arange(l_d))) 396*49fe348cSAndroid Build Coastguard Worker y[k] = x[k] - (k/n0) * u 397*49fe348cSAndroid Build Coastguard Worker 398*49fe348cSAndroid Build Coastguard Worker elif not self.active[0] and self.active[1]: 399*49fe348cSAndroid Build Coastguard Worker u = np.dot(c_n[1], np.take(x, k - np.arange(l_n))) - \ 400*49fe348cSAndroid Build Coastguard Worker np.dot(c_d[1], np.take(y, k - d[1] - np.arange(l_d))) 401*49fe348cSAndroid Build Coastguard Worker y[k] = x[k] - (1 - k/n0) * u 402*49fe348cSAndroid Build Coastguard Worker 403*49fe348cSAndroid Build Coastguard Worker elif self.p_e[0] == self.p_e[1] and self.p_f[0] == self.p_f[1]: 404*49fe348cSAndroid Build Coastguard Worker u = np.dot(c_n[0], np.take(x, k - np.arange(l_n))) - \ 405*49fe348cSAndroid Build Coastguard Worker np.dot(c_d[0], np.take(y, k - d[0] - np.arange(l_d))) 406*49fe348cSAndroid Build Coastguard Worker y[k] = x[k] - u 407*49fe348cSAndroid Build Coastguard Worker 408*49fe348cSAndroid Build Coastguard Worker else: 409*49fe348cSAndroid Build Coastguard Worker u = np.dot(c_n[1], np.take(x, k - np.arange(l_n))) - \ 410*49fe348cSAndroid Build Coastguard Worker np.dot(c_d[1], np.take(y, k - d[1] - np.arange(l_d))) 411*49fe348cSAndroid Build Coastguard Worker yc[k] = x[k] - (1 - k/n0) * u 412*49fe348cSAndroid Build Coastguard Worker 413*49fe348cSAndroid Build Coastguard Worker u = np.dot(c_n[0], np.take(yc, k - np.arange(l_n))) - \ 414*49fe348cSAndroid Build Coastguard Worker np.dot(c_d[0], np.take(y , k - d[0] - np.arange(l_d))) 415*49fe348cSAndroid Build Coastguard Worker y[k] = yc[k] - (k/n0) * u 416*49fe348cSAndroid Build Coastguard Worker 417*49fe348cSAndroid Build Coastguard Worker ### Remainder of the frame 418*49fe348cSAndroid Build Coastguard Worker 419*49fe348cSAndroid Build Coastguard Worker for k in range(n0, ns): 420*49fe348cSAndroid Build Coastguard Worker 421*49fe348cSAndroid Build Coastguard Worker if not self.active[0]: 422*49fe348cSAndroid Build Coastguard Worker y[k] = x[k] 423*49fe348cSAndroid Build Coastguard Worker 424*49fe348cSAndroid Build Coastguard Worker else: 425*49fe348cSAndroid Build Coastguard Worker u = np.dot(c_n[0], np.take(x, k - np.arange(l_n))) - \ 426*49fe348cSAndroid Build Coastguard Worker np.dot(c_d[0], np.take(y, k - d[0] - np.arange(l_d))) 427*49fe348cSAndroid Build Coastguard Worker y[k] = x[k] - u 428*49fe348cSAndroid Build Coastguard Worker 429*49fe348cSAndroid Build Coastguard Worker ### Sliding window 430*49fe348cSAndroid Build Coastguard Worker 431*49fe348cSAndroid Build Coastguard Worker self.active[1] = self.active[0] 432*49fe348cSAndroid Build Coastguard Worker self.p_e[1] = self.p_e[0] 433*49fe348cSAndroid Build Coastguard Worker self.p_f[1] = self.p_f[0] 434*49fe348cSAndroid Build Coastguard Worker self.c_n[1] = self.c_n[0] 435*49fe348cSAndroid Build Coastguard Worker self.c_d[1] = self.c_d[0] 436*49fe348cSAndroid Build Coastguard Worker 437*49fe348cSAndroid Build Coastguard Worker self.x = x[:ns] 438*49fe348cSAndroid Build Coastguard Worker self.y = np.append(self.y[ns:], y[:ns]) 439*49fe348cSAndroid Build Coastguard Worker 440*49fe348cSAndroid Build Coastguard Worker return y[:ns] 441*49fe348cSAndroid Build Coastguard Worker 442*49fe348cSAndroid Build Coastguard Workerdef initial_state(): 443*49fe348cSAndroid Build Coastguard Worker return { 'active' : False, 'pitch': 0, 'nc': np.zeros(2), 444*49fe348cSAndroid Build Coastguard Worker 'hp50' : initial_hp50_state(), 445*49fe348cSAndroid Build Coastguard Worker 'x_12k8' : np.zeros(384), 'x_6k4' : np.zeros(178), 'tc' : 0 } 446*49fe348cSAndroid Build Coastguard Worker 447*49fe348cSAndroid Build Coastguard Workerdef initial_sstate(): 448*49fe348cSAndroid Build Coastguard Worker return { 'active': False, 'pitch': 0, 449*49fe348cSAndroid Build Coastguard Worker 'c': np.zeros(2*12), 'x': np.zeros(12) } 450*49fe348cSAndroid Build Coastguard Worker 451*49fe348cSAndroid Build Coastguard Worker### ------------------------------------------------------------------------ ### 452*49fe348cSAndroid Build Coastguard Worker 453*49fe348cSAndroid Build Coastguard Workerdef check_resampler(rng, dt, sr): 454*49fe348cSAndroid Build Coastguard Worker 455*49fe348cSAndroid Build Coastguard Worker ns = T.NS[dt][sr] 456*49fe348cSAndroid Build Coastguard Worker nt = (5 * T.SRATE_KHZ[sr]) // 4 457*49fe348cSAndroid Build Coastguard Worker ok = True 458*49fe348cSAndroid Build Coastguard Worker 459*49fe348cSAndroid Build Coastguard Worker r = Resampler_12k8(dt, sr) 460*49fe348cSAndroid Build Coastguard Worker 461*49fe348cSAndroid Build Coastguard Worker hp50_c = initial_hp50_state() 462*49fe348cSAndroid Build Coastguard Worker x_c = np.zeros(nt) 463*49fe348cSAndroid Build Coastguard Worker y_c = np.zeros(384) 464*49fe348cSAndroid Build Coastguard Worker 465*49fe348cSAndroid Build Coastguard Worker for run in range(10): 466*49fe348cSAndroid Build Coastguard Worker 467*49fe348cSAndroid Build Coastguard Worker x = ((2 * rng.random(ns)) - 1) * (2 ** 15 - 1) 468*49fe348cSAndroid Build Coastguard Worker y = r.resample(x) 469*49fe348cSAndroid Build Coastguard Worker 470*49fe348cSAndroid Build Coastguard Worker x_c = np.append(x_c[-nt:], x.astype(np.int16)) 471*49fe348cSAndroid Build Coastguard Worker y_c[:-r.n] = y_c[r.n:] 472*49fe348cSAndroid Build Coastguard Worker y_c = lc3.ltpf_resample(dt, sr, hp50_c, x_c, y_c) 473*49fe348cSAndroid Build Coastguard Worker 474*49fe348cSAndroid Build Coastguard Worker ok = ok and np.amax(np.abs(y_c[-r.d-r.n:] - y[:r.d+r.n]/2)) < 4 475*49fe348cSAndroid Build Coastguard Worker 476*49fe348cSAndroid Build Coastguard Worker return ok 477*49fe348cSAndroid Build Coastguard Worker 478*49fe348cSAndroid Build Coastguard Workerdef check_resampler_appendix_c(dt): 479*49fe348cSAndroid Build Coastguard Worker 480*49fe348cSAndroid Build Coastguard Worker i0 = dt - T.DT_7M5 481*49fe348cSAndroid Build Coastguard Worker sr = T.SRATE_16K 482*49fe348cSAndroid Build Coastguard Worker 483*49fe348cSAndroid Build Coastguard Worker ok = True 484*49fe348cSAndroid Build Coastguard Worker 485*49fe348cSAndroid Build Coastguard Worker nt = (5 * T.SRATE_KHZ[sr]) // 4 486*49fe348cSAndroid Build Coastguard Worker n = [ 96, 128 ][i0] 487*49fe348cSAndroid Build Coastguard Worker k = [ 44, 24 ][i0] + n 488*49fe348cSAndroid Build Coastguard Worker 489*49fe348cSAndroid Build Coastguard Worker state = initial_hp50_state() 490*49fe348cSAndroid Build Coastguard Worker 491*49fe348cSAndroid Build Coastguard Worker x = np.append(np.zeros(nt), C.X_PCM[i0][0]) 492*49fe348cSAndroid Build Coastguard Worker y = np.zeros(384) 493*49fe348cSAndroid Build Coastguard Worker y = lc3.ltpf_resample(dt, sr, state, x, y) 494*49fe348cSAndroid Build Coastguard Worker u = y[-k:len(C.X_TILDE_12K8D[i0][0])-k] 495*49fe348cSAndroid Build Coastguard Worker 496*49fe348cSAndroid Build Coastguard Worker ok = ok and np.amax(np.abs(u - C.X_TILDE_12K8D[i0][0]/2)) < 2 497*49fe348cSAndroid Build Coastguard Worker 498*49fe348cSAndroid Build Coastguard Worker x = np.append(x[-nt:], C.X_PCM[i0][1]) 499*49fe348cSAndroid Build Coastguard Worker y[:-n] = y[n:] 500*49fe348cSAndroid Build Coastguard Worker y = lc3.ltpf_resample(dt, sr, state, x, y) 501*49fe348cSAndroid Build Coastguard Worker u = y[-k:len(C.X_TILDE_12K8D[i0][1])-k] 502*49fe348cSAndroid Build Coastguard Worker 503*49fe348cSAndroid Build Coastguard Worker ok = ok and np.amax(np.abs(u - C.X_TILDE_12K8D[i0][1]/2)) < 2 504*49fe348cSAndroid Build Coastguard Worker 505*49fe348cSAndroid Build Coastguard Worker return ok 506*49fe348cSAndroid Build Coastguard Worker 507*49fe348cSAndroid Build Coastguard Workerdef check_analysis(rng, dt, sr): 508*49fe348cSAndroid Build Coastguard Worker 509*49fe348cSAndroid Build Coastguard Worker ns = T.NS[dt][sr] 510*49fe348cSAndroid Build Coastguard Worker nt = (5 * T.SRATE_KHZ[sr]) // 4 511*49fe348cSAndroid Build Coastguard Worker ok = True 512*49fe348cSAndroid Build Coastguard Worker 513*49fe348cSAndroid Build Coastguard Worker state_c = initial_state() 514*49fe348cSAndroid Build Coastguard Worker x_c = np.zeros(ns+nt) 515*49fe348cSAndroid Build Coastguard Worker 516*49fe348cSAndroid Build Coastguard Worker ltpf = LtpfAnalysis(dt, sr) 517*49fe348cSAndroid Build Coastguard Worker 518*49fe348cSAndroid Build Coastguard Worker t = np.arange(100 * ns) / (T.SRATE_KHZ[sr] * 1000) 519*49fe348cSAndroid Build Coastguard Worker s = signal.chirp(t, f0=10, f1=2500, t1=t[-1], method='logarithmic') 520*49fe348cSAndroid Build Coastguard Worker 521*49fe348cSAndroid Build Coastguard Worker for i in range(20): 522*49fe348cSAndroid Build Coastguard Worker 523*49fe348cSAndroid Build Coastguard Worker x = s[i*ns:(i+1)*ns] * (2 ** 15 - 1) 524*49fe348cSAndroid Build Coastguard Worker 525*49fe348cSAndroid Build Coastguard Worker pitch_present = ltpf.run(x) 526*49fe348cSAndroid Build Coastguard Worker data = ltpf.get_data() 527*49fe348cSAndroid Build Coastguard Worker 528*49fe348cSAndroid Build Coastguard Worker x_c = np.append(x_c[-nt:], x.astype(np.int16)) 529*49fe348cSAndroid Build Coastguard Worker (pitch_present_c, data_c) = lc3.ltpf_analyse(dt, sr, state_c, x_c) 530*49fe348cSAndroid Build Coastguard Worker 531*49fe348cSAndroid Build Coastguard Worker ok = ok and (not pitch_present or state_c['tc'] == ltpf.tc) 532*49fe348cSAndroid Build Coastguard Worker ok = ok and np.amax(np.abs(state_c['nc'][0] - ltpf.nc[0])) < 1e-1 533*49fe348cSAndroid Build Coastguard Worker ok = ok and pitch_present_c == pitch_present 534*49fe348cSAndroid Build Coastguard Worker ok = ok and data_c['active'] == data['active'] 535*49fe348cSAndroid Build Coastguard Worker ok = ok and data_c['pitch_index'] == data['pitch_index'] 536*49fe348cSAndroid Build Coastguard Worker ok = ok and lc3.ltpf_get_nbits(pitch_present) == ltpf.get_nbits() 537*49fe348cSAndroid Build Coastguard Worker 538*49fe348cSAndroid Build Coastguard Worker return ok 539*49fe348cSAndroid Build Coastguard Worker 540*49fe348cSAndroid Build Coastguard Workerdef check_synthesis(rng, dt, sr): 541*49fe348cSAndroid Build Coastguard Worker 542*49fe348cSAndroid Build Coastguard Worker ok = True 543*49fe348cSAndroid Build Coastguard Worker 544*49fe348cSAndroid Build Coastguard Worker ns = T.NS[dt][sr] 545*49fe348cSAndroid Build Coastguard Worker nd = 18 * T.SRATE_KHZ[sr] 546*49fe348cSAndroid Build Coastguard Worker 547*49fe348cSAndroid Build Coastguard Worker synthesis = LtpfSynthesis(dt, sr) 548*49fe348cSAndroid Build Coastguard Worker 549*49fe348cSAndroid Build Coastguard Worker state_c = initial_sstate() 550*49fe348cSAndroid Build Coastguard Worker x_c = np.zeros(nd+ns) 551*49fe348cSAndroid Build Coastguard Worker 552*49fe348cSAndroid Build Coastguard Worker for i in range(50): 553*49fe348cSAndroid Build Coastguard Worker 554*49fe348cSAndroid Build Coastguard Worker pitch_present = bool(rng.integers(0, 10) >= 1) 555*49fe348cSAndroid Build Coastguard Worker if not pitch_present: 556*49fe348cSAndroid Build Coastguard Worker synthesis.disable() 557*49fe348cSAndroid Build Coastguard Worker else: 558*49fe348cSAndroid Build Coastguard Worker synthesis.active[0] = bool(rng.integers(0, 5) >= 1) 559*49fe348cSAndroid Build Coastguard Worker synthesis.pitch_index = rng.integers(0, 512) 560*49fe348cSAndroid Build Coastguard Worker 561*49fe348cSAndroid Build Coastguard Worker data_c = None if not pitch_present else \ 562*49fe348cSAndroid Build Coastguard Worker { 'active' : synthesis.active[0], 563*49fe348cSAndroid Build Coastguard Worker 'pitch_index' : synthesis.pitch_index } 564*49fe348cSAndroid Build Coastguard Worker 565*49fe348cSAndroid Build Coastguard Worker x = rng.random(ns) * 1e4 566*49fe348cSAndroid Build Coastguard Worker nbytes = rng.integers(10*(2+sr), 10*(6+sr)) 567*49fe348cSAndroid Build Coastguard Worker 568*49fe348cSAndroid Build Coastguard Worker x_c[:nd] = x_c[ns:] 569*49fe348cSAndroid Build Coastguard Worker x_c[nd:] = x 570*49fe348cSAndroid Build Coastguard Worker 571*49fe348cSAndroid Build Coastguard Worker y = synthesis.run(x, nbytes) 572*49fe348cSAndroid Build Coastguard Worker x_c = lc3.ltpf_synthesize(dt, sr, nbytes, state_c, data_c, x_c) 573*49fe348cSAndroid Build Coastguard Worker 574*49fe348cSAndroid Build Coastguard Worker ok = ok and np.amax(np.abs(x_c[nd:] - y)) < 1e-2 575*49fe348cSAndroid Build Coastguard Worker 576*49fe348cSAndroid Build Coastguard Worker return ok 577*49fe348cSAndroid Build Coastguard Worker 578*49fe348cSAndroid Build Coastguard Workerdef check_analysis_appendix_c(dt): 579*49fe348cSAndroid Build Coastguard Worker 580*49fe348cSAndroid Build Coastguard Worker i0 = dt - T.DT_7M5 581*49fe348cSAndroid Build Coastguard Worker sr = T.SRATE_16K 582*49fe348cSAndroid Build Coastguard Worker 583*49fe348cSAndroid Build Coastguard Worker ok = True 584*49fe348cSAndroid Build Coastguard Worker 585*49fe348cSAndroid Build Coastguard Worker nt = (5 * T.SRATE_KHZ[sr]) // 4 586*49fe348cSAndroid Build Coastguard Worker 587*49fe348cSAndroid Build Coastguard Worker state = initial_state() 588*49fe348cSAndroid Build Coastguard Worker 589*49fe348cSAndroid Build Coastguard Worker x = np.append(np.zeros(nt), C.X_PCM[i0][0]) 590*49fe348cSAndroid Build Coastguard Worker (pitch_present, data) = lc3.ltpf_analyse(dt, sr, state, x) 591*49fe348cSAndroid Build Coastguard Worker 592*49fe348cSAndroid Build Coastguard Worker ok = ok and C.T_CURR[i0][0] - state['tc'] == 17 593*49fe348cSAndroid Build Coastguard Worker ok = ok and np.amax(np.abs(state['nc'][0] - C.NC_LTPF[i0][0])) < 1e-5 594*49fe348cSAndroid Build Coastguard Worker ok = ok and pitch_present == C.PITCH_PRESENT[i0][0] 595*49fe348cSAndroid Build Coastguard Worker ok = ok and data['pitch_index'] == C.PITCH_INDEX[i0][0] 596*49fe348cSAndroid Build Coastguard Worker ok = ok and data['active'] == C.LTPF_ACTIVE[i0][0] 597*49fe348cSAndroid Build Coastguard Worker 598*49fe348cSAndroid Build Coastguard Worker x = np.append(x[-nt:], C.X_PCM[i0][1]) 599*49fe348cSAndroid Build Coastguard Worker (pitch_present, data) = lc3.ltpf_analyse(dt, sr, state, x) 600*49fe348cSAndroid Build Coastguard Worker 601*49fe348cSAndroid Build Coastguard Worker ok = ok and C.T_CURR[i0][1] - state['tc'] == 17 602*49fe348cSAndroid Build Coastguard Worker ok = ok and np.amax(np.abs(state['nc'][0] - C.NC_LTPF[i0][1])) < 1e-5 603*49fe348cSAndroid Build Coastguard Worker ok = ok and pitch_present == C.PITCH_PRESENT[i0][1] 604*49fe348cSAndroid Build Coastguard Worker ok = ok and data['pitch_index'] == C.PITCH_INDEX[i0][1] 605*49fe348cSAndroid Build Coastguard Worker ok = ok and data['active'] == C.LTPF_ACTIVE[i0][1] 606*49fe348cSAndroid Build Coastguard Worker 607*49fe348cSAndroid Build Coastguard Worker return ok 608*49fe348cSAndroid Build Coastguard Worker 609*49fe348cSAndroid Build Coastguard Workerdef check_synthesis_appendix_c(dt): 610*49fe348cSAndroid Build Coastguard Worker 611*49fe348cSAndroid Build Coastguard Worker sr = T.SRATE_16K 612*49fe348cSAndroid Build Coastguard Worker 613*49fe348cSAndroid Build Coastguard Worker ok = True 614*49fe348cSAndroid Build Coastguard Worker if dt != T.DT_10M: 615*49fe348cSAndroid Build Coastguard Worker return ok 616*49fe348cSAndroid Build Coastguard Worker 617*49fe348cSAndroid Build Coastguard Worker ns = T.NS[dt][sr] 618*49fe348cSAndroid Build Coastguard Worker nd = 18 * T.SRATE_KHZ[sr] 619*49fe348cSAndroid Build Coastguard Worker 620*49fe348cSAndroid Build Coastguard Worker NBYTES = [ C.LTPF_C2_NBITS // 8, C.LTPF_C3_NBITS // 8, 621*49fe348cSAndroid Build Coastguard Worker C.LTPF_C4_NBITS // 8, C.LTPF_C5_NBITS // 8 ] 622*49fe348cSAndroid Build Coastguard Worker 623*49fe348cSAndroid Build Coastguard Worker ACTIVE = [ C.LTPF_C2_ACTIVE, C.LTPF_C3_ACTIVE, 624*49fe348cSAndroid Build Coastguard Worker C.LTPF_C4_ACTIVE, C.LTPF_C5_ACTIVE ] 625*49fe348cSAndroid Build Coastguard Worker 626*49fe348cSAndroid Build Coastguard Worker PITCH_INDEX = [ C.LTPF_C2_PITCH_INDEX, C.LTPF_C3_PITCH_INDEX, 627*49fe348cSAndroid Build Coastguard Worker C.LTPF_C4_PITCH_INDEX, C.LTPF_C5_PITCH_INDEX ] 628*49fe348cSAndroid Build Coastguard Worker 629*49fe348cSAndroid Build Coastguard Worker X = [ C.LTPF_C2_X, C.LTPF_C3_X, 630*49fe348cSAndroid Build Coastguard Worker C.LTPF_C4_X, C.LTPF_C5_X ] 631*49fe348cSAndroid Build Coastguard Worker 632*49fe348cSAndroid Build Coastguard Worker PREV = [ C.LTPF_C2_PREV, C.LTPF_C3_PREV, 633*49fe348cSAndroid Build Coastguard Worker C.LTPF_C4_PREV, C.LTPF_C5_PREV ] 634*49fe348cSAndroid Build Coastguard Worker 635*49fe348cSAndroid Build Coastguard Worker TRANS = [ C.LTPF_C2_TRANS, C.LTPF_C3_TRANS, 636*49fe348cSAndroid Build Coastguard Worker C.LTPF_C4_TRANS, C.LTPF_C5_TRANS ] 637*49fe348cSAndroid Build Coastguard Worker 638*49fe348cSAndroid Build Coastguard Worker for i in range(4): 639*49fe348cSAndroid Build Coastguard Worker 640*49fe348cSAndroid Build Coastguard Worker state = initial_sstate() 641*49fe348cSAndroid Build Coastguard Worker nbytes = NBYTES[i] 642*49fe348cSAndroid Build Coastguard Worker 643*49fe348cSAndroid Build Coastguard Worker data = { 'active' : ACTIVE[i][0], 'pitch_index' : PITCH_INDEX[i][0] } 644*49fe348cSAndroid Build Coastguard Worker x = np.append(np.zeros(nd), X[i][0]) 645*49fe348cSAndroid Build Coastguard Worker 646*49fe348cSAndroid Build Coastguard Worker lc3.ltpf_synthesize(dt, sr, nbytes, state, data, x) 647*49fe348cSAndroid Build Coastguard Worker 648*49fe348cSAndroid Build Coastguard Worker data = { 'active' : ACTIVE[i][1], 'pitch_index' : PITCH_INDEX[i][1] } 649*49fe348cSAndroid Build Coastguard Worker x[ :nd-ns] = PREV[i][0][-nd+ns:] 650*49fe348cSAndroid Build Coastguard Worker x[nd-ns:nd] = PREV[i][1] 651*49fe348cSAndroid Build Coastguard Worker x[nd:nd+ns] = X[i][1] 652*49fe348cSAndroid Build Coastguard Worker 653*49fe348cSAndroid Build Coastguard Worker y = lc3.ltpf_synthesize(dt, sr, nbytes, state, data, x)[nd:] 654*49fe348cSAndroid Build Coastguard Worker 655*49fe348cSAndroid Build Coastguard Worker ok = ok and np.amax(np.abs(y - TRANS[i])) < 1e-3 656*49fe348cSAndroid Build Coastguard Worker 657*49fe348cSAndroid Build Coastguard Worker return ok 658*49fe348cSAndroid Build Coastguard Worker 659*49fe348cSAndroid Build Coastguard Workerdef check(): 660*49fe348cSAndroid Build Coastguard Worker 661*49fe348cSAndroid Build Coastguard Worker rng = np.random.default_rng(1234) 662*49fe348cSAndroid Build Coastguard Worker ok = True 663*49fe348cSAndroid Build Coastguard Worker 664*49fe348cSAndroid Build Coastguard Worker for dt in range(T.NUM_DT): 665*49fe348cSAndroid Build Coastguard Worker for sr in range(T.SRATE_8K, T.SRATE_48K + 1): 666*49fe348cSAndroid Build Coastguard Worker ok = ok and check_resampler(rng, dt, sr) 667*49fe348cSAndroid Build Coastguard Worker ok = ok and check_analysis(rng, dt, sr) 668*49fe348cSAndroid Build Coastguard Worker ok = ok and check_synthesis(rng, dt, sr) 669*49fe348cSAndroid Build Coastguard Worker 670*49fe348cSAndroid Build Coastguard Worker for dt in ( T.DT_7M5, T.DT_10M ): 671*49fe348cSAndroid Build Coastguard Worker ok = ok and check_resampler_appendix_c(dt) 672*49fe348cSAndroid Build Coastguard Worker ok = ok and check_analysis_appendix_c(dt) 673*49fe348cSAndroid Build Coastguard Worker ok = ok and check_synthesis_appendix_c(dt) 674*49fe348cSAndroid Build Coastguard Worker 675*49fe348cSAndroid Build Coastguard Worker return ok 676*49fe348cSAndroid Build Coastguard Worker 677*49fe348cSAndroid Build Coastguard Worker### ------------------------------------------------------------------------ ### 678