r128.integr_start();
locut.init(FILTER_HPF, 2);
+
+ // hlen=16 is pretty low quality, but we use quite a bit of CPU otherwise,
+ // and there's a limit to how important the peak meter is.
+ peak_resampler.setup(OUTPUT_FREQUENCY, OUTPUT_FREQUENCY * 4, /*num_channels=*/2, /*hlen=*/16);
}
Mixer::~Mixer()
}
}
-float find_peak(const vector<float> &samples)
+float find_peak(const float *samples, size_t num_samples)
{
float m = fabs(samples[0]);
- for (size_t i = 1; i < samples.size(); ++i) {
+ for (size_t i = 1; i < num_samples; ++i) {
m = std::max(m, fabs(samples[i]));
}
return m;
// Then a limiter at +0 dB (so, -14 dBFS) to take out the worst peaks only.
// Note that since ratio is not infinite, we could go slightly higher than this.
// Probably more tuning is warranted here.
- {
- float threshold = pow(10.0f, (ref_level_dbfs + 0.0f) / 20.0f); // +0 dB.
+ if (limiter_enabled) {
+ float threshold = pow(10.0f, limiter_threshold_dbfs / 20.0f);
float ratio = 30.0f;
float attack_time = 0.0f; // Instant.
float release_time = 0.005f;
}
// Finally, the real compressor.
- {
- float threshold = pow(10.0f, (ref_level_dbfs - 12.0f) / 20.0f); // -12 dB.
+ if (compressor_enabled) {
+ float threshold = pow(10.0f, compressor_threshold_dbfs / 20.0f);
float ratio = 20.0f;
float attack_time = 0.005f;
float release_time = 0.040f;
// printf("limiter=%+5.1f compressor=%+5.1f\n", 20.0*log10(limiter_att), 20.0*log10(compressor_att));
- // Find peak and R128 levels.
- peak = max<float>(peak, find_peak(samples_out));
+ // Upsample 4x to find interpolated peak.
+ peak_resampler.inp_data = samples_out.data();
+ peak_resampler.inp_count = samples_out.size() / 2;
+
+ vector<float> interpolated_samples_out;
+ interpolated_samples_out.resize(samples_out.size());
+ while (peak_resampler.inp_count > 0) { // About four iterations.
+ peak_resampler.out_data = &interpolated_samples_out[0];
+ peak_resampler.out_count = interpolated_samples_out.size() / 2;
+ peak_resampler.process();
+ size_t out_stereo_samples = interpolated_samples_out.size() / 2 - peak_resampler.out_count;
+ peak = max<float>(peak, find_peak(interpolated_samples_out.data(), out_stereo_samples * 2));
+ }
+
+ // Find R128 levels.
vector<float> left, right;
deinterleave_samples(samples_out, &left, &right);
float *ptrs[] = { left.data(), right.data() };
void Mixer::reset_meters()
{
+ peak_resampler.reset();
peak = 0.0f;
r128.reset();
r128.integr_start();