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):
|
def __init__(self, output):
|
||||||
self.samp_rate = 250000
|
self.samp_rate = 250000
|
||||||
self.output_rate = 11025
|
self.output_rate = 11025
|
||||||
|
self.hd_output_rate = 44100
|
||||||
self.fft_size = 1024
|
self.fft_size = 1024
|
||||||
self.fft_fps = 5
|
self.fft_fps = 5
|
||||||
self.center_freq = 0
|
self.center_freq = 0
|
||||||
@ -273,6 +274,13 @@ class dsp(object):
|
|||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
chain += ["csdr convert_f_s16"]
|
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):
|
elif self.isDigitalVoice(which):
|
||||||
chain += ["csdr fmdemod_quadri_cf", "dc_block "]
|
chain += ["csdr fmdemod_quadri_cf", "dc_block "]
|
||||||
chain += last_decimation_block
|
chain += last_decimation_block
|
||||||
@ -305,7 +313,7 @@ class dsp(object):
|
|||||||
chain += ["csdr amdemod_cf", "csdr fastdcblock_ff"]
|
chain += ["csdr amdemod_cf", "csdr fastdcblock_ff"]
|
||||||
chain += last_decimation_block
|
chain += last_decimation_block
|
||||||
chain += ["csdr agc_ff", "csdr limit_ff", "csdr convert_f_s16"]
|
chain += ["csdr agc_ff", "csdr limit_ff", "csdr convert_f_s16"]
|
||||||
elif which == "freedv":
|
elif self.isFreeDV(which):
|
||||||
chain += ["csdr realpart_cf"]
|
chain += ["csdr realpart_cf"]
|
||||||
chain += last_decimation_block
|
chain += last_decimation_block
|
||||||
chain += [
|
chain += [
|
||||||
@ -585,13 +593,18 @@ class dsp(object):
|
|||||||
def get_output_rate(self):
|
def get_output_rate(self):
|
||||||
return self.output_rate
|
return self.output_rate
|
||||||
|
|
||||||
|
def get_hd_output_rate(self):
|
||||||
|
return self.hd_output_rate
|
||||||
|
|
||||||
def get_audio_rate(self):
|
def get_audio_rate(self):
|
||||||
if self.isDigitalVoice() or self.isPacket() or self.isPocsag():
|
if self.isDigitalVoice() or self.isPacket() or self.isPocsag():
|
||||||
return 48000
|
return 48000
|
||||||
elif self.isWsjtMode() or self.isJs8():
|
elif self.isWsjtMode() or self.isJs8():
|
||||||
return 12000
|
return 12000
|
||||||
elif self.get_demodulator() == "freedv":
|
elif self.isFreeDV():
|
||||||
return 8000
|
return 8000
|
||||||
|
elif self.isHdAudio():
|
||||||
|
return self.get_hd_output_rate()
|
||||||
return self.get_output_rate()
|
return self.get_output_rate()
|
||||||
|
|
||||||
def isDigitalVoice(self, demodulator=None):
|
def isDigitalVoice(self, demodulator=None):
|
||||||
@ -619,6 +632,16 @@ class dsp(object):
|
|||||||
demodulator = self.get_secondary_demodulator()
|
demodulator = self.get_secondary_demodulator()
|
||||||
return demodulator == "pocsag"
|
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):
|
def set_output_rate(self, output_rate):
|
||||||
if self.output_rate == output_rate:
|
if self.output_rate == output_rate:
|
||||||
return
|
return
|
||||||
@ -626,6 +649,12 @@ class dsp(object):
|
|||||||
self.calculate_decimation()
|
self.calculate_decimation()
|
||||||
self.restart()
|
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):
|
def set_demodulator(self, demodulator):
|
||||||
if demodulator in ["usb", "lsb", "cw"]:
|
if demodulator in ["usb", "lsb", "cw"]:
|
||||||
demodulator = "ssb"
|
demodulator = "ssb"
|
||||||
@ -685,7 +714,7 @@ class dsp(object):
|
|||||||
def set_squelch_level(self, squelch_level):
|
def set_squelch_level(self, squelch_level):
|
||||||
self.squelch_level = squelch_level
|
self.squelch_level = squelch_level
|
||||||
# no squelch required on digital voice modes
|
# 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:
|
if self.running:
|
||||||
self.pipes["squelch_pipe"].write("%g\n" % (self.convertToLinear(actual_squelch)))
|
self.pipes["squelch_pipe"].write("%g\n" % (self.convertToLinear(actual_squelch)))
|
||||||
|
|
||||||
@ -818,9 +847,10 @@ class dsp(object):
|
|||||||
|
|
||||||
threading.Thread(target=watch_thread).start()
|
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(
|
self.output.send_output(
|
||||||
"audio",
|
audio_type,
|
||||||
partial(
|
partial(
|
||||||
self.process.stdout.read,
|
self.process.stdout.read,
|
||||||
self.get_fft_bytes_to_read() if self.demodulator == "fft" else self.get_audio_bytes_to_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) {
|
AudioEngine.prototype.setCompression = function(compression) {
|
||||||
this.compression = compression;
|
this.compression = compression;
|
||||||
};
|
};
|
||||||
|
@ -829,6 +829,10 @@ function on_ws_recv(evt) {
|
|||||||
secondary_demod_waterfall_add(waterfall_f32);
|
secondary_demod_waterfall_add(waterfall_f32);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
// hd audio data
|
||||||
|
audioEngine.pushHdAudio(data);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn('unknown type of binary message: ' + type)
|
console.warn('unknown type of binary message: ' + type)
|
||||||
}
|
}
|
||||||
|
@ -299,6 +299,9 @@ class OpenWebRxReceiverClient(OpenWebRxClient):
|
|||||||
def write_dsp_data(self, data):
|
def write_dsp_data(self, data):
|
||||||
self.send(bytes([0x02]) + data)
|
self.send(bytes([0x02]) + data)
|
||||||
|
|
||||||
|
def write_hd_audio(self, data):
|
||||||
|
self.send(bytes([0x04]) + data)
|
||||||
|
|
||||||
def write_s_meter_level(self, level):
|
def write_s_meter_level(self, level):
|
||||||
self.send({"type": "smeter", "value": 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("digimodes_fft_size", self.dsp.set_secondary_fft_size),
|
||||||
self.props.wireProperty("samp_rate", self.dsp.set_samp_rate),
|
self.props.wireProperty("samp_rate", self.dsp.set_samp_rate),
|
||||||
self.props.wireProperty("output_rate", self.dsp.set_output_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("offset_freq", self.dsp.set_offset_freq),
|
||||||
self.props.wireProperty("center_freq", self.dsp.set_center_freq),
|
self.props.wireProperty("center_freq", self.dsp.set_center_freq),
|
||||||
self.props.wireProperty("squelch_level", self.dsp.set_squelch_level),
|
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)
|
logger.debug("adding new output of type %s", t)
|
||||||
writers = {
|
writers = {
|
||||||
"audio": self.handler.write_dsp_data,
|
"audio": self.handler.write_dsp_data,
|
||||||
|
"hd_audio": self.handler.write_hd_audio,
|
||||||
"smeter": self.handler.write_s_meter_level,
|
"smeter": self.handler.write_s_meter_level,
|
||||||
"secondary_fft": self.handler.write_secondary_fft,
|
"secondary_fft": self.handler.write_secondary_fft,
|
||||||
"secondary_demod": self.handler.write_secondary_demod,
|
"secondary_demod": self.handler.write_secondary_demod,
|
||||||
|
@ -40,6 +40,7 @@ class DigitalMode(Mode):
|
|||||||
class Modes(object):
|
class Modes(object):
|
||||||
mappings = [
|
mappings = [
|
||||||
AnalogMode("nfm", "FM", bandpass=Bandpass(-4000, 4000)),
|
AnalogMode("nfm", "FM", bandpass=Bandpass(-4000, 4000)),
|
||||||
|
AnalogMode("wfm", "WFM", bandpass=Bandpass(-16000, 16000)),
|
||||||
AnalogMode("am", "AM", bandpass=Bandpass(-4000, 4000)),
|
AnalogMode("am", "AM", bandpass=Bandpass(-4000, 4000)),
|
||||||
AnalogMode("lsb", "LSB", bandpass=Bandpass(-3000, -300)),
|
AnalogMode("lsb", "LSB", bandpass=Bandpass(-3000, -300)),
|
||||||
AnalogMode("usb", "USB", bandpass=Bandpass(300, 3000)),
|
AnalogMode("usb", "USB", bandpass=Bandpass(300, 3000)),
|
||||||
|
Loading…
Reference in New Issue
Block a user