Replace in-memory LC3 file loading with streaming byte generator to reduce memory usage
Refactors LC3 file handling to stream frames byte-by-byte from disk instead of loading the entire file into memory. Adds _lc3_file_byte_gen generator function that skips the 18-byte LC3 header, reads frame size headers, and yields individual bytes with optional looping. Removes read_lc3_file usage and itertools.cycle approach in favor of the new streaming generator.
This commit is contained in:
@@ -551,6 +551,29 @@ async def init_broadcast(
|
|||||||
return bigs
|
return bigs
|
||||||
|
|
||||||
|
|
||||||
|
def _lc3_file_byte_gen(filename: str, loop: bool = False):
|
||||||
|
"""Stream LC3 frames from disk as individual bytes, with optional looping.
|
||||||
|
|
||||||
|
Yields one byte (int) at a time so it is compatible with the existing
|
||||||
|
``bytes(itertools.islice(gen, bytes_per_frame))`` consumer without loading
|
||||||
|
the whole file into memory.
|
||||||
|
"""
|
||||||
|
while True:
|
||||||
|
with open(filename, 'rb') as f:
|
||||||
|
f.read(18) # skip 18-byte LC3 header
|
||||||
|
while True:
|
||||||
|
size_b = f.read(2)
|
||||||
|
if len(size_b) < 2:
|
||||||
|
break
|
||||||
|
frame_size = struct.unpack('=H', size_b)[0]
|
||||||
|
frame = f.read(frame_size)
|
||||||
|
if len(frame) < frame_size:
|
||||||
|
break
|
||||||
|
yield from frame
|
||||||
|
if not loop:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class Streamer():
|
class Streamer():
|
||||||
"""
|
"""
|
||||||
Streamer class that supports multiple input formats. See bumble for streaming from wav or device
|
Streamer class that supports multiple input formats. See bumble for streaming from wav or device
|
||||||
@@ -706,13 +729,7 @@ class Streamer():
|
|||||||
big['precoded'] = True
|
big['precoded'] = True
|
||||||
big['lc3_bytes_per_frame'] = global_config.octets_per_frame
|
big['lc3_bytes_per_frame'] = global_config.octets_per_frame
|
||||||
filename = big_config[i].audio_source.replace('file:', '')
|
filename = big_config[i].audio_source.replace('file:', '')
|
||||||
|
big['lc3_frames'] = _lc3_file_byte_gen(filename, loop=big_config[i].loop)
|
||||||
lc3_bytes = read_lc3_file(filename)
|
|
||||||
lc3_frames = iter(lc3_bytes)
|
|
||||||
|
|
||||||
if big_config[i].loop:
|
|
||||||
lc3_frames = itertools.cycle(lc3_frames)
|
|
||||||
big['lc3_frames'] = lc3_frames
|
|
||||||
|
|
||||||
# use wav files and code them entirely before streaming
|
# use wav files and code them entirely before streaming
|
||||||
elif big_config[i].precode_wav and big_config[i].audio_source.endswith('.wav'):
|
elif big_config[i].precode_wav and big_config[i].audio_source.endswith('.wav'):
|
||||||
|
|||||||
Reference in New Issue
Block a user