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 204c4eb519SMatthias Ringwaldimport lc3 214930cef6SMatthias Ringwaldimport tables as T, appendix_c as C 224930cef6SMatthias Ringwald 234930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 244930cef6SMatthias Ringwald 254930cef6SMatthias Ringwaldclass Mdct: 264930cef6SMatthias Ringwald 27*6897da5cSDirk Helbig W = [ [ T.W_2M5_8K , T.W_2M5_16K, T.W_2M5_24K, 28*6897da5cSDirk Helbig T.W_2M5_32K, T.W_2M5_48K, T.W_2M5_48K_HR, T.W_2M5_96K_HR ], 29*6897da5cSDirk Helbig 30*6897da5cSDirk Helbig [ T.W_5M_8K , T.W_5M_16K , T.W_5M_24K , 31*6897da5cSDirk Helbig T.W_5M_32K , T.W_5M_48K , T.W_5M_48K_HR , T.W_5M_96K_HR ], 32*6897da5cSDirk Helbig 33*6897da5cSDirk Helbig [ T.W_7M5_8K , T.W_7M5_16K, T.W_7M5_24K, 34*6897da5cSDirk Helbig T.W_7M5_32K, T.W_7M5_48K, None, None ], 35*6897da5cSDirk Helbig 36*6897da5cSDirk Helbig [ T.W_10M_8K , T.W_10M_16K, T.W_10M_24K, 37*6897da5cSDirk Helbig T.W_10M_32K, T.W_10M_48K, T.W_10M_48K_HR, T.W_10M_96K_HR ] ] 384930cef6SMatthias Ringwald 394930cef6SMatthias Ringwald def __init__(self, dt, sr): 404930cef6SMatthias Ringwald 414930cef6SMatthias Ringwald self.ns = T.NS[dt][sr] 424930cef6SMatthias Ringwald self.nd = T.ND[dt][sr] 434930cef6SMatthias Ringwald 444930cef6SMatthias Ringwald self.t = np.zeros(2*self.ns) 454930cef6SMatthias Ringwald self.w = Mdct.W[dt][sr] 464930cef6SMatthias Ringwald 474930cef6SMatthias Ringwald 484930cef6SMatthias Ringwaldclass MdctForward(Mdct): 494930cef6SMatthias Ringwald 504930cef6SMatthias Ringwald def __init__(self, dt, sr): 514930cef6SMatthias Ringwald 524930cef6SMatthias Ringwald super().__init__(dt, sr) 534930cef6SMatthias Ringwald 544930cef6SMatthias Ringwald def run(self, x): 554930cef6SMatthias Ringwald 564930cef6SMatthias Ringwald ns = self.ns 574930cef6SMatthias Ringwald nd = self.nd 584930cef6SMatthias Ringwald 594930cef6SMatthias Ringwald self.t[nd:nd+ns] = x 604930cef6SMatthias Ringwald t = self.t * self.w 614930cef6SMatthias Ringwald self.t[0:nd] = x[ns-nd:] 624930cef6SMatthias Ringwald 634930cef6SMatthias Ringwald n = len(t) 644930cef6SMatthias Ringwald n2 = n // 2 654930cef6SMatthias Ringwald 664930cef6SMatthias Ringwald z = t * np.exp(-2j * np.pi * np.arange(n) / (2*n)) 674930cef6SMatthias Ringwald z = scipy.fft.fft(z)[:n2] 684930cef6SMatthias Ringwald z = z * np.exp(-2j * np.pi * 694930cef6SMatthias Ringwald (n2/2 + 0.5) * (np.arange(n2) + 0.5) / (2 * n2)) 704930cef6SMatthias Ringwald return np.real(z) * np.sqrt(2/n2) 714930cef6SMatthias Ringwald 724930cef6SMatthias Ringwald 734930cef6SMatthias Ringwaldclass MdctInverse(Mdct): 744930cef6SMatthias Ringwald 754930cef6SMatthias Ringwald def __init__(self, dt, sr): 764930cef6SMatthias Ringwald 774930cef6SMatthias Ringwald super().__init__(dt, sr) 784930cef6SMatthias Ringwald 794930cef6SMatthias Ringwald def run(self, x): 804930cef6SMatthias Ringwald 814930cef6SMatthias Ringwald ns = self.ns 824930cef6SMatthias Ringwald nd = self.nd 834930cef6SMatthias Ringwald 844930cef6SMatthias Ringwald n = len(x) 854930cef6SMatthias Ringwald 864930cef6SMatthias Ringwald x = np.append(x, -x[::-1]) 874930cef6SMatthias Ringwald z = x * np.exp(2j * np.pi * (n/2 + 0.5) * np.arange(2*n) / (2*n)) 884930cef6SMatthias Ringwald z = scipy.fft.ifft(z) * n 894930cef6SMatthias Ringwald z = z * np.exp(2j * np.pi * (np.arange(2*n) + (n/2 + 0.5)) / (4*n)) 904930cef6SMatthias Ringwald t = np.real(z) * np.sqrt(2/n) 914930cef6SMatthias Ringwald 924930cef6SMatthias Ringwald t = t * self.w[::-1] 934930cef6SMatthias Ringwald 944930cef6SMatthias Ringwald y = np.empty(ns) 954930cef6SMatthias Ringwald y[:nd] = t[ns-nd:ns] + self.t[2*ns-nd:] 964930cef6SMatthias Ringwald y[nd:] = t[ns:2*ns-nd] 974930cef6SMatthias Ringwald self.t = t 984930cef6SMatthias Ringwald 994930cef6SMatthias Ringwald return y 1004930cef6SMatthias Ringwald 1014930cef6SMatthias Ringwald### ------------------------------------------------------------------------ ### 1024930cef6SMatthias Ringwald 1034930cef6SMatthias Ringwalddef check_forward_unit(rng, dt, sr): 1044930cef6SMatthias Ringwald 1054930cef6SMatthias Ringwald ns = T.NS[dt][sr] 1064930cef6SMatthias Ringwald nd = T.ND[dt][sr] 1074930cef6SMatthias Ringwald ok = True 1084930cef6SMatthias Ringwald 1094930cef6SMatthias Ringwald x = (2 * rng.random(ns)) - 1 1104930cef6SMatthias Ringwald 1114930cef6SMatthias Ringwald y = [ None ] * 2 1124930cef6SMatthias Ringwald y_c = [ None ] * 2 1134930cef6SMatthias Ringwald 1144930cef6SMatthias Ringwald mdct = MdctForward(dt, sr) 1154930cef6SMatthias Ringwald y[0] = mdct.run(x) 1164930cef6SMatthias Ringwald y[1] = mdct.run(x) 1174930cef6SMatthias Ringwald 1184930cef6SMatthias Ringwald (y_c[0], d_c) = lc3.mdct_forward(dt, sr, x, np.zeros(nd)) 1194930cef6SMatthias Ringwald y_c[1] = lc3.mdct_forward(dt, sr, x, d_c)[0] 1204930cef6SMatthias Ringwald 1214930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y[0] - y_c[0])) < 1e-5 1224930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y[1] - y_c[1])) < 1e-5 1234930cef6SMatthias Ringwald 1244930cef6SMatthias Ringwald return ok 1254930cef6SMatthias Ringwald 1264930cef6SMatthias Ringwald 1274930cef6SMatthias Ringwalddef check_forward_appendix_c(dt): 1284930cef6SMatthias Ringwald 129*6897da5cSDirk Helbig i0 = dt - T.DT_7M5 1304930cef6SMatthias Ringwald sr = T.SRATE_16K 131*6897da5cSDirk Helbig 1324930cef6SMatthias Ringwald ok = True 1334930cef6SMatthias Ringwald 134*6897da5cSDirk Helbig ns = T.NS[dt][sr] 135*6897da5cSDirk Helbig nd = T.ND[dt][sr] 1364930cef6SMatthias Ringwald 137*6897da5cSDirk Helbig (y, d) = lc3.mdct_forward(dt, sr, C.X_PCM[i0][0], np.zeros(nd)) 138*6897da5cSDirk Helbig ok = ok and np.amax(np.abs(y - C.X[i0][0])) < 1e-1 139*6897da5cSDirk Helbig 140*6897da5cSDirk Helbig (y, d) = lc3.mdct_forward(dt, sr, C.X_PCM[i0][1], d) 141*6897da5cSDirk Helbig ok = ok and np.amax(np.abs(y - C.X[i0][1])) < 1e-1 1424930cef6SMatthias Ringwald 1434930cef6SMatthias Ringwald return ok 1444930cef6SMatthias Ringwald 1454930cef6SMatthias Ringwald 1464930cef6SMatthias Ringwalddef check_inverse_unit(rng, dt, sr): 1474930cef6SMatthias Ringwald 1484930cef6SMatthias Ringwald ns = T.NS[dt][sr] 149*6897da5cSDirk Helbig nd = T.ND[dt][sr] 1504930cef6SMatthias Ringwald ok = True 1514930cef6SMatthias Ringwald 1524930cef6SMatthias Ringwald x = (2 * rng.random(ns)) - 1 1534930cef6SMatthias Ringwald 1544930cef6SMatthias Ringwald y = [ None ] * 2 1554930cef6SMatthias Ringwald y_c = [ None ] * 2 1564930cef6SMatthias Ringwald 1574930cef6SMatthias Ringwald mdct = MdctInverse(dt, sr) 1584930cef6SMatthias Ringwald y[0] = mdct.run(x) 1594930cef6SMatthias Ringwald y[1] = mdct.run(x) 1604930cef6SMatthias Ringwald 1614930cef6SMatthias Ringwald (y_c[0], d_c) = lc3.mdct_inverse(dt, sr, x, np.zeros(nd)) 1624930cef6SMatthias Ringwald y_c[1] = lc3.mdct_inverse(dt, sr, x, d_c)[0] 1634930cef6SMatthias Ringwald 1644930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y[0] - y_c[0])) < 1e-5 1654930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(y[1] - y_c[1])) < 1e-5 1664930cef6SMatthias Ringwald 1674930cef6SMatthias Ringwald return ok 1684930cef6SMatthias Ringwald 1694930cef6SMatthias Ringwald 1704930cef6SMatthias Ringwalddef check_inverse_appendix_c(dt): 1714930cef6SMatthias Ringwald 172*6897da5cSDirk Helbig i0 = dt - T.DT_7M5 1734930cef6SMatthias Ringwald sr = T.SRATE_16K 174*6897da5cSDirk Helbig 1754930cef6SMatthias Ringwald ok = True 1764930cef6SMatthias Ringwald 177*6897da5cSDirk Helbig ns = T.NS[dt][sr] 178*6897da5cSDirk Helbig nd = T.ND[dt][sr] 179*6897da5cSDirk Helbig 180*6897da5cSDirk Helbig (y, d0) = lc3.mdct_inverse(dt, sr, C.X_HAT_SNS[i0][0], np.zeros(nd)) 181*6897da5cSDirk Helbig yr = C.T_HAT_MDCT[i0][0][ns-nd:2*ns-nd] 182*6897da5cSDirk Helbig dr = C.T_HAT_MDCT[i0][0][2*ns-nd:] 1834930cef6SMatthias Ringwald 1844930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(yr - y )) < 1e-1 1854930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(dr - d0)) < 1e-1 1864930cef6SMatthias Ringwald 187*6897da5cSDirk Helbig (y, d1) = lc3.mdct_inverse(dt, sr, C.X_HAT_SNS[i0][1], d0) 188*6897da5cSDirk Helbig yr[ :nd] = C.T_HAT_MDCT[i0][1][ns-nd:ns] + d0 189*6897da5cSDirk Helbig yr[nd:ns] = C.T_HAT_MDCT[i0][1][ns:2*ns-nd] 190*6897da5cSDirk Helbig dr = C.T_HAT_MDCT[i0][1][2*ns-nd:] 1914930cef6SMatthias Ringwald 1924930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(yr - y )) < 1e-1 1934930cef6SMatthias Ringwald ok = ok and np.amax(np.abs(dr - d1)) < 1e-1 1944930cef6SMatthias Ringwald 1954930cef6SMatthias Ringwald return ok 1964930cef6SMatthias Ringwald 1974930cef6SMatthias Ringwald 1984930cef6SMatthias Ringwalddef check(): 1994930cef6SMatthias Ringwald 2004930cef6SMatthias Ringwald rng = np.random.default_rng(1234) 2014930cef6SMatthias Ringwald 2024930cef6SMatthias Ringwald ok = True 2034930cef6SMatthias Ringwald 2044930cef6SMatthias Ringwald for dt in range(T.NUM_DT): 205*6897da5cSDirk Helbig for sr in range(T.SRATE_8K, T.SRATE_48K + 1): 2064930cef6SMatthias Ringwald ok = ok and check_forward_unit(rng, dt, sr) 2074930cef6SMatthias Ringwald ok = ok and check_inverse_unit(rng, dt, sr) 2084930cef6SMatthias Ringwald 209*6897da5cSDirk Helbig for dt in ( T.DT_2M5, T.DT_5M, T.DT_10M ): 210*6897da5cSDirk Helbig for sr in ( T.SRATE_48K_HR, T.SRATE_96K_HR ): 211*6897da5cSDirk Helbig ok = ok and check_forward_unit(rng, dt, sr) 212*6897da5cSDirk Helbig ok = ok and check_inverse_unit(rng, dt, sr) 213*6897da5cSDirk Helbig 214*6897da5cSDirk Helbig for dt in ( T.DT_7M5, T.DT_10M ): 2154930cef6SMatthias Ringwald ok = ok and check_forward_appendix_c(dt) 2164930cef6SMatthias Ringwald ok = ok and check_inverse_appendix_c(dt) 2174930cef6SMatthias Ringwald 2184930cef6SMatthias Ringwald return ok 219