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 Ringwaldimport scipy.fft 194930cef6SMatthias Ringwald 20*4c4eb519SMatthias Ringwaldimport lc3 214930cef6SMatthias Ringwaldimport tables as T, appendix_c as C 224930cef6SMatthias Ringwald 234930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 244930cef6SMatthias Ringwald 254930cef6SMatthias Ringwaldclass Mdct: 264930cef6SMatthias Ringwald 274930cef6SMatthias Ringwald W = [ [ T.W_7M5_60, T.W_7M5_120, T.W_7M5_180, T.W_7M5_240, T.W_7M5_360 ], 284930cef6SMatthias Ringwald [ T.W_10M_80, T.W_10M_160, T.W_10M_240, T.W_10M_320, T.W_10M_480 ] ] 294930cef6SMatthias Ringwald 304930cef6SMatthias Ringwald def __init__(self, dt, sr): 314930cef6SMatthias Ringwald 324930cef6SMatthias Ringwald self.ns = T.NS[dt][sr] 334930cef6SMatthias Ringwald self.nd = T.ND[dt][sr] 344930cef6SMatthias Ringwald 354930cef6SMatthias Ringwald self.t = np.zeros(2*self.ns) 364930cef6SMatthias Ringwald self.w = Mdct.W[dt][sr] 374930cef6SMatthias Ringwald 384930cef6SMatthias Ringwald 394930cef6SMatthias Ringwaldclass MdctForward(Mdct): 404930cef6SMatthias Ringwald 414930cef6SMatthias Ringwald def __init__(self, dt, sr): 424930cef6SMatthias Ringwald 434930cef6SMatthias Ringwald super().__init__(dt, sr) 444930cef6SMatthias Ringwald 454930cef6SMatthias Ringwald def run(self, x): 464930cef6SMatthias Ringwald 474930cef6SMatthias Ringwald ns = self.ns 484930cef6SMatthias Ringwald nd = self.nd 494930cef6SMatthias Ringwald 504930cef6SMatthias Ringwald self.t[nd:nd+ns] = x 514930cef6SMatthias Ringwald t = self.t * self.w 524930cef6SMatthias Ringwald self.t[0:nd] = x[ns-nd:] 534930cef6SMatthias Ringwald 544930cef6SMatthias Ringwald n = len(t) 554930cef6SMatthias Ringwald n2 = n // 2 564930cef6SMatthias Ringwald 574930cef6SMatthias Ringwald z = t * np.exp(-2j * np.pi * np.arange(n) / (2*n)) 584930cef6SMatthias Ringwald z = scipy.fft.fft(z)[:n2] 594930cef6SMatthias Ringwald z = z * np.exp(-2j * np.pi * 604930cef6SMatthias Ringwald (n2/2 + 0.5) * (np.arange(n2) + 0.5) / (2 * n2)) 614930cef6SMatthias Ringwald return np.real(z) * np.sqrt(2/n2) 624930cef6SMatthias Ringwald 634930cef6SMatthias Ringwald 644930cef6SMatthias Ringwaldclass MdctInverse(Mdct): 654930cef6SMatthias Ringwald 664930cef6SMatthias Ringwald def __init__(self, dt, sr): 674930cef6SMatthias Ringwald 684930cef6SMatthias Ringwald super().__init__(dt, sr) 694930cef6SMatthias Ringwald 704930cef6SMatthias Ringwald def run(self, x): 714930cef6SMatthias Ringwald 724930cef6SMatthias Ringwald ns = self.ns 734930cef6SMatthias Ringwald nd = self.nd 744930cef6SMatthias Ringwald 754930cef6SMatthias Ringwald n = len(x) 764930cef6SMatthias Ringwald 774930cef6SMatthias Ringwald x = np.append(x, -x[::-1]) 784930cef6SMatthias Ringwald z = x * np.exp(2j * np.pi * (n/2 + 0.5) * np.arange(2*n) / (2*n)) 794930cef6SMatthias Ringwald z = scipy.fft.ifft(z) * n 804930cef6SMatthias Ringwald z = z * np.exp(2j * np.pi * (np.arange(2*n) + (n/2 + 0.5)) / (4*n)) 814930cef6SMatthias Ringwald t = np.real(z) * np.sqrt(2/n) 824930cef6SMatthias Ringwald 834930cef6SMatthias Ringwald t = t * self.w[::-1] 844930cef6SMatthias Ringwald 854930cef6SMatthias Ringwald y = np.empty(ns) 864930cef6SMatthias Ringwald y[:nd] = t[ns-nd:ns] + self.t[2*ns-nd:] 874930cef6SMatthias Ringwald y[nd:] = t[ns:2*ns-nd] 884930cef6SMatthias Ringwald self.t = t 894930cef6SMatthias Ringwald 904930cef6SMatthias Ringwald return y 914930cef6SMatthias Ringwald 924930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 934930cef6SMatthias Ringwald 944930cef6SMatthias Ringwalddef check_forward_unit(rng, dt, sr): 954930cef6SMatthias Ringwald 964930cef6SMatthias Ringwald ns = T.NS[dt][sr] 974930cef6SMatthias Ringwald nd = T.ND[dt][sr] 984930cef6SMatthias Ringwald ok = True 994930cef6SMatthias Ringwald 1004930cef6SMatthias Ringwald x = (2 * rng.random(ns)) - 1 1014930cef6SMatthias Ringwald 1024930cef6SMatthias Ringwald y = [ None ] * 2 1034930cef6SMatthias Ringwald y_c = [ None ] * 2 1044930cef6SMatthias Ringwald 1054930cef6SMatthias Ringwald mdct = MdctForward(dt, sr) 1064930cef6SMatthias Ringwald y[0] = mdct.run(x) 1074930cef6SMatthias Ringwald y[1] = mdct.run(x) 1084930cef6SMatthias Ringwald 1094930cef6SMatthias Ringwald (y_c[0], d_c) = lc3.mdct_forward(dt, sr, x, np.zeros(nd)) 1104930cef6SMatthias Ringwald y_c[1] = lc3.mdct_forward(dt, sr, x, d_c)[0] 1114930cef6SMatthias Ringwald 1124930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y[0] - y_c[0])) < 1e-5 1134930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y[1] - y_c[1])) < 1e-5 1144930cef6SMatthias Ringwald 1154930cef6SMatthias Ringwald return ok 1164930cef6SMatthias Ringwald 1174930cef6SMatthias Ringwald 1184930cef6SMatthias Ringwalddef check_forward_appendix_c(dt): 1194930cef6SMatthias Ringwald 1204930cef6SMatthias Ringwald sr = T.SRATE_16K 1214930cef6SMatthias Ringwald ns = T.NS[dt][sr] 1224930cef6SMatthias Ringwald nd = T.ND[dt][sr] 1234930cef6SMatthias Ringwald ok = True 1244930cef6SMatthias Ringwald 1254930cef6SMatthias Ringwald (y, d) = lc3.mdct_forward(dt, sr, C.X_PCM[dt][0], np.zeros(nd)) 1264930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y - C.X[dt][0])) < 1e-1 1274930cef6SMatthias Ringwald 1284930cef6SMatthias Ringwald (y, d) = lc3.mdct_forward(dt, sr, C.X_PCM[dt][1], d) 1294930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y - C.X[dt][1])) < 1e-1 1304930cef6SMatthias Ringwald 1314930cef6SMatthias Ringwald return ok 1324930cef6SMatthias Ringwald 1334930cef6SMatthias Ringwald 1344930cef6SMatthias Ringwalddef check_inverse_unit(rng, dt, sr): 1354930cef6SMatthias Ringwald 1364930cef6SMatthias Ringwald ns = T.NS[dt][sr] 1374930cef6SMatthias Ringwald nd = [ (23 * ns) // 30, (5 * ns) // 8 ][dt] 1384930cef6SMatthias Ringwald ok = True 1394930cef6SMatthias Ringwald 1404930cef6SMatthias Ringwald x = (2 * rng.random(ns)) - 1 1414930cef6SMatthias Ringwald 1424930cef6SMatthias Ringwald y = [ None ] * 2 1434930cef6SMatthias Ringwald y_c = [ None ] * 2 1444930cef6SMatthias Ringwald 1454930cef6SMatthias Ringwald mdct = MdctInverse(dt, sr) 1464930cef6SMatthias Ringwald y[0] = mdct.run(x) 1474930cef6SMatthias Ringwald y[1] = mdct.run(x) 1484930cef6SMatthias Ringwald 1494930cef6SMatthias Ringwald (y_c[0], d_c) = lc3.mdct_inverse(dt, sr, x, np.zeros(nd)) 1504930cef6SMatthias Ringwald y_c[1] = lc3.mdct_inverse(dt, sr, x, d_c)[0] 1514930cef6SMatthias Ringwald 1524930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y[0] - y_c[0])) < 1e-5 1534930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y[1] - y_c[1])) < 1e-5 1544930cef6SMatthias Ringwald 1554930cef6SMatthias Ringwald return ok 1564930cef6SMatthias Ringwald 1574930cef6SMatthias Ringwald 1584930cef6SMatthias Ringwalddef check_inverse_appendix_c(dt): 1594930cef6SMatthias Ringwald 1604930cef6SMatthias Ringwald sr = T.SRATE_16K 1614930cef6SMatthias Ringwald ns = T.NS[dt][sr] 1624930cef6SMatthias Ringwald nd = [ (23 * ns) // 30, (5 * ns) // 8 ][dt] 1634930cef6SMatthias Ringwald ok = True 1644930cef6SMatthias Ringwald 1654930cef6SMatthias Ringwald (y, d0) = lc3.mdct_inverse(dt, sr, C.X_HAT_SNS[dt][0], np.zeros(nd)) 1664930cef6SMatthias Ringwald yr = C.T_HAT_MDCT[dt][0][ns-nd:2*ns-nd] 1674930cef6SMatthias Ringwald dr = C.T_HAT_MDCT[dt][0][2*ns-nd:] 1684930cef6SMatthias Ringwald 1694930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(yr - y )) < 1e-1 1704930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(dr - d0)) < 1e-1 1714930cef6SMatthias Ringwald 1724930cef6SMatthias Ringwald (y, d1) = lc3.mdct_inverse(dt, sr, C.X_HAT_SNS[dt][1], d0) 1734930cef6SMatthias Ringwald yr[ :nd] = C.T_HAT_MDCT[dt][1][ns-nd:ns] + d0 1744930cef6SMatthias Ringwald yr[nd:ns] = C.T_HAT_MDCT[dt][1][ns:2*ns-nd] 1754930cef6SMatthias Ringwald dr = C.T_HAT_MDCT[dt][1][2*ns-nd:] 1764930cef6SMatthias Ringwald 1774930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(yr - y )) < 1e-1 1784930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(dr - d1)) < 1e-1 1794930cef6SMatthias Ringwald 1804930cef6SMatthias Ringwald return ok 1814930cef6SMatthias Ringwald 1824930cef6SMatthias Ringwald 1834930cef6SMatthias Ringwalddef check(): 1844930cef6SMatthias Ringwald 1854930cef6SMatthias Ringwald rng = np.random.default_rng(1234) 1864930cef6SMatthias Ringwald 1874930cef6SMatthias Ringwald ok = True 1884930cef6SMatthias Ringwald 1894930cef6SMatthias Ringwald for dt in range(T.NUM_DT): 1904930cef6SMatthias Ringwald for sr in range(T.NUM_SRATE): 1914930cef6SMatthias Ringwald ok = ok and check_forward_unit(rng, dt, sr) 1924930cef6SMatthias Ringwald ok = ok and check_inverse_unit(rng, dt, sr) 1934930cef6SMatthias Ringwald 1944930cef6SMatthias Ringwald for dt in range(T.NUM_DT): 1954930cef6SMatthias Ringwald ok = ok and check_forward_appendix_c(dt) 1964930cef6SMatthias Ringwald ok = ok and check_inverse_appendix_c(dt) 1974930cef6SMatthias Ringwald 1984930cef6SMatthias Ringwald return ok 199