mpx seperation

This commit is contained in:
2026-02-15 18:18:54 +01:00
parent 743df55b00
commit 73396a6cba
5 changed files with 20 additions and 16 deletions
+6 -4
View File
@@ -30,7 +30,9 @@ void init_bs412(BS412Compressor* mpx, uint32_t mpx_deviation, float target_power
#endif #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); 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); float avg_deviation = sqrtf(mpx->avg_power);
@@ -44,7 +46,7 @@ float bs412_compress(BS412Compressor* mpx, float sample) {
} }
#endif #endif
mpx->sample_counter++; mpx->sample_counter++;
return sample; return combined;
} }
if(mpx->sample_counter > mpx->sample_rate) { if(mpx->sample_counter > mpx->sample_rate) {
@@ -65,7 +67,7 @@ float bs412_compress(BS412Compressor* mpx, float sample) {
if(mpx->can_compress == 0) { if(mpx->can_compress == 0) {
mpx->sample_counter++; mpx->sample_counter++;
return sample; return combined;
} }
float target_gain = powf(10.0f, (mpx->target - modulation_power) / 10.0f); 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)); 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) { if(deviation_to_dbr(avg_deviation * mpx->gain) > mpx->target && deviation_to_dbr(avg_deviation) < mpx->target) {
// Gain is too much, reduce // Gain is too much, reduce
float overshoot_dbr = deviation_to_dbr(avg_deviation * mpx->gain) - mpx->target; float overshoot_dbr = deviation_to_dbr(avg_deviation * mpx->gain) - mpx->target;
+2 -2
View File
@@ -27,8 +27,8 @@ typedef struct
float last_output; float last_output;
} BS412Compressor; } 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_bs412(BS412Compressor *mpx, uint32_t mpx_deviation, float target_power, float attack, float release, uint32_t sample_rate); 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); float bs412_compress(BS412Compressor *mpx, float audio, float sample_mpx);
+5 -5
View File
@@ -13,7 +13,7 @@ void init_stereo_encoder(StereoEncoder* st, uint8_t stereo_ssb, uint8_t multipli
} else st->stereo_hilbert = NULL; } 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; float mid = (left+right) * 0.5f;
if(!enabled) return mid * st->audio_volume; 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); float signalx2 = get_oscillator_sin_multiplier_ni(st->osc, st->multiplier * 2.0f);
*audio = (mid*half_audio);
if(st->stereo_hilbert) { if(st->stereo_hilbert) {
float stereo = (crealf(stereo_hilbert) * signalx2cos) + (cimagf(stereo_hilbert) * signalx2); float stereo = (crealf(stereo_hilbert) * signalx2cos) + (cimagf(stereo_hilbert) * signalx2);
return (mid*half_audio) + (signalx1*st->pilot_volume) + (stereo * half_audio); *audio += (stereo * half_audio)
} else { } else *audio += ((side*signalx2) * half_audio);
return (mid*half_audio) + (signalx1*st->pilot_volume) + ((side*signalx2) * half_audio); return (signalx1*st->pilot_volume);
}
} }
void exit_stereo_encoder(StereoEncoder* st) { void exit_stereo_encoder(StereoEncoder* st) {
+1 -1
View File
@@ -18,5 +18,5 @@ typedef struct
} StereoEncoder; } StereoEncoder;
void init_stereo_encoder(StereoEncoder *st, uint8_t stereo_ssb, uint8_t multiplier, Oscillator *osc, float audio_volume, float pilot_volume); 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); void exit_stereo_encoder(StereoEncoder* st);
+6 -4
View File
@@ -199,6 +199,7 @@ int run_fm95(const FM95_Config config, FM95_Runtime* runtime) {
for (uint16_t i = 0; i < BUFFER_SIZE; i++) { for (uint16_t i = 0; i < BUFFER_SIZE; i++) {
float mpx = 0.0f; float mpx = 0.0f;
float audio = 0.0f;
float l = audio_stereo_input[2*i+0]*config.audio_preamp; float l = audio_stereo_input[2*i+0]*config.audio_preamp;
float r = audio_stereo_input[2*i+1]*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); 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) { if(rds_on) {
float rds_level = config.volumes.rds; 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; uint8_t osc_stream = 12 + stream;
if(osc_stream >= 13) osc_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; float carrier = get_oscillator_cos_multiplier_ni(&runtime->osc, osc_stream);
else mpx += (runtime->rds_in[config.rds_streams * i + stream] * get_oscillator_cos_multiplier_ni(&runtime->osc, osc_stream)) * rds_level; 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 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 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); advance_oscillator(&runtime->osc);