work on some todos
This commit is contained in:
parent
5b1000df87
commit
edace3d451
@ -83,3 +83,14 @@ class FftChain(Chain):
|
||||
self._setBlockSize(self.sampleRate / self.fps)
|
||||
else:
|
||||
self._setBlockSize(self.sampleRate / self.fps / fftAverages)
|
||||
|
||||
def setCompression(self, compression: str) -> None:
|
||||
if compression == "adpcm" and not self.compressFftAdpcm:
|
||||
self.compressFftAdpcm = FftAdpcm(self.size)
|
||||
# should always be at the end
|
||||
self.append(self.compressFftAdpcm)
|
||||
elif compression == "none" and self.compressFftAdpcm:
|
||||
self.compressFftAdpcm.stop()
|
||||
self.compressFftAdpcm = None
|
||||
# should always be at that position (right?)
|
||||
self.remove(3)
|
||||
|
125
owrx/dsp.py
125
owrx/dsp.py
@ -36,6 +36,10 @@ class ClientDemodulatorChain(Chain):
|
||||
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)
|
||||
self.secondaryFftSize = 2048
|
||||
self.secondaryFftOverlapFactor = 0.3
|
||||
self.secondaryFftFps = 9
|
||||
self.secondaryFftCompression = "adpcm"
|
||||
self.secondaryFftChain = None
|
||||
self.metaWriter = None
|
||||
self.secondaryFftWriter = None
|
||||
@ -157,14 +161,18 @@ class ClientDemodulatorChain(Chain):
|
||||
self.secondaryFftChain = None
|
||||
|
||||
if self.secondaryDemodulator is not None and self.secondaryFftChain is None:
|
||||
# TODO eliminate constants
|
||||
self.secondaryFftChain = FftChain(self._getSelectorOutputRate(), 2048, 0.3, 9, "adpcm")
|
||||
self.secondaryFftChain.setReader(self.selectorBuffer.getReader())
|
||||
self.secondaryFftChain.setWriter(self.secondaryFftWriter)
|
||||
self._createSecondaryFftChain()
|
||||
|
||||
if self.secondaryFftChain is not None:
|
||||
self.secondaryFftChain.setSampleRate(rate)
|
||||
|
||||
def _createSecondaryFftChain(self):
|
||||
if self.secondaryFftChain is not None:
|
||||
self.secondaryFftChain.stop()
|
||||
self.secondaryFftChain = FftChain(self._getSelectorOutputRate(), self.secondaryFftSize, self.secondaryFftOverlapFactor, self.secondaryFftFps, self.secondaryFftCompression)
|
||||
self.secondaryFftChain.setReader(self.selectorBuffer.getReader())
|
||||
self.secondaryFftChain.setWriter(self.secondaryFftWriter)
|
||||
|
||||
def _syncSquelch(self):
|
||||
if not self.demodulator.supportsSquelch() or (self.secondaryDemodulator is not None and not self.secondaryDemodulator.supportsSquelch()):
|
||||
self.selector.setSquelchLevel(-150)
|
||||
@ -245,7 +253,6 @@ class ClientDemodulatorChain(Chain):
|
||||
return
|
||||
self.sampleRate = sampleRate
|
||||
self.selector.setInputRate(sampleRate)
|
||||
# TODO update secondary FFT
|
||||
|
||||
def setPowerWriter(self, writer: Writer) -> None:
|
||||
self.selector.setPowerWriter(writer)
|
||||
@ -278,8 +285,12 @@ class ClientDemodulatorChain(Chain):
|
||||
self.demodulator.setSlotFilter(filter)
|
||||
|
||||
def setSecondaryFftSize(self, size: int) -> None:
|
||||
# TODO
|
||||
pass
|
||||
if size == self.secondaryFftSize:
|
||||
return
|
||||
self.secondaryFftSize = size
|
||||
if not self.secondaryFftChain:
|
||||
return
|
||||
self._createSecondaryFftChain()
|
||||
|
||||
def setSecondaryFrequencyOffset(self, freq: int) -> None:
|
||||
if self.secondaryFrequencyOffset == freq:
|
||||
@ -290,6 +301,35 @@ class ClientDemodulatorChain(Chain):
|
||||
return
|
||||
self.secondarySelector.setFrequencyOffset(self.secondaryFrequencyOffset)
|
||||
|
||||
def setSecondaryFftCompression(self, compression: str) -> None:
|
||||
if compression == self.secondaryFftCompression:
|
||||
return
|
||||
self.secondaryFftCompression = compression
|
||||
if not self.secondaryFftChain:
|
||||
return
|
||||
self.secondaryFftChain.setCompression(self.secondaryFftCompression)
|
||||
|
||||
def setSecondaryFftOverlapFactor(self, overlap: float) -> None:
|
||||
if overlap == self.secondaryFftOverlapFactor:
|
||||
return
|
||||
self.secondaryFftOverlapFactor = overlap
|
||||
if not self.secondaryFftChain:
|
||||
return
|
||||
self.secondaryFftChain.setVOverlapFactor(self.secondaryFftOverlapFactor)
|
||||
|
||||
def setSecondaryFftFps(self, fps: int) -> None:
|
||||
if fps == self.secondaryFftFps:
|
||||
return
|
||||
self.secondaryFftFps = fps
|
||||
if not self.secondaryFftChain:
|
||||
return
|
||||
self.secondaryFftChain.setFps(self.secondaryFftFps)
|
||||
|
||||
def getSecondaryFftOutputFormat(self) -> Format:
|
||||
if self.secondaryFftCompression == "adpcm":
|
||||
return Format.CHAR
|
||||
return Format.SHORT
|
||||
|
||||
|
||||
class ModulationValidator(OrValidator):
|
||||
"""
|
||||
@ -307,6 +347,9 @@ class DspManager(SdrSourceEventClient):
|
||||
|
||||
self.props = PropertyStack()
|
||||
|
||||
# current audio mode. should be "audio" or "hd_audio" depending on what demodulatur is in use.
|
||||
self.audioOutput = None
|
||||
|
||||
# local demodulator properties not forwarded to the sdr
|
||||
# ensure strict validation since these can be set from the client
|
||||
# and are used to build executable commands
|
||||
@ -361,34 +404,6 @@ class DspManager(SdrSourceEventClient):
|
||||
|
||||
self.readers = {}
|
||||
|
||||
# wire audio output
|
||||
buffer = Buffer(self.chain.getOutputFormat())
|
||||
self.chain.setWriter(buffer)
|
||||
# TODO check for hd audio
|
||||
self.wireOutput("audio", buffer)
|
||||
|
||||
# wire power level output
|
||||
buffer = Buffer(Format.FLOAT)
|
||||
self.chain.setPowerWriter(buffer)
|
||||
self.wireOutput("smeter", buffer)
|
||||
|
||||
# wire meta output
|
||||
buffer = Buffer(Format.CHAR)
|
||||
self.chain.setMetaWriter(buffer)
|
||||
self.wireOutput("meta", buffer)
|
||||
|
||||
# wire secondary FFT
|
||||
# TODO format is different depending on compression
|
||||
buffer = Buffer(Format.CHAR)
|
||||
self.chain.setSecondaryFftWriter(buffer)
|
||||
self.wireOutput("secondary_fft", buffer)
|
||||
|
||||
# wire secondary demodulator
|
||||
buffer = Buffer(Format.CHAR)
|
||||
self.chain.setSecondaryWriter(buffer)
|
||||
# TODO there's multiple outputs depending on the modulation right now
|
||||
self.wireOutput("secondary_demod", buffer)
|
||||
|
||||
if "start_mod" in self.props:
|
||||
self.setDemodulator(self.props["start_mod"])
|
||||
mode = Modes.findByModulation(self.props["start_mod"])
|
||||
@ -404,8 +419,9 @@ class DspManager(SdrSourceEventClient):
|
||||
|
||||
self.subscriptions = [
|
||||
self.props.wireProperty("audio_compression", self.setAudioCompression),
|
||||
# probably unused:
|
||||
# self.props.wireProperty("fft_compression", self.dsp.set_fft_compression),
|
||||
self.props.wireProperty("fft_compression", self.chain.setSecondaryFftCompression),
|
||||
self.props.wireProperty("fft_voverlap_factor", self.chain.setSecondaryFftOverlapFactor),
|
||||
self.props.wireProperty("fft_fps", self.chain.setSecondaryFftFps),
|
||||
self.props.wireProperty("digimodes_fft_size", self.chain.setSecondaryFftSize),
|
||||
self.props.wireProperty("samp_rate", self.chain.setSampleRate),
|
||||
self.props.wireProperty("output_rate", self.chain.setOutputRate),
|
||||
@ -437,6 +453,26 @@ class DspManager(SdrSourceEventClient):
|
||||
self.props.wireProperty("secondary_offset_freq", self.chain.setSecondaryFrequencyOffset),
|
||||
]
|
||||
|
||||
# wire power level output
|
||||
buffer = Buffer(Format.FLOAT)
|
||||
self.chain.setPowerWriter(buffer)
|
||||
self.wireOutput("smeter", buffer)
|
||||
|
||||
# wire meta output
|
||||
buffer = Buffer(Format.CHAR)
|
||||
self.chain.setMetaWriter(buffer)
|
||||
self.wireOutput("meta", buffer)
|
||||
|
||||
# wire secondary FFT
|
||||
buffer = Buffer(self.chain.getSecondaryFftOutputFormat())
|
||||
self.chain.setSecondaryFftWriter(buffer)
|
||||
self.wireOutput("secondary_fft", buffer)
|
||||
|
||||
# wire secondary demodulator
|
||||
buffer = Buffer(Format.CHAR)
|
||||
self.chain.setSecondaryWriter(buffer)
|
||||
self.wireOutput("secondary_demod", buffer)
|
||||
|
||||
self.startOnAvailable = False
|
||||
|
||||
self.sdrSource.addClient(self)
|
||||
@ -487,13 +523,14 @@ class DspManager(SdrSourceEventClient):
|
||||
raise ValueError("unsupported demodulator: {}".format(mod))
|
||||
self.chain.setDemodulator(demodulator)
|
||||
|
||||
# re-wire the audio to the correct client API
|
||||
buffer = Buffer(self.chain.getOutputFormat())
|
||||
self.chain.setWriter(buffer)
|
||||
if isinstance(demodulator, HdAudio):
|
||||
self.wireOutput("hd_audio", buffer)
|
||||
else:
|
||||
self.wireOutput("audio", buffer)
|
||||
output = "hd_audio" if isinstance(demodulator, HdAudio) else "audio"
|
||||
|
||||
if output != self.audioOutput:
|
||||
self.audioOutput = output
|
||||
# re-wire the audio to the correct client API
|
||||
buffer = Buffer(self.chain.getOutputFormat())
|
||||
self.chain.setWriter(buffer)
|
||||
self.wireOutput(self.audioOutput, buffer)
|
||||
|
||||
def sendSecondaryConfig(self):
|
||||
self.handler.write_secondary_dsp_config(
|
||||
|
@ -47,11 +47,12 @@ class SpectrumThread(SdrSourceEventClient):
|
||||
self.sdrSource.addClient(self)
|
||||
|
||||
self.subscriptions += [
|
||||
self.props.filter("fft_size", "fft_compression").wire(self.restart),
|
||||
self.props.filter("fft_size").wire(self.restart),
|
||||
# these props can be set on the fly
|
||||
self.props.wireProperty("samp_rate", self.dsp.setSampleRate),
|
||||
self.props.wireProperty("fft_fps", self.dsp.setFps),
|
||||
self.props.wireProperty("fft_voverlap_factor", self.dsp.setVOverlapFactor),
|
||||
self.props.wireProperty("fft_compression", self.dsp.setCompression),
|
||||
]
|
||||
|
||||
buffer = Buffer(self.dsp.getOutputFormat())
|
||||
|
Loading…
Reference in New Issue
Block a user