Implement basic support for multiple broadcasters

This commit is contained in:
2025-01-25 17:06:54 +01:00
parent 292cacb397
commit 36af8c3eb4

View File

@@ -121,7 +121,11 @@ async def run_broadcast(
logger.error(color('Periodic advertising not supported', 'red')) logger.error(color('Periodic advertising not supported', 'red'))
return return
with wave.open(big_config[0].broacast_wav_file_path, 'rb') as wav: bap_sampling_freq = getattr(bap.SamplingFrequency, f"FREQ_{global_config.auracast_sampling_rate_khz}")
bigs = {}
for i, conf in enumerate(big_config):
bigs[f'big{i}'] = {}
with wave.open(conf.broacast_wav_file_path, 'rb') as wav:
logger.info('Encoding wav file into lc3...') logger.info('Encoding wav file into lc3...')
logger.info('Frame rate of .wav file is: %s', wav.getframerate()) logger.info('Frame rate of .wav file is: %s', wav.getframerate())
encoder = lc3.Encoder( encoder = lc3.Encoder(
@@ -136,11 +140,13 @@ async def run_broadcast(
encoder.encode(pcm, num_bytes=global_config.octets_per_frame, bit_depth=wav.getsampwidth() * 8) encoder.encode(pcm, num_bytes=global_config.octets_per_frame, bit_depth=wav.getsampwidth() * 8)
) )
del encoder del encoder
print('Encoding complete.') logger.info('Encoding complete.')
bigs.update()
bigs[f'big{i}']['frames'] = frames
# Config advertising set # Config advertising set
bap_sampling_freq = getattr(bap.SamplingFrequency, f"FREQ_{global_config.auracast_sampling_rate_khz}") bigs[f'big{i}']['basic_audio_announcement'] = bap.BasicAudioAnnouncement(
basic_audio_announcement = bap.BasicAudioAnnouncement(
presentation_delay=global_config.presentation_delay_us, presentation_delay=global_config.presentation_delay_us,
subgroups=[ subgroups=[
bap.BasicAudioAnnouncement.Subgroup( bap.BasicAudioAnnouncement.Subgroup(
@@ -153,10 +159,10 @@ async def run_broadcast(
metadata=le_audio.Metadata( metadata=le_audio.Metadata(
[ [
le_audio.Metadata.Entry( le_audio.Metadata.Entry(
tag=le_audio.Metadata.Tag.LANGUAGE, data=big_config[0].broadcast_language.encode() tag=le_audio.Metadata.Tag.LANGUAGE, data=conf.broadcast_language.encode()
), ),
le_audio.Metadata.Entry( le_audio.Metadata.Entry(
tag=le_audio.Metadata.Tag.PROGRAM_INFO, data=big_config[0].broadcast_program_info.encode() tag=le_audio.Metadata.Tag.PROGRAM_INFO, data=conf.broadcast_program_info.encode()
), ),
] ]
), ),
@@ -172,8 +178,8 @@ async def run_broadcast(
], ],
) )
logging.info('Setup Advertising') logging.info('Setup Advertising')
broadcast_audio_announcement = bap.BroadcastAudioAnnouncement(big_config[0].broadcast_id) bigs[f'big{i}']['broadcast_audio_announcement'] = bap.BroadcastAudioAnnouncement(conf.broadcast_id)
advertising_set0 = await device.create_advertising_set( advertising_set = await device.create_advertising_set(
advertising_parameters=bumble.device.AdvertisingParameters( advertising_parameters=bumble.device.AdvertisingParameters(
advertising_event_properties=bumble.device.AdvertisingEventProperties( advertising_event_properties=bumble.device.AdvertisingEventProperties(
is_connectable=False is_connectable=False
@@ -184,10 +190,10 @@ async def run_broadcast(
# TODO: use 2mbit phy # TODO: use 2mbit phy
), ),
advertising_data=( advertising_data=(
broadcast_audio_announcement.get_advertising_data() bigs[f'big{i}']['broadcast_audio_announcement'].get_advertising_data()
+ bytes( + bytes(
core.AdvertisingData( core.AdvertisingData(
[(core.AdvertisingData.BROADCAST_NAME, big_config[0].broadcast_name.encode())] [(core.AdvertisingData.BROADCAST_NAME, conf.broadcast_name.encode())]
) )
) )
), ),
@@ -195,17 +201,18 @@ async def run_broadcast(
periodic_advertising_interval_min=80, periodic_advertising_interval_min=80,
periodic_advertising_interval_max=160, periodic_advertising_interval_max=160,
), ),
periodic_advertising_data=basic_audio_announcement.get_advertising_data(), periodic_advertising_data=bigs[f'big{i}']['basic_audio_announcement'].get_advertising_data(),
auto_restart=True, auto_restart=True,
auto_start=True, auto_start=True,
) )
bigs[f'big{i}']['advertising_set'] = advertising_set
logging.info('Start Periodic Advertising') logging.info('Start Periodic Advertising')
await advertising_set0.start_periodic() await bigs[f'big{i}']['advertising_set'].start_periodic()
logging.info('Setup BIG') logging.info('Setup BIG')
big0 = await device.create_big( big = await device.create_big(
advertising_set0, bigs[f'big{i}']['advertising_set'] ,
parameters=bumble.device.BigParameters( parameters=bumble.device.BigParameters(
num_bis=1, num_bis=1,
sdu_interval=global_config.frame_duration_us, sdu_interval=global_config.frame_duration_us,
@@ -213,23 +220,25 @@ async def run_broadcast(
max_transport_latency=65, max_transport_latency=65,
rtn=4, rtn=4,
broadcast_code=( broadcast_code=(
bytes.fromhex(big_config[0].broadcast_code) if big_config[0].broadcast_code else None bytes.fromhex(conf.broadcast_code) if conf.broadcast_code else None
), ),
), ),
) )
bigs[f'big{i}']['big'] = big
logging.info('Setup ISO Data Path') logging.info('Setup ISO Data Path')
for bis_link in big0.bis_links: for bis_link in big.bis_links:
await bis_link.setup_data_path( await bis_link.setup_data_path(
direction=bis_link.Direction.HOST_TO_CONTROLLER direction=bis_link.Direction.HOST_TO_CONTROLLER
) )
frames_iterator = itertools.cycle(frames) bigs[f'big{i}']['frames_iterator'] = itertools.cycle(frames)
logging.info("Broadcasting...")
logging.info("Broadcasting...")
def on_packet_complete(event): def on_packet_complete(event):
frame = next(frames_iterator) for val in bigs.values():
big0.bis_links[0].write(frame) frame = next(val['frames_iterator'] )
val['big'].bis_links[0].write(frame)
device.host.on('hci_number_of_completed_packets_event', on_packet_complete) device.host.on('hci_number_of_completed_packets_event', on_packet_complete)
@@ -259,7 +268,8 @@ if __name__ == "__main__":
global_conf = auracast_config.global_base_config global_conf = auracast_config.global_base_config
bigs = [ bigs = [
auracast_config.broadcast_de #auracast_config.broadcast_de,
auracast_config.broadcast_en
] ]
global_conf.octets_per_frame=60# 48kbps@24kHz global_conf.octets_per_frame=60# 48kbps@24kHz