Browse Source

obs-filters: Refactor expander filter expansion code

Things were a bit unoptimal and were squished together, making the code
much more difficult to work with. Instead, separate the code for
processing individual samples into its own function.
Jim 3 years ago
parent
commit
56cfaf792d
1 changed files with 59 additions and 38 deletions
  1. 59 38
      plugins/obs-filters/expander-filter.c

+ 59 - 38
plugins/obs-filters/expander-filter.c

@@ -304,59 +304,80 @@ static void analyze_envelope(struct expander_data *cd, float **samples,
 	}
 }
 
+static inline void process_sample(size_t idx, float *samples, float *env_buf,
+				  float *gain_db, float channel_gain,
+				  float threshold, float slope,
+				  float attack_gain, float inv_attack_gain,
+				  float release_gain, float inv_release_gain,
+				  float output_gain)
+{
+	/* --------------------------------- */
+	/* gain stage of expansion           */
+
+	float env_db = mul_to_db(env_buf[idx]);
+	float diff = threshold - env_db;
+	float gain = diff > 0.0f ? fmaxf(slope * diff, -60.0f) : 0.0f;
+	float prev_gain = gain_db[idx - 1];
+
+	/* --------------------------------- */
+	/* ballastics (attack/release)       */
+
+	if (idx > 0) {
+		if (gain > prev_gain)
+			gain_db[idx] = attack_gain * prev_gain +
+				       inv_attack_gain * gain;
+		else
+			gain_db[idx] = release_gain * prev_gain +
+				       inv_release_gain * gain;
+	} else {
+		if (gain > channel_gain)
+			gain_db[idx] = attack_gain * channel_gain +
+				       inv_attack_gain * gain;
+		else
+			gain_db[idx] = release_gain * channel_gain +
+				       inv_release_gain * gain;
+	}
+
+	/* --------------------------------- */
+	/* output                            */
+
+	gain = db_to_mul(fminf(0.0f, gain_db[idx]));
+	samples[idx] *= gain * output_gain;
+}
+
 // gain stage and ballistics in dB domain
 static inline void process_expansion(struct expander_data *cd, float **samples,
 				     uint32_t num_samples)
 {
 	const float attack_gain = cd->attack_gain;
 	const float release_gain = cd->release_gain;
+	const float inv_attack_gain = 1.0f - attack_gain;
+	const float inv_release_gain = 1.0f - release_gain;
+	const float threshold = cd->threshold;
+	const float slope = cd->slope;
+	const float output_gain = cd->output_gain;
 
 	if (cd->gain_db_len < num_samples)
 		resize_gain_db_buffer(cd, num_samples);
-	for (int i = 0; i < MAX_AUDIO_CHANNELS; i++)
+
+	for (size_t i = 0; i < cd->num_channels; i++)
 		memset(cd->gain_db[i], 0,
 		       num_samples * sizeof(cd->gain_db[i][0]));
 
 	for (size_t chan = 0; chan < cd->num_channels; chan++) {
-		for (size_t i = 0; i < num_samples; ++i) {
-			// gain stage of expansion
-			float env_db = mul_to_db(cd->envelope_buf[chan][i]);
-			float gain =
-				cd->threshold - env_db > 0.0f
-					? fmaxf(cd->slope * (cd->threshold -
-							     env_db),
-						-60.0f)
-					: 0.0f;
-			// ballistics (attack/release)
-			if (i > 0) {
-				if (gain > cd->gain_db[chan][i - 1])
-					cd->gain_db[chan][i] =
-						attack_gain *
-							cd->gain_db[chan][i - 1] +
-						(1.0f - attack_gain) * gain;
-				else
-					cd->gain_db[chan][i] =
-						release_gain *
-							cd->gain_db[chan][i - 1] +
-						(1.0f - release_gain) * gain;
-			} else {
-				if (gain > cd->gain_db_buf[chan])
-					cd->gain_db[chan][i] =
-						attack_gain *
-							cd->gain_db_buf[chan] +
-						(1.0f - attack_gain) * gain;
-				else
-					cd->gain_db[chan][i] =
-						release_gain *
-							cd->gain_db_buf[chan] +
-						(1.0f - release_gain) * gain;
-			}
+		float *channel_samples = samples[chan];
+		float *env_buf = cd->envelope_buf[chan];
+		float *gain_db = cd->gain_db[chan];
+		float channel_gain = cd->gain_db_buf[chan];
 
-			gain = db_to_mul(fminf(0, cd->gain_db[chan][i]));
-			if (samples[chan])
-				samples[chan][i] *= gain * cd->output_gain;
+		for (size_t i = 0; i < num_samples; ++i) {
+			process_sample(i, channel_samples, env_buf, gain_db,
+				       channel_gain, threshold, slope,
+				       attack_gain, inv_attack_gain,
+				       release_gain, inv_release_gain,
+				       output_gain);
 		}
-		cd->gain_db_buf[chan] = cd->gain_db[chan][num_samples - 1];
+		cd->gain_db_buf[chan] = gain_db[num_samples - 1];
 	}
 }