From 0f74e8e1b779dd350f807c9e6553025606b8cde6 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Wed, 30 Apr 2025 20:00:00 +0200 Subject: [PATCH] rename bs412 names and also add debug there, convert to tabs, remove 38 khz min for mpx dev and change bs412 gain reduction logic --- dsp/bs412.c | 17 +++++++++++++---- dsp/bs412.h | 3 ++- io/audio.c | 16 ++++++++-------- src/fm95.c | 18 ++++++++++-------- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/dsp/bs412.c b/dsp/bs412.c index 97a463b..1f17f02 100644 --- a/dsp/bs412.c +++ b/dsp/bs412.c @@ -9,21 +9,30 @@ float deviation_to_dbr(float deviation) { } void init_modulation_power_measure(MPXPowerMeasurement* mpx, int sample_rate) { - mpx->i = 0; + mpx->sample_counter = 0; mpx->sample = 0; mpx->sample_rate = sample_rate; } float measure_mpx(MPXPowerMeasurement* mpx, float deviation) { mpx->sample += deviation * deviation; // rmS - mpx->i++; + mpx->sample_counter++; - float avg_deviation = sqrtf(mpx->sample / mpx->i); // RMs + float avg_deviation = sqrtf(mpx->sample / mpx->sample_counter); // RMs float modulation_power = deviation_to_dbr(avg_deviation); + #ifdef BS412_DEBUG + if(mpx->i % mpx->sample_rate == 0) { + debug_printf("MPX power: %f dBr\n", modulation_power); + } + #endif + if (mpx->i >= mpx->sample_rate * 60) { + #ifdef BS412_DEBUG + debug_printf("Resetting MPX power measurement\n"); + #endif mpx->sample = avg_deviation * avg_deviation; - mpx->i = 1; + mpx->sample_counter = 1; } return modulation_power; diff --git a/dsp/bs412.h b/dsp/bs412.h index 6c395b1..d4b389a 100644 --- a/dsp/bs412.h +++ b/dsp/bs412.h @@ -1,9 +1,10 @@ #pragma once #include +#include "../lib/debug.h" typedef struct { - int i; + int sample_counter; int sample_rate; double sample; } MPXPowerMeasurement; diff --git a/io/audio.c b/io/audio.c index 350c794..4925839 100644 --- a/io/audio.c +++ b/io/audio.c @@ -41,10 +41,10 @@ int read_PulseInputDevice(PulseInputDevice* dev, float* buffer, size_t size) { void free_PulseInputDevice(PulseInputDevice* dev) { if (dev->dev && dev->initialized) pa_simple_free(dev->dev); - free(dev->app_name); - free(dev->stream_name); - free(dev->device); - dev->initialized = 0; + free(dev->app_name); + free(dev->stream_name); + free(dev->device); + dev->initialized = 0; } int init_PulseOutputDevice(PulseOutputDevice* dev, int sample_rate, int channels, char* app_name, char *stream_name, char* device, pa_buffer_attr* buffer_attr) { @@ -88,8 +88,8 @@ int write_PulseOutputDevice(PulseOutputDevice* dev, float* buffer, size_t size) void free_PulseOutputDevice(PulseOutputDevice* dev) { if (dev->dev && dev->initialized) pa_simple_free(dev->dev); - free(dev->app_name); - free(dev->stream_name); - free(dev->device); - dev->initialized = 0; + free(dev->app_name); + free(dev->stream_name); + free(dev->device); + dev->initialized = 0; } \ No newline at end of file diff --git a/src/fm95.c b/src/fm95.c index e11b69b..5877d50 100644 --- a/src/fm95.c +++ b/src/fm95.c @@ -237,10 +237,6 @@ int main(int argc, char **argv) { break; case 'd': // MPX deviation mpx_deviation = strtof(optarg, NULL); - if (mpx_deviation < 38000) { - fprintf(stderr, "Warning: MPX deviation cannot be lower than 38000. Setting to 38000.\n"); - mpx_deviation = 38000; - } break; case 'A': // Master vol master_volume = strtof(optarg, NULL); @@ -370,6 +366,8 @@ int main(int argc, char **argv) { MPXPowerMeasurement mpx_only_power; init_modulation_power_measure(&mpx_only_power, sample_rate); + float bs412_audio_gain = 1.0f; + AGC agc; // fs target min max attack relese initAGC(&agc, sample_rate, 0.625f, 0.0f, 1.25f, 0.025f, 0.25f); @@ -463,13 +461,17 @@ int main(int argc, char **argv) { if(sca_on) mpx += modulate_fm(&sca_mod, hard_clip(current_sca_in, sca_clipper_threshold))*SCA_VOLUME; float mpx_only = measure_mpx(&mpx_only_power, mpx * mpx_deviation); - float mpower = measure_mpx(&power, (audio+mpx) * mpx_deviation); + float mpower = measure_mpx(&power, (audio+mpx) * mpx_deviation); // Standard requires that the output is measured specifically if (mpower > mpx_power) { - float excess_power = mpower - mpx_only - mpx_power; // Make sure that MPX doesn't affect the audio - audio *= (dbr_to_deviation(-excess_power)/mpx_deviation); // This should be more dynamic, but too bad + float excess_power = mpower - mpx_power; + excess_power = deviation_to_dbr(dbr_to_deviation(excess_power) - dbr_to_deviation(mpx_only)); // make sure mpx is not included in the power to attenuate, because we'd be attuating the mpx signal for audio + + float target_gain = dbr_to_deviation(-excess_power)/mpx_deviation; + bs412_audio_gain = 0.9f * bs412_audio_gain + 0.1f * target_gain; + audio *= bs412_audio_gain; } - audio = hard_clip(audio, 1-mpx); // Prevent clipping, via clipping the audio signal with relation to the mpx signal + audio = hard_clip(audio, 1.0f-mpx); // Prevent clipping, via clipping the audio signal with relation to the mpx signal output[i] = (audio+mpx)*master_volume; if(rds_on || stereo) advance_oscillator(&osc);