from csdr.chain import Chain from pycsdr.modules import Module, Shift, FirDecimate, Bandpass, Squelch, FractionalDecimator from abc import ABCMeta, abstractmethod class Demodulator(Chain, metaclass=ABCMeta): @abstractmethod def setLastDecimation(self, decimation: Module): pass class DemodulatorChain(Chain): def __init__(self, samp_rate: int, audioRate: int, shiftRate: float, demodulator: Demodulator): self.shift = Shift(shiftRate) decimation, fraction = self._getDecimation(samp_rate, audioRate) if_samp_rate = samp_rate / decimation transition = 0.15 * (if_samp_rate / float(samp_rate)) self.decimation = FirDecimate(decimation, transition) bp_transition = 320.0 / if_samp_rate self.bandpass = Bandpass(transition=bp_transition, use_fft=True) self.squelch = Squelch(5) if fraction != 1.0: demodulator.setLastDecimation(FractionalDecimator(fraction)) workers = [ self.shift, self.decimation, self.bandpass, self.squelch, demodulator ] super().__init__(*workers) def setShiftRate(self, rate: float): self.shift.setRate(rate) def setSquelchLevel(self, level: float): self.squelch.setSquelchLevel(level) def setBandpass(self, low_cut: float, high_cut: float): self.bandpass.setBandpass(low_cut, high_cut) def _getDecimation(self, input_rate, output_rate): if output_rate <= 0: raise ValueError("invalid output rate: {rate}".format(rate=output_rate)) decimation = 1 target_rate = output_rate while input_rate / (decimation + 1) >= target_rate: decimation += 1 fraction = float(input_rate / decimation) / output_rate return decimation, fraction