0
1
mirror of https://github.com/radio95-rnt/fm95.git synced 2026-02-26 19:23:51 +01:00

try another bs412 compressor implementation

This commit is contained in:
2025-07-08 22:56:44 +02:00
parent 52f2f61a9a
commit 69494eaac4
3 changed files with 24 additions and 27 deletions

View File

@@ -11,16 +11,20 @@ inline float deviation_to_dbr(float deviation) {
return 10.0f * (log2f(deviation) - LOG2_19000) * 0.30103f; 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_counter = 0;
mpx->sample = 0; mpx->sample = 0;
mpx->sample_rate = sample_rate; 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 #ifdef BS412_DEBUG
debug_printf("Initialized MPX power measurement with sample rate: %d\n", sample_rate); debug_printf("Initialized MPX power measurement with sample rate: %d\n", sample_rate);
#endif #endif
} }
float measure_mpx(MPXPowerMeasurement* mpx, float deviation) { float bs412_compress(BS412Compressor* mpx, float deviation) {
mpx->sample += deviation * deviation; // rmS mpx->sample += deviation * deviation; // rmS
mpx->sample_counter++; mpx->sample_counter++;
@@ -42,5 +46,12 @@ float measure_mpx(MPXPowerMeasurement* mpx, float deviation) {
mpx->sample_counter = 1; 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;
} }

View File

@@ -13,11 +13,15 @@ typedef struct
{ {
int sample_counter; int sample_counter;
int sample_rate; int sample_rate;
float target;
float attack;
float release;
float gain;
double sample; double sample;
} MPXPowerMeasurement; } BS412Compressor;
float dbr_to_deviation(float dbr); float dbr_to_deviation(float dbr);
float deviation_to_dbr(float deviation); float deviation_to_dbr(float deviation);
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);
float measure_mpx(MPXPowerMeasurement *mpx, float deviation); float bs412_compress(BS412Compressor *mpx, float deviation);

View File

@@ -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_l, config.preemphasis, config.sample_rate, config.preemp_unity_freq);
init_preemphasis(&preemp_r, config.preemphasis, config.sample_rate, config.preemp_unity_freq); init_preemphasis(&preemp_r, config.preemphasis, config.sample_rate, config.preemp_unity_freq);
MPXPowerMeasurement power; BS412Compressor bs412;
init_modulation_power_measure(&power, config.sample_rate); init_bs412(&bs412, config.mpx_power, config.bs412_attack, config.bs412_release, config.sample_rate);
TiltCorrectionFilter tilter; TiltCorrectionFilter tilter;
tilt_init(&tilter, config.tilt); tilt_init(&tilter, config.tilt);
@@ -175,10 +175,6 @@ int run_fm95(const FM95_Config config, FM95_Runtime* runtime) {
StereoEncoder stencode; StereoEncoder stencode;
init_stereo_encoder(&stencode, 4.0f, &osc, (config.stereo == 2), config.volumes.mono, config.volumes.pilot, config.volumes.stereo); 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; AGC agc;
initAGC(&agc, config.sample_rate, config.agc_target, config.agc_min, config.agc_max, config.agc_attack, config.agc_release); 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); mpx = bs412_compress(&bs412, 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;
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) 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); advance_oscillator(&osc);