mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-17 20:42:47 +00:00
97 lines
2.5 KiB
Python
Executable File
97 lines
2.5 KiB
Python
Executable File
#!/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 struct
|
|
import sys
|
|
import wave
|
|
|
|
parser = argparse.ArgumentParser(description='LC3 Decoder')
|
|
|
|
parser.add_argument(
|
|
'lc3_file', nargs='?',
|
|
help='Input bitstream file, default is stdin',
|
|
type=argparse.FileType('rb'), default=sys.stdin.buffer)
|
|
|
|
parser.add_argument(
|
|
'wav_file', nargs='?',
|
|
help='Output wave file, default is stdout',
|
|
type=argparse.FileType('wb'), default=sys.stdout.buffer)
|
|
|
|
parser.add_argument(
|
|
'--bitdepth',
|
|
help='Output bitdepth, default is 16 bits',
|
|
type=int, choices=[16, 24], default=16)
|
|
|
|
parser.add_argument(
|
|
'--libpath', help='LC3 Library path')
|
|
|
|
args = parser.parse_args()
|
|
|
|
# --- LC3 File input ---
|
|
|
|
f_lc3 = args.lc3_file
|
|
|
|
header = struct.unpack('=HHHHHHHI', f_lc3.read(18))
|
|
if header[0] != 0xcc1c:
|
|
raise ValueError('Invalid bitstream file')
|
|
|
|
samplerate = header[2] * 100
|
|
nchannels = header[4]
|
|
frame_duration = header[5] / 100
|
|
stream_length = header[7]
|
|
|
|
# --- Setup output ---
|
|
|
|
bitdepth = args.bitdepth
|
|
pcm_size = nchannels * (bitdepth // 8)
|
|
|
|
f_wav = args.wav_file
|
|
wavfile = wave.open(f_wav)
|
|
wavfile.setnchannels(nchannels)
|
|
wavfile.setsampwidth(bitdepth // 8)
|
|
wavfile.setframerate(samplerate)
|
|
wavfile.setnframes(stream_length)
|
|
|
|
# --- Setup decoder ---
|
|
|
|
dec = lc3.Decoder(
|
|
frame_duration, samplerate, nchannels, libpath=args.libpath)
|
|
frame_length = dec.get_frame_samples()
|
|
encoded_length = stream_length + dec.get_delay_samples()
|
|
|
|
# --- Decoding loop ---
|
|
|
|
for i in range(0, encoded_length, frame_length):
|
|
|
|
lc3_frame_size = struct.unpack('=H', f_lc3.read(2))[0]
|
|
pcm = dec.decode(f_lc3.read(lc3_frame_size), bitdepth=bitdepth)
|
|
|
|
pcm = pcm[max(encoded_length - stream_length - i, 0) * pcm_size:
|
|
min(encoded_length - i, frame_length) * pcm_size]
|
|
|
|
wavfile.writeframesraw(pcm)
|
|
|
|
# --- Cleanup ---
|
|
|
|
wavfile.close()
|
|
|
|
for f in (f_lc3, f_wav):
|
|
if f is not sys.stdout.buffer:
|
|
f.close()
|