Compare commits

...

26 Commits

Author SHA1 Message Date
Jakob Ketterl 72aad99d20 Merge branch 'develop' into csdr++ 2021-08-03 22:22:43 +02:00
Jakob Ketterl 38cc900b1c Merge branch 'develop' into csdr++ 2021-07-15 12:55:43 +02:00
Jakob Ketterl db0efc14f5 use csdr++ timingrecovery 2021-07-10 23:03:14 +02:00
Jakob Ketterl 72e05f5276 use csdr++ bpsk & varicode 2021-07-09 22:00:01 +02:00
Jakob Ketterl e088006b4d use new csdr++ bandpass filters 2021-07-09 20:25:07 +02:00
Jakob Ketterl 483d954b95 Merge branch 'develop' into csdr++ 2021-07-09 13:53:25 +02:00
Jakob Ketterl a92f587734 use csdr++ gain 2021-07-06 21:42:29 +02:00
Jakob Ketterl 8f0b33eb83 activate adpcm sync flag 2021-07-06 21:20:33 +02:00
Jakob Ketterl 14eb71c8de implement adpcdm synchronization, refs #203 2021-07-06 19:40:06 +02:00
Jakob Ketterl 1a9bcdeb07 use new csdr++ deemphasis filters 2021-07-06 16:26:16 +02:00
Jakob Ketterl 6cce1ccdaa use new csdr++ squelch and power; disable squelch when unused 2021-07-06 00:05:24 +02:00
Jakob Ketterl f0933472c9 use cxdr++ limit 2021-07-05 17:41:11 +02:00
Jakob Ketterl fc5fb9166e use new adpcm methods in csdr++ 2021-07-05 17:20:57 +02:00
Jakob Ketterl 59de2628c3 Merge branch 'develop' into csdr++ 2021-07-05 13:06:06 +02:00
Jakob Ketterl 44c1e00509 use csdr++ fractionaldecimator 2021-07-05 12:42:35 +02:00
Jakob Ketterl 4a68c9d3da use new csdr++ firdecimate 2021-07-02 19:15:10 +02:00
Jakob Ketterl 2d183ffeac use new csdr++ shift 2021-07-01 15:52:30 +02:00
Jakob Ketterl 808418c723 use csdr++ realpart 2021-06-30 23:17:37 +02:00
Jakob Ketterl c3cac092bd use new fft functions in csdr++ 2021-06-30 23:06:28 +02:00
Jakob Ketterl 8797615720 use new fft 2021-06-30 21:23:25 +02:00
Jakob Ketterl b3cdc568d9 use new csdr++ converter 2021-06-30 14:22:26 +02:00
Jakob Ketterl 666c286485 use new dcblock 2021-06-30 13:53:56 +02:00
Jakob Ketterl d431e37d7b use am and fm demodulator 2021-06-29 11:52:17 +02:00
Jakob Ketterl 566b747928 Merge branch 'develop' into csdr++ 2021-06-28 15:14:24 +02:00
Jakob Ketterl 22f0d90896 use new agc in all the spots 2021-06-28 13:01:26 +02:00
Jakob Ketterl 6b4432982e use new csdr++; first stage: agc 2021-06-25 00:29:56 +02:00
4 changed files with 113 additions and 74 deletions

View File

@ -59,7 +59,6 @@ class Dsp(DirewolfConfigSubscriber):
self.fft_compression = "none"
self.demodulator = "nfm"
self.name = "csdr"
self.base_bufsize = 512
self.decimation = None
self.last_decimation = None
self.nc_port = None
@ -109,23 +108,24 @@ class Dsp(DirewolfConfigSubscriber):
chain = ["nc -v 127.0.0.1 {nc_port}"]
if which == "fft":
chain += [
"csdr fft_cc {fft_size} {fft_block_size}",
"csdr logpower_cf -70"
"csdr++ fft {fft_size} {fft_block_size}",
"csdr++ logpower -70"
if self.fft_averages == 0
else "csdr logaveragepower_cf -70 {fft_size} {fft_averages}",
"csdr fft_exchange_sides_ff {fft_size}",
else "csdr++ logaveragepower {fft_size} {fft_averages} --add -70",
"csdr++ fftswap {fft_size}",
]
if self.fft_compression == "adpcm":
chain += ["csdr compress_fft_adpcm_f_u8 {fft_size}"]
chain += ["csdr++ fftadpcm {fft_size}"]
return chain
chain += ["csdr shift_addfast_cc --fifo {shift_pipe}"]
chain += ["csdr++ shift --fifo {shift_pipe}"]
if self.decimation > 1:
chain += ["csdr fir_decimate_cc {decimation} {ddc_transition_bw} HAMMING"]
chain += ["csdr bandpass_fir_fft_cc --fifo {bpf_pipe} {bpf_transition_bw} HAMMING"]
chain += ["csdr++ firdecimate {decimation} {ddc_transition_bw} --window hamming"]
chain += ["csdr++ bandpass --fft --fifo {bpf_pipe} {bpf_transition_bw} --window hamming"]
if self.output.supports_type("smeter"):
chain += [
"csdr squelch_and_smeter_cc --fifo {squelch_pipe} --outfifo {smeter_pipe} 5 {smeter_report_every}"
]
if self.isSquelchActive():
chain += ["csdr++ squelch --fifo {squelch_pipe} --outfifo {smeter_pipe} 5 {smeter_report_every}"]
else:
chain += ["csdr++ power --outfifo {smeter_pipe} 5 {smeter_report_every}"]
if self.secondary_demodulator:
if self.output.supports_type("secondary_fft"):
chain += ["csdr tee {iqtee_pipe}"]
@ -137,38 +137,38 @@ class Dsp(DirewolfConfigSubscriber):
last_decimation_block = []
if self.last_decimation >= 2.0:
# activate prefilter if signal has been oversampled, e.g. WFM
last_decimation_block = ["csdr fractional_decimator_ff {last_decimation} 12 --prefilter"]
last_decimation_block = ["csdr++ fractionaldecimator --format float {last_decimation} --prefilter"]
elif self.last_decimation != 1.0:
last_decimation_block = ["csdr fractional_decimator_ff {last_decimation}"]
last_decimation_block = ["csdr++ fractionaldecimator --format float {last_decimation}"]
if which == "nfm":
chain += ["csdr fmdemod_quadri_cf", "csdr limit_ff"]
chain += ["csdr++ fmdemod", "csdr++ limit"]
chain += last_decimation_block
chain += [
"csdr deemphasis_nfm_ff {audio_rate}",
"csdr agc_ff --profile slow --max 3",
"csdr++ deemphasis --nfm {audio_rate}",
"csdr++ agc --format float --profile slow --max 3",
]
if self.get_audio_rate() != self.get_output_rate():
chain += [
"sox -t raw -r {audio_rate} -e floating-point -b 32 -c 1 --buffer 32 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - "
]
else:
chain += ["csdr convert_f_s16"]
chain += ["csdr++ convert -i float -o s16"]
elif which == "wfm":
chain += [
"csdr fmdemod_quadri_cf",
"csdr limit_ff",
"csdr++ fmdemod",
"csdr++ limit",
]
chain += last_decimation_block
chain += ["csdr deemphasis_wfm_ff {audio_rate} {wfm_deemphasis_tau}", "csdr convert_f_s16"]
chain += ["csdr++ deemphasis --wfm {audio_rate} {wfm_deemphasis_tau}", "csdr++ convert -i float -o s16"]
elif self.isDigitalVoice(which):
chain += ["csdr fmdemod_quadri_cf"]
chain += ["csdr++ fmdemod"]
chain += last_decimation_block
chain += ["dc_block"]
# m17
if which == "m17":
chain += [
"csdr limit_ff",
"csdr convert_f_s16",
"csdr++ limit",
"csdr++ convert -i float -o s16",
"m17-demod",
]
else:
@ -197,87 +197,87 @@ class Dsp(DirewolfConfigSubscriber):
chain += ["ysf_decoder --fifo {meta_pipe}", "mbe_synthesizer -y {codecserver_arg}"]
chain += ["digitalvoice_filter"]
chain += [
"CSDR_FIXED_BUFSIZE=32 csdr agc_s16 --max 30 --initial 3",
"sox -t raw -r 8000 -e signed-integer -b 16 -c 1 --buffer 32 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - ",
"csdr++ agc --format s16 --max 30 --initial 3",
"sox --buffer 320 -t raw -r 8000 -e signed-integer -b 16 -c 1 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - ",
]
elif which == "am":
chain += ["csdr amdemod_cf", "csdr fastdcblock_ff"]
chain += ["csdr++ amdemod", "csdr++ dcblock"]
chain += last_decimation_block
chain += [
"csdr agc_ff --profile slow --initial 200",
"csdr convert_f_s16",
"csdr++ agc --format float --profile slow --initial 200",
"csdr++ convert -i float -o s16",
]
elif self.isFreeDV(which):
chain += ["csdr realpart_cf"]
chain += ["csdr++ realpart"]
chain += last_decimation_block
chain += [
"csdr agc_ff",
"csdr convert_f_s16",
"csdr++ agc --format float",
"csdr++ convert -i float -o s16",
"freedv_rx 1600 - -",
"csdr agc_s16 --max 30 --initial 3",
"csdr++ agc --format s16 --max 30 --initial 3",
"sox -t raw -r 8000 -e signed-integer -b 16 -c 1 --buffer 32 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - ",
]
elif self.isDrm(which):
if self.last_decimation != 1.0:
# we are still dealing with complex samples here, so the regular last_decimation_block doesn't fit
chain += ["csdr fractional_decimator_cc {last_decimation}"]
chain += ["csdr++ fractionaldecimator --format complex {last_decimation}"]
chain += [
"csdr convert_f_s16",
"csdr++ convert -i float -o s16",
"dream -c 6 --sigsrate 48000 --audsrate 48000 -I - -O -",
"sox -t raw -r 48000 -e signed-integer -b 16 -c 2 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - ",
]
elif which == "ssb":
chain += ["csdr realpart_cf"]
chain += ["csdr++ realpart"]
chain += last_decimation_block
chain += ["csdr agc_ff"]
chain += ["csdr++ agc --format float"]
# fixed sample rate necessary for the wsjt-x tools. fix with sox...
if self.get_audio_rate() != self.get_output_rate():
chain += [
"sox -t raw -r {audio_rate} -e floating-point -b 32 -c 1 --buffer 32 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - "
]
else:
chain += ["csdr convert_f_s16"]
chain += ["csdr++ convert -i float -o s16"]
if self.audio_compression == "adpcm":
chain += ["csdr encode_ima_adpcm_i16_u8"]
chain += ["csdr++ adpcm -e --sync"]
return chain
def secondary_chain(self, which):
chain = ["cat {input_pipe}"]
if which == "fft":
chain += [
"csdr fft_cc {secondary_fft_input_size} {secondary_fft_block_size}",
"csdr logpower_cf -70"
"csdr++ fft {secondary_fft_input_size} {secondary_fft_block_size}",
"csdr++ logpower -70"
if self.fft_averages == 0
else "csdr logaveragepower_cf -70 {secondary_fft_size} {fft_averages}",
"csdr fft_exchange_sides_ff {secondary_fft_input_size}",
else "csdr++ logaveragepower {secondary_fft_size} {fft_averages} --add -70",
"csdr++ fftswap {secondary_fft_input_size}",
]
if self.fft_compression == "adpcm":
chain += ["csdr compress_fft_adpcm_f_u8 {secondary_fft_size}"]
chain += ["csdr++ fftadpcm {secondary_fft_size}"]
return chain
elif which == "bpsk31" or which == "bpsk63":
return chain + [
"csdr shift_addfast_cc --fifo {secondary_shift_pipe}",
"csdr bandpass_fir_fft_cc -{secondary_bpf_cutoff} {secondary_bpf_cutoff} {secondary_bpf_cutoff}",
"csdr simple_agc_cc 0.001 0.5",
"csdr timing_recovery_cc GARDNER {secondary_samples_per_bits} 0.5 2 --add_q",
"CSDR_FIXED_BUFSIZE=1 csdr dbpsk_decoder_c_u8",
"CSDR_FIXED_BUFSIZE=1 csdr psk31_varicode_decoder_u8_u8",
"csdr++ shift --fifo {secondary_shift_pipe}",
"csdr++ bandpass --low -{secondary_bpf_cutoff} --high {secondary_bpf_cutoff} {secondary_bpf_cutoff}",
"csdr++ agc --format complex",
"csdr++ timingrecovery --algorithm gardner {secondary_samples_per_bits} 0.5 2 --add_q",
"csdr++ dbpskdecode",
"csdr++ varicodedecode",
]
elif self.isWsjtMode(which) or self.isJs8(which):
chain += ["csdr realpart_cf"]
chain += ["csdr++ realpart"]
if self.last_decimation != 1.0:
chain += ["csdr fractional_decimator_ff {last_decimation}"]
return chain + ["csdr agc_ff", "csdr convert_f_s16"]
chain += ["csdr++ fractionaldecimator --format float {last_decimation}"]
return chain + ["csdr++ agc --format float", "csdr++ convert -i float -o s16"]
elif which == "packet":
chain += ["csdr fmdemod_quadri_cf"]
chain += ["csdr++ fmdemod"]
if self.last_decimation != 1.0:
chain += ["csdr fractional_decimator_ff {last_decimation}"]
return chain + ["csdr convert_f_s16", "direwolf -c {direwolf_config} -r {audio_rate} -t 0 -q d -q h 1>&2"]
chain += ["csdr++ fractionaldecimator --format float {last_decimation}"]
return chain + ["csdr++ convert -i float -o s16", "direwolf -c {direwolf_config} -r {audio_rate} -t 0 -q d -q h 1>&2"]
elif which == "pocsag":
chain += ["csdr fmdemod_quadri_cf"]
chain += ["csdr++ fmdemod"]
if self.last_decimation != 1.0:
chain += ["csdr fractional_decimator_ff {last_decimation}"]
chain += ["csdr++ fractionaldecimator --format float {last_decimation}"]
return chain + ["fsk_demodulator -i", "pocsag_decoder"]
def set_secondary_demodulator(self, what):
@ -290,8 +290,8 @@ class Dsp(DirewolfConfigSubscriber):
def secondary_fft_block_size(self):
base = (self.samp_rate / self.decimation) / (self.fft_fps * 2)
if self.fft_averages == 0:
return base
return base / self.fft_averages
return round(base)
return round(base / self.fft_averages)
def secondary_decimation(self):
return 1 # currently unused
@ -594,9 +594,9 @@ class Dsp(DirewolfConfigSubscriber):
def fft_block_size(self):
if self.fft_averages == 0:
return self.samp_rate / self.fft_fps
return round(self.samp_rate / self.fft_fps)
else:
return self.samp_rate / self.fft_fps / self.fft_averages
return round(self.samp_rate / self.fft_fps / self.fft_averages)
def set_offset_freq(self, offset_freq):
if offset_freq is None:
@ -629,15 +629,14 @@ class Dsp(DirewolfConfigSubscriber):
def convertToLinear(self, db):
return float(math.pow(10, db / 10))
def isSquelchActive(self):
return not self.isDigitalVoice() and not self.isPacket() and not self.isPocsag() and not self.isFreeDV() and not self.isDrm()
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.isFreeDV() or self.isDrm()
else self.squelch_level
)
if self.running:
actual_squelch = self.squelch_level if self.isSquelchActive() else -150
if self.running and "squelch_pipe" in self.pipes:
self.pipes["squelch_pipe"].write("%g\n" % (self.convertToLinear(actual_squelch)))
def set_codecserver(self, s):
@ -757,7 +756,6 @@ class Dsp(DirewolfConfigSubscriber):
bpf_transition_bw=float(self.bpf_transition_bw) / self.if_samp_rate(),
ddc_transition_bw=self.ddc_transition_bw(),
flowcontrol=int(self.samp_rate * 2),
start_bufsize=self.base_bufsize * self.decimation,
nc_port=self.nc_port,
output_rate=self.get_output_rate(),
smeter_report_every=int(self.if_samp_rate() / 6000),
@ -769,7 +767,7 @@ class Dsp(DirewolfConfigSubscriber):
logger.debug("Command = %s", command)
out = subprocess.PIPE if self.output.supports_type("audio") else subprocess.DEVNULL
self.process = subprocess.Popen(command, stdout=out, shell=True, start_new_session=True)
self.process = subprocess.Popen(command, stdout=out, shell=True, start_new_session=True, bufsize=128)
def watch_thread():
rc = self.process.wait()

View File

@ -282,7 +282,7 @@ AudioEngine.prototype.processAudio = function(data, resampler) {
var buffer;
if (this.compression === "adpcm") {
//resampling & ADPCM
buffer = this.audioCodec.decode(new Uint8Array(data));
buffer = this.audioCodec.decodeWithSync(new Uint8Array(data));
} else {
buffer = new Int16Array(data);
}
@ -328,6 +328,10 @@ ImaAdpcmCodec.prototype.reset = function() {
this.stepIndex = 0;
this.predictor = 0;
this.step = 0;
this.synchronized = 0;
this.syncWord = "SYNC";
this.syncCounter = 0;
this.skip = 0;
};
ImaAdpcmCodec.imaIndexTable = [ -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 ];
@ -353,6 +357,43 @@ ImaAdpcmCodec.prototype.decode = function(data) {
return output;
};
ImaAdpcmCodec.prototype.decodeWithSync = function(data) {
var output = new Int16Array(data.length * 2);
var index = this.skip;
var oi = 0;
while (index < data.length) {
while (this.synchronized < 4 && index < data.length) {
if (data[index] === this.syncWord.charCodeAt(this.synchronized)) {
this.synchronized++;
} else {
this.synchronized = 0;
}
index++;
if (this.synchronized === 4) {
if (index + 4 < data.length) {
var syncData = new Int16Array(data.buffer.slice(index, index + 4));
this.stepIndex = syncData[0];
this.predictor = syncData[1];
}
this.syncCounter = 1000;
index += 4;
break;
}
}
while (index < data.length) {
if (this.syncCounter-- < 0) {
this.synchronized = 0;
break;
}
output[oi++] = this.decodeNibble(data[index] & 0x0F);
output[oi++] = this.decodeNibble(data[index] >> 4);
index++;
}
}
this.skip = index - data.length;
return output.slice(0, oi);
};
ImaAdpcmCodec.prototype.decodeNibble = function(nibble) {
this.stepIndex += ImaAdpcmCodec.imaIndexTable[nibble];
this.stepIndex = Math.min(Math.max(this.stepIndex, 0), 88);

View File

@ -21,7 +21,7 @@ class FifiSdrSource(DirectSource):
return super().getEventNames() + ["device"]
def getFormatConversion(self):
return ["csdr convert_s16_f", "csdr gain_ff 5"]
return ["csdr++ convert -i s16 -o float", "csdr++ gain 5"]
def sendRockProgFrequency(self, frequency):
process = Popen(["rockprog", "--vco", "-w", "--freq={}".format(frequency / 1e6)])

View File

@ -23,8 +23,8 @@ class Resampler(DirectSource):
def getCommand(self):
return [
"nc -v 127.0.0.1 {nc_port}".format(nc_port=self.sdr.getPort()),
"csdr shift_addfast_cc {shift}".format(shift=self.shift),
"csdr fir_decimate_cc {decimation} {ddc_transition_bw} HAMMING".format(
"csdr++ shift {shift}".format(shift=self.shift),
"csdr++ firdecimate {decimation} {ddc_transition_bw} --window hamming".format(
decimation=self.decimation, ddc_transition_bw=self.transition_bw
),
] + self.getNmuxCommand()