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
This commit is contained in:
Jakob Ketterl 2021-12-23 16:32:51 +01:00
parent 40c68933e1
commit 46c78f6463
2 changed files with 29 additions and 0 deletions

14
csdr/chain/dummy.py Normal file
View File

@ -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

View File

@ -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: