From 81ed1a9ebbdf204d7b11d4deffa66f00b12aa12f Mon Sep 17 00:00:00 2001 From: Jakob Ketterl Date: Mon, 20 Sep 2021 16:14:23 +0200 Subject: [PATCH] abstract chain features; use local imports to avoid hard dependencies --- csdr/__init__.py | 2 +- csdr/chain/demodulator.py | 13 +++++++++++++ csdr/chain/digiham.py | 8 ++++---- owrx/dsp.py | 28 +++++++++++++++++----------- owrx/service/__init__.py | 7 +++++-- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/csdr/__init__.py b/csdr/__init__.py index 561997a..9ea983b 100644 --- a/csdr/__init__.py +++ b/csdr/__init__.py @@ -671,7 +671,7 @@ class Dsp(DirewolfConfigSubscriber): if self.has_pipe("dmr_control_pipe"): self.pipes["dmr_control_pipe"].write("{0}\n".format(filter)) if self.pycsdr_enabled and self.pycsdr_chain is not None and isinstance(self.pycsdr_chain, DemodulatorChain): - self.pycsdr_chain.setDmrFilter(filter) + self.pycsdr_chain.setSlotFilter(filter) def set_wfm_deemphasis_tau(self, tau): if self.wfm_deemphasis_tau == tau: diff --git a/csdr/chain/demodulator.py b/csdr/chain/demodulator.py index ceb6bdb..b65a8bc 100644 --- a/csdr/chain/demodulator.py +++ b/csdr/chain/demodulator.py @@ -1,5 +1,6 @@ from csdr.chain import Chain from abc import ABC, abstractmethod +from pycsdr.modules import Writer class BaseDemodulatorChain(Chain): @@ -36,3 +37,15 @@ class DialFrequencyReceiver(ABC): # marker interface class HdAudio: pass + + +class MetaProvider(ABC): + @abstractmethod + def setMetaWriter(self, writer: Writer) -> None: + pass + + +class SlotFilterChain(ABC): + @abstractmethod + def setSlotFilter(self, filter: int) -> None: + pass diff --git a/csdr/chain/digiham.py b/csdr/chain/digiham.py index 8409dff..f586358 100644 --- a/csdr/chain/digiham.py +++ b/csdr/chain/digiham.py @@ -1,4 +1,4 @@ -from csdr.chain.demodulator import BaseDemodulatorChain, FixedAudioRateChain, FixedIfSampleRateChain, DialFrequencyReceiver +from csdr.chain.demodulator import BaseDemodulatorChain, FixedAudioRateChain, FixedIfSampleRateChain, DialFrequencyReceiver, MetaProvider, SlotFilterChain from pycsdr.modules import FmDemod, Agc, Writer, Buffer from pycsdr.types import Format from digiham.modules import DstarDecoder, DcBlock, FskDemodulator, GfskDemodulator, DigitalVoiceFilter, MbeSynthesizer, NarrowRrcFilter, NxdnDecoder, DmrDecoder, WideRrcFilter, YsfDecoder @@ -6,7 +6,7 @@ from digiham.ambe import Modes from owrx.meta import MetaParser -class DigihamChain(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, DialFrequencyReceiver): +class DigihamChain(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, DialFrequencyReceiver, MetaProvider): def __init__(self, fskDemodulator, decoder, mbeMode, filter=None, codecserver: str = ""): self.decoder = decoder if codecserver is None: @@ -34,7 +34,7 @@ class DigihamChain(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateC def getFixedAudioRate(self): return 8000 - def setMetaWriter(self, writer: Writer): + def setMetaWriter(self, writer: Writer) -> None: if self.metaParser is None: self.metaParser = MetaParser() buffer = Buffer(Format.CHAR) @@ -80,7 +80,7 @@ class Nxdn(DigihamChain): ) -class Dmr(DigihamChain): +class Dmr(DigihamChain, SlotFilterChain): def __init__(self, codecserver: str = ""): super().__init__( fskDemodulator=GfskDemodulator(samplesPerSymbol=10), diff --git a/owrx/dsp.py b/owrx/dsp.py index c13957c..7869fbe 100644 --- a/owrx/dsp.py +++ b/owrx/dsp.py @@ -5,14 +5,9 @@ from owrx.property import PropertyStack, PropertyLayer, PropertyValidator from owrx.property.validators import OrValidator, RegexValidator, BoolValidator from owrx.modes import Modes from csdr.chain import Chain -from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, SecondaryDemodulator, DialFrequencyReceiver +from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, SecondaryDemodulator, DialFrequencyReceiver, MetaProvider, SlotFilterChain from csdr.chain.selector import Selector from csdr.chain.clientaudio import ClientAudioChain -from csdr.chain.analog import NFm, WFm, Am, Ssb -from csdr.chain.digiham import DigihamChain, Dmr, Dstar, Nxdn, Ysf -from csdr.chain.m17 import M17 -from csdr.chain.freedv import FreeDV -from csdr.chain.drm import Drm from csdr.chain.fft import FftChain from csdr.chain.digimodes import AudioChopperDemodulator, PacketDemodulator, PocsagDemodulator from pycsdr.modules import Buffer, Writer @@ -113,7 +108,7 @@ class ClientDemodulatorChain(Chain): self.clientAudioChain.setClientRate(outputRate) - if self.metaWriter is not None and isinstance(demodulator, DigihamChain): + if self.metaWriter is not None and isinstance(demodulator, MetaProvider): demodulator.setMetaWriter(self.metaWriter) def _getSelectorOutputRate(self): @@ -249,7 +244,7 @@ class ClientDemodulatorChain(Chain): if writer is self.metaWriter: return self.metaWriter = writer - if isinstance(self.demodulator, DigihamChain): + if isinstance(self.demodulator, MetaProvider): self.demodulator.setMetaWriter(self.metaWriter) def setSecondaryFftWriter(self, writer: Writer) -> None: @@ -267,8 +262,8 @@ class ClientDemodulatorChain(Chain): if self.secondaryDemodulator is not None: self.secondaryDemodulator.setWriter(writer) - def setDmrFilter(self, filter: int) -> None: - if not isinstance(self.demodulator, Dmr): + def setSlotFilter(self, filter: int) -> None: + if not isinstance(self.demodulator, SlotFilterChain): return self.demodulator.setSlotFilter(filter) @@ -398,7 +393,7 @@ class DspManager(SdrSourceEventClient): self.props.wireProperty("low_cut", self.chain.setLowCut), self.props.wireProperty("high_cut", self.chain.setHighCut), self.props.wireProperty("mod", self.setDemodulator), - self.props.wireProperty("dmr_filter", self.chain.setDmrFilter), + self.props.wireProperty("dmr_filter", self.chain.setSlotFilter), # TODO # self.props.wireProperty("wfm_deemphasis_tau", self.dsp.set_wfm_deemphasis_tau), # TODO @@ -433,26 +428,37 @@ class DspManager(SdrSourceEventClient): return demod # TODO: move this to Modes if demod == "nfm": + from csdr.chain.analog import NFm return NFm(self.props["output_rate"]) elif demod == "wfm": + from csdr.chain.analog import WFm return WFm(self.props["hd_output_rate"], self.props["wfm_deemphasis_tau"]) elif demod == "am": + from csdr.chain.analog import Am return Am() elif demod in ["usb", "lsb", "cw"]: + from csdr.chain.analog import Ssb return Ssb() elif demod == "dmr": + from csdr.chain.digiham import Dmr return Dmr(self.props["digital_voice_codecserver"]) elif demod == "dstar": + from csdr.chain.digiham import Dstar return Dstar(self.props["digital_voice_codecserver"]) elif demod == "ysf": + from csdr.chain.digiham import Ysf return Ysf(self.props["digital_voice_codecserver"]) elif demod == "nxdn": + from csdr.chain.digiham import Nxdn return Nxdn(self.props["digital_voice_codecserver"]) elif demod == "m17": + from csdr.chain.m17 import M17 return M17() elif demod == "drm": + from csdr.chain.drm import Drm return Drm() elif demod == "freedv": + from csdr.chain.freedv import FreeDV return FreeDV() def setDemodulator(self, mod): diff --git a/owrx/service/__init__.py b/owrx/service/__init__.py index d6d6698..cc160e2 100644 --- a/owrx/service/__init__.py +++ b/owrx/service/__init__.py @@ -12,8 +12,6 @@ from owrx.service.chain import ServiceDemodulatorChain from owrx.modes import Modes, DigitalMode from typing import Union from csdr.chain.demodulator import BaseDemodulatorChain, SecondaryDemodulator, DialFrequencyReceiver -from csdr.chain.analog import NFm, Ssb -from csdr.chain.digimodes import AudioChopperDemodulator, PacketDemodulator from pycsdr.modules import Buffer import logging @@ -274,8 +272,10 @@ class ServiceHandler(SdrSourceEventClient): return demod # TODO: move this to Modes if demod == "nfm": + from csdr.chain.analog import NFm return NFm(48000) elif demod in ["usb", "lsb", "cw"]: + from csdr.chain.analog import Ssb return Ssb() # TODO move this elsewhere @@ -284,10 +284,13 @@ class ServiceHandler(SdrSourceEventClient): return mod # TODO add remaining modes if mod in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w", "q65"]: + from csdr.chain.digimodes import AudioChopperDemodulator return AudioChopperDemodulator(mod, WsjtParser()) elif mod == "js8": + from csdr.chain.digimodes import AudioChopperDemodulator return AudioChopperDemodulator(mod, Js8Parser()) elif mod == "packet": + from csdr.chain.digimodes import PacketDemodulator return PacketDemodulator(service=True) return None