From f0245bcc26fe1435dd33669b6e06413ae5785672 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Thu, 1 May 2025 11:40:45 +0200 Subject: [PATCH] use real parts, and add a mpx lpf for audio --- README.md | 6 +++--- src/fm95.c | 23 ++++++++++++----------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 934e239..5bb6e40 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ FM95 is a audio processor for FM, it does: Supports these inputs: - Audio (via Pulse) -- MPX (via Pulse, basically passthrough, i don't recommend this unless you have something else than rds or sca to modulate) +- MPX (via Pulse, basically passthrough, i don't recommend this unless you have something else than rds or sca to modulate, you could run chimer95 via here) - RDS (via Pulse, expects unmodulated RDS, stereo, left channel on 57 KHz, right on 66.5, rds95 is recommended here, in modulation this is inphase to the pilot) - SCA (via Pulse, by default on 67 khz with a 7 khz deviation) @@ -21,7 +21,7 @@ and one output: ## How to compile? -To compile you need `cmake` and `libpulse-dev`, if you have those then do these commands: +To compile you need `cmake`, `liquid-dsp` and `libpulse-dev`, if you have those then do these commands: ```bash mkdir build @@ -34,7 +34,7 @@ Done! ## CPU Usage? -Should run completly fine on a pi 5, fine on a pi 3b (30% cpu) +Should run completly fine on a pi 5, fine on a pi 3b (30% cpu, 45% with lpf) ## Other Apps diff --git a/src/fm95.c b/src/fm95.c index 3483079..16eed34 100644 --- a/src/fm95.c +++ b/src/fm95.c @@ -360,9 +360,11 @@ int main(int argc, char **argv) { FMModulator sca_mod; init_fm_modulator(&sca_mod, sca_frequency, sca_deviation, sample_rate); - iirfilt_crcf lpf_l, lpf_r; - lpf_l = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_LOWPASS, LIQUID_IIRDES_SOS, LPF_ORDER, (15000.0f/sample_rate), 0.0f, 1.0f, 40.0f); - lpf_r = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_LOWPASS, LIQUID_IIRDES_SOS, LPF_ORDER, (15000.0f/sample_rate), 0.0f, 1.0f, 40.0f); + iirfilt_rrrf lpf_l, lpf_r; + lpf_l = iirfilt_rrrf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_LOWPASS, LIQUID_IIRDES_SOS, LPF_ORDER, (15000.0f/sample_rate), 0.0f, 1.0f, 40.0f); + lpf_r = iirfilt_rrrf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_LOWPASS, LIQUID_IIRDES_SOS, LPF_ORDER, (15000.0f/sample_rate), 0.0f, 1.0f, 40.0f); + + iirfilt_rrrf mpx_lpf = iirfilt_rrrf_create_prototype(LIQUID_IIRDES_BUTTER, LIQUID_IIRDES_LOWPASS, LIQUID_IIRDES_SOS, 2, (polar_stereo ? (46250/sample_rate) : (53000/sample_rate)), 0.0f, 1.0f, 1.0f); ResistorCapacitor preemp_l, preemp_r; init_preemphasis(&preemp_l, preemphasis_tau, sample_rate); @@ -439,12 +441,8 @@ int main(int argc, char **argv) { float ready_l = apply_preemphasis(&preemp_l, l_in); float ready_r = apply_preemphasis(&preemp_r, r_in); - complex float temp_l = ready_l + ready_l * I; - iirfilt_crcf_execute(lpf_l, temp_l, &temp_l); - ready_l = creal(temp_l); - complex float temp_r = ready_r + ready_r * I; - iirfilt_crcf_execute(lpf_r, temp_r, &temp_r); - ready_r = creal(temp_r); + iirfilt_rrrf_execute(lpf_l, ready_l, &ready_l); + iirfilt_rrrf_execute(lpf_r, ready_r, &ready_r); ready_l = process_agc_stereo(&agc, ready_l, ready_r, &ready_r); ready_l = hard_clip(ready_l*audio_volume, clipper_threshold); @@ -488,6 +486,8 @@ int main(int argc, char **argv) { audio = hard_clip(audio, 1.0f-mpx); // Prevent clipping, via clipping the audio signal with relation to the mpx signal + iirfilt_rrrf_execute(mpx_lpf, audio, &audio); + output[i] = (audio+mpx)*master_volume; if(rds_on || stereo) advance_oscillator(&osc); } @@ -499,8 +499,9 @@ int main(int argc, char **argv) { } } printf("Cleaning up...\n"); - iirfilt_crcf_destroy(lpf_l); - iirfilt_crcf_destroy(lpf_r); + iirfilt_rrrf_destroy(lpf_l); + iirfilt_rrrf_destroy(lpf_r); + iirfilt_rrrf_destroy(mpx_lpf); free_PulseInputDevice(&input_device); if(mpx_on) free_PulseInputDevice(&mpx_device); if(rds_on) free_PulseInputDevice(&rds_device);