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