xref: /btstack/3rd-party/lc3-google/test/decoder.py (revision 6897da5c53aac5b1f90f41b5b15d0bd43d61dfff)
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