xref: /btstack/3rd-party/lc3-google/test/encoder.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 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