Adding Wefax demodulation mode inside Audio App (#2539)

* Adding_new_WFAX_GUI_mode_Audio_App

* Wefax_APT_demodulation_structure

* Solving REC Apt signal.wav from WFAX

* clang format issues

* correcting comments
This commit is contained in:
Brumi-2021
2025-03-05 04:27:18 +01:00
committed by GitHub
parent b6e498a6d3
commit 52c3760e90
19 changed files with 383 additions and 55 deletions

View File

@@ -553,14 +553,14 @@ constexpr fir_taps_real<32> taps_6k0_decim_2{
}},
};
// IFIR prototype filter fs=48000 ; pass=4500 (cutt off -3dBs) , stop=8000 (<-60dBs), decim=4, fout=12000
// IFIR prototype filter fs=48000 ; pass=4500 (cutoff -3dBs) , stop=8000 (<-60dBs), decim=4, fout=12000
// For Europe AM commercial broadcasting stations in LF/MF/HF, Emissions Designator 9K00A3E Bandwidth: 9.00 kHz (derivated from taps_6k0_decim_2 )
// Pre-decimate LPF FIR filter design Created with SciPy Python with the "window method", num_taps = 32, cut_off = 5150. sample_rate = 48000 # Hz,
// Created with h = signal.firwin(num_taps, cut_off, nyq=sample_rate/2, window=('chebwin',50)) , achieving good STOP band plot < -60 dB's with some ripple.
// Pre-decimate LPF FIR filter design Created with SciPy Python with the "window method", num_taps = 32, cutoff = 5150. sample_rate = 48000 # Hz,
// Created with h = signal.firwin(num_taps, cutoff, nyq=sample_rate/2, window=('chebwin',50)) , achieving good STOP band plot < -60 dB's with some ripple.
// post-scaled h taps to avoid decimals , targeting <= similar int values as previous taps_6k0_dsb_channel peak < 32.767 (2 exp 15) and similar H(f)gain
constexpr fir_taps_real<32> taps_9k0_decim_2{
.low_frequency_normalized = -4500.0f / 48000.0f, // Negative -cutt off freq -3dB (real achieved data ,in the plot and measurements)
.high_frequency_normalized = 4500.0f / 48000.0f, // Positive +cutt off freq -3dB (idem)
.low_frequency_normalized = -4500.0f / 48000.0f, // Negative -cutoff freq -3dB (real achieved data ,in the plot and measurements)
.high_frequency_normalized = 4500.0f / 48000.0f, // Positive +cutoff freq -3dB (idem)
.transition_normalized = 3500.0f / 48000.0f, // 3500 Hz = (8000 Hz - 4500 Hz) (both from plot H(f) curve plot)
.taps = {{-53, -30, 47, 198, 355, 372, 89, -535,
-1307, -1771, -1353, 370, 3384, 7109, 10535, 12591,
@@ -644,14 +644,14 @@ constexpr fir_taps_complex<64> taps_6k0_dsb_channel{
}},
};
// Channel filter: fs=12000, pass=4500 (cutt off -3dBs), stop=4940 (<-60dBs), decim=1, fout=12000 (*1) real frec pass / stop , based on plotted H(f) curve)
// Channel filter: fs=12000, pass=4500 (cutoff -3dBs), stop=4940 (<-60dBs), decim=1, fout=12000 (*1) real frec pass / stop , based on plotted H(f) curve)
// For Europe AM commercial broadcasting stations in LF/MF/HF, Emissions Designator 9K00A3E Bandwidth: 9.00 kHz (derivative from taps_6k0_dsb_channel)
// FIR filter design created with SciPy Python using "window method"; selected design parameters: num_taps = 64, cut_off = 4575. sample_rate = 12000 # Hz,
// Created with : h = signal.firwin(num_taps, cut_off, nyq=sample_rate/2, window=('chebwin',50)) , achieving real plot curve (*1) with peak stop band ripple -60dBs.
// FIR filter design created with SciPy Python using "window method"; selected design parameters: num_taps = 64, cutoff = 4575. sample_rate = 12000 # Hz,
// Created with : h = signal.firwin(num_taps, cutoff, nyq=sample_rate/2, window=('chebwin',50)) , achieving real plot curve (*1) with peak stop band ripple -60dBs.
// post-scaled h taps to avoid decimals , targeting <= similar int values as previous taps_6k0_dsb_channel peak < 32.767 (2 exp 15), (29625) and similar H(f)gain
constexpr fir_taps_complex<64> taps_9k0_dsb_channel{
.low_frequency_normalized = -4500.0f / 12000.0f, // Negative -cutt off freq -3dB (in the H(f) curve plot)
.high_frequency_normalized = 4500.0f / 12000.0f, // Positive +cutt off freq -3dB (in the H(f) curve plot)
.low_frequency_normalized = -4500.0f / 12000.0f, // Negative -cutoff freq -3dB (in the H(f) curve plot)
.high_frequency_normalized = 4500.0f / 12000.0f, // Positive +cutoff freq -3dB (in the H(f) curve plot)
.transition_normalized = 440.0f / 12000.0f, // 440Hz = (4940 Hz -4500 Hz) cut-3dB's (both data comes from H(f) curve plot and confirmed by measurements )
.taps = {{
{2, 0},
@@ -945,6 +945,82 @@ constexpr fir_taps_complex<64> taps_0k7_usb_channel{
}},
};
// USB AM+FM for Wefax (Weather fax RX) , based USB AM with truncated Differentiator band limmited cuttoff 2.400Hz for Audio Tones FM dem. ///////////////////
// IFIR prototype filter: fs=12000, pass=2600, stop=3200, decim=1, fout=12000 // stop band minimum att < -48 dB's (+3300 Hz min atten peak) , rest <50 to -60dB's
constexpr fir_taps_complex<64> taps_2k6_usb_wefax_channel{
.low_frequency_normalized = 0,
.high_frequency_normalized = 2600.0f / 12000.0f,
.transition_normalized = 600.0f / 12000.0f,
.taps = {{{-14 + 2},
{-11 - 5},
{-2 - 8},
{6 - 5},
{13 + 1},
{15 + 14},
{0 + 26},
{-22 + 13},
{-13 - 11},
{7 - 1},
{-20 + 17},
{-47 - 37},
{33 - 89},
{122 + 8},
{19 + 131},
{-124 + 26},
{1 - 123},
{158 + 52},
{-94 + 245},
{-363 - 91},
{36 - 468},
{524 - 37},
{67 + 531},
{-552 + 5},
{136 - 686},
{1013 + 258},
{-204 + 1527},
{-2104 + 168},
{-900 - 2529},
{2577 - 1881},
{2868 + 2122},
{-1209 + 3570},
{-3768 - 52},
{-1043 - 3412},
{2634 - 1801},
{2083 + 1693},
{-861 + 1927},
{-1507 - 318},
{95 - 1041},
{692 + 100},
{-189 + 519},
{-478 - 241},
{210 - 481},
{454 + 122},
{-35 + 372},
{-262 + 7},
{4 - 166},
{116 + 40},
{-66 + 108},
{-117 - 62},
{33 - 117},
{95 - 2},
{19 + 57},
{-23 + 13},
{3 - 7},
{6 + 16},
{-20 + 16},
{-25 - 9},
{-8 - 19},
{4 - 12},
{7 - 4},
{7 + 4},
{2 + 12},
{-7 + 13}
}}
};
// WFM 200KF8E emission type //////////////////////////////////////////////
// IFIR image-reject filter: fs=3072000, pass=100000, stop=484000, decim=4, fout=768000

View File

@@ -55,6 +55,12 @@ constexpr iir_biquad_config_t audio_12k_hpf_300hz_config{
{0.89485861f, -1.78971721f, 0.89485861f},
{1.00000000f, -1.77863178f, 0.80080265f}};
// scipy.signal.butter(2, 1500 / 6000.0, 'low', analog=False)
constexpr iir_biquad_config_t audio_12k_lpf_1500hz_config{
// Added to lpf the audio in wefax mode , before sending to SD card or spk.
{0.09763107f, 0.19526215f, 0.09763107f},
{1.00000000f, -0.94280904f, 0.33333333f}};
// scipy.signal.butter(2, 300 / 4000.0, 'highpass', analog=False)
constexpr iir_biquad_config_t audio_8k_hpf_300hz_config{
{0.84645925f, -1.69291851f, 0.84645925f},

View File

@@ -25,7 +25,7 @@
#include "dsp_iir.hpp"
// scipy.signal.iirfilter(ftype="ellip", N = 10, rp = 0.5, rs = 60.0, Wn = 0.5, btype = 'lowpass', output="sos")
// 3khz cutofff @fs:12Khz , used in Hilbert
constexpr iir_biquad_df2_config_t half_band_lpf_config[5] = {
{0.02339042f, 0.0411599f, 0.02339042f, 1.0f, -0.95317621f, 0.33446485f},
{1.0f, 0.82196114f, 1.0f, 1.0f, -0.50327735f, 0.63611027f},
@@ -33,4 +33,22 @@ constexpr iir_biquad_df2_config_t half_band_lpf_config[5] = {
{1.0f, 0.14394122f, 1.0f, 1.0f, -0.04368236f, 0.94798064f},
{1.0f, 0.08720754, 1.0f, 1.0f, 0.00220944f, 0.98743139f}};
// scipy.signal.iirfilter(ftype="ellip", N = 10, rp = 0.5, rs = 60.0, Wn = 0.99, btype = 'lowpass', output="sos")
// 6khz cutofff @fs:12Khz , used in WFAX demod.
constexpr iir_biquad_df2_config_t full_band_lpf_config[5] = {
{0.88095275f, 1.76184993f, 0.88095275f, 1.0f, 1.89055677f, 0.89616378f},
{1.0f, 1.99958798f, 1.0f, 1.0f, 1.9781807f, 0.98002549f},
{1.0f, 1.99928911f, 1.0f, 1.0f, 1.99328036f, 0.99447816f},
{1.0f, 1.99914562f, 1.0f, 1.0f, 1.997254f, 0.99828526f},
{1.0f, 1.99909558f, 1.0f, 1.0f, 1.9986187f, 0.99960319f}};
// scipy.signal.iirfilter(ftype="ellip", N = 10, rp = 0.5 , rs = 60.0, Wn = 0.25, btype = 'lowpass', output="sos")
// 1.5khz cutofff @fs:12Khz, used in WFAX demod.
constexpr iir_biquad_df2_config_t quarter_band_lpf_config[5] = {
{0.00349312f, 0.00319397f, 0.00349312f, 1.0f, -1.53025211f, 0.6203438f},
{1.0f, -0.83483341f, 1.0f, 1.0f, -1.47619047f, 0.77120659f},
{1.0f, -1.23050154f, 1.0f, 1.0f, -1.43058949f, 0.9000896f},
{1.0f, -1.33837384f, 1.0f, 1.0f, -1.41007744f, 0.96349953f},
{1.0f, -1.36921549f, 1.0f, 1.0f, -1.40680439f, 0.9910884f}};
#endif /*__DSP_SOS_CONFIG_H__*/

View File

@@ -585,6 +585,7 @@ class AMConfigureMessage : public Message {
enum class Modulation : int32_t {
DSB = 0,
SSB = 1,
SSB_FM = 2, // Added new for RX Wefax mode, to demodulate APT signal ,FM modulated inside audio subcarrier tones, and then up broadcasted in SSB USB .
};
constexpr AMConfigureMessage(
@@ -593,14 +594,14 @@ class AMConfigureMessage : public Message {
const fir_taps_real<32> decim_2_filter,
const fir_taps_complex<64> channel_filter,
const Modulation modulation,
const iir_biquad_config_t audio_hpf_config)
const iir_biquad_config_t audio_hpf_lpf_config)
: Message{ID::AMConfigure},
decim_0_filter(decim_0_filter),
decim_1_filter(decim_1_filter),
decim_2_filter(decim_2_filter),
channel_filter(channel_filter),
modulation{modulation},
audio_hpf_config(audio_hpf_config) {
audio_hpf_lpf_config(audio_hpf_lpf_config) {
}
const fir_taps_real<24> decim_0_filter;
@@ -608,7 +609,7 @@ class AMConfigureMessage : public Message {
const fir_taps_real<32> decim_2_filter;
const fir_taps_complex<64> channel_filter;
const Modulation modulation;
const iir_biquad_config_t audio_hpf_config;
const iir_biquad_config_t audio_hpf_lpf_config;
};
// TODO: Put this somewhere else, or at least the implementation part.