implement wfm demodulator chain
This commit is contained in:
parent
da3f59fb9b
commit
448e266097
40
csdr/csdr.py
40
csdr/csdr.py
@ -165,6 +165,7 @@ class dsp(object):
|
||||
def __init__(self, output):
|
||||
self.samp_rate = 250000
|
||||
self.output_rate = 11025
|
||||
self.hd_output_rate = 44100
|
||||
self.fft_size = 1024
|
||||
self.fft_fps = 5
|
||||
self.center_freq = 0
|
||||
@ -273,6 +274,13 @@ class dsp(object):
|
||||
]
|
||||
else:
|
||||
chain += ["csdr convert_f_s16"]
|
||||
elif which == "wfm":
|
||||
chain += ["csdr fmdemod_quadri_cf", "csdr limit_ff"]
|
||||
chain += last_decimation_block
|
||||
chain += [
|
||||
"csdr deemphasis_wfm_ff {audio_rate} 50e-6",
|
||||
"csdr convert_f_s16"
|
||||
]
|
||||
elif self.isDigitalVoice(which):
|
||||
chain += ["csdr fmdemod_quadri_cf", "dc_block "]
|
||||
chain += last_decimation_block
|
||||
@ -305,7 +313,7 @@ class dsp(object):
|
||||
chain += ["csdr amdemod_cf", "csdr fastdcblock_ff"]
|
||||
chain += last_decimation_block
|
||||
chain += ["csdr agc_ff", "csdr limit_ff", "csdr convert_f_s16"]
|
||||
elif which == "freedv":
|
||||
elif self.isFreeDV(which):
|
||||
chain += ["csdr realpart_cf"]
|
||||
chain += last_decimation_block
|
||||
chain += [
|
||||
@ -585,13 +593,18 @@ class dsp(object):
|
||||
def get_output_rate(self):
|
||||
return self.output_rate
|
||||
|
||||
def get_hd_output_rate(self):
|
||||
return self.hd_output_rate
|
||||
|
||||
def get_audio_rate(self):
|
||||
if self.isDigitalVoice() or self.isPacket() or self.isPocsag():
|
||||
return 48000
|
||||
elif self.isWsjtMode() or self.isJs8():
|
||||
return 12000
|
||||
elif self.get_demodulator() == "freedv":
|
||||
elif self.isFreeDV():
|
||||
return 8000
|
||||
elif self.isHdAudio():
|
||||
return self.get_hd_output_rate()
|
||||
return self.get_output_rate()
|
||||
|
||||
def isDigitalVoice(self, demodulator=None):
|
||||
@ -619,6 +632,16 @@ class dsp(object):
|
||||
demodulator = self.get_secondary_demodulator()
|
||||
return demodulator == "pocsag"
|
||||
|
||||
def isFreeDV(self, demodulator=None):
|
||||
if demodulator is None:
|
||||
demodulator = self.get_demodulator()
|
||||
return demodulator == "freedv"
|
||||
|
||||
def isHdAudio(self, demodulator=None):
|
||||
if demodulator is None:
|
||||
demodulator = self.get_demodulator()
|
||||
return demodulator == "wfm"
|
||||
|
||||
def set_output_rate(self, output_rate):
|
||||
if self.output_rate == output_rate:
|
||||
return
|
||||
@ -626,6 +649,12 @@ class dsp(object):
|
||||
self.calculate_decimation()
|
||||
self.restart()
|
||||
|
||||
def set_hd_output_rate(self, hd_output_rate):
|
||||
if self.hd_output_rate == hd_output_rate:
|
||||
return
|
||||
self.hd_output_rate = hd_output_rate
|
||||
self.restart()
|
||||
|
||||
def set_demodulator(self, demodulator):
|
||||
if demodulator in ["usb", "lsb", "cw"]:
|
||||
demodulator = "ssb"
|
||||
@ -685,7 +714,7 @@ class dsp(object):
|
||||
def set_squelch_level(self, squelch_level):
|
||||
self.squelch_level = squelch_level
|
||||
# no squelch required on digital voice modes
|
||||
actual_squelch = -150 if self.isDigitalVoice() or self.isPacket() or self.isPocsag() or self.get_demodulator() == "freedv" else self.squelch_level
|
||||
actual_squelch = -150 if self.isDigitalVoice() or self.isPacket() or self.isPocsag() or self.isFreeDV() else self.squelch_level
|
||||
if self.running:
|
||||
self.pipes["squelch_pipe"].write("%g\n" % (self.convertToLinear(actual_squelch)))
|
||||
|
||||
@ -818,9 +847,10 @@ class dsp(object):
|
||||
|
||||
threading.Thread(target=watch_thread).start()
|
||||
|
||||
if self.output.supports_type("audio"):
|
||||
audio_type = "hd_audio" if self.isHdAudio() else "audio"
|
||||
if self.output.supports_type(audio_type):
|
||||
self.output.send_output(
|
||||
"audio",
|
||||
audio_type,
|
||||
partial(
|
||||
self.process.stdout.read,
|
||||
self.get_fft_bytes_to_read() if self.demodulator == "fft" else self.get_audio_bytes_to_read(),
|
||||
|
@ -238,6 +238,28 @@ AudioEngine.prototype.pushAudio = function(data) {
|
||||
}
|
||||
};
|
||||
|
||||
AudioEngine.prototype.pushHdAudio = function(data) {
|
||||
if (!this.audioNode) return;
|
||||
this.audioBytes.add(data.byteLength);
|
||||
var buffer;
|
||||
if (this.compression === "adpcm") {
|
||||
//resampling & ADPCM
|
||||
buffer = this.audioCodec.decode(new Uint8Array(data));
|
||||
} else {
|
||||
buffer = new Int16Array(data);
|
||||
}
|
||||
buffer = this.hdResampler.process(buffer);
|
||||
if (this.audioNode.port) {
|
||||
// AudioWorklets supported
|
||||
this.audioNode.port.postMessage(buffer);
|
||||
} else {
|
||||
// silently drop excess samples
|
||||
if (this.getBuffersize() + buffer.length <= this.maxBufferSize) {
|
||||
this.audioBuffers.push(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioEngine.prototype.setCompression = function(compression) {
|
||||
this.compression = compression;
|
||||
};
|
||||
|
@ -829,6 +829,10 @@ function on_ws_recv(evt) {
|
||||
secondary_demod_waterfall_add(waterfall_f32);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
// hd audio data
|
||||
audioEngine.pushHdAudio(data);
|
||||
break;
|
||||
default:
|
||||
console.warn('unknown type of binary message: ' + type)
|
||||
}
|
||||
|
@ -299,6 +299,9 @@ class OpenWebRxReceiverClient(OpenWebRxClient):
|
||||
def write_dsp_data(self, data):
|
||||
self.send(bytes([0x02]) + data)
|
||||
|
||||
def write_hd_audio(self, data):
|
||||
self.send(bytes([0x04]) + data)
|
||||
|
||||
def write_s_meter_level(self, level):
|
||||
self.send({"type": "smeter", "value": level})
|
||||
|
||||
|
@ -95,6 +95,7 @@ class DspManager(csdr.output):
|
||||
self.props.wireProperty("digimodes_fft_size", self.dsp.set_secondary_fft_size),
|
||||
self.props.wireProperty("samp_rate", self.dsp.set_samp_rate),
|
||||
self.props.wireProperty("output_rate", self.dsp.set_output_rate),
|
||||
self.props.wireProperty("hd_output_rate", self.dsp.set_hd_output_rate),
|
||||
self.props.wireProperty("offset_freq", self.dsp.set_offset_freq),
|
||||
self.props.wireProperty("center_freq", self.dsp.set_center_freq),
|
||||
self.props.wireProperty("squelch_level", self.dsp.set_squelch_level),
|
||||
@ -147,6 +148,7 @@ class DspManager(csdr.output):
|
||||
logger.debug("adding new output of type %s", t)
|
||||
writers = {
|
||||
"audio": self.handler.write_dsp_data,
|
||||
"hd_audio": self.handler.write_hd_audio,
|
||||
"smeter": self.handler.write_s_meter_level,
|
||||
"secondary_fft": self.handler.write_secondary_fft,
|
||||
"secondary_demod": self.handler.write_secondary_demod,
|
||||
|
@ -40,6 +40,7 @@ class DigitalMode(Mode):
|
||||
class Modes(object):
|
||||
mappings = [
|
||||
AnalogMode("nfm", "FM", bandpass=Bandpass(-4000, 4000)),
|
||||
AnalogMode("wfm", "WFM", bandpass=Bandpass(-16000, 16000)),
|
||||
AnalogMode("am", "AM", bandpass=Bandpass(-4000, 4000)),
|
||||
AnalogMode("lsb", "LSB", bandpass=Bandpass(-3000, -300)),
|
||||
AnalogMode("usb", "USB", bandpass=Bandpass(300, 3000)),
|
||||
|
Loading…
Reference in New Issue
Block a user