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.signal as signal 194930cef6SMatthias Ringwaldimport scipy.io.wavfile as wavfile 204930cef6SMatthias Ringwaldimport struct 214930cef6SMatthias Ringwaldimport argparse 224930cef6SMatthias Ringwald 234c4eb519SMatthias Ringwaldimport lc3 244930cef6SMatthias Ringwaldimport tables as T, appendix_c as C 254930cef6SMatthias Ringwald 264930cef6SMatthias Ringwaldimport mdct, energy, bwdet, sns, tns, spec, ltpf 274930cef6SMatthias Ringwaldimport bitstream 284930cef6SMatthias Ringwald 294930cef6SMatthias Ringwaldclass Decoder: 304930cef6SMatthias Ringwald 314930cef6SMatthias Ringwald def __init__(self, dt_ms, sr_hz): 324930cef6SMatthias Ringwald 334930cef6SMatthias Ringwald dt = { 7.5: T.DT_7M5, 10: T.DT_10M }[dt_ms] 344930cef6SMatthias Ringwald 354930cef6SMatthias Ringwald sr = { 8000: T.SRATE_8K , 16000: T.SRATE_16K, 24000: T.SRATE_24K, 364930cef6SMatthias Ringwald 32000: T.SRATE_32K, 48000: T.SRATE_48K }[sr_hz] 374930cef6SMatthias Ringwald 384930cef6SMatthias Ringwald self.sr = sr 394930cef6SMatthias Ringwald self.ne = T.NE[dt][sr] 404930cef6SMatthias Ringwald self.ns = T.NS[dt][sr] 414930cef6SMatthias Ringwald 424930cef6SMatthias Ringwald self.mdct = mdct.MdctInverse(dt, sr) 434930cef6SMatthias Ringwald 444930cef6SMatthias Ringwald self.bwdet = bwdet.BandwidthDetector(dt, sr) 454930cef6SMatthias Ringwald self.spec = spec.SpectrumSynthesis(dt, sr) 464930cef6SMatthias Ringwald self.tns = tns.TnsSynthesis(dt) 474930cef6SMatthias Ringwald self.sns = sns.SnsSynthesis(dt, sr) 484930cef6SMatthias Ringwald self.ltpf = ltpf.LtpfSynthesis(dt, sr) 494930cef6SMatthias Ringwald 504930cef6SMatthias Ringwald def decode(self, data): 514930cef6SMatthias Ringwald 524930cef6SMatthias Ringwald b = bitstream.BitstreamReader(data) 534930cef6SMatthias Ringwald 544c4eb519SMatthias Ringwald bw = self.bwdet.get(b) 554930cef6SMatthias Ringwald if bw > self.sr: 564930cef6SMatthias Ringwald raise ValueError('Invalid bandwidth indication') 574930cef6SMatthias Ringwald 584930cef6SMatthias Ringwald self.spec.load(b) 594930cef6SMatthias Ringwald 604930cef6SMatthias Ringwald self.tns.load(b, bw, len(data)) 614930cef6SMatthias Ringwald 624930cef6SMatthias Ringwald pitch = b.read_bit() 634930cef6SMatthias Ringwald 644930cef6SMatthias Ringwald self.sns.load(b) 654930cef6SMatthias Ringwald 664930cef6SMatthias Ringwald if pitch: 674930cef6SMatthias Ringwald self.ltpf.load(b) 684930cef6SMatthias Ringwald else: 694930cef6SMatthias Ringwald self.ltpf.disable() 704930cef6SMatthias Ringwald 714930cef6SMatthias Ringwald x = self.spec.decode(b, bw, len(data)) 724930cef6SMatthias Ringwald 734930cef6SMatthias Ringwald return (x, bw, pitch) 744930cef6SMatthias Ringwald 754930cef6SMatthias Ringwald def synthesize(self, x, bw, pitch, nbytes): 764930cef6SMatthias Ringwald 774930cef6SMatthias Ringwald x = self.tns.run(x, bw) 784930cef6SMatthias Ringwald 794930cef6SMatthias Ringwald x = self.sns.run(x) 804930cef6SMatthias Ringwald 814930cef6SMatthias Ringwald x = np.append(x, np.zeros(self.ns - self.ne)) 824930cef6SMatthias Ringwald x = self.mdct.run(x) 834930cef6SMatthias Ringwald 84*6897da5cSDirk Helbig x = self.ltpf.run(x) 854930cef6SMatthias Ringwald 864930cef6SMatthias Ringwald return x 874930cef6SMatthias Ringwald 884930cef6SMatthias Ringwald def run(self, data): 894930cef6SMatthias Ringwald 904930cef6SMatthias Ringwald (x, bw, pitch) = self.decode(data) 914930cef6SMatthias Ringwald 924930cef6SMatthias Ringwald x = self.synthesize(x, bw, pitch, len(data)) 934930cef6SMatthias Ringwald 944930cef6SMatthias Ringwald return x 954930cef6SMatthias Ringwald 964930cef6SMatthias Ringwalddef check_appendix_c(dt): 974930cef6SMatthias Ringwald 98*6897da5cSDirk Helbig i0 = dt - T.DT_7M5 994930cef6SMatthias Ringwald 1004930cef6SMatthias Ringwald dec_c = lc3.setup_decoder(int(T.DT_MS[dt] * 1000), 16000) 101*6897da5cSDirk Helbig ok = True 1024930cef6SMatthias Ringwald 103*6897da5cSDirk Helbig for i in range(len(C.BYTES_AC[i0])): 1044930cef6SMatthias Ringwald 105*6897da5cSDirk Helbig pcm = lc3.decode(dec_c, bytes(C.BYTES_AC[i0][i])) 106*6897da5cSDirk Helbig ok = ok and np.max(np.abs(pcm - C.X_HAT_CLIP[i0][i])) < 1 1074930cef6SMatthias Ringwald 1084930cef6SMatthias Ringwald return ok 1094930cef6SMatthias Ringwald 1104930cef6SMatthias Ringwalddef check(): 1114930cef6SMatthias Ringwald 1124930cef6SMatthias Ringwald ok = True 1134930cef6SMatthias Ringwald 114*6897da5cSDirk Helbig for dt in range(T.DT_7M5, T.NUM_DT): 1154930cef6SMatthias Ringwald ok = ok and check_appendix_c(dt) 1164930cef6SMatthias Ringwald 1174930cef6SMatthias Ringwald return ok 118