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 attdet, ltpf 274930cef6SMatthias Ringwaldimport mdct, energy, bwdet, sns, tns, spec 284930cef6SMatthias Ringwaldimport bitstream 294930cef6SMatthias Ringwald 304930cef6SMatthias Ringwaldclass Encoder: 314930cef6SMatthias Ringwald 324930cef6SMatthias Ringwald def __init__(self, dt_ms, sr_hz): 334930cef6SMatthias Ringwald 344930cef6SMatthias Ringwald dt = { 7.5: T.DT_7M5, 10: T.DT_10M }[dt_ms] 354930cef6SMatthias Ringwald 364930cef6SMatthias Ringwald sr = { 8000: T.SRATE_8K , 16000: T.SRATE_16K, 24000: T.SRATE_24K, 374930cef6SMatthias Ringwald 32000: T.SRATE_32K, 48000: T.SRATE_48K }[sr_hz] 384930cef6SMatthias Ringwald 394930cef6SMatthias Ringwald self.ne = T.NE[dt][sr] 404930cef6SMatthias Ringwald 414930cef6SMatthias Ringwald self.attdet = attdet.AttackDetector(dt, sr) 424c4eb519SMatthias Ringwald self.ltpf = ltpf.LtpfAnalysis(dt, sr) 434930cef6SMatthias Ringwald 444c4eb519SMatthias Ringwald self.mdct = mdct.MdctForward(dt, sr) 454c4eb519SMatthias Ringwald self.energy = energy.EnergyBand(dt, sr) 464930cef6SMatthias Ringwald self.bwdet = bwdet.BandwidthDetector(dt, sr) 474930cef6SMatthias Ringwald self.sns = sns.SnsAnalysis(dt, sr) 484930cef6SMatthias Ringwald self.tns = tns.TnsAnalysis(dt) 494c4eb519SMatthias Ringwald self.spec = spec.SpectrumAnalysis(dt, sr) 504930cef6SMatthias Ringwald 514930cef6SMatthias Ringwald def analyse(self, x, nbytes): 524930cef6SMatthias Ringwald 534930cef6SMatthias Ringwald att = self.attdet.run(nbytes, x) 544930cef6SMatthias Ringwald 554930cef6SMatthias Ringwald pitch_present = self.ltpf.run(x) 564930cef6SMatthias Ringwald 574c4eb519SMatthias Ringwald x = self.mdct.run(x)[:self.ne] 584930cef6SMatthias Ringwald 594930cef6SMatthias Ringwald (e, nn_flag) = self.energy.compute(x) 604930cef6SMatthias Ringwald if nn_flag: 614930cef6SMatthias Ringwald self.ltpf.disable() 624930cef6SMatthias Ringwald 634930cef6SMatthias Ringwald bw = self.bwdet.run(e) 644930cef6SMatthias Ringwald 654930cef6SMatthias Ringwald x = self.sns.run(e, att, x) 664930cef6SMatthias Ringwald 674930cef6SMatthias Ringwald x = self.tns.run(x, bw, nn_flag, nbytes) 684930cef6SMatthias Ringwald 694c4eb519SMatthias Ringwald (xq, lastnz, x) = self.spec.run(bw, nbytes, 704930cef6SMatthias Ringwald self.bwdet.get_nbits(), self.ltpf.get_nbits(), 714930cef6SMatthias Ringwald self.sns.get_nbits(), self.tns.get_nbits(), x) 724930cef6SMatthias Ringwald 734930cef6SMatthias Ringwald return pitch_present 744930cef6SMatthias Ringwald 754930cef6SMatthias Ringwald def encode(self, pitch_present, nbytes): 764930cef6SMatthias Ringwald 774930cef6SMatthias Ringwald b = bitstream.BitstreamWriter(nbytes) 784930cef6SMatthias Ringwald 794930cef6SMatthias Ringwald self.bwdet.store(b) 804930cef6SMatthias Ringwald 814930cef6SMatthias Ringwald self.spec.store(b) 824930cef6SMatthias Ringwald 834930cef6SMatthias Ringwald self.tns.store(b) 844930cef6SMatthias Ringwald 854930cef6SMatthias Ringwald b.write_bit(pitch_present) 864930cef6SMatthias Ringwald 874930cef6SMatthias Ringwald self.sns.store(b) 884930cef6SMatthias Ringwald 894930cef6SMatthias Ringwald if pitch_present: 904c4eb519SMatthias Ringwald self.ltpf.store(b) 914930cef6SMatthias Ringwald 924930cef6SMatthias Ringwald self.spec.encode(b) 934930cef6SMatthias Ringwald 944930cef6SMatthias Ringwald return b.terminate() 954930cef6SMatthias Ringwald 964930cef6SMatthias Ringwald def run(self, x, nbytes): 974930cef6SMatthias Ringwald 984930cef6SMatthias Ringwald pitch_present = self.analyse(x, nbytes) 994930cef6SMatthias Ringwald 1004930cef6SMatthias Ringwald data = self.encode(pitch_present, nbytes) 1014930cef6SMatthias Ringwald 1024930cef6SMatthias Ringwald return data 1034930cef6SMatthias Ringwald 1044930cef6SMatthias Ringwalddef check_appendix_c(dt): 1054930cef6SMatthias Ringwald 106*6897da5cSDirk Helbig i0 = dt - T.DT_7M5 1074930cef6SMatthias Ringwald 1084930cef6SMatthias Ringwald enc_c = lc3.setup_encoder(int(T.DT_MS[dt] * 1000), 16000) 109*6897da5cSDirk Helbig ok = True 1104930cef6SMatthias Ringwald 111*6897da5cSDirk Helbig for i in range(len(C.X_PCM[i0])): 1124930cef6SMatthias Ringwald 113*6897da5cSDirk Helbig data = lc3.encode(enc_c, C.X_PCM[i0][i], C.NBYTES[i0]) 114*6897da5cSDirk Helbig ok = ok and data == C.BYTES_AC[i0][i] 1154930cef6SMatthias Ringwald 1164930cef6SMatthias Ringwald return ok 1174930cef6SMatthias Ringwald 1184930cef6SMatthias Ringwalddef check(): 1194930cef6SMatthias Ringwald 1204930cef6SMatthias Ringwald ok = True 1214930cef6SMatthias Ringwald 122*6897da5cSDirk Helbig for dt in ( T.DT_7M5, T.DT_10M ): 1234930cef6SMatthias Ringwald ok = ok and check_appendix_c(dt) 1244930cef6SMatthias Ringwald 1254930cef6SMatthias Ringwald return ok 126