adjusted modem startup and audio tests

This commit is contained in:
DJ2LS 2023-11-11 10:41:16 +01:00
parent a7ef928d0f
commit 722f1ef785
3 changed files with 151 additions and 114 deletions

View file

@ -129,42 +129,47 @@ def get_device_index_from_crc(crc, isInput: bool):
except Exception as e: except Exception as e:
log.warning(f"Audio device {crc} not detected ", devices=detected_devices, isInput=isInput) log.warning(f"Audio device {crc} not detected ", devices=detected_devices, isInput=isInput)
return [None, None]
import sounddevice as sd
def test_audio_devices(input_id: str, output_id: str) -> list: def test_audio_devices(input_id: str, output_id: str) -> list:
result = [False, False] test_result = [False, False]
try: try:
device_index = get_device_index_from_crc(input_id, True) result = get_device_index_from_crc(output_id, True)
if device_index is None: if result is None:
# in_dev_index, in_dev_name = None, None
raise ValueError("Invalid input device index.") raise ValueError("Invalid input device index.")
else:
sd.check_input_settings( in_dev_index, in_dev_name = result
device=device_index[0], sd.check_input_settings(
channels=1, device=in_dev_index,
dtype="int16", channels=1,
samplerate=48000, dtype="int16",
) samplerate=48000,
result[0] = True )
test_result[0] = True
except (sd.PortAudioError, ValueError) as e: except (sd.PortAudioError, ValueError) as e:
print("Input device error:", e) log.warning("Input device error:", e=e)
test_result[0] = False
try: try:
device_index = get_device_index_from_crc(output_id, False) result = get_device_index_from_crc(input_id, False)
if device_index is None: if result is None:
# out_dev_index, out_dev_name = None, None
raise ValueError("Invalid output device index.") raise ValueError("Invalid output device index.")
else:
out_dev_index, out_dev_name = result
sd.check_input_settings(
device=out_dev_index,
channels=1,
dtype="int16",
samplerate=48000,
)
test_result[1] = True
sd.check_output_settings(
device=device_index[0],
channels=1,
dtype="int16",
samplerate=48000,
)
result[1] = True
except (sd.PortAudioError, ValueError) as e: except (sd.PortAudioError, ValueError) as e:
print("Output device error:", e) log.warning("Output device error:", e=e)
test_result[1] = False
return result sd._terminate()
sd._initialize()
return test_result

View file

@ -99,8 +99,6 @@ class RF:
# Make sure our resampler will work # Make sure our resampler will work
assert (self.AUDIO_SAMPLE_RATE_RX / self.MODEM_SAMPLE_RATE) == codec2.api.FDMDV_OS_48 # type: ignore assert (self.AUDIO_SAMPLE_RATE_RX / self.MODEM_SAMPLE_RATE) == codec2.api.FDMDV_OS_48 # type: ignore
# init codec2 resampler
self.resampler = codec2.resampler()
self.modem_transmit_queue = MODEM_TRANSMIT_QUEUE self.modem_transmit_queue = MODEM_TRANSMIT_QUEUE
self.modem_received_queue = MODEM_RECEIVED_QUEUE self.modem_received_queue = MODEM_RECEIVED_QUEUE
@ -117,11 +115,8 @@ class RF:
self.fft_queue = fft_queue self.fft_queue = fft_queue
self.init_codec2() self.start_modem()
self.init_audio()
self.init_rig_control()
self.init_decoders()
self.init_data_threads()
# -------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------
def tci_tx_callback(self) -> None: def tci_tx_callback(self) -> None:
@ -138,15 +133,64 @@ class RF:
data_out = self.modoutqueue.popleft() data_out = self.modoutqueue.popleft()
self.tci_module.push_audio(data_out) self.tci_module.push_audio(data_out)
def init_audio(self): def start_modem(self):
# --------------------------------------------CREATE PORTAUDIO INSTANCE if not TESTMODE and HamlibParam.hamlib_radiocontrol not in ["tci"]:
if not TESTMODE and not HamlibParam.hamlib_radiocontrol in ["tci"]: self.init_audio()
try:
(in_dev_index, in_dev_name) = audio.get_device_index_from_crc(
self.audio_input_device, True)
(out_dev_index, out_dev_name) = audio.get_device_index_from_crc(
self.audio_output_device, False)
elif not TESTMODE:
self.init_tci()
else:
self.init_mkfifo()
# init codec2 instances
self.init_codec2()
# init rig control
self.init_rig_control()
# init decoders
self.init_decoders()
# init decoding threads
self.init_data_threads()
atexit.register(self.stream.stop)
def stop_modem(self):
try:
# let's stop the modem service
self.service_queue.put("stop")
# simulate audio class active state for reducing cli output
# self.stream = lambda: None
# self.stream.active = False
# self.stream.stop
except Exception:
self.log.error("[MDM] Error stopping modem", e=err)
def init_audio(self):
try:
self.log.info(f"[MDM] init: get audio devices", input_device=self.audio_input_device,
output_device=self.audio_output_device)
try:
result = audio.get_device_index_from_crc(self.audio_input_device, True)
if result is None:
raise ValueError("Invalid input device")
else:
in_dev_index, in_dev_name = result
result = audio.get_device_index_from_crc(self.audio_output_device, False)
if result is None:
raise ValueError("Invalid output device")
else:
out_dev_index, out_dev_name = result
self.log.info(f"[MDM] init: receiving audio from '{in_dev_name}'")
self.log.info(f"[MDM] init: transmiting audio on '{out_dev_name}'")
self.log.debug("[MDM] init: starting pyaudio callback and decoding threads")
# init codec2 resampler
self.resampler = codec2.resampler()
# init audio stream
self.stream = sd.RawStream( self.stream = sd.RawStream(
channels=1, channels=1,
dtype="int16", dtype="int16",
@ -155,87 +199,76 @@ class RF:
samplerate=self.AUDIO_SAMPLE_RATE_RX, samplerate=self.AUDIO_SAMPLE_RATE_RX,
blocksize=4800, blocksize=4800,
) )
atexit.register(self.stream.stop) self.stream.start()
self.log.info("[MDM] init: receiving audio from '%s'" % in_dev_name)
self.log.info("[MDM] init: transmiting audio on '%s'" % out_dev_name)
try:
self.log.debug("[MDM] init: starting pyaudio callback")
self.stream.start()
except Exception as audioerr:
self.log.error("[MDM] init: starting pyaudio callback failed", e=audioerr)
except Exception as err:
self.log.error("[MDM] init: can't open audio device. Exit", e=err)
self.stream.stop
self.stream = lambda: None
self.stream.active = False
# let's stop the modem service
self.service_queue.put("stop")
# simulate audio class active state for reducing cli output
elif not TESTMODE:
# placeholder area for processing audio via TCI
# https://github.com/maksimus1210/TCI
self.log.warning("[MDM] [TCI] Not yet fully implemented", ip=TCIParam.ip, port=TCIParam.port)
# we are trying this by simulating an audio stream Object like with mkfifo except Exception as audioerr:
class Object: self.log.error("[MDM] init: starting pyaudio callback failed", e=audioerr)
"""An object for simulating audio stream"""
active = True
self.stream = Object() except Exception as err:
self.log.warning("[MDM] init: can't open audio device. Stopping modem", e=err)
self.stop_modem()
# lets init TCI module def init_tci(self):
self.tci_module = tci.TCICtrl() # placeholder area for processing audio via TCI
# https://github.com/maksimus1210/TCI
self.log.warning("[MDM] [TCI] Not yet fully implemented", ip=TCIParam.ip, port=TCIParam.port)
tci_rx_callback_thread = threading.Thread( # we are trying this by simulating an audio stream Object like with mkfifo
target=self.tci_rx_callback, class Object:
name="TCI RX CALLBACK THREAD", """An object for simulating audio stream"""
daemon=True, active = True
)
tci_rx_callback_thread.start()
# let's start the audio tx callback self.stream = Object()
self.log.debug("[MDM] Starting tci tx callback thread")
tci_tx_callback_thread = threading.Thread(
target=self.tci_tx_callback,
name="TCI TX CALLBACK THREAD",
daemon=True,
)
tci_tx_callback_thread.start()
else: # lets init TCI module
self.tci_module = tci.TCICtrl()
class Object: tci_rx_callback_thread = threading.Thread(
"""An object for simulating audio stream""" target=self.tci_rx_callback,
active = True name="TCI RX CALLBACK THREAD",
daemon=True,
)
tci_rx_callback_thread.start()
self.stream = Object() # let's start the audio tx callback
self.log.debug("[MDM] Starting tci tx callback thread")
tci_tx_callback_thread = threading.Thread(
target=self.tci_tx_callback,
name="TCI TX CALLBACK THREAD",
daemon=True,
)
tci_tx_callback_thread.start()
def init_mkfifo(self):
class Object:
"""An object for simulating audio stream"""
active = True
# Create mkfifo buffers self.stream = Object()
try:
os.mkfifo(RXCHANNEL)
os.mkfifo(TXCHANNEL)
except Exception as err:
self.log.info(f"[MDM] init:mkfifo: Exception: {err}")
mkfifo_write_callback_thread = threading.Thread( # Create mkfifo buffers
target=self.mkfifo_write_callback, try:
name="MKFIFO WRITE CALLBACK THREAD", os.mkfifo(RXCHANNEL)
daemon=True, os.mkfifo(TXCHANNEL)
) except Exception as err:
mkfifo_write_callback_thread.start() self.log.info(f"[MDM] init:mkfifo: Exception: {err}")
mkfifo_write_callback_thread = threading.Thread(
target=self.mkfifo_write_callback,
name="MKFIFO WRITE CALLBACK THREAD",
daemon=True,
)
mkfifo_write_callback_thread.start()
self.log.debug("[MDM] Starting mkfifo_read_callback")
mkfifo_read_callback_thread = threading.Thread(
target=self.mkfifo_read_callback,
name="MKFIFO READ CALLBACK THREAD",
daemon=True,
)
mkfifo_read_callback_thread.start()
self.log.debug("[MDM] Starting mkfifo_read_callback")
mkfifo_read_callback_thread = threading.Thread(
target=self.mkfifo_read_callback,
name="MKFIFO READ CALLBACK THREAD",
daemon=True,
)
mkfifo_read_callback_thread.start()
def tci_rx_callback(self) -> None: def tci_rx_callback(self) -> None:
""" """

View file

@ -27,9 +27,8 @@ class SM:
cmd = self.modem_service.get() cmd = self.modem_service.get()
if cmd in ['start'] and not self.modem: if cmd in ['start'] and not self.modem:
audio_test = audio.test_audio_devices(self.config['AUDIO']['rx'], self.config['AUDIO']['tx']) audio_test = audio.test_audio_devices(self.config['AUDIO']['rx'], self.config['AUDIO']['tx'])
print(self.config['AUDIO']['rx'])
print(audio_test) print(audio_test)
if False not in audio_test: if False not in audio_test and None not in audio_test:
self.log.info("starting modem....") self.log.info("starting modem....")
self.modem = modem.RF(self.config, self.modem_events, self.modem_fft, self.modem_service) self.modem = modem.RF(self.config, self.modem_events, self.modem_fft, self.modem_service)
self.data_handler = data_handler.DATA(self.config, self.modem_events) self.data_handler = data_handler.DATA(self.config, self.modem_events)