1#!/usr/bin/env python3 2# 3# Copyright 2024 Google LLC 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import argparse 19import lc3 20import struct 21import sys 22import wave 23 24parser = argparse.ArgumentParser(description='LC3 Encoder') 25 26parser.add_argument( 27 'wav_file', nargs='?', 28 help='Input wave file, default is stdin', 29 type=argparse.FileType('rb'), default=sys.stdin.buffer) 30 31parser.add_argument( 32 'lc3_file', nargs='?', 33 help='Output bitstream file, default is stdout', 34 type=argparse.FileType('wb'), default=sys.stdout.buffer) 35 36parser.add_argument( 37 '--bitrate', help='Bitrate in bps', type=int, required=True) 38 39parser.add_argument( 40 '--frame_duration', help='Frame duration in ms', type=float, default=10) 41 42parser.add_argument( 43 '--libpath', help='LC3 Library path') 44 45args = parser.parse_args() 46 47# --- WAV File input --- 48 49f_wav = args.wav_file 50wavfile = wave.open(f_wav, 'rb') 51 52samplerate = wavfile.getframerate() 53nchannels = wavfile.getnchannels() 54bitdepth = wavfile.getsampwidth() * 8 55stream_length = wavfile.getnframes() 56 57# --- Setup encoder --- 58 59enc = lc3.Encoder( 60 args.frame_duration, samplerate, nchannels, libpath=args.libpath) 61frame_size = enc.get_frame_bytes(args.bitrate) 62frame_length = enc.get_frame_samples() 63bitrate = enc.resolve_bitrate(frame_size) 64 65# --- Setup output --- 66 67f_lc3 = args.lc3_file 68f_lc3.write(struct.pack( 69 '=HHHHHHHI', 0xcc1c, 18, 70 samplerate // 100, bitrate // 100, nchannels, 71 int(args.frame_duration * 100), 0, stream_length)) 72 73# --- Encoding loop --- 74 75for i in range(0, stream_length, frame_length): 76 77 f_lc3.write(struct.pack('=H', frame_size)) 78 79 pcm = wavfile.readframes(frame_length) 80 f_lc3.write(enc.encode(pcm, frame_size, bitdepth=bitdepth)) 81 82# --- Cleanup --- 83 84wavfile.close() 85 86for f in (f_wav, f_lc3): 87 if f is not sys.stdout.buffer: 88 f.close() 89