openwebrx-clone/owrx/fft.py

92 lines
2.9 KiB
Python
Raw Normal View History

from owrx.config import Config, CoreConfig
from csdr import csdr
import threading
from owrx.source import SdrSource, SdrSourceEventClient
from owrx.property import PropertyStack
import logging
logger = logging.getLogger(__name__)
class SpectrumThread(csdr.output, SdrSourceEventClient):
def __init__(self, sdrSource):
self.sdrSource = sdrSource
super().__init__()
stack = PropertyStack()
stack.addLayer(0, self.sdrSource.props)
stack.addLayer(1, Config.get())
2020-03-24 21:16:11 +00:00
self.props = props = stack.filter(
"samp_rate",
"fft_size",
"fft_fps",
"fft_voverlap_factor",
"fft_compression",
"csdr_dynamic_bufsize",
"csdr_print_bufsizes",
"csdr_through",
)
self.dsp = dsp = csdr.dsp(self)
dsp.nc_port = self.sdrSource.getPort()
dsp.set_demodulator("fft")
2020-12-30 16:18:46 +00:00
def set_fft_averages(changes=None):
samp_rate = props["samp_rate"]
fft_size = props["fft_size"]
fft_fps = props["fft_fps"]
fft_voverlap_factor = props["fft_voverlap_factor"]
dsp.set_fft_averages(
int(round(1.0 * samp_rate / fft_size / fft_fps / (1.0 - fft_voverlap_factor)))
if fft_voverlap_factor > 0
else 0
)
self.subscriptions = [
props.wireProperty("samp_rate", dsp.set_samp_rate),
props.wireProperty("fft_size", dsp.set_fft_size),
props.wireProperty("fft_fps", dsp.set_fft_fps),
props.wireProperty("fft_compression", dsp.set_fft_compression),
2020-03-24 21:16:11 +00:00
props.filter("samp_rate", "fft_size", "fft_fps", "fft_voverlap_factor").wire(set_fft_averages),
]
2020-12-30 16:18:46 +00:00
set_fft_averages()
dsp.csdr_dynamic_bufsize = props["csdr_dynamic_bufsize"]
dsp.csdr_print_bufsizes = props["csdr_print_bufsizes"]
dsp.csdr_through = props["csdr_through"]
dsp.set_temporary_directory(CoreConfig().get_temporary_directory())
logger.debug("Spectrum thread initialized successfully.")
def start(self):
self.sdrSource.addClient(self)
if self.sdrSource.isAvailable():
self.dsp.start()
def supports_type(self, t):
return t == "audio"
def receive_output(self, type, read_fn):
threading.Thread(target=self.pump(read_fn, self.sdrSource.writeSpectrumData)).start()
def stop(self):
self.dsp.stop()
self.sdrSource.removeClient(self)
for c in self.subscriptions:
c.cancel()
self.subscriptions = []
def getClientClass(self):
return SdrSource.CLIENT_USER
def onStateChange(self, state):
if state in [SdrSource.STATE_STOPPING, SdrSource.STATE_FAILED]:
self.dsp.stop()
elif state == SdrSource.STATE_RUNNING:
self.dsp.start()
def onBusyStateChange(self, state):
pass