14930cef6SMatthias Ringwald# 24930cef6SMatthias Ringwald# Copyright 2022 Google LLC 34930cef6SMatthias Ringwald# 44930cef6SMatthias Ringwald# Licensed under the Apache License, Version 2.0 (the "License"); 54930cef6SMatthias Ringwald# you may not use this file except in compliance with the License. 64930cef6SMatthias Ringwald# You may obtain a copy of the License at 74930cef6SMatthias Ringwald# 84930cef6SMatthias Ringwald# http://www.apache.org/licenses/LICENSE-2.0 94930cef6SMatthias Ringwald# 104930cef6SMatthias Ringwald# Unless required by applicable law or agreed to in writing, software 114930cef6SMatthias Ringwald# distributed under the License is distributed on an "AS IS" BASIS, 124930cef6SMatthias Ringwald# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134930cef6SMatthias Ringwald# See the License for the specific language governing permissions and 144930cef6SMatthias Ringwald# limitations under the License. 154930cef6SMatthias Ringwald# 164930cef6SMatthias Ringwald 174930cef6SMatthias Ringwaldimport numpy as np 184930cef6SMatthias Ringwald 194c4eb519SMatthias Ringwaldimport lc3 204930cef6SMatthias Ringwaldimport tables as T, appendix_c as C 214930cef6SMatthias Ringwald 224930cef6SMatthias Ringwald 234930cef6SMatthias RingwaldBW_START = [ 24*6897da5cSDirk Helbig [ [], [ 24 ], [ 24, 35 ], [ 24, 33, 39 ], [ 22, 31, 37, 41 ] ], 25*6897da5cSDirk Helbig [ [], [ 39 ], [ 35, 47 ], [ 34, 44, 50 ], [ 32, 42, 48, 52 ] ], 264930cef6SMatthias Ringwald [ [], [ 51 ], [ 45, 58 ], [ 42, 53, 60 ], [ 40, 51, 57, 61 ] ], 274930cef6SMatthias Ringwald [ [], [ 53 ], [ 47, 59 ], [ 44, 54, 60 ], [ 41, 51, 57, 61 ] ] 284930cef6SMatthias Ringwald] 294930cef6SMatthias Ringwald 304930cef6SMatthias RingwaldBW_STOP = [ 31*6897da5cSDirk Helbig [ [], [ 34 ], [ 32, 39 ], [ 31, 38, 42 ], [ 29, 35, 40, 43 ] ], 32*6897da5cSDirk Helbig [ [], [ 49 ], [ 44, 51 ], [ 42, 49, 53 ], [ 40, 46, 51, 54 ] ], 334930cef6SMatthias Ringwald [ [], [ 63 ], [ 55, 63 ], [ 51, 58, 63 ], [ 48, 55, 60, 63 ] ], 344930cef6SMatthias Ringwald [ [], [ 63 ], [ 56, 63 ], [ 52, 59, 63 ], [ 49, 55, 60, 63 ] ] 354930cef6SMatthias Ringwald] 364930cef6SMatthias Ringwald 374930cef6SMatthias RingwaldTQ = [ 20, 10, 10, 10 ] 384930cef6SMatthias Ringwald 394930cef6SMatthias RingwaldTC = [ 15, 23, 20, 20 ] 40*6897da5cSDirk HelbigL = [ [ 4, 4, 3, 1 ], [ 4, 4, 3, 1 ], 41*6897da5cSDirk Helbig [ 4, 4, 3, 2 ], [ 4, 4, 3, 1 ] ] 424930cef6SMatthias Ringwald 434930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 444930cef6SMatthias Ringwald 454930cef6SMatthias Ringwaldclass BandwidthDetector: 464930cef6SMatthias Ringwald 474930cef6SMatthias Ringwald def __init__(self, dt, sr): 484930cef6SMatthias Ringwald 494930cef6SMatthias Ringwald self.dt = dt 504930cef6SMatthias Ringwald self.sr = sr 514930cef6SMatthias Ringwald 524930cef6SMatthias Ringwald def run(self, e): 534930cef6SMatthias Ringwald 544930cef6SMatthias Ringwald dt = self.dt 554930cef6SMatthias Ringwald sr = self.sr 564930cef6SMatthias Ringwald 574930cef6SMatthias Ringwald ### Stage 1, determine bw0 candidate 584930cef6SMatthias Ringwald 594930cef6SMatthias Ringwald bw0 = 0 604930cef6SMatthias Ringwald 614930cef6SMatthias Ringwald for bw in range(sr): 624930cef6SMatthias Ringwald i0 = BW_START[dt][sr][bw] 634930cef6SMatthias Ringwald i1 = BW_STOP[dt][sr][bw] 644930cef6SMatthias Ringwald if np.mean(e[i0:i1+1]) >= TQ[bw]: 654930cef6SMatthias Ringwald bw0 = bw + 1 664930cef6SMatthias Ringwald 674930cef6SMatthias Ringwald ### Stage 2, Cut-off random coefficients at each steps 684930cef6SMatthias Ringwald 694930cef6SMatthias Ringwald bw = bw0 704930cef6SMatthias Ringwald 714930cef6SMatthias Ringwald if bw0 < sr: 724930cef6SMatthias Ringwald l = L[dt][bw0] 734930cef6SMatthias Ringwald i0 = BW_START[dt][sr][bw0] - l 744930cef6SMatthias Ringwald i1 = BW_START[dt][sr][bw0] 754930cef6SMatthias Ringwald 764930cef6SMatthias Ringwald c = 10 * np.log10(1e-31 + e[i0-l+1:i1-l+2] / e[i0+1:i1+2]) 774930cef6SMatthias Ringwald if np.amax(c) <= TC[bw0]: 784930cef6SMatthias Ringwald bw = sr 794930cef6SMatthias Ringwald 804930cef6SMatthias Ringwald self.bw = bw 814930cef6SMatthias Ringwald return self.bw 824930cef6SMatthias Ringwald 834930cef6SMatthias Ringwald def get_nbits(self): 844930cef6SMatthias Ringwald 854930cef6SMatthias Ringwald return 0 if self.sr == 0 else \ 864930cef6SMatthias Ringwald 1 + np.log2(self.sr).astype(int) 874930cef6SMatthias Ringwald 884c4eb519SMatthias Ringwald def store(self, b): 894930cef6SMatthias Ringwald 904930cef6SMatthias Ringwald b.write_uint(self.bw, self.get_nbits()) 914930cef6SMatthias Ringwald 924c4eb519SMatthias Ringwald def get(self, b): 934930cef6SMatthias Ringwald 944930cef6SMatthias Ringwald return b.read_uint(self.get_nbits()) 954930cef6SMatthias Ringwald 964930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 974930cef6SMatthias Ringwald 984930cef6SMatthias Ringwalddef check_unit(rng, dt, sr): 994930cef6SMatthias Ringwald 1004930cef6SMatthias Ringwald ok = True 1014930cef6SMatthias Ringwald 1024930cef6SMatthias Ringwald bwdet = BandwidthDetector(dt, sr) 1034930cef6SMatthias Ringwald 1044930cef6SMatthias Ringwald for bw0 in range(sr+1): 1054930cef6SMatthias Ringwald for drop in range(10): 1064930cef6SMatthias Ringwald 1074930cef6SMatthias Ringwald ### Generate random 'high' energy and 1084930cef6SMatthias Ringwald ### scale relevant bands to select 'bw0' 1094930cef6SMatthias Ringwald 1104930cef6SMatthias Ringwald e = 20 + 100 * rng.random(64) 1114930cef6SMatthias Ringwald 1124930cef6SMatthias Ringwald for i in range(sr): 1134930cef6SMatthias Ringwald if i+1 != bw0: 1144930cef6SMatthias Ringwald i0 = BW_START[dt][sr][i] 1154930cef6SMatthias Ringwald i1 = BW_STOP[dt][sr][i] 1164930cef6SMatthias Ringwald e[i0:i1+1] /= (np.mean(e[i0:i1+1]) / TQ[i] + 1e-3) 1174930cef6SMatthias Ringwald 1184930cef6SMatthias Ringwald ### Stage 2 Condition, 1194930cef6SMatthias Ringwald ### cut-off random coefficients at each steps 1204930cef6SMatthias Ringwald 1214930cef6SMatthias Ringwald if bw0 < sr: 1224930cef6SMatthias Ringwald l = L[dt][bw0] 1234930cef6SMatthias Ringwald i0 = BW_START[dt][sr][bw0] - l 1244930cef6SMatthias Ringwald i1 = BW_START[dt][sr][bw0] 1254930cef6SMatthias Ringwald 1264930cef6SMatthias Ringwald e[i0-l+1:i1+2] /= np.power(10, np.arange(2*l+1) / (1 + drop)) 1274930cef6SMatthias Ringwald 1284930cef6SMatthias Ringwald ### Check with implementation 1294930cef6SMatthias Ringwald 1304930cef6SMatthias Ringwald bw_c = lc3.bwdet_run(dt, sr, e) 1314930cef6SMatthias Ringwald 1324930cef6SMatthias Ringwald ok = ok and bw_c == bwdet.run(e) 1334930cef6SMatthias Ringwald 1344930cef6SMatthias Ringwald return ok 1354930cef6SMatthias Ringwald 1364930cef6SMatthias Ringwalddef check_appendix_c(dt): 1374930cef6SMatthias Ringwald 138*6897da5cSDirk Helbig i0 = dt - T.DT_7M5 1394930cef6SMatthias Ringwald sr = T.SRATE_16K 140*6897da5cSDirk Helbig 1414930cef6SMatthias Ringwald ok = True 1424930cef6SMatthias Ringwald 143*6897da5cSDirk Helbig E_B = C.E_B[i0] 144*6897da5cSDirk Helbig P_BW = C.P_BW[i0] 1454930cef6SMatthias Ringwald 1464930cef6SMatthias Ringwald bw = lc3.bwdet_run(dt, sr, E_B[0]) 1474930cef6SMatthias Ringwald ok = ok and bw == P_BW[0] 1484930cef6SMatthias Ringwald 1494930cef6SMatthias Ringwald bw = lc3.bwdet_run(dt, sr, E_B[1]) 1504930cef6SMatthias Ringwald ok = ok and bw == P_BW[1] 1514930cef6SMatthias Ringwald 1524930cef6SMatthias Ringwald return ok 1534930cef6SMatthias Ringwald 1544930cef6SMatthias Ringwalddef check(): 1554930cef6SMatthias Ringwald 1564930cef6SMatthias Ringwald rng = np.random.default_rng(1234) 1574930cef6SMatthias Ringwald 1584930cef6SMatthias Ringwald ok = True 1594930cef6SMatthias Ringwald for dt in range(T.NUM_DT): 160*6897da5cSDirk Helbig for sr in range(T.SRATE_8K, T.SRATE_48K + 1): 1614930cef6SMatthias Ringwald ok = ok and check_unit(rng, dt, sr) 1624930cef6SMatthias Ringwald 163*6897da5cSDirk Helbig for dt in ( T.DT_7M5, T.DT_10M ): 1644930cef6SMatthias Ringwald ok = ok and check_appendix_c(dt) 1654930cef6SMatthias Ringwald 1664930cef6SMatthias Ringwald return ok 1674930cef6SMatthias Ringwald 1684930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 169