update auracaster for latest bumble version

This commit is contained in:
2025-02-17 10:56:20 +01:00
parent 169b738a4b
commit fa05236aee
4 changed files with 55 additions and 70 deletions

Binary file not shown.

View File

@@ -43,31 +43,14 @@ from bumble.profiles import bass
import bumble.device
import bumble.transport
import bumble.utils
from bumble.device import Host, BIGInfoAdvertisement
from bumble.device import Host, BIGInfoAdvertisement, AdvertisingChannelMap
import auracast_config
def modified_on_hci_number_of_completed_packets_event(self, event):
for connection_handle, num_completed_packets in zip(
event.connection_handles, event.num_completed_packets
):
if connection := self.connections.get(connection_handle):
connection.acl_packet_queue.on_packets_completed(num_completed_packets)
elif connection_handle not in itertools.chain(
self.cis_links.keys(),
self.sco_links.keys(),
itertools.chain.from_iterable(self.bigs.values()),
):
logger.warning(
'received packet completion event for unknown handle '
f'0x{connection_handle:04X}'
)
self.emit('hci_number_of_completed_packets_event', event)
Host.on_hci_number_of_completed_packets_event = modified_on_hci_number_of_completed_packets_event
ADVERTISING_CHANNELS = (
AdvertisingChannelMap.CHANNEL_37 ,AdvertisingChannelMap.CHANNEL_38 ,AdvertisingChannelMap.CHANNEL_39
)
# -----------------------------------------------------------------------------
# Logging
@@ -113,8 +96,6 @@ def run_async(async_command: Coroutine) -> None:
)
ADVERTISING_SLOWDOWN_FACTOR=1
PKGS_COUNT = 0
async def run_broadcast(
global_config : auracast_config.AuracastGlobalConfig,
big_config: List[auracast_config.AuracastBigConfig]
@@ -151,6 +132,7 @@ async def run_broadcast(
bigs.update()
bigs[f'big{i}']['frames'] = frames
bigs[f'big{i}']['frames_iterator'] = itertools.cycle(frames)
# Config advertising set
bigs[f'big{i}']['basic_audio_announcement'] = bap.BasicAudioAnnouncement(
@@ -201,6 +183,7 @@ async def run_broadcast(
primary_advertising_phy=hci.Phy.LE_1M, # 2m phy config throws error - because for primary advertising channels, 1mbit is only supported
secondary_advertising_phy=hci.Phy.LE_2M, # this is the secondary advertising beeing send on non advertising channels (extendend advertising)
#advertising_tx_power= # tx power in dbm (max 20)
secondary_advertising_max_skip=10,
),
advertising_data=(
bigs[f'big{i}']['broadcast_audio_announcement'].get_advertising_data()
@@ -230,7 +213,7 @@ async def run_broadcast(
frame_enable = 1
big = await device.create_big(
bigs[f'big{i}']['advertising_set'] ,
bigs[f'big{i}']['advertising_set'],
parameters=bumble.device.BigParameters(
num_bis=1,
sdu_interval=global_config.qos_config.iso_int_multiple_10ms*10000, # Is the same as iso interval
@@ -245,54 +228,54 @@ async def run_broadcast(
)
bigs[f'big{i}']['big'] = big
iso_queues = [
bumble.device.IsoPacketStream(big.bis_links[0], 64),
#bumble.device.IsoPacketStream(big.bis_links[1], 64), # right channel
]
logging.info('Setup ISO Data Path')
for bis_link in big.bis_links:
await bis_link.setup_data_path(
direction=bis_link.Direction.HOST_TO_CONTROLLER
for queue in iso_queues:
await queue.iso_link.setup_data_path(
direction=queue.iso_link.Direction.HOST_TO_CONTROLLER
)
bigs[f'big{i}']['frames_iterator'] = itertools.cycle(frames)
bigs[f'big{i}']['iso_queues'] = iso_queues
logging.debug(f'big{i} parameters are:')
logging.debug('%s', pprint.pformat(vars(big)))
logging.debug(f'Finished setup of big{i}.')
await asyncio.sleep(3) # Wait for advertising to set up
LOOP_FINITE_PKGS = -1 # set -1 to loop infinitely
def on_packet_complete(event):
global PKGS_COUNT
PKGS_COUNT = PKGS_COUNT + 1
event_handle = event.connection_handles[0]
if PKGS_COUNT < LOOP_FINITE_PKGS or LOOP_FINITE_PKGS == -1:
event_found = False
for big in bigs.values():
if big['big'].bis_links[0].handle == event_handle:
frame = b''
for _ in range(0, global_config.qos_config.iso_int_multiple_10ms):
# loop is nececarry if iso interval is not frame interval of codec
frame += next(big['frames_iterator'])
big['big'].bis_links[0].write(frame)
event_found = True
if not event_found:
logging.warning('unknown event on packet complete with handle: %s', event_handle)
else:
logging.warning("Stopping iso loop")
await asyncio.sleep(i+1) # Wait for advertising to set up
logging.info("Broadcasting...")
device.host.on('hci_number_of_completed_packets_event', on_packet_complete)
# Send the first packet for each big, to get the event loop running
def on_flow():
data_packet_queue = iso_queues[0].data_packet_queue
print(
f'\rPACKETS: pending={data_packet_queue.pending}, '
f'queued={data_packet_queue.queued}, '
f'completed={data_packet_queue.completed}',
end='',
)
bigs[f'big{0}']['iso_queues'][0].data_packet_queue.on('flow', on_flow)
async def streamer(queue, iterator):
while True:
frame = next(iterator)
await queue[0].write(frame)
streams = []
for big in bigs.values():
frame = next(big['frames_iterator'])
big['big'].bis_links[0].write(frame)
streams.append(
asyncio.create_task(
streamer(big['iso_queues'], big['frames_iterator'])
)
)
await asyncio.wait(streams)
print("Done.")
while True:
await asyncio.sleep(1)
# -----------------------------------------------------------------------------
# Main
@@ -312,7 +295,7 @@ if __name__ == "__main__":
logging.basicConfig(
level=logging.INFO,
format='%(module)s.py:%(lineno)d %(levelname)s: %(message)s'
)
)
global_conf = auracast_config.global_base_config
@@ -322,22 +305,24 @@ if __name__ == "__main__":
#global_conf.transport='serial:/dev/serial/by-id/usb-SEGGER_J-Link_001057705357-if02,1000000,rtscts' # transport for nrf54l15dk
global_conf.transport='serial:/dev/serial/by-id/usb-ZEPHYR_Zephyr_HCI_UART_sample_81BD14B8D71B5662-if02,115200,rtscts' #nrf52dongle usb cdc uart
global_conf.transport='serial:/dev/serial/by-id/usb-ZEPHYR_Zephyr_HCI_UART_sample_81BD14B8D71B5662-if00,115200,rtscts' #nrf52dongle hci_uart usb cdc
# TODO use nrf52dongle with hci over usb
# global_conf.transport='usb:2fe3:000b' #nrf52dongle hci_usb #TODO: iso packet over usb seems not to be supported
# TODO: How can we use other iso interval than 10ms ?(medium or low rel) ? - nrf53audio receiver repports I2S tx underrun
#global_conf.qos_config = auracast_config.qos_config_mono_medium_rel
global_conf.qos_config = auracast_config.qos_config_mono_high_rel
bigs = [
auracast_config.broadcast_de,
auracast_config.broadcast_en,
auracast_config.broadcast_fr,
auracast_config.broadcast_es,
# auracast_config.broadcast_it, #TODO: with more than three broadcasts, not advertising at all is present, regardless the adv. interval
] # TODO: more than three broadcasters lead to some buffer overflow on hci side- try to increase some buffer lengths
#auracast_config.broadcast_es,
#auracast_config.broadcast_it,
]
# TODO: with more than three broadcasters no advertising (no primary channels is present anymore) - is this a number of advertising sets constraint?
# TODO: solve the advertising problem and 5 broadcaster may be possible
global_conf.auracast_sampling_rate_hz = 16000
global_conf.octets_per_frame = 40 # 32kbps@16kHz
@@ -345,8 +330,8 @@ if __name__ == "__main__":
# 16kHz works reliably with 3 streams
# use thread usage debugger on controller to check actual cpu load - not much load
# TODO: How can we use other iso interval than 10ms ?(medium or low rel) ? - nrf53audio receiver repports I2S tx underrun
# TODO; I dont think hci is really the bottleneck. probably limited airtime is the problem. Analyze this somehow.
# TODO: upgrade to latests bumble version
broadcast(
global_conf,

View File

@@ -4,8 +4,8 @@ version = "0.0.1"
requires-python = ">=3.8"
dependencies = [
"bumble @ git+ssh://git@hinterwaldner.duckdns.org:222/auracaster/bumble.git@af466c29704d4d47b291e697b1990621c0b7d86b",
"lc3 @ git+https://github.com/google/liblc3.git@7558637303106c7ea971e7bb8cedf379d3e08bcc",
"bumble @ git+ssh://git@ssh.pstruebi.xyz:222/auracaster/bumble.git@3f6f0362704f51cba7c8f4f66bcd6117d2fd7fc1",
"lc3 @ git+ssh://git@ssh.pstruebi.xyz:222/auracaster/liblc3.git@7558637303106c7ea971e7bb8cedf379d3e08bcc",
]
[project.optional-dependencies]