1*49fe348cSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*49fe348cSAndroid Build Coastguard Worker# 3*49fe348cSAndroid Build Coastguard Worker# Copyright 2024 Google LLC 4*49fe348cSAndroid Build Coastguard Worker# 5*49fe348cSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*49fe348cSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*49fe348cSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*49fe348cSAndroid Build Coastguard Worker# 9*49fe348cSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*49fe348cSAndroid Build Coastguard Worker# 11*49fe348cSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*49fe348cSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*49fe348cSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*49fe348cSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*49fe348cSAndroid Build Coastguard Worker# limitations under the License. 16*49fe348cSAndroid Build Coastguard Worker# 17*49fe348cSAndroid Build Coastguard Worker 18*49fe348cSAndroid Build Coastguard Workerimport argparse 19*49fe348cSAndroid Build Coastguard Workerimport lc3 20*49fe348cSAndroid Build Coastguard Workerimport matplotlib 21*49fe348cSAndroid Build Coastguard Workerimport matplotlib.pyplot as plt 22*49fe348cSAndroid Build Coastguard Workerimport numpy as np 23*49fe348cSAndroid Build Coastguard Workerimport scipy.signal as signal 24*49fe348cSAndroid Build Coastguard Worker 25*49fe348cSAndroid Build Coastguard Workermatplotlib.use('QtAgg') 26*49fe348cSAndroid Build Coastguard Worker 27*49fe348cSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(description='LC3 Encoder') 28*49fe348cSAndroid Build Coastguard Worker 29*49fe348cSAndroid Build Coastguard Workerparser.add_argument( 30*49fe348cSAndroid Build Coastguard Worker '--frame_duration', help='Frame duration (ms)', type=float, default=10) 31*49fe348cSAndroid Build Coastguard Worker 32*49fe348cSAndroid Build Coastguard Workerparser.add_argument( 33*49fe348cSAndroid Build Coastguard Worker '--sample_rate', help='Sampling frequency (Hz)', type=float, default=48000) 34*49fe348cSAndroid Build Coastguard Worker 35*49fe348cSAndroid Build Coastguard Workerparser.add_argument( 36*49fe348cSAndroid Build Coastguard Worker '--hrmode', help='Enable high-resolution mode', action='store_true') 37*49fe348cSAndroid Build Coastguard Worker 38*49fe348cSAndroid Build Coastguard Workerparser.add_argument( 39*49fe348cSAndroid Build Coastguard Worker '--bitrate', help='Bitrate (bps)', type=int, default=96000) 40*49fe348cSAndroid Build Coastguard Worker 41*49fe348cSAndroid Build Coastguard Workerparser.add_argument( 42*49fe348cSAndroid Build Coastguard Worker '--libpath', help='LC3 Library path') 43*49fe348cSAndroid Build Coastguard Worker 44*49fe348cSAndroid Build Coastguard Workerargs = parser.parse_args() 45*49fe348cSAndroid Build Coastguard Worker 46*49fe348cSAndroid Build Coastguard Worker# --- Setup encoder + decoder --- 47*49fe348cSAndroid Build Coastguard Worker 48*49fe348cSAndroid Build Coastguard Workerfs = args.sample_rate 49*49fe348cSAndroid Build Coastguard Worker 50*49fe348cSAndroid Build Coastguard Workerenc = lc3.Encoder( 51*49fe348cSAndroid Build Coastguard Worker args.frame_duration, fs, hrmode=args.hrmode, libpath=args.libpath) 52*49fe348cSAndroid Build Coastguard Workerdec = lc3.Decoder( 53*49fe348cSAndroid Build Coastguard Worker args.frame_duration, fs, hrmode=args.hrmode, libpath=args.libpath) 54*49fe348cSAndroid Build Coastguard Worker 55*49fe348cSAndroid Build Coastguard Workerframe_len = enc.get_frame_samples() 56*49fe348cSAndroid Build Coastguard Workerdelay_len = enc.get_delay_samples() 57*49fe348cSAndroid Build Coastguard Worker 58*49fe348cSAndroid Build Coastguard Worker# --- Generate 10 seconds chirp --- 59*49fe348cSAndroid Build Coastguard Worker 60*49fe348cSAndroid Build Coastguard Workern = 10 * int(fs) 61*49fe348cSAndroid Build Coastguard Workert = np.arange(n - (n % frame_len)) / fs 62*49fe348cSAndroid Build Coastguard Workers = signal.chirp(t, f0=10, f1=fs/2, t1=t[-1], phi=-90, method='linear') 63*49fe348cSAndroid Build Coastguard Worker 64*49fe348cSAndroid Build Coastguard Worker# --- Encoding / decoding loop --- 65*49fe348cSAndroid Build Coastguard Worker 66*49fe348cSAndroid Build Coastguard Workerframe_size = enc.get_frame_bytes(args.bitrate) 67*49fe348cSAndroid Build Coastguard Workerbitrate = enc.resolve_bitrate(frame_size) 68*49fe348cSAndroid Build Coastguard Worker 69*49fe348cSAndroid Build Coastguard Workery = np.empty(len(s) + frame_len) 70*49fe348cSAndroid Build Coastguard Worker 71*49fe348cSAndroid Build Coastguard Workerfor i in range(0, len(s), frame_len): 72*49fe348cSAndroid Build Coastguard Worker y[i:i+frame_len] = dec.decode(enc.encode(s[i:i+frame_len], frame_size)) 73*49fe348cSAndroid Build Coastguard Worker 74*49fe348cSAndroid Build Coastguard Workery[len(s):] = dec.decode(enc.encode(np.zeros(frame_len), frame_size)) 75*49fe348cSAndroid Build Coastguard Workery = y[delay_len:len(s)+delay_len] 76*49fe348cSAndroid Build Coastguard Worker 77*49fe348cSAndroid Build Coastguard Worker# --- Plot spectrograms --- 78*49fe348cSAndroid Build Coastguard Worker 79*49fe348cSAndroid Build Coastguard Workerfig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True) 80*49fe348cSAndroid Build Coastguard Worker 81*49fe348cSAndroid Build Coastguard WorkerNFFT = 512 82*49fe348cSAndroid Build Coastguard Workerfor (ax, s) in [(ax1, s), (ax2, y)]: 83*49fe348cSAndroid Build Coastguard Worker ax.specgram(s, Fs=fs, NFFT=NFFT, pad_to=4*NFFT, noverlap=NFFT//2, 84*49fe348cSAndroid Build Coastguard Worker vmin=-160, vmax=0) 85*49fe348cSAndroid Build Coastguard Worker 86*49fe348cSAndroid Build Coastguard Workerax1.set_title('Input signal') 87*49fe348cSAndroid Build Coastguard Workerax1.set_ylabel('Frequency (Hz)') 88*49fe348cSAndroid Build Coastguard Worker 89*49fe348cSAndroid Build Coastguard Workerax2.set_title(('Processed signal (%.1f kbps)' % (bitrate/1000))) 90*49fe348cSAndroid Build Coastguard Workerax2.set_ylabel('Frequency (Hz)') 91*49fe348cSAndroid Build Coastguard Worker 92*49fe348cSAndroid Build Coastguard Workerplt.show() 93