update auracaster for latest bumble version
This commit is contained in:
BIN
auracast/announcement_48_10_96000_en_stereo.wav
Normal file
BIN
auracast/announcement_48_10_96000_en_stereo.wav
Normal file
Binary file not shown.
@@ -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,
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user