Files
lc3_quali/qualification/lc3_encode.py
pstruebi 2845458d3f chore: add gitignore, documentation, and LC3 conformance test software
- Add .gitignore for Python, virtual environments, testing artifacts, IDE files, and LC3 test outputs including SQAM audio files
- Add AGENTS.md with project context for LC3 implementation testing
- Add LC3.TS.p5.pdf test specification document
- Add LC3 conformance interoperability test software V1.0.8 with script readme and reference binary symlink
2026-02-27 14:56:35 +01:00

80 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""LC3 encoder wrapper for conformanceCheck.py.
Called by conformanceCheck.py as:
python lc3_encode.py -frame_ms <ms> [options] "<input.wav>" "<output.lc3>" <bitrate_bps>
Bitstream format: 18-byte header (LC3 TS §3.2.8.2) + per-frame 2-byte size prefix + LC3 payload.
"""
import lc3
import struct
import sys
import wave
def main():
args = sys.argv[1:]
frame_ms = 10.0
positional = []
i = 0
while i < len(args):
if args[i] == '-frame_ms' and i + 1 < len(args):
try:
frame_ms = float(args[i + 1])
except ValueError:
print(f'Usage: {sys.argv[0]} -frame_ms <ms> [opts] <input.wav> <output.lc3> <bitrate_bps>',
file=sys.stderr)
sys.exit(1)
i += 2
elif args[i].startswith('-'):
i += 1 # skip unknown flags (e.g. -q)
else:
positional.append(args[i])
i += 1
if len(positional) < 3:
print(f'Usage: {sys.argv[0]} -frame_ms <ms> [opts] <input.wav> <output.lc3> <bitrate_bps>',
file=sys.stderr)
sys.exit(1)
wav_path = positional[0]
lc3_path = positional[1]
bitrate_bps = int(positional[2])
frame_duration_us = int(frame_ms * 1000)
with wave.open(wav_path, 'rb') as wavfile:
samplerate = wavfile.getframerate()
nchannels = wavfile.getnchannels()
bit_depth = wavfile.getsampwidth() * 8
stream_length = wavfile.getnframes()
enc = lc3.Encoder(frame_duration_us, samplerate, nchannels)
frame_size = enc.get_frame_bytes(bitrate_bps)
frame_length = enc.get_frame_samples()
resolved_bitrate = enc.resolve_bitrate(frame_size)
with open(lc3_path, 'wb') as f_lc3:
f_lc3.write(struct.pack(
'=HHHHHHHI',
0xcc1c, # signature
18, # header size
samplerate // 100, # sample rate / 100
resolved_bitrate // 100, # bitrate / 100
nchannels,
int(frame_ms * 100), # frame duration * 100
0, # reserved
stream_length, # total PCM samples
))
for _ in range(0, stream_length, frame_length):
pcm = wavfile.readframes(frame_length)
encoded = enc.encode(pcm, frame_size, bit_depth=bit_depth)
f_lc3.write(struct.pack('=H', frame_size))
f_lc3.write(encoded)
if __name__ == '__main__':
main()