first steps adding RDS decoding with redsea

This commit is contained in:
Jakob Ketterl 2024-01-18 02:07:55 +01:00
parent 6aabff034a
commit 71f1b3dfb1
4 changed files with 62 additions and 4 deletions

View file

@ -1,6 +1,10 @@
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, HdAudio, DeemphasisTauChain
from pycsdr.modules import AmDemod, DcBlock, FmDemod, Limit, NfmDeemphasis, Agc, WfmDeemphasis, FractionalDecimator, RealPart
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, HdAudio, DeemphasisTauChain, MetaProvider
from pycsdr.modules import AmDemod, DcBlock, FmDemod, Limit, NfmDeemphasis, Agc, WfmDeemphasis, FractionalDecimator, \
RealPart, Writer, Buffer
from pycsdr.types import Format, AgcProfile
from csdr.chain.redsea import Redsea
from typing import Optional
from owrx.feature import FeatureDetector
class Am(BaseDemodulatorChain):
@ -38,18 +42,27 @@ class NFm(BaseDemodulatorChain):
self.replace(2, NfmDeemphasis(sampleRate))
class WFm(BaseDemodulatorChain, FixedIfSampleRateChain, DeemphasisTauChain, HdAudio):
class WFm(BaseDemodulatorChain, FixedIfSampleRateChain, DeemphasisTauChain, HdAudio, MetaProvider):
def __init__(self, sampleRate: int, tau: float):
self.sampleRate = sampleRate
self.tau = tau
self.limit = Limit()
# this buffer is used to tap into the raw audio stream for redsea RDS decoding
self.metaTapBuffer = Buffer(Format.FLOAT)
workers = [
FmDemod(),
Limit(),
self.limit,
FractionalDecimator(Format.FLOAT, 200000.0 / self.sampleRate, prefilter=True),
WfmDeemphasis(self.sampleRate, self.tau),
]
self.metaChain = None
super().__init__(workers)
def _connect(self, w1, w2, buffer: Optional[Buffer] = None) -> None:
if w1 is self.limit:
buffer = self.metaTapBuffer
super()._connect(w1, w2, buffer)
def getFixedIfSampleRate(self):
return 200000
@ -66,6 +79,14 @@ class WFm(BaseDemodulatorChain, FixedIfSampleRateChain, DeemphasisTauChain, HdAu
self.replace(2, FractionalDecimator(Format.FLOAT, 200000.0 / self.sampleRate, prefilter=True))
self.replace(3, WfmDeemphasis(self.sampleRate, self.tau))
def setMetaWriter(self, writer: Writer) -> None:
if not FeatureDetector().is_available("redsea"):
return
if self.metaChain is None:
self.metaChain = Redsea(self.getFixedIfSampleRate())
self.metaChain.setReader(self.metaTapBuffer.getReader())
self.metaChain.setWriter(writer)
class Ssb(BaseDemodulatorChain):
def __init__(self):

14
csdr/chain/redsea.py Normal file
View file

@ -0,0 +1,14 @@
from csdr.chain import Chain
from pycsdr.modules import Convert
from pycsdr.types import Format
from owrx.rds.redsea import RedseaModule
from csdr.module import JsonParser
class Redsea(Chain):
def __init__(self, sampleRate: int):
super().__init__([
Convert(Format.FLOAT, Format.SHORT),
RedseaModule(sampleRate),
JsonParser("RDS"),
])

View file

@ -89,6 +89,7 @@ class FeatureDetector(object):
"ism": ["rtl_433"],
"dumphfdl": ["dumphfdl"],
"dumpvdl2": ["dumpvdl2"],
"redsea": ["redsea"],
}
def feature_availability(self):
@ -636,3 +637,14 @@ class FeatureDetector(object):
`dumpvdl2`.
"""
return self.command_is_runnable("dumpvdl2 --version")
def has_redsea(self):
"""
OpenWebRX can decode RDS data on WFM broadcast station if the `redsea` decoder is available.
You can find more information [here](https://github.com/windytan/redsea)
If you are using the OpenWebRX Debian or Ubuntu repository, you should be able to install the package
`redsea`.
"""
return self.command_is_runnable("redsea --version")

11
owrx/rds/redsea.py Normal file
View file

@ -0,0 +1,11 @@
from pycsdr.modules import ExecModule
from pycsdr.types import Format
class RedseaModule(ExecModule):
def __init__(self, sampleRate: int):
super().__init__(
Format.SHORT,
Format.CHAR,
["redsea", "--input", "mpx", "--samplerate", str(sampleRate)]
)