diff --git a/filter/bs412.c b/filter/bs412.c index 15133a2..5232a1b 100644 --- a/filter/bs412.c +++ b/filter/bs412.c @@ -11,16 +11,20 @@ inline float deviation_to_dbr(float deviation) { return 10.0f * (log2f(deviation) - LOG2_19000) * 0.30103f; } -void init_modulation_power_measure(MPXPowerMeasurement* mpx, int sample_rate) { +void init_bs412(BS412Compressor* mpx, float target_power, float attack, float release, int sample_rate) { mpx->sample_counter = 0; mpx->sample = 0; mpx->sample_rate = sample_rate; + mpx->attack = expf(-1.0f / (attack * sample_rate)); + mpx->release = expf(-1.0f / (release * sample_rate)); + mpx->target = target_power; + mpx->gain = 1.0f; #ifdef BS412_DEBUG debug_printf("Initialized MPX power measurement with sample rate: %d\n", sample_rate); #endif } -float measure_mpx(MPXPowerMeasurement* mpx, float deviation) { +float bs412_compress(BS412Compressor* mpx, float deviation) { mpx->sample += deviation * deviation; // rmS mpx->sample_counter++; @@ -42,5 +46,12 @@ float measure_mpx(MPXPowerMeasurement* mpx, float deviation) { mpx->sample_counter = 1; } - return modulation_power; + float gain_target = powf(10.0f, (mpx->target - modulation_power) / 20.0f); // dB to linear + if (gain_target > mpx->gain) + mpx->gain = mpx->gain * mpx->attack + (1.0f - mpx->attack) * gain_target; + else + mpx->gain = mpx->gain * mpx->release + (1.0f - mpx->release) * gain_target; + + + return deviation*mpx->gain; } diff --git a/filter/bs412.h b/filter/bs412.h index 3ae166b..10985f8 100644 --- a/filter/bs412.h +++ b/filter/bs412.h @@ -13,11 +13,15 @@ typedef struct { int sample_counter; int sample_rate; + float target; + float attack; + float release; + float gain; double sample; -} MPXPowerMeasurement; +} BS412Compressor; float dbr_to_deviation(float dbr); float deviation_to_dbr(float deviation); -void init_modulation_power_measure(MPXPowerMeasurement *mpx, int sample_rate); -float measure_mpx(MPXPowerMeasurement *mpx, float deviation); \ No newline at end of file +void init_bs412(BS412Compressor *mpx, float target_power, float attack, float release, int sample_rate); +float bs412_compress(BS412Compressor *mpx, float deviation); \ No newline at end of file diff --git a/src/fm95.c b/src/fm95.c index 5653c62..4a6ad45 100644 --- a/src/fm95.c +++ b/src/fm95.c @@ -166,8 +166,8 @@ int run_fm95(const FM95_Config config, FM95_Runtime* runtime) { init_preemphasis(&preemp_l, config.preemphasis, config.sample_rate, config.preemp_unity_freq); init_preemphasis(&preemp_r, config.preemphasis, config.sample_rate, config.preemp_unity_freq); - MPXPowerMeasurement power; - init_modulation_power_measure(&power, config.sample_rate); + BS412Compressor bs412; + init_bs412(&bs412, config.mpx_power, config.bs412_attack, config.bs412_release, config.sample_rate); TiltCorrectionFilter tilter; tilt_init(&tilter, config.tilt); @@ -175,10 +175,6 @@ int run_fm95(const FM95_Config config, FM95_Runtime* runtime) { StereoEncoder stencode; init_stereo_encoder(&stencode, 4.0f, &osc, (config.stereo == 2), config.volumes.mono, config.volumes.pilot, config.volumes.stereo); - float bs412_audio_gain = 1.0f; - float bs412_attack_alpha = expf(-1.0f / (config.bs412_attack * config.sample_rate)); - float bs412_release_alpha = expf(-1.0f / (config.bs412_release * config.sample_rate)); - AGC agc; initAGC(&agc, config.sample_rate, config.agc_target, config.agc_min, config.agc_max, config.agc_attack, config.agc_release); @@ -236,21 +232,7 @@ int run_fm95(const FM95_Config config, FM95_Runtime* runtime) { } } - float mpx_power = measure_mpx(&power, mpx * config.mpx_deviation); - if (mpx_power > config.mpx_power) { - float excess_power = mpx_power - config.mpx_power; - - if (excess_power > 0.0f && excess_power < 10.0f) { - float target_gain = dbr_to_deviation(-excess_power) / config.mpx_deviation; - - target_gain = fmaxf(target_gain, 0.1f); - target_gain = fminf(target_gain, 1.0f); - - bs412_audio_gain = bs412_attack_alpha * bs412_audio_gain + (1 - bs412_attack_alpha) * target_gain; - } - } else bs412_audio_gain = fminf(1.0f, bs412_release_alpha * bs412_audio_gain + (1 - bs412_release_alpha) * 1.0f); - - mpx *= bs412_audio_gain; + mpx = bs412_compress(&bs412, mpx*config.mpx_deviation); output[i] = hard_clip(tilt(&tilter, (mpx_in[i]+mpx))*config.master_volume, 1.0); // Ensure peak deviation of 75 khz, assuming we're calibrated correctly (lower) advance_oscillator(&osc);