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 RingwaldBW_START = [ 24*4930cef6SMatthias Ringwald [ [], [ 51 ], [ 45, 58 ], [ 42, 53, 60 ], [ 40, 51, 57, 61 ] ], 25*4930cef6SMatthias Ringwald [ [], [ 53 ], [ 47, 59 ], [ 44, 54, 60 ], [ 41, 51, 57, 61 ] ] 26*4930cef6SMatthias Ringwald] 27*4930cef6SMatthias Ringwald 28*4930cef6SMatthias RingwaldBW_STOP = [ 29*4930cef6SMatthias Ringwald [ [], [ 63 ], [ 55, 63 ], [ 51, 58, 63 ], [ 48, 55, 60, 63 ] ], 30*4930cef6SMatthias Ringwald [ [], [ 63 ], [ 56, 63 ], [ 52, 59, 63 ], [ 49, 55, 60, 63 ] ] 31*4930cef6SMatthias Ringwald] 32*4930cef6SMatthias Ringwald 33*4930cef6SMatthias RingwaldTQ = [ 20, 10, 10, 10 ] 34*4930cef6SMatthias Ringwald 35*4930cef6SMatthias RingwaldTC = [ 15, 23, 20, 20 ] 36*4930cef6SMatthias RingwaldL = [ [ 4, 4, 3, 2 ], [ 4, 4, 3, 1 ] ] 37*4930cef6SMatthias Ringwald 38*4930cef6SMatthias Ringwald 39*4930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 40*4930cef6SMatthias Ringwald 41*4930cef6SMatthias Ringwaldclass BandwidthDetector: 42*4930cef6SMatthias Ringwald 43*4930cef6SMatthias Ringwald def __init__(self, dt, sr): 44*4930cef6SMatthias Ringwald 45*4930cef6SMatthias Ringwald self.dt = dt 46*4930cef6SMatthias Ringwald self.sr = sr 47*4930cef6SMatthias Ringwald 48*4930cef6SMatthias Ringwald def run(self, e): 49*4930cef6SMatthias Ringwald 50*4930cef6SMatthias Ringwald dt = self.dt 51*4930cef6SMatthias Ringwald sr = self.sr 52*4930cef6SMatthias Ringwald 53*4930cef6SMatthias Ringwald ### Stage 1, determine bw0 candidate 54*4930cef6SMatthias Ringwald 55*4930cef6SMatthias Ringwald bw0 = 0 56*4930cef6SMatthias Ringwald 57*4930cef6SMatthias Ringwald for bw in range(sr): 58*4930cef6SMatthias Ringwald i0 = BW_START[dt][sr][bw] 59*4930cef6SMatthias Ringwald i1 = BW_STOP[dt][sr][bw] 60*4930cef6SMatthias Ringwald if np.mean(e[i0:i1+1]) >= TQ[bw]: 61*4930cef6SMatthias Ringwald bw0 = bw + 1 62*4930cef6SMatthias Ringwald 63*4930cef6SMatthias Ringwald ### Stage 2, Cut-off random coefficients at each steps 64*4930cef6SMatthias Ringwald 65*4930cef6SMatthias Ringwald bw = bw0 66*4930cef6SMatthias Ringwald 67*4930cef6SMatthias Ringwald if bw0 < sr: 68*4930cef6SMatthias Ringwald l = L[dt][bw0] 69*4930cef6SMatthias Ringwald i0 = BW_START[dt][sr][bw0] - l 70*4930cef6SMatthias Ringwald i1 = BW_START[dt][sr][bw0] 71*4930cef6SMatthias Ringwald 72*4930cef6SMatthias Ringwald c = 10 * np.log10(1e-31 + e[i0-l+1:i1-l+2] / e[i0+1:i1+2]) 73*4930cef6SMatthias Ringwald if np.amax(c) <= TC[bw0]: 74*4930cef6SMatthias Ringwald bw = sr 75*4930cef6SMatthias Ringwald 76*4930cef6SMatthias Ringwald self.bw = bw 77*4930cef6SMatthias Ringwald return self.bw 78*4930cef6SMatthias Ringwald 79*4930cef6SMatthias Ringwald def get_nbits(self): 80*4930cef6SMatthias Ringwald 81*4930cef6SMatthias Ringwald return 0 if self.sr == 0 else \ 82*4930cef6SMatthias Ringwald 1 + np.log2(self.sr).astype(int) 83*4930cef6SMatthias Ringwald 84*4930cef6SMatthias Ringwald def store_bw(self, b): 85*4930cef6SMatthias Ringwald 86*4930cef6SMatthias Ringwald b.write_uint(self.bw, self.get_nbits()) 87*4930cef6SMatthias Ringwald 88*4930cef6SMatthias Ringwald def get_bw(self, b): 89*4930cef6SMatthias Ringwald 90*4930cef6SMatthias Ringwald return b.read_uint(self.get_nbits()) 91*4930cef6SMatthias Ringwald 92*4930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 93*4930cef6SMatthias Ringwald 94*4930cef6SMatthias Ringwalddef check_unit(rng, dt, sr): 95*4930cef6SMatthias Ringwald 96*4930cef6SMatthias Ringwald ok = True 97*4930cef6SMatthias Ringwald 98*4930cef6SMatthias Ringwald bwdet = BandwidthDetector(dt, sr) 99*4930cef6SMatthias Ringwald 100*4930cef6SMatthias Ringwald for bw0 in range(sr+1): 101*4930cef6SMatthias Ringwald for drop in range(10): 102*4930cef6SMatthias Ringwald 103*4930cef6SMatthias Ringwald ### Generate random 'high' energy and 104*4930cef6SMatthias Ringwald ### scale relevant bands to select 'bw0' 105*4930cef6SMatthias Ringwald 106*4930cef6SMatthias Ringwald e = 20 + 100 * rng.random(64) 107*4930cef6SMatthias Ringwald 108*4930cef6SMatthias Ringwald for i in range(sr): 109*4930cef6SMatthias Ringwald if i+1 != bw0: 110*4930cef6SMatthias Ringwald i0 = BW_START[dt][sr][i] 111*4930cef6SMatthias Ringwald i1 = BW_STOP[dt][sr][i] 112*4930cef6SMatthias Ringwald e[i0:i1+1] /= (np.mean(e[i0:i1+1]) / TQ[i] + 1e-3) 113*4930cef6SMatthias Ringwald 114*4930cef6SMatthias Ringwald ### Stage 2 Condition, 115*4930cef6SMatthias Ringwald ### cut-off random coefficients at each steps 116*4930cef6SMatthias Ringwald 117*4930cef6SMatthias Ringwald if bw0 < sr: 118*4930cef6SMatthias Ringwald l = L[dt][bw0] 119*4930cef6SMatthias Ringwald i0 = BW_START[dt][sr][bw0] - l 120*4930cef6SMatthias Ringwald i1 = BW_START[dt][sr][bw0] 121*4930cef6SMatthias Ringwald 122*4930cef6SMatthias Ringwald e[i0-l+1:i1+2] /= np.power(10, np.arange(2*l+1) / (1 + drop)) 123*4930cef6SMatthias Ringwald 124*4930cef6SMatthias Ringwald ### Check with implementation 125*4930cef6SMatthias Ringwald 126*4930cef6SMatthias Ringwald bw_c = lc3.bwdet_run(dt, sr, e) 127*4930cef6SMatthias Ringwald 128*4930cef6SMatthias Ringwald ok = ok and bw_c == bwdet.run(e) 129*4930cef6SMatthias Ringwald 130*4930cef6SMatthias Ringwald return ok 131*4930cef6SMatthias Ringwald 132*4930cef6SMatthias Ringwalddef check_appendix_c(dt): 133*4930cef6SMatthias Ringwald 134*4930cef6SMatthias Ringwald sr = T.SRATE_16K 135*4930cef6SMatthias Ringwald ok = True 136*4930cef6SMatthias Ringwald 137*4930cef6SMatthias Ringwald E_B = C.E_B[dt] 138*4930cef6SMatthias Ringwald P_BW = C.P_BW[dt] 139*4930cef6SMatthias Ringwald 140*4930cef6SMatthias Ringwald bw = lc3.bwdet_run(dt, sr, E_B[0]) 141*4930cef6SMatthias Ringwald ok = ok and bw == P_BW[0] 142*4930cef6SMatthias Ringwald 143*4930cef6SMatthias Ringwald bw = lc3.bwdet_run(dt, sr, E_B[1]) 144*4930cef6SMatthias Ringwald ok = ok and bw == P_BW[1] 145*4930cef6SMatthias Ringwald 146*4930cef6SMatthias Ringwald return ok 147*4930cef6SMatthias Ringwald 148*4930cef6SMatthias Ringwalddef check(): 149*4930cef6SMatthias Ringwald 150*4930cef6SMatthias Ringwald rng = np.random.default_rng(1234) 151*4930cef6SMatthias Ringwald 152*4930cef6SMatthias Ringwald ok = True 153*4930cef6SMatthias Ringwald for dt in range(T.NUM_DT): 154*4930cef6SMatthias Ringwald for sr in range(T.NUM_SRATE): 155*4930cef6SMatthias Ringwald ok = ok and check_unit(rng, dt, sr) 156*4930cef6SMatthias Ringwald 157*4930cef6SMatthias Ringwald for dt in range(T.NUM_DT): 158*4930cef6SMatthias Ringwald ok = ok and check_appendix_c(dt) 159*4930cef6SMatthias Ringwald 160*4930cef6SMatthias Ringwald return ok 161*4930cef6SMatthias Ringwald 162*4930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 163