From 909a969e043c0ef6359b4e1b8b04136730403333 Mon Sep 17 00:00:00 2001 From: Jakob Ketterl Date: Mon, 27 Sep 2021 17:46:19 +0200 Subject: [PATCH] restore wfm deemphasis tau functionality --- csdr/chain/analog.py | 23 +++++++++++++++++++---- csdr/chain/demodulator.py | 6 ++++++ owrx/dsp.py | 33 ++++++++++++++++++++------------- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/csdr/chain/analog.py b/csdr/chain/analog.py index c065193..6bb277f 100644 --- a/csdr/chain/analog.py +++ b/csdr/chain/analog.py @@ -1,4 +1,4 @@ -from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, HdAudio +from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, HdAudio, DeemphasisTauChain from pycsdr.modules import AmDemod, DcBlock, FmDemod, Limit, NfmDeemphasis, Agc, WfmDeemphasis, FractionalDecimator, RealPart from pycsdr.types import Format, AgcProfile @@ -38,19 +38,34 @@ class NFm(BaseDemodulatorChain): self.replace(2, NfmDeemphasis(sampleRate)) -class WFm(BaseDemodulatorChain, FixedIfSampleRateChain, HdAudio): +class WFm(BaseDemodulatorChain, FixedIfSampleRateChain, DeemphasisTauChain, HdAudio): def __init__(self, sampleRate: int, tau: float): + self.sampleRate = sampleRate + self.tau = tau workers = [ FmDemod(), Limit(), - FractionalDecimator(Format.FLOAT, 200000.0 / sampleRate, prefilter=True), - WfmDeemphasis(sampleRate, tau), + FractionalDecimator(Format.FLOAT, 200000.0 / self.sampleRate, prefilter=True), + WfmDeemphasis(self.sampleRate, self.tau), ] super().__init__(workers) def getFixedIfSampleRate(self): return 200000 + def setDeemphasisTau(self, tau: float) -> None: + if tau == self.tau: + return + self.tau = tau + self.replace(3, WfmDeemphasis(self.sampleRate, self.tau)) + + def setSampleRate(self, sampleRate: int) -> None: + if sampleRate == self.sampleRate: + return + self.sampleRate = sampleRate + self.replace(2, FractionalDecimator(Format.FLOAT, 200000.0 / self.sampleRate, prefilter=True)) + self.replace(3, WfmDeemphasis(self.sampleRate, self.tau)) + class Ssb(BaseDemodulatorChain): def __init__(self): diff --git a/csdr/chain/demodulator.py b/csdr/chain/demodulator.py index 64399b6..034540c 100644 --- a/csdr/chain/demodulator.py +++ b/csdr/chain/demodulator.py @@ -43,6 +43,12 @@ class SecondarySelectorChain(ABC): pass +class DeemphasisTauChain(ABC): + @abstractmethod + def setDeemphasisTau(self, tau: float) -> None: + pass + + class BaseDemodulatorChain(Chain): def supportsSquelch(self) -> bool: return True diff --git a/owrx/dsp.py b/owrx/dsp.py index ba493fd..be7e5d9 100644 --- a/owrx/dsp.py +++ b/owrx/dsp.py @@ -3,7 +3,7 @@ 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, MetaProvider, SlotFilterChain, SecondarySelectorChain +from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, SecondaryDemodulator, DialFrequencyReceiver, MetaProvider, SlotFilterChain, SecondarySelectorChain, DeemphasisTauChain from csdr.chain.selector import Selector, SecondarySelector from csdr.chain.clientaudio import ClientAudioChain from csdr.chain.fft import FftChain @@ -33,6 +33,7 @@ class ClientDemodulatorChain(Chain): self.secondaryDemodulator = None self.centerFrequency = None self.frequencyOffset = None + self.wfmDeemphasisTau = 50e-6 inputRate = demod.getFixedAudioRate() if isinstance(demod, FixedAudioRateChain) else outputRate oRate = hdOutputRate if isinstance(demod, HdAudio) else outputRate self.clientAudioChain = ClientAudioChain(demod.getOutputFormat(), inputRate, oRate, audioCompression) @@ -106,6 +107,9 @@ class ClientDemodulatorChain(Chain): else: self.clientAudioChain.setInputRate(outputRate) + if isinstance(self.demodulator, DeemphasisTauChain): + self.demodulator.setDeemphasisTau(self.wfmDeemphasisTau) + self._updateDialFrequency() self._syncSquelch() @@ -227,13 +231,7 @@ class ClientDemodulatorChain(Chain): if isinstance(self.demodulator, HdAudio): return - if not isinstance(self.demodulator, FixedIfSampleRateChain): - self.selector.setOutputRate(outputRate) - self.demodulator.setSampleRate(outputRate) - if self.secondaryDemodulator is not None: - self.secondaryDemodulator.setSampleRate(outputRate) - if not isinstance(self.demodulator, FixedAudioRateChain): - self.clientAudioChain.setClientRate(outputRate) + self._updateDemodulatorOutputRate(outputRate) def setHdOutputRate(self, outputRate) -> None: if outputRate == self.hdOutputRate: @@ -243,8 +241,14 @@ class ClientDemodulatorChain(Chain): if not isinstance(self.demodulator, HdAudio): return + self._updateDemodulatorOutputRate(outputRate) + + def _updateDemodulatorOutputRate(self, outputRate): if not isinstance(self.demodulator, FixedIfSampleRateChain): self.selector.setOutputRate(outputRate) + self.demodulator.setSampleRate(outputRate) + if self.secondaryDemodulator is not None: + self.secondaryDemodulator.setSampleRate(outputRate) if not isinstance(self.demodulator, FixedAudioRateChain): self.clientAudioChain.setClientRate(outputRate) @@ -330,6 +334,13 @@ class ClientDemodulatorChain(Chain): return Format.CHAR return Format.SHORT + def setWfmDeemphasisTau(self, tau: float) -> None: + if tau == self.wfmDeemphasisTau: + return + self.wfmDeemphasisTau = tau + if isinstance(self.demodulator, DeemphasisTauChain): + self.demodulator.setDeemphasisTau(self.wfmDeemphasisTau) + class ModulationValidator(OrValidator): """ @@ -433,13 +444,9 @@ class DspManager(SdrSourceEventClient): self.props.wireProperty("high_cut", self.chain.setHighCut), self.props.wireProperty("mod", self.setDemodulator), self.props.wireProperty("dmr_filter", self.chain.setSlotFilter), - # TODO - # self.props.wireProperty("wfm_deemphasis_tau", self.dsp.set_wfm_deemphasis_tau), + self.props.wireProperty("wfm_deemphasis_tau", self.chain.setWfmDeemphasisTau), ] - # TODO - # sp.set_temporary_directory(CoreConfig().get_temporary_directory()) - def set_secondary_mod(mod): if mod == False: mod = None