From 73396a6cbac2642125a221772601663adcc48db9 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Sun, 15 Feb 2026 18:18:54 +0100 Subject: [PATCH] mpx seperation --- filter/bs412.c | 10 ++++++---- filter/bs412.h | 4 ++-- modulation/stereo_encoder.c | 10 +++++----- modulation/stereo_encoder.h | 2 +- src/fm95.c | 10 ++++++---- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/filter/bs412.c b/filter/bs412.c index 1880f46..929dd6e 100644 --- a/filter/bs412.c +++ b/filter/bs412.c @@ -30,7 +30,9 @@ void init_bs412(BS412Compressor* mpx, uint32_t mpx_deviation, float target_power #endif } -float bs412_compress(BS412Compressor* mpx, float sample) { +float bs412_compress(BS412Compressor* mpx, float audio, float sample_mpx) { + float combined = audio + sample_mpx; + mpx->avg_power += mpx->alpha * ((mpx->last_output * mpx->last_output * mpx->mpx_deviation * mpx->mpx_deviation) - mpx->avg_power); float avg_deviation = sqrtf(mpx->avg_power); @@ -44,7 +46,7 @@ float bs412_compress(BS412Compressor* mpx, float sample) { } #endif mpx->sample_counter++; - return sample; + return combined; } if(mpx->sample_counter > mpx->sample_rate) { @@ -65,7 +67,7 @@ float bs412_compress(BS412Compressor* mpx, float sample) { if(mpx->can_compress == 0) { mpx->sample_counter++; - return sample; + return combined; } float target_gain = powf(10.0f, (mpx->target - modulation_power) / 10.0f); @@ -77,7 +79,7 @@ float bs412_compress(BS412Compressor* mpx, float sample) { mpx->gain = fmaxf(0.0f, fminf(2.0f, mpx->gain)); - float output_sample = sample * mpx->gain; + float output_sample = (audio * mpx->gain) + mpx; if(deviation_to_dbr(avg_deviation * mpx->gain) > mpx->target && deviation_to_dbr(avg_deviation) < mpx->target) { // Gain is too much, reduce float overshoot_dbr = deviation_to_dbr(avg_deviation * mpx->gain) - mpx->target; diff --git a/filter/bs412.h b/filter/bs412.h index 73936d1..cd4e5ee 100644 --- a/filter/bs412.h +++ b/filter/bs412.h @@ -27,8 +27,8 @@ typedef struct float last_output; } BS412Compressor; -float dbr_to_deviation(float dbr); +// float dbr_to_deviation(float dbr); float deviation_to_dbr(float deviation); void init_bs412(BS412Compressor *mpx, uint32_t mpx_deviation, float target_power, float attack, float release, uint32_t sample_rate); -float bs412_compress(BS412Compressor *mpx, float average); \ No newline at end of file +float bs412_compress(BS412Compressor *mpx, float audio, float sample_mpx); \ No newline at end of file diff --git a/modulation/stereo_encoder.c b/modulation/stereo_encoder.c index 4d887e0..3525f87 100644 --- a/modulation/stereo_encoder.c +++ b/modulation/stereo_encoder.c @@ -13,7 +13,7 @@ void init_stereo_encoder(StereoEncoder* st, uint8_t stereo_ssb, uint8_t multipli } else st->stereo_hilbert = NULL; } -float stereo_encode(StereoEncoder* st, uint8_t enabled, float left, float right) { +float stereo_encode(StereoEncoder* st, uint8_t enabled, float left, float right, float *audio) { float mid = (left+right) * 0.5f; if(!enabled) return mid * st->audio_volume; @@ -35,12 +35,12 @@ float stereo_encode(StereoEncoder* st, uint8_t enabled, float left, float right) } float signalx2 = get_oscillator_sin_multiplier_ni(st->osc, st->multiplier * 2.0f); + *audio = (mid*half_audio); if(st->stereo_hilbert) { float stereo = (crealf(stereo_hilbert) * signalx2cos) + (cimagf(stereo_hilbert) * signalx2); - return (mid*half_audio) + (signalx1*st->pilot_volume) + (stereo * half_audio); - } else { - return (mid*half_audio) + (signalx1*st->pilot_volume) + ((side*signalx2) * half_audio); - } + *audio += (stereo * half_audio) + } else *audio += ((side*signalx2) * half_audio); + return (signalx1*st->pilot_volume); } void exit_stereo_encoder(StereoEncoder* st) { diff --git a/modulation/stereo_encoder.h b/modulation/stereo_encoder.h index 2c210f6..ef8a54b 100644 --- a/modulation/stereo_encoder.h +++ b/modulation/stereo_encoder.h @@ -18,5 +18,5 @@ typedef struct } StereoEncoder; void init_stereo_encoder(StereoEncoder *st, uint8_t stereo_ssb, uint8_t multiplier, Oscillator *osc, float audio_volume, float pilot_volume); -float stereo_encode(StereoEncoder* st, uint8_t enabled, float left, float right); +float stereo_encode(StereoEncoder* st, uint8_t enabled, float left, float right, float *audio); void exit_stereo_encoder(StereoEncoder* st); \ No newline at end of file diff --git a/src/fm95.c b/src/fm95.c index ef4a20e..3a7ad67 100644 --- a/src/fm95.c +++ b/src/fm95.c @@ -199,6 +199,7 @@ int run_fm95(const FM95_Config config, FM95_Runtime* runtime) { for (uint16_t i = 0; i < BUFFER_SIZE; i++) { float mpx = 0.0f; + float audio = 0.0f; float l = audio_stereo_input[2*i+0]*config.audio_preamp; float r = audio_stereo_input[2*i+1]*config.audio_preamp; @@ -226,7 +227,7 @@ int run_fm95(const FM95_Config config, FM95_Runtime* runtime) { mod_r = apply_preemphasis(&runtime->preemp_r, mod_r); } - mpx = stereo_encode(&runtime->stencode, config.stereo, mod_l, mod_r); + mpx = stereo_encode(&runtime->stencode, config.stereo, mod_l, mod_r, &audio); if(rds_on) { float rds_level = config.volumes.rds; @@ -234,14 +235,15 @@ int run_fm95(const FM95_Config config, FM95_Runtime* runtime) { uint8_t osc_stream = 12 + stream; if(osc_stream >= 13) osc_stream++; - if(config.stereo_ssb) mpx += (runtime->rds_in[config.rds_streams * i + stream] * delay_line(&runtime->rds_delays[stream], get_oscillator_cos_multiplier_ni(&runtime->osc, osc_stream))) * rds_level; - else mpx += (runtime->rds_in[config.rds_streams * i + stream] * get_oscillator_cos_multiplier_ni(&runtime->osc, osc_stream)) * rds_level; + float carrier = get_oscillator_cos_multiplier_ni(&runtime->osc, osc_stream); + if(config.stereo_ssb) carrier = delay_line(&runtime->rds_delays[stream], carrier); + mpx += (runtime->rds_in[config.rds_streams * i + stream] * carrier) * rds_level; rds_level *= config.volumes.rds_step; // Prepare level for the next stream } } - mpx = bs412_compress(&runtime->bs412, mpx+mpx_in[i]); + mpx = bs412_compress(&runtime->bs412, audio, mpx+mpx_in[i]); output[i] = hard_clip(mpx, 1.0)*config.master_volume; // Ensure peak deviation of 75 khz (or the set deviation), assuming we're calibrated correctly advance_oscillator(&runtime->osc);