Adaptions to multicast to work with bumble audio io
This commit is contained in:
@@ -121,7 +121,7 @@ async def run_broadcast(
|
||||
logger.error(color('Periodic advertising not supported', 'red'))
|
||||
return
|
||||
|
||||
with wave.open(big_config[0].broacast_wav_file_path, 'rb') as wav:
|
||||
with wave.open(big_config[0].audio_source, 'rb') as wav:
|
||||
logger.info('Encoding wav file into lc3...')
|
||||
logger.info('Frame rate of .wav file is: %s', wav.getframerate())
|
||||
encoder = lc3.Encoder(
|
||||
@@ -153,10 +153,10 @@ async def run_broadcast(
|
||||
metadata=le_audio.Metadata(
|
||||
[
|
||||
le_audio.Metadata.Entry(
|
||||
tag=le_audio.Metadata.Tag.LANGUAGE, data=big_config[0].broadcast_language.encode()
|
||||
tag=le_audio.Metadata.Tag.LANGUAGE, data=big_config[0].language.encode()
|
||||
),
|
||||
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=big_config[0].program_info.encode()
|
||||
),
|
||||
]
|
||||
),
|
||||
@@ -172,7 +172,7 @@ async def run_broadcast(
|
||||
],
|
||||
)
|
||||
logging.info('Setup Advertising')
|
||||
broadcast_audio_announcement = bap.BroadcastAudioAnnouncement(big_config[0].broadcast_id)
|
||||
broadcast_audio_announcement = bap.BroadcastAudioAnnouncement(big_config[0].id)
|
||||
advertising_set0 = await device.create_advertising_set(
|
||||
advertising_parameters=bumble.device.AdvertisingParameters(
|
||||
advertising_event_properties=bumble.device.AdvertisingEventProperties(
|
||||
@@ -187,7 +187,7 @@ async def run_broadcast(
|
||||
broadcast_audio_announcement.get_advertising_data()
|
||||
+ bytes(
|
||||
core.AdvertisingData(
|
||||
[(core.AdvertisingData.BROADCAST_NAME, big_config[0].broadcast_name.encode())]
|
||||
[(core.AdvertisingData.BROADCAST_NAME, big_config[0].name.encode())]
|
||||
)
|
||||
)
|
||||
),
|
||||
@@ -213,7 +213,7 @@ async def run_broadcast(
|
||||
max_transport_latency=65,
|
||||
rtn=4,
|
||||
broadcast_code=(
|
||||
bytes.fromhex(big_config[0].broadcast_code) if big_config[0].broadcast_code else None
|
||||
bytes.fromhex(big_config[0].code) if big_config[0].code else None
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -34,60 +34,70 @@ class AuracastGlobalConfig:
|
||||
presentation_delay_us: int = 40000
|
||||
manufacturer_data: tuple[int, bytes] = None
|
||||
|
||||
global_base_config = AuracastGlobalConfig(qos_config=AuracastQoSConfig())
|
||||
|
||||
# "Audio input. "
|
||||
# "'device' -> use the host's default sound input device, "
|
||||
# "'device:<DEVICE_ID>' -> use one of the host's sound input devices "
|
||||
# "(specify 'device:?' to get a list of available sound input devices), "
|
||||
# "'stdin' -> receive audio from stdin as int16 PCM, "
|
||||
# "'file:<filename> -> read audio from a .wav or raw int16 PCM file. "
|
||||
|
||||
|
||||
@dataclass
|
||||
class AuracastBigConfig:
|
||||
broadcast_id: int =123456,
|
||||
broadcast_random_address: hci.Address = hci.Address('F1:F1:F2:F3:F4:F5')
|
||||
broadcast_code: str = None # a hexstr
|
||||
broadcast_language: str = 'eng' # See: https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
|
||||
broadcast_name: str = 'Broadcast0'
|
||||
broadcast_program_info: str = 'Some Announcements'
|
||||
broacast_wav_file_path: str = './auracast/announcement_48_10_96000_en.wav'
|
||||
id: int = 123456,
|
||||
random_address: hci.Address = hci.Address('F1:F1:F2:F3:F4:F5')
|
||||
code: str = None # Broadcast_Code – a 16-octet parameter provided by the Host
|
||||
language: str = 'eng' # See: https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
|
||||
name: str = 'Broadcast0'
|
||||
program_info: str = 'Some Announcements'
|
||||
audio_source: str = 'file:./auracast/announcement_48_10_96000_en.wav'
|
||||
loop_wav: bool = True
|
||||
|
||||
global_base_config = AuracastGlobalConfig(qos_config=AuracastQoSConfig())
|
||||
|
||||
# Instanciate some example configurations
|
||||
broadcast_de = AuracastBigConfig(
|
||||
broadcast_id=12,
|
||||
broadcast_random_address=hci.Address('F1:F1:F2:F3:F4:F5'),
|
||||
broadcast_name = 'Broadcast0',
|
||||
broadcast_language='deu',
|
||||
broadcast_program_info = 'Announcements German',
|
||||
broacast_wav_file_path = './auracast/announcement_48_10_96000_de.wav',
|
||||
id=12,
|
||||
random_address=hci.Address('F1:F1:F2:F3:F4:F5'),
|
||||
name = 'Broadcast0',
|
||||
language='deu',
|
||||
program_info = 'Announcements German',
|
||||
audio_source = 'file:./auracast/announcement_48_10_96000_de.wav',
|
||||
)
|
||||
|
||||
broadcast_en = AuracastBigConfig(
|
||||
broadcast_id=123,
|
||||
broadcast_random_address=hci.Address('F2:F1:F2:F3:F4:F5'),
|
||||
broadcast_name = 'Broadcast1',
|
||||
broadcast_language='eng',
|
||||
broadcast_program_info = 'Announcements English',
|
||||
broacast_wav_file_path = './auracast/announcement_48_10_96000_en.wav',
|
||||
id=123,
|
||||
random_address=hci.Address('F2:F1:F2:F3:F4:F5'),
|
||||
name = 'Broadcast1',
|
||||
language='eng',
|
||||
program_info = 'Announcements English',
|
||||
audio_source = 'file:./auracast/announcement_48_10_96000_en.wav',
|
||||
)
|
||||
|
||||
broadcast_fr = AuracastBigConfig(
|
||||
broadcast_id=1234,
|
||||
broadcast_random_address=hci.Address('F3:F1:F2:F3:F4:F5'),
|
||||
broadcast_name = 'Broadcast2',
|
||||
broadcast_language='fra',
|
||||
broadcast_program_info = 'Announcements French',
|
||||
broacast_wav_file_path = './auracast/announcement_48_10_96000_fr.wav',
|
||||
id=1234,
|
||||
random_address=hci.Address('F3:F1:F2:F3:F4:F5'),
|
||||
name = 'Broadcast2',
|
||||
language='fra',
|
||||
program_info = 'Announcements French',
|
||||
audio_source = 'file:./auracast/announcement_48_10_96000_fr.wav',
|
||||
)
|
||||
|
||||
broadcast_es = AuracastBigConfig(
|
||||
broadcast_id=12345,
|
||||
broadcast_random_address=hci.Address('F4:F1:F2:F3:F4:F5'),
|
||||
broadcast_name = 'Broadcast3',
|
||||
broadcast_language='spa',
|
||||
broadcast_program_info = 'Announcements Spanish',
|
||||
broacast_wav_file_path = './auracast/announcement_48_10_96_es.wav',
|
||||
id=12345,
|
||||
random_address=hci.Address('F4:F1:F2:F3:F4:F5'),
|
||||
name = 'Broadcast3',
|
||||
language='spa',
|
||||
program_info = 'Announcements Spanish',
|
||||
audio_source = 'file:./auracast/announcement_48_10_96_es.wav',
|
||||
)
|
||||
|
||||
broadcast_it = AuracastBigConfig(
|
||||
broadcast_id=123456,
|
||||
broadcast_random_address=hci.Address('F5:F1:F2:F3:F4:F5'),
|
||||
broadcast_name = 'Broadcast4',
|
||||
broadcast_language='ita',
|
||||
broadcast_program_info = 'Announcements Italian',
|
||||
broacast_wav_file_path = './auracast/announcement_48_10_96_it.wav',
|
||||
id=123456,
|
||||
random_address=hci.Address('F5:F1:F2:F3:F4:F5'),
|
||||
name = 'Broadcast4',
|
||||
language='ita',
|
||||
program_info = 'Announcements Italian',
|
||||
audio_source = 'file:./auracast/announcement_48_10_96_it.wav',
|
||||
)
|
||||
@@ -126,7 +126,7 @@ async def run_broadcast(
|
||||
return
|
||||
|
||||
|
||||
with wave.open(big_config[0].broacast_wav_file_path, 'rb') as wav:
|
||||
with wave.open(big_config[0].audio_source, 'rb') as wav:
|
||||
logger.info('Encoding wav file into lc3...')
|
||||
logger.info('Frame rate of .wav file is: %s', wav.getframerate())
|
||||
encoder = lc3.Encoder(
|
||||
@@ -158,10 +158,10 @@ async def run_broadcast(
|
||||
metadata=le_audio.Metadata(
|
||||
[
|
||||
le_audio.Metadata.Entry(
|
||||
tag=le_audio.Metadata.Tag.LANGUAGE, data=big_config[0].broadcast_language.encode()
|
||||
tag=le_audio.Metadata.Tag.LANGUAGE, data=big_config[0].language.encode()
|
||||
),
|
||||
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=big_config[0].program_info.encode()
|
||||
),
|
||||
le_audio.Metadata.Entry(
|
||||
tag=le_audio.Metadata.Tag.BROADCAST_NAME, data=b'Broadcast0'
|
||||
@@ -192,10 +192,10 @@ async def run_broadcast(
|
||||
metadata=le_audio.Metadata(
|
||||
[
|
||||
le_audio.Metadata.Entry(
|
||||
tag=le_audio.Metadata.Tag.LANGUAGE, data=big_config[0].broadcast_language.encode()
|
||||
tag=le_audio.Metadata.Tag.LANGUAGE, data=big_config[0].language.encode()
|
||||
),
|
||||
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=big_config[0].program_info.encode()
|
||||
),
|
||||
le_audio.Metadata.Entry(
|
||||
tag=le_audio.Metadata.Tag.BROADCAST_NAME, data=b'Broadcast1'
|
||||
@@ -294,7 +294,7 @@ async def run_broadcast(
|
||||
max_transport_latency=65,
|
||||
rtn=4,
|
||||
broadcast_code=(
|
||||
bytes.fromhex(big_config[0].broadcast_code) if big_config[0].broadcast_code else None
|
||||
bytes.fromhex(big_config[0].code) if big_config[0].code else None
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -308,7 +308,7 @@ async def run_broadcast(
|
||||
max_transport_latency=65,
|
||||
rtn=4,
|
||||
broadcast_code=(
|
||||
bytes.fromhex(big_config[0].broadcast_code) if big_config[0].broadcast_code else None
|
||||
bytes.fromhex(big_config[0].code) if big_config[0].code else None
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -25,6 +25,7 @@ import itertools
|
||||
import struct
|
||||
from typing import cast, Any, AsyncGenerator, Coroutine, Dict, Optional, Tuple
|
||||
from typing import List
|
||||
import itertools
|
||||
|
||||
|
||||
try:
|
||||
@@ -45,13 +46,12 @@ import bumble.device
|
||||
import bumble.transport
|
||||
import bumble.utils
|
||||
from bumble.device import Host, BIGInfoAdvertisement, AdvertisingChannelMap
|
||||
from bumble.audio import io as audio_io
|
||||
|
||||
import auracast_config
|
||||
|
||||
|
||||
ADVERTISING_CHANNELS = (
|
||||
AdvertisingChannelMap.CHANNEL_37 ,AdvertisingChannelMap.CHANNEL_38 ,AdvertisingChannelMap.CHANNEL_39
|
||||
)
|
||||
def chunker(b, size):
|
||||
return (b[i:i+size] for i in range(0, len(b), size))
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Logging
|
||||
@@ -96,8 +96,7 @@ def run_async(async_command: Coroutine) -> None:
|
||||
color('!!! An error occurred while executing the command:', 'red'), message
|
||||
)
|
||||
|
||||
ADVERTISING_SLOWDOWN_FACTOR=1.25
|
||||
async def run_broadcast(
|
||||
async def setup_broadcast(
|
||||
global_config : auracast_config.AuracastGlobalConfig,
|
||||
big_config: List[auracast_config.AuracastBigConfig]
|
||||
|
||||
@@ -111,30 +110,6 @@ async def run_broadcast(
|
||||
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('Frame rate of .wav file is: %s', wav.getframerate())
|
||||
encoder = lc3.Encoder(
|
||||
frame_duration_us=global_config.frame_duration_us,
|
||||
sample_rate_hz=global_config.auracast_sampling_rate_hz,
|
||||
num_channels=1,
|
||||
input_sample_rate_hz=wav.getframerate(),
|
||||
)
|
||||
frames = list[bytes]()
|
||||
while pcm := wav.readframes(encoder.get_frame_samples()):
|
||||
frames.append(
|
||||
encoder.encode(
|
||||
pcm,
|
||||
num_bytes=global_config.octets_per_frame,
|
||||
bit_depth=wav.getsampwidth() * 8)
|
||||
)
|
||||
del encoder
|
||||
logger.info('Encoding complete.')
|
||||
|
||||
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(
|
||||
presentation_delay=global_config.presentation_delay_us,
|
||||
@@ -149,13 +124,13 @@ async def run_broadcast(
|
||||
metadata=le_audio.Metadata(
|
||||
[
|
||||
le_audio.Metadata.Entry(
|
||||
tag=le_audio.Metadata.Tag.LANGUAGE, data=conf.broadcast_language.encode()
|
||||
tag=le_audio.Metadata.Tag.LANGUAGE, data=conf.language.encode()
|
||||
),
|
||||
le_audio.Metadata.Entry(
|
||||
tag=le_audio.Metadata.Tag.PROGRAM_INFO, data=conf.broadcast_program_info.encode()
|
||||
tag=le_audio.Metadata.Tag.PROGRAM_INFO, data=conf.program_info.encode()
|
||||
),
|
||||
le_audio.Metadata.Entry(
|
||||
tag=le_audio.Metadata.Tag.BROADCAST_NAME, data=conf.broadcast_name.encode()
|
||||
tag=le_audio.Metadata.Tag.BROADCAST_NAME, data=conf.name.encode()
|
||||
),
|
||||
]
|
||||
),
|
||||
@@ -186,15 +161,15 @@ async def run_broadcast(
|
||||
)
|
||||
)
|
||||
)
|
||||
bigs[f'big{i}']['broadcast_audio_announcement'] = bap.BroadcastAudioAnnouncement(conf.broadcast_id)
|
||||
bigs[f'big{i}']['broadcast_audio_announcement'] = bap.BroadcastAudioAnnouncement(conf.id)
|
||||
advertising_set = await device.create_advertising_set(
|
||||
random_address=conf.broadcast_random_address,
|
||||
random_address=conf.random_address,
|
||||
advertising_parameters=bumble.device.AdvertisingParameters(
|
||||
advertising_event_properties=bumble.device.AdvertisingEventProperties(
|
||||
is_connectable=False
|
||||
),
|
||||
primary_advertising_interval_min=round(100*ADVERTISING_SLOWDOWN_FACTOR),
|
||||
primary_advertising_interval_max=round(200*ADVERTISING_SLOWDOWN_FACTOR),
|
||||
primary_advertising_interval_min=round(100),
|
||||
primary_advertising_interval_max=round(200),
|
||||
advertising_sid=i,
|
||||
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)
|
||||
@@ -205,14 +180,14 @@ async def run_broadcast(
|
||||
bigs[f'big{i}']['broadcast_audio_announcement'].get_advertising_data()
|
||||
+ bytes(
|
||||
core.AdvertisingData(
|
||||
[(core.AdvertisingData.BROADCAST_NAME, conf.broadcast_name.encode())]
|
||||
[(core.AdvertisingData.BROADCAST_NAME, conf.name.encode())]
|
||||
)
|
||||
)
|
||||
+ advertising_manufacturer_data
|
||||
),
|
||||
periodic_advertising_parameters=bumble.device.PeriodicAdvertisingParameters(
|
||||
periodic_advertising_interval_min=round(80*ADVERTISING_SLOWDOWN_FACTOR),
|
||||
periodic_advertising_interval_max=round(160*ADVERTISING_SLOWDOWN_FACTOR),
|
||||
periodic_advertising_interval_min=round(80),
|
||||
periodic_advertising_interval_max=round(160),
|
||||
),
|
||||
periodic_advertising_data=bigs[f'big{i}']['basic_audio_announcement'].get_advertising_data(),
|
||||
auto_restart=True,
|
||||
@@ -238,7 +213,7 @@ async def run_broadcast(
|
||||
max_transport_latency=global_config.qos_config.max_transport_latency_ms,
|
||||
rtn=global_config.qos_config.number_of_retransmissions,
|
||||
broadcast_code=(
|
||||
bytes.fromhex(conf.broadcast_code) if conf.broadcast_code else None
|
||||
bytes.fromhex(conf.code) if conf.code else None
|
||||
),
|
||||
framing=frame_enable # needed if iso interval is not frame interval of codedc
|
||||
),
|
||||
@@ -250,12 +225,11 @@ async def run_broadcast(
|
||||
direction=bis_link.Direction.HOST_TO_CONTROLLER
|
||||
)
|
||||
|
||||
iso_queue =bumble.device.IsoPacketStream(big.bis_links[0], 64),
|
||||
iso_queue = bumble.device.IsoPacketStream(big.bis_links[0], 64)
|
||||
|
||||
logging.info('Setup ISO Data Path')
|
||||
|
||||
|
||||
bigs[f'big{i}']['iso_queues'] = iso_queue
|
||||
bigs[f'big{i}']['iso_queue'] = iso_queue
|
||||
|
||||
logging.debug(f'big{i} parameters are:')
|
||||
logging.debug('%s', pprint.pformat(vars(big)))
|
||||
@@ -275,40 +249,84 @@ async def run_broadcast(
|
||||
)
|
||||
|
||||
if global_conf.debug:
|
||||
bigs[f'big{0}']['iso_queues'][0].data_packet_queue.on('flow', on_flow)
|
||||
bigs[f'big{0}']['iso_queue'][0].data_packet_queue.on('flow', on_flow)
|
||||
|
||||
for i, big in enumerate(bigs.values()):
|
||||
audio_source = big_config[i].audio_source
|
||||
input_format = 'auto'
|
||||
audio_input = await audio_io.create_audio_input(audio_source, input_format)
|
||||
audio_input.rewind = big_config[i].loop_wav
|
||||
pcm_format = await audio_input.open()
|
||||
|
||||
#try:
|
||||
if pcm_format.channels != 1:
|
||||
print("Only 1 channels PCM configurations are supported")
|
||||
return
|
||||
if pcm_format.sample_type == audio_io.PcmFormat.SampleType.INT16:
|
||||
pcm_bit_depth = 16
|
||||
elif pcm_format.sample_type == audio_io.PcmFormat.SampleType.FLOAT32:
|
||||
pcm_bit_depth = None
|
||||
else:
|
||||
print("Only INT16 and FLOAT32 sample types are supported")
|
||||
return
|
||||
encoder = lc3.Encoder(
|
||||
frame_duration_us=global_config.frame_duration_us,
|
||||
sample_rate_hz=global_config.auracast_sampling_rate_hz,
|
||||
num_channels=1,
|
||||
input_sample_rate_hz=pcm_format.sample_rate,
|
||||
)
|
||||
lc3_frame_samples = encoder.get_frame_samples() # number of the pcm samples per lc3 frame
|
||||
lc3_frame_size = global_config.octets_per_frame #encoder.get_frame_bytes(bitrate)
|
||||
lc3_bytes_per_frame = lc3_frame_size #* 2 #multiplied by number of channels
|
||||
|
||||
bigs[f'big{i}']['lc3_frame_samples'] = lc3_frame_samples
|
||||
bigs[f'big{i}']['audio_input'] = audio_input
|
||||
bigs[f'big{i}']['encoder'] = encoder
|
||||
|
||||
async def streamer(bigs):
|
||||
# TODO: do some pre buffering so the stream is stable from the beginning. One half iso queue would be appropriate
|
||||
while True:
|
||||
for big in bigs.values():
|
||||
# write one frame to each queue
|
||||
frame = next(big['frames_iterator'])
|
||||
await big['iso_queues'][0].write(frame)
|
||||
stream_finished = [False for _ in range(len(bigs))]
|
||||
for i, big in enumerate(bigs.values()):
|
||||
pcm_frame = await anext(big['audio_input'].frames(big['lc3_frame_samples']), None)
|
||||
if pcm_frame is None: # Not all streams may stop at the same time
|
||||
stream_finished[i] = True
|
||||
continue
|
||||
|
||||
lc3_frame = big['encoder'].encode(
|
||||
pcm_frame, num_bytes=lc3_bytes_per_frame, bit_depth=pcm_bit_depth
|
||||
)
|
||||
await big['iso_queue'].write(lc3_frame) # iso_queue.write(lc3_frame)
|
||||
|
||||
|
||||
if all(stream_finished): # TODO: Take into account that multiple files have different lengths
|
||||
print('All streams finished, stopping streamer')
|
||||
break
|
||||
|
||||
stream = streamer(bigs)
|
||||
|
||||
await stream # running endlessly
|
||||
|
||||
print("Done.")
|
||||
|
||||
|
||||
await stream # running until stream ends
|
||||
|
||||
return bigs
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Main
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def broadcast(global_conf: auracast_config.AuracastGlobalConfig, big_conf: List[auracast_config.AuracastBigConfig]):
|
||||
async def broadcast(global_conf: auracast_config.AuracastGlobalConfig, big_conf: List[auracast_config.AuracastBigConfig]):
|
||||
"""Start a broadcast as a source."""
|
||||
run_async(
|
||||
run_broadcast(
|
||||
global_conf,
|
||||
big_conf
|
||||
)
|
||||
ret = await setup_broadcast(
|
||||
global_conf,
|
||||
big_conf
|
||||
)
|
||||
# make a second coroutine to run the streaming - maybe even use the streamer coroutine
|
||||
# start it without await and go into a infinite loop were further instrucations via a ui can be given ?
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
level=logging.DEBUG,
|
||||
format='%(module)s.py:%(lineno)d %(levelname)s: %(message)s'
|
||||
)
|
||||
|
||||
@@ -318,12 +336,14 @@ if __name__ == "__main__":
|
||||
|
||||
#global_conf.transport='serial:/dev/serial/by-id/usb-SEGGER_J-Link_001050076061-if02,1000000,rtscts' # transport for nrf53dk
|
||||
|
||||
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-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-if00,115200,rtscts' #nrf52dongle hci_uart usb cdc
|
||||
global_conf.transport='serial:/dev/serial/by-id/usb-ZEPHYR_Zephyr_HCI_UART_sample_81BD14B8D71B5662-if00,115200,rtscts' #nrf52dongle hci_uart usb cdc
|
||||
|
||||
# global_conf.transport='usb:2fe3:000b' #nrf52dongle hci_usb # TODO: iso packet over usb not 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
|
||||
|
||||
@@ -333,25 +353,33 @@ if __name__ == "__main__":
|
||||
auracast_config.broadcast_fr,
|
||||
#auracast_config.broadcast_es,
|
||||
#auracast_config.broadcast_it,
|
||||
]
|
||||
]
|
||||
#for big in bigs:
|
||||
# big.code = 'ff'*16 # returns hci/HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE_ERROR
|
||||
|
||||
# 16kHz works reliably with 3 streams
|
||||
# 24kHz is only working with 2 streams - probably airtime constraint
|
||||
# TODO: with more than three broadcasters (16kHz) no advertising (no primary channels is present anymore)
|
||||
# TODO: find the bottleneck - probably airtime
|
||||
# TODO: test encrypted streams
|
||||
|
||||
global_conf.auracast_sampling_rate_hz = 16000
|
||||
global_conf.octets_per_frame = 40 # 32kbps@16kHz
|
||||
#global_conf.debug = True
|
||||
|
||||
# TODO: How can we use other iso interval than 10ms ?(medium or low rel) ? - nrf53audio receiver repports I2S tx underrun
|
||||
broadcast(
|
||||
global_conf,
|
||||
bigs
|
||||
|
||||
run_async(
|
||||
broadcast(
|
||||
global_conf,
|
||||
bigs
|
||||
)
|
||||
)
|
||||
|
||||
# TODO: possible inputs:
|
||||
# wav file locally
|
||||
# precoded lc3 file locally
|
||||
# realtime audio locally
|
||||
# realtime audio network lc3 coded
|
||||
# (realtime audio network uncoded)
|
||||
# (realtime audio network uncoded)
|
||||
|
||||
# TODO: add support for playing new files will keeping the advertising running
|
||||
|
||||
@@ -4,8 +4,9 @@ version = "0.0.1"
|
||||
requires-python = ">=3.8"
|
||||
|
||||
dependencies = [
|
||||
"bumble @ git+ssh://git@ssh.pstruebi.xyz:222/auracaster/bumble.git@3f6f0362704f51cba7c8f4f66bcd6117d2fd7fc1",
|
||||
"bumble @ git+ssh://git@ssh.pstruebi.xyz:222/auracaster/bumble.git@e027bcb57a0f29c82e3c02c8bb8691dcb91eac62",
|
||||
"lc3 @ git+ssh://git@ssh.pstruebi.xyz:222/auracaster/liblc3.git@7558637303106c7ea971e7bb8cedf379d3e08bcc",
|
||||
"sounddevice",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
|
||||
Reference in New Issue
Block a user