1""" 2Tensorflow/Keras helper functions to do the following: 3 1. \mu law <-> Linear domain conversion 4 2. Differentiable prediction from the input signal and LP coefficients 5 3. Differentiable transformations Reflection Coefficients (RCs) <-> LP Coefficients 6""" 7from tensorflow.keras.layers import Lambda, Multiply, Layer, Concatenate 8from tensorflow.keras import backend as K 9import tensorflow as tf 10 11# \mu law <-> Linear conversion functions 12scale = 255.0/32768.0 13scale_1 = 32768.0/255.0 14def tf_l2u(x): 15 s = K.sign(x) 16 x = K.abs(x) 17 u = (s*(128*K.log(1+scale*x)/K.log(256.0))) 18 u = K.clip(128 + u, 0, 255) 19 return u 20 21def tf_u2l(u): 22 u = tf.cast(u,"float32") 23 u = u - 128.0 24 s = K.sign(u) 25 u = K.abs(u) 26 return s*scale_1*(K.exp(u/128.*K.log(256.0))-1) 27 28# Differentiable Prediction Layer 29# Computes the LP prediction from the input lag signal and the LP coefficients 30# The inputs xt and lpc conform with the shapes in lpcnet.py (the '2400' is coded keeping this in mind) 31class diff_pred(Layer): 32 def call(self, inputs, lpcoeffs_N = 16, frame_size = 160): 33 xt = inputs[0] 34 lpc = inputs[1] 35 36 rept = Lambda(lambda x: K.repeat_elements(x , frame_size, 1)) 37 zpX = Lambda(lambda x: K.concatenate([0*x[:,0:lpcoeffs_N,:], x],axis = 1)) 38 cX = Lambda(lambda x: K.concatenate([x[:,(lpcoeffs_N - i):(lpcoeffs_N - i + 2400),:] for i in range(lpcoeffs_N)],axis = 2)) 39 40 pred = -Multiply()([rept(lpc),cX(zpX(xt))]) 41 42 return K.sum(pred,axis = 2,keepdims = True) 43 44# Differentiable Transformations (RC <-> LPC) computed using the Levinson Durbin Recursion 45class diff_rc2lpc(Layer): 46 def call(self, inputs, lpcoeffs_N = 16): 47 def pred_lpc_recursive(input): 48 temp = (input[0] + K.repeat_elements(input[1],input[0].shape[2],2)*K.reverse(input[0],axes = 2)) 49 temp = Concatenate(axis = 2)([temp,input[1]]) 50 return temp 51 Llpc = Lambda(pred_lpc_recursive) 52 inputs = inputs[:,:,:lpcoeffs_N] 53 lpc_init = inputs 54 for i in range(1,lpcoeffs_N): 55 lpc_init = Llpc([lpc_init[:,:,:i],K.expand_dims(inputs[:,:,i],axis = -1)]) 56 return lpc_init 57 58class diff_lpc2rc(Layer): 59 def call(self, inputs, lpcoeffs_N = 16): 60 def pred_rc_recursive(input): 61 ki = K.repeat_elements(K.expand_dims(input[1][:,:,0],axis = -1),input[0].shape[2],2) 62 temp = (input[0] - ki*K.reverse(input[0],axes = 2))/(1 - ki*ki) 63 temp = Concatenate(axis = 2)([temp,input[1]]) 64 return temp 65 Lrc = Lambda(pred_rc_recursive) 66 rc_init = inputs 67 for i in range(1,lpcoeffs_N): 68 j = (lpcoeffs_N - i + 1) 69 rc_init = Lrc([rc_init[:,:,:(j - 1)],rc_init[:,:,(j - 1):]]) 70 return rc_init 71