| #!/usr/bin/env python3 |
| # |
| # Copyright 2024 Google LLC |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| |
| import argparse |
| import lc3 |
| import matplotlib |
| import matplotlib.pyplot as plt |
| import numpy as np |
| import scipy.signal as signal |
| |
| matplotlib.use('QtAgg') |
| |
| parser = argparse.ArgumentParser(description='LC3 Encoder') |
| |
| parser.add_argument( |
| '--frame_duration', help='Frame duration (ms)', type=float, default=10) |
| |
| parser.add_argument( |
| '--sample_rate', help='Sampling frequency (Hz)', type=float, default=48000) |
| |
| parser.add_argument( |
| '--hrmode', help='Enable high-resolution mode', action='store_true') |
| |
| parser.add_argument( |
| '--bitrate', help='Bitrate (bps)', type=int, default=96000) |
| |
| parser.add_argument( |
| '--libpath', help='LC3 Library path') |
| |
| args = parser.parse_args() |
| |
| # --- Setup encoder + decoder --- |
| |
| fs = args.sample_rate |
| |
| enc = lc3.Encoder( |
| args.frame_duration, fs, hrmode=args.hrmode, libpath=args.libpath) |
| dec = lc3.Decoder( |
| args.frame_duration, fs, hrmode=args.hrmode, libpath=args.libpath) |
| |
| frame_len = enc.get_frame_samples() |
| delay_len = enc.get_delay_samples() |
| |
| # --- Generate 10 seconds chirp --- |
| |
| n = 10 * int(fs) |
| t = np.arange(n - (n % frame_len)) / fs |
| s = signal.chirp(t, f0=10, f1=fs/2, t1=t[-1], phi=-90, method='linear') |
| |
| # --- Encoding / decoding loop --- |
| |
| frame_size = enc.get_frame_bytes(args.bitrate) |
| bitrate = enc.resolve_bitrate(frame_size) |
| |
| y = np.empty(len(s) + frame_len) |
| |
| for i in range(0, len(s), frame_len): |
| y[i:i+frame_len] = dec.decode(enc.encode(s[i:i+frame_len], frame_size)) |
| |
| y[len(s):] = dec.decode(enc.encode(np.zeros(frame_len), frame_size)) |
| y = y[delay_len:len(s)+delay_len] |
| |
| # --- Plot spectrograms --- |
| |
| fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True) |
| |
| NFFT = 512 |
| for (ax, s) in [(ax1, s), (ax2, y)]: |
| ax.specgram(s, Fs=fs, NFFT=NFFT, pad_to=4*NFFT, noverlap=NFFT//2, |
| vmin=-160, vmax=0) |
| |
| ax1.set_title('Input signal') |
| ax1.set_ylabel('Frequency (Hz)') |
| |
| ax2.set_title(('Processed signal (%.1f kbps)' % (bitrate/1000))) |
| ax2.set_ylabel('Frequency (Hz)') |
| |
| plt.show() |