preliminary work to allow dynamic audio format switching

This commit is contained in:
Jakob Ketterl 2024-07-10 13:49:40 +02:00
parent a9f47be96d
commit 853ee5b024
4 changed files with 57 additions and 8 deletions

View file

@ -1,4 +1,4 @@
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, \
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, DynamicAudioRateChain, HdAudio, \
MetaProvider, DabServiceSelector, DialFrequencyReceiver
from csdr.module import PickleModule
from csdreti.modules import EtiDecoder
@ -58,8 +58,10 @@ class MetaProcessor(PickleModule):
self.shifter.setRate(0)
class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, MetaProvider, DabServiceSelector, DialFrequencyReceiver):
class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, DynamicAudioRateChain, HdAudio, MetaProvider, DabServiceSelector, DialFrequencyReceiver):
def __init__(self):
self.audioRate = 48000
shift = Shift(0)
self.decoder = EtiDecoder()
@ -77,7 +79,7 @@ class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain,
shift,
self.decoder,
self.dablin,
Downmix(Format.FLOAT),
Downmix(Format.SHORT),
]
super().__init__(workers)
@ -90,8 +92,8 @@ class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain,
def getFixedIfSampleRate(self) -> int:
return 2048000
def getFixedAudioRate(self) -> int:
return 48000
def getAudioRate(self) -> int:
return self.audioRate
def stop(self):
self.processor.stop()

View file

@ -2,6 +2,10 @@ from csdr.chain import Chain
from abc import ABC, ABCMeta, abstractmethod
from pycsdr.modules import Writer
import logging
logger = logging.getLogger(__name__)
class FixedAudioRateChain(ABC):
@abstractmethod
@ -9,6 +13,39 @@ class FixedAudioRateChain(ABC):
pass
class DynamicAudioRateListener(ABC):
@abstractmethod
def onAudioRateChange(self, rate: int):
pass
class DynamicAudioRateChain(ABC):
def __init__(self):
self.listeners = []
super().__init__()
def addListener(self, listener: DynamicAudioRateListener):
if listener in self.listeners:
return
self.listeners.append(listener)
def removeListener(self, listener: DynamicAudioRateListener):
if listener not in self.listeners:
return
self.listeners.remove(listener)
def fireAudioRateChange(self, rate: int):
for listener in self.listeners:
try:
listener.onAudioRateChange(rate)
except:
logger.exception("error while sending audio rate change")
@abstractmethod
def getAudioRate(self) -> int:
pass
class FixedIfSampleRateChain(ABC):
@abstractmethod
def getFixedIfSampleRate(self) -> int:

View file

@ -7,7 +7,7 @@ class DablinModule(ExecModule):
self.serviceId = 0
super().__init__(
Format.CHAR,
Format.FLOAT,
Format.SHORT,
self._buildArgs()
)

View file

@ -5,7 +5,7 @@ from owrx.modes import Modes, DigitalMode
from csdr.chain import Chain
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, \
SecondaryDemodulator, DialFrequencyReceiver, MetaProvider, SlotFilterChain, SecondarySelectorChain, \
DeemphasisTauChain, DemodulatorError, RdsChain, DabServiceSelector
DeemphasisTauChain, DemodulatorError, RdsChain, DabServiceSelector, DynamicAudioRateChain, DynamicAudioRateListener
from csdr.chain.selector import Selector, SecondarySelector
from csdr.chain.clientaudio import ClientAudioChain
from csdr.chain.fft import FftChain
@ -35,7 +35,7 @@ class ClientDemodulatorSecondaryDspEventClient(ABC):
pass
class ClientDemodulatorChain(Chain):
class ClientDemodulatorChain(Chain, DynamicAudioRateListener):
def __init__(self, demod: BaseDemodulatorChain, sampleRate: int, outputRate: int, hdOutputRate: int, audioCompression: str, secondaryDspEventReceiver: ClientDemodulatorSecondaryDspEventClient):
self.sampleRate = sampleRate
self.outputRate = outputRate
@ -101,11 +101,16 @@ class ClientDemodulatorChain(Chain):
if self.demodulator is not None:
self.demodulator.stop()
if isinstance(self.demodulator, DynamicAudioRateChain):
self.demodulator.removeListener(self)
self.demodulator = demodulator
self.selector.setOutputRate(self._getSelectorOutputRate())
if isinstance(self.demodulator, DynamicAudioRateChain):
self.demodulator.addListener(self)
clientRate = self._getClientAudioInputRate()
self.demodulator.setSampleRate(clientRate)
@ -155,6 +160,8 @@ class ClientDemodulatorChain(Chain):
def _getClientAudioInputRate(self):
if isinstance(self.demodulator, FixedAudioRateChain):
return self.demodulator.getFixedAudioRate()
elif isinstance(self.demodulator, DynamicAudioRateChain):
return self.demodulator.getAudioRate()
elif isinstance(self.secondaryDemodulator, FixedAudioRateChain):
return self.secondaryDemodulator.getFixedAudioRate()
else:
@ -395,6 +402,9 @@ class ClientDemodulatorChain(Chain):
if isinstance(self.demodulator, RdsChain):
self.demodulator.setRdsRbds(self.rdsRbds)
def onAudioRateChange(self, rate: int):
self.clientAudioChain.setInputRate(self._getClientAudioInputRate())
class ModulationValidator(OrValidator):
"""