diff --git a/multilang_translator/backend_controller/broadcaster_config.py b/multilang_translator/backend_controller/broadcaster_config.py index ebb2baa..71a7c66 100644 --- a/multilang_translator/backend_controller/broadcaster_config.py +++ b/multilang_translator/backend_controller/broadcaster_config.py @@ -1,20 +1,16 @@ -import serial import time import logging as log +import os +import serial +from ..config import SAMPLING_RATE_HZ, LANG_CONFIG +PRESET = f'{SAMPLING_RATE_HZ//1000}_2_1' +BROADCAST_CONFIG = {} -SAMPLING_RATE_KHZ = 16 -FRAME_DUR_MS = 10 -PRESET = f'{SAMPLING_RATE_KHZ}_2_1' +for i, d in enumerate(list(LANG_CONFIG.items())): + key, val = d + BROADCAST_CONFIG[i] = os.path.basename(val["file"]) -if SAMPLING_RATE_KHZ == 8: - BITRATE_KBPS = 16 -elif SAMPLING_RATE_KHZ == 16: - BITRATE_KBPS = 32 -elif SAMPLING_RATE_KHZ == 24: - BITRATE_KBPS = 48 -else: - raise NotImplemented() def write_to_serial_read_respone(port, cmd, timeout = 2): # Initialize serial connection @@ -68,19 +64,12 @@ def gen_broadcast_config_cmd(preset, broadcast_config: dict): cmds.append(f"nac preset {preset} {ch}") cmds.append(f"nac broadcast_name broadcast{ch} {ch}") - cmds.append(f"nac file select_play_once {file_name} {ch} 0 0") + cmds.append(f"nac file select_play_once {file_name}.lc3 {ch} 0 0") cmds.append(f"nac num_bises 1 {ch} 0") return cmds # TODO: Advertising interval wird ungelmäßig bei mehr als 3 broadcasts 10ms -> 1s< bei 24kHz sampling rate -BROADCAST_CONFIG = { - 0: f"announcement_{SAMPLING_RATE_KHZ}_{FRAME_DUR_MS}_{BITRATE_KBPS}_de.lc3", - 1: f"announcement_{SAMPLING_RATE_KHZ}_{FRAME_DUR_MS}_{BITRATE_KBPS}_en.lc3", - 2: f"announcement_{SAMPLING_RATE_KHZ}_{FRAME_DUR_MS}_{BITRATE_KBPS}_fr.lc3", - #3: f"announcement_{SAMPLING_RATE_KHZ}_{FRAME_DUR_MS}_{BITRATE_KBPS}_es.lc3", - #4: f"announcement_{SAMPLING_RATE_KHZ}_{FRAME_DUR_MS}_{BITRATE_KBPS}_it.lc3" -} def broadcaster_config(): diff --git a/multilang_translator/config.py b/multilang_translator/config.py index e69de29..651f384 100644 --- a/multilang_translator/config.py +++ b/multilang_translator/config.py @@ -0,0 +1,30 @@ +import os + +ANNOUNCEMENT_DIR = os.path.join(os.path.dirname(__file__), 'announcements') +SAMPLING_RATE_HZ = int(16e3) +FRAME_DUR_MS = 10 +BITRATE_BPS = int(32e3) # TODO: test 16khz 16kbps +LANG_CONFIG = { + "de": { + "file": f"{ANNOUNCEMENT_DIR}/announcement_{SAMPLING_RATE_HZ//1000}_{FRAME_DUR_MS}_{BITRATE_BPS//1000}_de", + "tts": 'de_DE-kerstin-low', + }, + "en": { + "file": f"{ANNOUNCEMENT_DIR}/announcement_{SAMPLING_RATE_HZ//1000}_{FRAME_DUR_MS}_{BITRATE_BPS//1000}_en", + "tts": 'en_US-lessac-medium' + }, + "fr": { + "file": f"{ANNOUNCEMENT_DIR}/announcement_{SAMPLING_RATE_HZ//1000}_{FRAME_DUR_MS}_{BITRATE_BPS//1000}_fr", + "tts": 'fr_FR-siwis-medium' + }, + # "es": { + # "file": f"{ANNOUNCEMENT_DIR}/announcement_{SAMPLING_RATE_HZ//1000}_{FRAME_DUR_MS}_{BITRATE_BPS//1000}_es", + # "tts": 'es_ES-sharvard-medium' + # }, + # "it": { + # "file": f"{ANNOUNCEMENT_DIR}/announcement_{SAMPLING_RATE_HZ//1000}_{FRAME_DUR_MS}_{BITRATE_BPS//1000}_it", + # "tts": 'it_IT-paola-medium' + # } +} + +os.makedirs(ANNOUNCEMENT_DIR, exist_ok=True) diff --git a/multilang_translator/main.py b/multilang_translator/main.py index f405e48..df7d2a9 100644 --- a/multilang_translator/main.py +++ b/multilang_translator/main.py @@ -19,54 +19,27 @@ from .text_to_speech import text_to_speech, resample from .backend_controller.broadcaster_config import broadcaster_config from .backend_controller.broadcaster_play_once import broadcaster_play_file from .backend_controller.broadcaster_copy_files import copy_to_broadcaster - from .encode import encode_lc3 -ANNOUNCEMENT_DIR = os.path.join(os.path.dirname(__file__), 'announcements') -SAMPLING_RATE = int(16e3) -FRAME_DUR_MS = 10 -BPS = int(32e3) # TODO test 16khz 16kbps -CONFIG = { - "de": { - "file": f"{ANNOUNCEMENT_DIR}/announcement_{SAMPLING_RATE//1000}_{FRAME_DUR_MS}_{BPS//1000}_de", - "tts": 'de_DE-kerstin-low', - }, - "en": { - "file": f"{ANNOUNCEMENT_DIR}/announcement_{SAMPLING_RATE//1000}_{FRAME_DUR_MS}_{BPS//1000}_en", - "tts": 'en_US-lessac-medium' - }, - "fr": { - "file": f"{ANNOUNCEMENT_DIR}/announcement_{SAMPLING_RATE//1000}_{FRAME_DUR_MS}_{BPS//1000}_fr", - "tts": 'fr_FR-siwis-medium' - }, - "es": { - "file": f"{ANNOUNCEMENT_DIR}/announcement_{SAMPLING_RATE//1000}_{FRAME_DUR_MS}_{BPS//1000}_es", - "tts": 'es_ES-sharvard-medium' - }, - "it": { - "file": f"{ANNOUNCEMENT_DIR}/announcement_{SAMPLING_RATE//1000}_{FRAME_DUR_MS}_{BPS//1000}_it", - "tts": 'it_IT-paola-medium' - } -} +from .config import LANG_CONFIG, BITRATE_BPS, SAMPLING_RATE_HZ, FRAME_DUR_MS -os.makedirs(ANNOUNCEMENT_DIR, exist_ok=True) def synthesize_resample_encode(text, tts_model, output_file): audio_dur = text_to_speech.synthesize(text, tts_model, output_file) - resample.resample(output_file, output_file, target_rate=SAMPLING_RATE) - encode_lc3.encode_lc3(output_file, bps=BPS, frame_dur_ms=FRAME_DUR_MS) + resample.resample(output_file, output_file, target_rate=SAMPLING_RATE_HZ) + encode_lc3.encode_lc3(output_file, bps=BITRATE_BPS, frame_dur_ms=FRAME_DUR_MS) return audio_dur def translate_from_german_and_encode(text_de): - config = copy(CONFIG) + config = copy(LANG_CONFIG) base_lang = "de" file = config[base_lang]["file"] + audio_dur_s = {} audio_dur_s [base_lang] = synthesize_resample_encode(text_de, config['de']["tts"], f'{file}.wav') del config[base_lang] - audio_dur_s = {} for key, val in config.items(): text = llm_translator.translate_de_to_x(key, text_de) file = val['file'] @@ -78,15 +51,17 @@ def announcement_from_german_text(text_de): audio_durs = translate_from_german_and_encode(text_de) # Transfer the files to broadcaster memory start = time.time() - for val in CONFIG.values(): + for val in LANG_CONFIG.values(): copy_to_broadcaster(f'{val["file"]}.lc3') log.info("Transfering files to broadcaster took %s s", round(time.time() - start, 3)) + time.sleep(2) + # Instruct the broadcaster to stream the files - for i, d in enumerate(list(CONFIG.items())): + for i, d in enumerate(list(LANG_CONFIG.items())): key, val = d broadcaster_play_file(i, f'{os.path.basename(val["file"])}.lc3') - time.sleep(audio_durs[key] + 1) + time.sleep(audio_durs[key]) log.info("Starting all broadcasts %s s", round(time.time() - start, 3)) diff --git a/multilang_translator/translator/test_content.py b/multilang_translator/translator/test_content.py index 87f3b2c..e204037 100644 --- a/multilang_translator/translator/test_content.py +++ b/multilang_translator/translator/test_content.py @@ -1,2 +1,4 @@ +TESTSENTENCE_DE_HELLO = 'Hallo Welt.' +TESTSENTENCE_DE_WAVE_PARTICLE = 'Der Wellen-Teilchen-Dualismus beschreibt die Eigenschaft von Teilchen, sowohl als Wellen auf der Mikroebene zu verhalten und gleichzeitig bestimmte Eigenschaften wie Impuls und Energietrang zu besitzen.' TESTSENTENCE_DE_BROKER = 'Ein Broker (oder Makler) ist eine Person oder ein Unternehmen, das sich zwischen dem Kauf- und Verkaufsberechtigten einer Wirtschaftsgüter (z.B. Aktien, Optionen, Derivate, Währungen, Rohstoffe usw.) stellt und als Vermittler fungiert. Sein Hauptziel ist es, Transaktionen zu erleichtern und Geld für sich selbst zu verdienen.' -TESTSENTENCE_DE_RAINBOW = 'Der Regenbogen ist ein atmosphärisch-optisches Phänomen, das als kreisbogenförmiges farbiges Lichtband in einer von der Sonne beschienenen Regenwand oder wolke wahrgenommen wird. ' \ No newline at end of file +TESTSENTENCE_DE_RAINBOW = 'Der Regenbogen ist ein atmosphärisch-optisches Phänomen, das als kreisbogenförmiges farbiges Lichtband in einer von der Sonne beschienenen Regenwand oder wolke wahrgenommen wird.' \ No newline at end of file diff --git a/tests/test_backend.py b/tests/test_backend.py index 242b63a..4fc577b 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -4,7 +4,7 @@ import time import os import subprocess -from multilang_translator.backend_controller.broadcaster_config import broadcaster_config, BROADCAST_CONFIG +from multilang_translator.config import LANG_CONFIG from multilang_translator.backend_controller.broadcaster_play_once import broadcaster_play_file from multilang_translator.backend_controller.broadcaster_copy_files import copy_to_broadcaster @@ -13,14 +13,14 @@ def test_config_broadcaster(ft_configure_broadcaster): ret = ft_configure_broadcaster def test_play_files( - ft_configure_broadcaster + #ft_configure_broadcaster ): - - for key, val in BROADCAST_CONFIG.items(): - ret = broadcaster_play_file(key, val) + for i, d in enumerate(list(LANG_CONFIG.items())): + key, val = d + ret = broadcaster_play_file(i, f'{os.path.basename(val["file"])}.lc3') assert "err" not in ret assert "Failed" not in ret - time.sleep(9) + time.sleep(3) def test_copy_to_broadcaster(ft_configure_broadcaster): log.info("Current working directory is: " + os.getcwd()) diff --git a/tests/test_system.py b/tests/test_system.py index 2ec0f0a..6dac681 100644 --- a/tests/test_system.py +++ b/tests/test_system.py @@ -4,11 +4,11 @@ from multilang_translator.translator import test_content def test_announcement_from_german_text( ft_configure_broadcaster - ): + ): - announcement_from_german_text(test_content.TESTSENTENCE_DE_RAINBOW) + announcement_from_german_text(test_content.TESTSENTENCE_DE_HELLO) def test_announcement_from_german_text_without_config(): - announcement_from_german_text(test_content.TESTSENTENCE_DE_RAINBOW) + announcement_from_german_text(test_content.TESTSENTENCE_DE_WAVE_PARTICLE)