From 46c78f64639b6f6c86a14d4c5d9afc9a70431ec0 Mon Sep 17 00:00:00 2001 From: Jakob Ketterl Date: Thu, 23 Dec 2021 16:32:51 +0100 Subject: [PATCH] avoid demodulator concurrency * this frees up resources used by the current demodulator before starting a new one * this addresses an issue where users of single-channel AMBE sticks could not seamlessly switch between digital modes --- csdr/chain/dummy.py | 14 ++++++++++++++ owrx/dsp.py | 15 +++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 csdr/chain/dummy.py diff --git a/csdr/chain/dummy.py b/csdr/chain/dummy.py new file mode 100644 index 0000000..b4e0220 --- /dev/null +++ b/csdr/chain/dummy.py @@ -0,0 +1,14 @@ +from pycsdr.types import Format +from csdr.chain import Module + + +class DummyDemodulator(Module): + def __init__(self, outputFormat: Format): + self.outputFormat = outputFormat + super().__init__() + + def getInputFormat(self) -> Format: + return Format.COMPLEX_FLOAT + + def getOutputFormat(self) -> Format: + return self.outputFormat diff --git a/owrx/dsp.py b/owrx/dsp.py index 7793598..effeec8 100644 --- a/owrx/dsp.py +++ b/owrx/dsp.py @@ -7,6 +7,7 @@ from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, from csdr.chain.selector import Selector, SecondarySelector from csdr.chain.clientaudio import ClientAudioChain from csdr.chain.fft import FftChain +from csdr.chain.dummy import DummyDemodulator from pycsdr.modules import Buffer, Writer from pycsdr.types import Format from typing import Union, Optional @@ -121,6 +122,19 @@ class ClientDemodulatorChain(Chain): if self.metaWriter is not None and isinstance(demodulator, MetaProvider): demodulator.setMetaWriter(self.metaWriter) + def stopDemodulator(self): + if self.demodulator is None: + return + + # we need to get the currrent demodulator out of the chain so that it can be deallocated properly + # so we just replace it with a dummy here + # in order to avoid any client audio chain hassle, the dummy simply imitates the output format of the current + # demodulator + self.replace(1, DummyDemodulator(self.demodulator.getOutputFormat())) + + self.demodulator.stop() + self.demodulator = None + def _getSelectorOutputRate(self): if isinstance(self.demodulator, FixedIfSampleRateChain): return self.demodulator.getFixedIfSampleRate() @@ -544,6 +558,7 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient) return FreeDV() def setDemodulator(self, mod): + self.chain.stopDemodulator() try: demodulator = self._getDemodulator(mod) if demodulator is None: