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)
|
self._setBlockSize(self.sampleRate / self.fps)
|
||||||
else:
|
else:
|
||||||
self._setBlockSize(self.sampleRate / self.fps / fftAverages)
|
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)
|
||||||
|
119
owrx/dsp.py
119
owrx/dsp.py
@ -36,6 +36,10 @@ class ClientDemodulatorChain(Chain):
|
|||||||
inputRate = demod.getFixedAudioRate() if isinstance(demod, FixedAudioRateChain) else outputRate
|
inputRate = demod.getFixedAudioRate() if isinstance(demod, FixedAudioRateChain) else outputRate
|
||||||
oRate = hdOutputRate if isinstance(demod, HdAudio) else outputRate
|
oRate = hdOutputRate if isinstance(demod, HdAudio) else outputRate
|
||||||
self.clientAudioChain = ClientAudioChain(demod.getOutputFormat(), inputRate, oRate, audioCompression)
|
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.secondaryFftChain = None
|
||||||
self.metaWriter = None
|
self.metaWriter = None
|
||||||
self.secondaryFftWriter = None
|
self.secondaryFftWriter = None
|
||||||
@ -157,14 +161,18 @@ class ClientDemodulatorChain(Chain):
|
|||||||
self.secondaryFftChain = None
|
self.secondaryFftChain = None
|
||||||
|
|
||||||
if self.secondaryDemodulator is not None and self.secondaryFftChain is None:
|
if self.secondaryDemodulator is not None and self.secondaryFftChain is None:
|
||||||
# TODO eliminate constants
|
self._createSecondaryFftChain()
|
||||||
self.secondaryFftChain = FftChain(self._getSelectorOutputRate(), 2048, 0.3, 9, "adpcm")
|
|
||||||
self.secondaryFftChain.setReader(self.selectorBuffer.getReader())
|
|
||||||
self.secondaryFftChain.setWriter(self.secondaryFftWriter)
|
|
||||||
|
|
||||||
if self.secondaryFftChain is not None:
|
if self.secondaryFftChain is not None:
|
||||||
self.secondaryFftChain.setSampleRate(rate)
|
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):
|
def _syncSquelch(self):
|
||||||
if not self.demodulator.supportsSquelch() or (self.secondaryDemodulator is not None and not self.secondaryDemodulator.supportsSquelch()):
|
if not self.demodulator.supportsSquelch() or (self.secondaryDemodulator is not None and not self.secondaryDemodulator.supportsSquelch()):
|
||||||
self.selector.setSquelchLevel(-150)
|
self.selector.setSquelchLevel(-150)
|
||||||
@ -245,7 +253,6 @@ class ClientDemodulatorChain(Chain):
|
|||||||
return
|
return
|
||||||
self.sampleRate = sampleRate
|
self.sampleRate = sampleRate
|
||||||
self.selector.setInputRate(sampleRate)
|
self.selector.setInputRate(sampleRate)
|
||||||
# TODO update secondary FFT
|
|
||||||
|
|
||||||
def setPowerWriter(self, writer: Writer) -> None:
|
def setPowerWriter(self, writer: Writer) -> None:
|
||||||
self.selector.setPowerWriter(writer)
|
self.selector.setPowerWriter(writer)
|
||||||
@ -278,8 +285,12 @@ class ClientDemodulatorChain(Chain):
|
|||||||
self.demodulator.setSlotFilter(filter)
|
self.demodulator.setSlotFilter(filter)
|
||||||
|
|
||||||
def setSecondaryFftSize(self, size: int) -> None:
|
def setSecondaryFftSize(self, size: int) -> None:
|
||||||
# TODO
|
if size == self.secondaryFftSize:
|
||||||
pass
|
return
|
||||||
|
self.secondaryFftSize = size
|
||||||
|
if not self.secondaryFftChain:
|
||||||
|
return
|
||||||
|
self._createSecondaryFftChain()
|
||||||
|
|
||||||
def setSecondaryFrequencyOffset(self, freq: int) -> None:
|
def setSecondaryFrequencyOffset(self, freq: int) -> None:
|
||||||
if self.secondaryFrequencyOffset == freq:
|
if self.secondaryFrequencyOffset == freq:
|
||||||
@ -290,6 +301,35 @@ class ClientDemodulatorChain(Chain):
|
|||||||
return
|
return
|
||||||
self.secondarySelector.setFrequencyOffset(self.secondaryFrequencyOffset)
|
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):
|
class ModulationValidator(OrValidator):
|
||||||
"""
|
"""
|
||||||
@ -307,6 +347,9 @@ class DspManager(SdrSourceEventClient):
|
|||||||
|
|
||||||
self.props = PropertyStack()
|
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
|
# local demodulator properties not forwarded to the sdr
|
||||||
# ensure strict validation since these can be set from the client
|
# ensure strict validation since these can be set from the client
|
||||||
# and are used to build executable commands
|
# and are used to build executable commands
|
||||||
@ -361,34 +404,6 @@ class DspManager(SdrSourceEventClient):
|
|||||||
|
|
||||||
self.readers = {}
|
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:
|
if "start_mod" in self.props:
|
||||||
self.setDemodulator(self.props["start_mod"])
|
self.setDemodulator(self.props["start_mod"])
|
||||||
mode = Modes.findByModulation(self.props["start_mod"])
|
mode = Modes.findByModulation(self.props["start_mod"])
|
||||||
@ -404,8 +419,9 @@ class DspManager(SdrSourceEventClient):
|
|||||||
|
|
||||||
self.subscriptions = [
|
self.subscriptions = [
|
||||||
self.props.wireProperty("audio_compression", self.setAudioCompression),
|
self.props.wireProperty("audio_compression", self.setAudioCompression),
|
||||||
# probably unused:
|
self.props.wireProperty("fft_compression", self.chain.setSecondaryFftCompression),
|
||||||
# self.props.wireProperty("fft_compression", self.dsp.set_fft_compression),
|
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("digimodes_fft_size", self.chain.setSecondaryFftSize),
|
||||||
self.props.wireProperty("samp_rate", self.chain.setSampleRate),
|
self.props.wireProperty("samp_rate", self.chain.setSampleRate),
|
||||||
self.props.wireProperty("output_rate", self.chain.setOutputRate),
|
self.props.wireProperty("output_rate", self.chain.setOutputRate),
|
||||||
@ -437,6 +453,26 @@ class DspManager(SdrSourceEventClient):
|
|||||||
self.props.wireProperty("secondary_offset_freq", self.chain.setSecondaryFrequencyOffset),
|
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.startOnAvailable = False
|
||||||
|
|
||||||
self.sdrSource.addClient(self)
|
self.sdrSource.addClient(self)
|
||||||
@ -487,13 +523,14 @@ class DspManager(SdrSourceEventClient):
|
|||||||
raise ValueError("unsupported demodulator: {}".format(mod))
|
raise ValueError("unsupported demodulator: {}".format(mod))
|
||||||
self.chain.setDemodulator(demodulator)
|
self.chain.setDemodulator(demodulator)
|
||||||
|
|
||||||
|
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
|
# re-wire the audio to the correct client API
|
||||||
buffer = Buffer(self.chain.getOutputFormat())
|
buffer = Buffer(self.chain.getOutputFormat())
|
||||||
self.chain.setWriter(buffer)
|
self.chain.setWriter(buffer)
|
||||||
if isinstance(demodulator, HdAudio):
|
self.wireOutput(self.audioOutput, buffer)
|
||||||
self.wireOutput("hd_audio", buffer)
|
|
||||||
else:
|
|
||||||
self.wireOutput("audio", buffer)
|
|
||||||
|
|
||||||
def sendSecondaryConfig(self):
|
def sendSecondaryConfig(self):
|
||||||
self.handler.write_secondary_dsp_config(
|
self.handler.write_secondary_dsp_config(
|
||||||
|
@ -47,11 +47,12 @@ class SpectrumThread(SdrSourceEventClient):
|
|||||||
self.sdrSource.addClient(self)
|
self.sdrSource.addClient(self)
|
||||||
|
|
||||||
self.subscriptions += [
|
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
|
# these props can be set on the fly
|
||||||
self.props.wireProperty("samp_rate", self.dsp.setSampleRate),
|
self.props.wireProperty("samp_rate", self.dsp.setSampleRate),
|
||||||
self.props.wireProperty("fft_fps", self.dsp.setFps),
|
self.props.wireProperty("fft_fps", self.dsp.setFps),
|
||||||
self.props.wireProperty("fft_voverlap_factor", self.dsp.setVOverlapFactor),
|
self.props.wireProperty("fft_voverlap_factor", self.dsp.setVOverlapFactor),
|
||||||
|
self.props.wireProperty("fft_compression", self.dsp.setCompression),
|
||||||
]
|
]
|
||||||
|
|
||||||
buffer = Buffer(self.dsp.getOutputFormat())
|
buffer = Buffer(self.dsp.getOutputFormat())
|
||||||
|
Loading…
Reference in New Issue
Block a user