File: decoder.py

package info (click to toggle)
liblc3 1.1.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,760 kB
  • sloc: ansic: 12,075; python: 10,948; cpp: 282; makefile: 119
file content (96 lines) | stat: -rwxr-xr-x 2,525 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/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(
    '--bit_depth',
    help='Output bit depth, 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] * 10
stream_length = header[7]

# --- Setup output ---

bit_depth = args.bit_depth
pcm_size = nchannels * (bit_depth // 8)

f_wav = args.wav_file
wavfile = wave.open(f_wav)
wavfile.setnchannels(nchannels)
wavfile.setsampwidth(bit_depth // 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), bit_depth=bit_depth)

    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()