+ Compressor simplification, added optional audio ports
(cherry picked from commit 653033d711b1d497d7d465f5ab9a61133c8653f6)
This commit is contained in:
committed by
Tobias Doerffel
parent
3a046201ba
commit
610e170445
@@ -306,6 +306,10 @@ struct plugin_metadata_iface
|
||||
virtual int get_input_count()=0;
|
||||
/// @return number of audio outputs
|
||||
virtual int get_output_count()=0;
|
||||
/// @return number of optional inputs
|
||||
virtual int get_inputs_optional()=0;
|
||||
/// @return number of optional outputs
|
||||
virtual int get_outputs_optional()=0;
|
||||
/// @return true if plugin can work in hard-realtime conditions
|
||||
virtual bool is_rt_capable()=0;
|
||||
/// @return true if plugin has MIDI input
|
||||
@@ -489,6 +493,8 @@ public:
|
||||
const char *get_label() { return Metadata::impl_get_label(); }
|
||||
int get_input_count() { return Metadata::in_count; }
|
||||
int get_output_count() { return Metadata::out_count; }
|
||||
int get_inputs_optional() { return Metadata::ins_optional; }
|
||||
int get_outputs_optional() { return Metadata::outs_optional; }
|
||||
int get_param_count() { return Metadata::param_count; }
|
||||
bool get_midi() { return Metadata::support_midi; }
|
||||
bool requires_midi() { return Metadata::require_midi; }
|
||||
@@ -528,6 +534,8 @@ public:
|
||||
const char *get_label() { return impl->get_label(); }
|
||||
int get_input_count() { return impl->get_input_count(); }
|
||||
int get_output_count() { return impl->get_output_count(); }
|
||||
int get_inputs_optional() { return impl->get_inputs_optional(); }
|
||||
int get_outputs_optional() { return impl->get_outputs_optional(); }
|
||||
int get_param_count() { return impl->get_param_count(); }
|
||||
bool get_midi() { return impl->get_midi(); }
|
||||
bool requires_midi() { return impl->requires_midi(); }
|
||||
|
||||
@@ -31,21 +31,21 @@ struct flanger_metadata: public plugin_metadata<flanger_metadata>
|
||||
{
|
||||
public:
|
||||
enum { par_delay, par_depth, par_rate, par_fb, par_stereo, par_reset, par_amount, par_dryamount, param_count };
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
|
||||
PLUGIN_NAME_ID_LABEL("flanger", "flanger", "Flanger")
|
||||
};
|
||||
|
||||
struct phaser_metadata: public plugin_metadata<phaser_metadata>
|
||||
{
|
||||
enum { par_freq, par_depth, par_rate, par_fb, par_stages, par_stereo, par_reset, par_amount, par_dryamount, param_count };
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
|
||||
PLUGIN_NAME_ID_LABEL("phaser", "phaser", "Phaser")
|
||||
};
|
||||
|
||||
struct filter_metadata: public plugin_metadata<filter_metadata>
|
||||
{
|
||||
enum { par_cutoff, par_resonance, par_mode, par_inertia, param_count };
|
||||
enum { in_count = 2, out_count = 2, rt_capable = true, require_midi = false, support_midi = false };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, require_midi = false, support_midi = false };
|
||||
PLUGIN_NAME_ID_LABEL("filter", "filter", "Filter")
|
||||
/// do not export mode and inertia as CVs, as those are settings and not parameters
|
||||
bool is_cv(int param_no) { return param_no != par_mode && param_no != par_inertia; }
|
||||
@@ -55,7 +55,7 @@ struct filter_metadata: public plugin_metadata<filter_metadata>
|
||||
struct filterclavier_metadata: public plugin_metadata<filterclavier_metadata>
|
||||
{
|
||||
enum { par_transpose, par_detune, par_max_resonance, par_mode, par_inertia, param_count };
|
||||
enum { in_count = 2, out_count = 2, rt_capable = true, require_midi = true, support_midi = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, require_midi = true, support_midi = true };
|
||||
PLUGIN_NAME_ID_LABEL("filterclavier", "filterclavier", "Filterclavier")
|
||||
/// do not export mode and inertia as CVs, as those are settings and not parameters
|
||||
bool is_cv(int param_no) { return param_no != par_mode && param_no != par_inertia; }
|
||||
@@ -64,14 +64,14 @@ struct filterclavier_metadata: public plugin_metadata<filterclavier_metadata>
|
||||
struct reverb_metadata: public plugin_metadata<reverb_metadata>
|
||||
{
|
||||
enum { par_clip, par_meter_wet, par_meter_out, par_decay, par_hfdamp, par_roomsize, par_diffusion, par_amount, par_dry, par_predelay, par_basscut, par_treblecut, param_count };
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
|
||||
PLUGIN_NAME_ID_LABEL("reverb", "reverb", "Reverb")
|
||||
};
|
||||
|
||||
struct vintage_delay_metadata: public plugin_metadata<vintage_delay_metadata>
|
||||
{
|
||||
enum { par_bpm, par_divide, par_time_l, par_time_r, par_feedback, par_amount, par_mixmode, par_medium, par_dryamount, param_count };
|
||||
enum { in_count = 2, out_count = 2, rt_capable = true, support_midi = false, require_midi = false };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, support_midi = false, require_midi = false };
|
||||
PLUGIN_NAME_ID_LABEL("vintage_delay", "vintagedelay", "Vintage Delay")
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@ struct rotary_speaker_metadata: public plugin_metadata<rotary_speaker_metadata>
|
||||
{
|
||||
public:
|
||||
enum { par_speed, par_spacing, par_shift, par_moddepth, par_treblespeed, par_bassspeed, par_micdistance, par_reflection, par_meter_l, par_meter_h, param_count };
|
||||
enum { in_count = 2, out_count = 2, support_midi = true, require_midi = false, rt_capable = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = false, rt_capable = true };
|
||||
PLUGIN_NAME_ID_LABEL("rotary_speaker", "rotaryspeaker", "Rotary Speaker")
|
||||
};
|
||||
|
||||
@@ -88,7 +88,7 @@ struct multichorus_metadata: public plugin_metadata<multichorus_metadata>
|
||||
{
|
||||
public:
|
||||
enum { par_delay, par_depth, par_rate, par_stereo, par_voices, par_vphase, par_amount, par_dryamount, par_freq, par_freq2, par_q, par_overlap, param_count };
|
||||
enum { in_count = 2, out_count = 2, rt_capable = true, support_midi = false, require_midi = false };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, support_midi = false, require_midi = false };
|
||||
PLUGIN_NAME_ID_LABEL("multichorus", "multichorus", "Multi Chorus")
|
||||
};
|
||||
|
||||
@@ -101,7 +101,7 @@ struct monosynth_metadata: public plugin_metadata<monosynth_metadata>
|
||||
par_keyfollow, par_legato, par_portamento, par_vel2filter, par_vel2amp, par_master, par_pwhlrange,
|
||||
par_lforate, par_lfodelay, par_lfofilter, par_lfopitch, par_lfopw, par_mwhl_lfo, par_scaledetune,
|
||||
param_count };
|
||||
enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true };
|
||||
enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = true };
|
||||
enum { step_size = 64, step_shift = 6 };
|
||||
enum {
|
||||
modsrc_none,
|
||||
@@ -128,18 +128,20 @@ struct monosynth_metadata: public plugin_metadata<monosynth_metadata>
|
||||
};
|
||||
|
||||
/// Thor's compressor - metadata
|
||||
/// Added some meters and stripped the weighting part
|
||||
struct compressor_metadata: public plugin_metadata<compressor_metadata>
|
||||
{
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_aweighting, param_compression, param_peak, param_clip, param_bypass, param_input,// param_freq, param_bw,
|
||||
param_count };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { param_bypass, param_level_in, param_meter_in, param_meter_out, param_clip_in, param_clip_out,
|
||||
param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_compression,
|
||||
param_count };
|
||||
PLUGIN_NAME_ID_LABEL("compressor", "compressor", "Compressor")
|
||||
};
|
||||
|
||||
/// Markus's sidechain compressor - metadata
|
||||
struct sidechaincompressor_metadata: public plugin_metadata<sidechaincompressor_metadata>
|
||||
{
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { param_bypass, param_level_in, param_meter_in, param_meter_out, param_clip_in, param_clip_out,
|
||||
param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_compression,
|
||||
param_sc_mode, param_f1_freq, param_f2_freq, param_f1_level, param_f2_level,
|
||||
@@ -150,7 +152,7 @@ struct sidechaincompressor_metadata: public plugin_metadata<sidechaincompressor_
|
||||
/// Markus's multibandcompressor - metadata
|
||||
struct multibandcompressor_metadata: public plugin_metadata<multibandcompressor_metadata>
|
||||
{
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { param_bypass, param_level_in, param_level_out, param_meter_inL, param_meter_inR,
|
||||
param_meter_outL, param_meter_outR, param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR,
|
||||
param_freq0, param_freq1, param_freq2,
|
||||
@@ -171,7 +173,7 @@ struct multibandcompressor_metadata: public plugin_metadata<multibandcompressor_
|
||||
/// Markus's deesser - metadata
|
||||
struct deesser_metadata: public plugin_metadata<deesser_metadata>
|
||||
{
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { param_bypass, param_detected, param_compression, param_detected_led, param_clip_out,
|
||||
param_detection, param_mode,
|
||||
param_threshold, param_ratio, param_laxity, param_makeup,
|
||||
@@ -183,7 +185,7 @@ struct deesser_metadata: public plugin_metadata<deesser_metadata>
|
||||
/// Markus's 5-band EQ - metadata
|
||||
struct equalizer5band_metadata: public plugin_metadata<equalizer5band_metadata>
|
||||
{
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { param_bypass, param_level_in, param_level_out, param_meter_in,
|
||||
param_meter_out, param_clip_in, param_clip_out,
|
||||
param_ls_active, param_ls_level, param_ls_freq,
|
||||
@@ -197,7 +199,7 @@ struct equalizer5band_metadata: public plugin_metadata<equalizer5band_metadata>
|
||||
/// Markus's 8-band EQ - metadata
|
||||
struct equalizer8band_metadata: public plugin_metadata<equalizer8band_metadata>
|
||||
{
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { param_bypass, param_level_in, param_level_out, param_meter_inL, param_meter_inR,
|
||||
param_meter_outL, param_meter_outR, param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR,
|
||||
param_hp_active, param_hp_freq, param_hp_mode,
|
||||
@@ -214,7 +216,7 @@ struct equalizer8band_metadata: public plugin_metadata<equalizer8band_metadata>
|
||||
/// Markus's 12-band EQ - metadata
|
||||
struct equalizer12band_metadata: public plugin_metadata<equalizer12band_metadata>
|
||||
{
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { param_bypass, param_level_in, param_level_out, param_meter_inL, param_meter_inR,
|
||||
param_meter_outL, param_meter_outR, param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR,
|
||||
param_hp_active, param_hp_freq, param_hp_mode,
|
||||
@@ -319,7 +321,7 @@ struct organ_enums
|
||||
/// Organ - metadata
|
||||
struct organ_metadata: public organ_enums, public plugin_metadata<organ_metadata>
|
||||
{
|
||||
enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true };
|
||||
enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = true };
|
||||
PLUGIN_NAME_ID_LABEL("organ", "organ", "Organ")
|
||||
plugin_command_info *get_commands();
|
||||
const char **get_default_configure_vars();
|
||||
@@ -329,7 +331,7 @@ struct organ_metadata: public organ_enums, public plugin_metadata<organ_metadata
|
||||
struct fluidsynth_metadata: public plugin_metadata<fluidsynth_metadata>
|
||||
{
|
||||
enum { par_master, par_soundfont, par_interpolation, par_reverb, par_chorus, param_count };
|
||||
enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = false };
|
||||
enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = false };
|
||||
PLUGIN_NAME_ID_LABEL("fluidsynth", "fluidsynth", "Fluidsynth")
|
||||
const char **get_default_configure_vars();
|
||||
};
|
||||
@@ -399,7 +401,7 @@ struct wavetable_metadata: public plugin_metadata<wavetable_metadata>
|
||||
par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3fade, par_eg3release, par_eg3velscl,
|
||||
par_pwhlrange,
|
||||
param_count };
|
||||
enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true };
|
||||
enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = true };
|
||||
enum { step_size = 64 };
|
||||
PLUGIN_NAME_ID_LABEL("wavetable", "wavetable", "Wavetable")
|
||||
};
|
||||
|
||||
@@ -846,82 +846,6 @@ public:
|
||||
bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context);
|
||||
};
|
||||
|
||||
class compressor_audio_module: public audio_module<compressor_metadata>, public line_graph_iface {
|
||||
private:
|
||||
float linSlope, peak, detected, kneeSqrt, kneeStart, linKneeStart, kneeStop, threshold, ratio, knee, makeup, compressedKneeStop, adjKneeStart;
|
||||
float old_threshold, old_ratio, old_knee, old_makeup, old_bypass;
|
||||
int last_generation;
|
||||
uint32_t clip;
|
||||
aweighter awL, awR;
|
||||
biquad_d2<float> bpL, bpR;
|
||||
public:
|
||||
float *ins[in_count];
|
||||
float *outs[out_count];
|
||||
float *params[param_count];
|
||||
uint32_t srate;
|
||||
bool is_active;
|
||||
compressor_audio_module();
|
||||
void activate();
|
||||
void deactivate();
|
||||
uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
|
||||
|
||||
inline float output_level(float slope) {
|
||||
return slope * output_gain(slope, false) * makeup;
|
||||
}
|
||||
|
||||
inline float output_gain(float linSlope, bool rms) {
|
||||
if(linSlope > (rms ? adjKneeStart : linKneeStart)) {
|
||||
float slope = log(linSlope);
|
||||
if(rms) slope *= 0.5f;
|
||||
|
||||
float gain = 0.f;
|
||||
float delta = 0.f;
|
||||
if(IS_FAKE_INFINITY(ratio)) {
|
||||
gain = threshold;
|
||||
delta = 0.f;
|
||||
} else {
|
||||
gain = (slope - threshold) / ratio + threshold;
|
||||
delta = 1.f / ratio;
|
||||
}
|
||||
|
||||
if(knee > 1.f && slope < kneeStop) {
|
||||
gain = hermite_interpolation(slope, kneeStart, kneeStop, kneeStart, compressedKneeStop, 1.f, delta);
|
||||
}
|
||||
|
||||
return exp(gain - slope);
|
||||
}
|
||||
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
void set_sample_rate(uint32_t sr);
|
||||
|
||||
virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context);
|
||||
virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context);
|
||||
virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context);
|
||||
|
||||
virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
|
||||
{
|
||||
subindex_graph = 0;
|
||||
subindex_dot = 0;
|
||||
subindex_gridline = generation ? INT_MAX : 0;
|
||||
|
||||
if (fabs(threshold-old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs( makeup - old_makeup) + fabs( *params[param_bypass] - old_bypass) > 0.01f)
|
||||
{
|
||||
old_threshold = threshold;
|
||||
old_ratio = ratio;
|
||||
old_knee = knee;
|
||||
old_makeup = makeup;
|
||||
old_bypass = *params[param_bypass];
|
||||
last_generation++;
|
||||
}
|
||||
|
||||
if (generation == last_generation)
|
||||
subindex_graph = 2;
|
||||
return last_generation;
|
||||
}
|
||||
};
|
||||
|
||||
class gain_reduction_audio_module {
|
||||
private:
|
||||
float linSlope, detected, kneeSqrt, kneeStart, linKneeStart, kneeStop;
|
||||
@@ -949,6 +873,32 @@ public:
|
||||
virtual int get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline);
|
||||
};
|
||||
|
||||
/// Compressor by Thor
|
||||
class compressor_audio_module: public audio_module<compressor_metadata>, public line_graph_iface {
|
||||
private:
|
||||
uint32_t clip_in, clip_out;
|
||||
float meter_in, meter_out;
|
||||
gain_reduction_audio_module compressor;
|
||||
public:
|
||||
typedef std::complex<double> cfloat;
|
||||
float *ins[in_count];
|
||||
float *outs[out_count];
|
||||
float *params[param_count];
|
||||
uint32_t srate;
|
||||
bool is_active;
|
||||
volatile int last_generation, last_calculated_generation;
|
||||
compressor_audio_module();
|
||||
void activate();
|
||||
void deactivate();
|
||||
void params_changed();
|
||||
void set_sample_rate(uint32_t sr);
|
||||
uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
|
||||
bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context);
|
||||
bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context);
|
||||
bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context);
|
||||
int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline);
|
||||
};
|
||||
|
||||
/// Sidecain Compressor by Markus Schmidt (based on Thor's compressor and Krzysztof's filters)
|
||||
class sidechaincompressor_audio_module: public audio_module<sidechaincompressor_metadata>, public frequency_response_line_graph {
|
||||
private:
|
||||
|
||||
@@ -215,25 +215,23 @@ CALF_PORT_NAMES(compressor) = {"In L", "In R", "Out L", "Out R"};
|
||||
|
||||
const char *compressor_detection_names[] = { "RMS", "Peak" };
|
||||
const char *compressor_stereo_link_names[] = { "Average", "Maximum" };
|
||||
const char *compressor_weighting_names[] = { "Normal", "A-weighted", "Deesser (low)", "Deesser (med)", "Deesser (high)" };
|
||||
|
||||
CALF_PORT_PROPS(compressor) = {
|
||||
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
|
||||
{ 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" },
|
||||
{ 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" },
|
||||
{ 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" },
|
||||
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" },
|
||||
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" },
|
||||
{ 0.125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" },
|
||||
{ 2, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" },
|
||||
{ 20, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Attack" },
|
||||
{ 250, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release", "Release" },
|
||||
{ 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup Gain" },
|
||||
{ 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup Gain" },
|
||||
{ 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee", "Knee" },
|
||||
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, compressor_detection_names, "detection", "Detection" },
|
||||
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, compressor_stereo_link_names, "stereo_link", "Stereo Link" },
|
||||
{ 0, 0, 4, 0, PF_ENUM | PF_CTL_COMBO, compressor_weighting_names, "aweighting", "Weighting" },
|
||||
{ 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Compression" },
|
||||
{ 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "peak", "Peak Output" },
|
||||
{ 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip", "0dB" },
|
||||
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
|
||||
{ 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "input", "Input" },
|
||||
// { 2000, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "deess_freq", "Frequency" },
|
||||
// { 0.707, 0.707, 32, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "deess_res", "Q" },
|
||||
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, compressor_detection_names, "detection", "Detection" },
|
||||
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, compressor_stereo_link_names, "stereo_link", "Stereo Link" },
|
||||
{ 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Reduction" },
|
||||
};
|
||||
|
||||
CALF_PLUGIN_INFO(compressor) = { 0x8502, "Compressor", "Calf Compressor", "Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
|
||||
|
||||
@@ -425,218 +425,6 @@ float multichorus_audio_module::freq_gain(int subindex, float freq, float srate)
|
||||
return (subindex ? right : left).freq_gain(freq, srate);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
compressor_audio_module::compressor_audio_module()
|
||||
{
|
||||
is_active = false;
|
||||
srate = 0;
|
||||
last_generation = 0;
|
||||
}
|
||||
|
||||
void compressor_audio_module::activate()
|
||||
{
|
||||
is_active = true;
|
||||
linSlope = 0.f;
|
||||
peak = 0.f;
|
||||
clip = 0.f;
|
||||
}
|
||||
|
||||
void compressor_audio_module::deactivate()
|
||||
{
|
||||
is_active = false;
|
||||
}
|
||||
|
||||
void compressor_audio_module::set_sample_rate(uint32_t sr)
|
||||
{
|
||||
srate = sr;
|
||||
awL.set(sr);
|
||||
awR.set(sr);
|
||||
}
|
||||
|
||||
bool compressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
|
||||
{
|
||||
if (!is_active)
|
||||
return false;
|
||||
if (subindex > 1) // 1
|
||||
return false;
|
||||
for (int i = 0; i < points; i++)
|
||||
{
|
||||
float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1));
|
||||
float output = output_level(input);
|
||||
if (subindex == 0)
|
||||
data[i] = dB_grid(input);
|
||||
else
|
||||
data[i] = dB_grid(output);
|
||||
}
|
||||
if (subindex == (*params[param_bypass] > 0.5f ? 1 : 0))
|
||||
context->set_source_rgba(0.35, 0.4, 0.2, 0.3);
|
||||
else {
|
||||
context->set_source_rgba(0.35, 0.4, 0.2, 1);
|
||||
context->set_line_width(2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool compressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
|
||||
{
|
||||
if (!is_active)
|
||||
return false;
|
||||
if (!subindex)
|
||||
{
|
||||
bool rms = *params[param_detection] == 0;
|
||||
float det = rms ? sqrt(detected) : detected;
|
||||
x = 0.5 + 0.5 * dB_grid(det);
|
||||
y = dB_grid(*params[param_bypass] > 0.5f ? det : output_level(det));
|
||||
return *params[param_bypass] > 0.5f ? false : true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool compressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
|
||||
{
|
||||
bool tmp;
|
||||
vertical = (subindex & 1) != 0;
|
||||
bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false);
|
||||
if (result && vertical) {
|
||||
if ((subindex & 4) && !legend.empty()) {
|
||||
legend = "";
|
||||
}
|
||||
else {
|
||||
size_t pos = legend.find(" dB");
|
||||
if (pos != std::string::npos)
|
||||
legend.erase(pos);
|
||||
}
|
||||
pos = 0.5 + 0.5 * pos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// In case of doubt: this function is written by Thor. I just moved it to this file, damaging
|
||||
// the output of "git annotate" in the process.
|
||||
uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
|
||||
{
|
||||
bool bypass = *params[param_bypass] > 0.5f;
|
||||
|
||||
if(bypass) {
|
||||
numsamples += offset;
|
||||
while(offset < numsamples) {
|
||||
outs[0][offset] = ins[0][offset];
|
||||
outs[1][offset] = ins[1][offset];
|
||||
++offset;
|
||||
}
|
||||
|
||||
if(params[param_compression] != NULL) {
|
||||
*params[param_compression] = 1.f;
|
||||
}
|
||||
|
||||
if(params[param_clip] != NULL) {
|
||||
*params[param_clip] = 0.f;
|
||||
}
|
||||
|
||||
if(params[param_peak] != NULL) {
|
||||
*params[param_peak] = 0.f;
|
||||
}
|
||||
|
||||
return inputs_mask;
|
||||
}
|
||||
|
||||
bool rms = *params[param_detection] == 0;
|
||||
bool average = *params[param_stereo_link] == 0;
|
||||
int aweighting = fastf2i_drm(*params[param_aweighting]);
|
||||
float linThreshold = *params[param_threshold];
|
||||
ratio = *params[param_ratio];
|
||||
float attack = *params[param_attack];
|
||||
float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f));
|
||||
float release = *params[param_release];
|
||||
float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f));
|
||||
makeup = *params[param_makeup];
|
||||
knee = *params[param_knee];
|
||||
|
||||
float linKneeSqrt = sqrt(knee);
|
||||
linKneeStart = linThreshold / linKneeSqrt;
|
||||
adjKneeStart = linKneeStart*linKneeStart;
|
||||
float linKneeStop = linThreshold * linKneeSqrt;
|
||||
|
||||
threshold = log(linThreshold);
|
||||
kneeStart = log(linKneeStart);
|
||||
kneeStop = log(linKneeStop);
|
||||
compressedKneeStop = (kneeStop - threshold) / ratio + threshold;
|
||||
|
||||
if (aweighting >= 2)
|
||||
{
|
||||
bpL.set_highshelf_rbj(5000, 0.707, 10 << (aweighting - 2), srate);
|
||||
bpR.copy_coeffs(bpL);
|
||||
bpL.sanitize();
|
||||
bpR.sanitize();
|
||||
}
|
||||
|
||||
numsamples += offset;
|
||||
|
||||
float compression = 1.f;
|
||||
peak = 0.f;
|
||||
clip -= std::min(clip, numsamples);
|
||||
|
||||
while(offset < numsamples) {
|
||||
float left = ins[0][offset] * *params[param_input];
|
||||
float right = ins[1][offset] * *params[param_input];
|
||||
|
||||
if(aweighting == 1) {
|
||||
left = awL.process(left);
|
||||
right = awR.process(right);
|
||||
}
|
||||
else if(aweighting >= 2) {
|
||||
left = bpL.process(left);
|
||||
right = bpR.process(right);
|
||||
}
|
||||
|
||||
float absample = average ? (fabs(left) + fabs(right)) * 0.5f : std::max(fabs(left), fabs(right));
|
||||
if(rms) absample *= absample;
|
||||
|
||||
linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff);
|
||||
|
||||
float gain = 1.f;
|
||||
|
||||
if(linSlope > 0.f) {
|
||||
gain = output_gain(linSlope, rms);
|
||||
}
|
||||
|
||||
compression = gain;
|
||||
gain *= makeup;
|
||||
|
||||
float outL = ins[0][offset] * gain * *params[param_input];
|
||||
float outR = ins[1][offset] * gain * *params[param_input];
|
||||
|
||||
outs[0][offset] = outL;
|
||||
outs[1][offset] = outR;
|
||||
|
||||
++offset;
|
||||
|
||||
float maxLR = std::max(fabs(outL), fabs(outR));
|
||||
if(maxLR > peak)
|
||||
peak = maxLR;
|
||||
|
||||
if(peak > 1.f) clip = srate >> 3; /* blink clip LED for 125 ms */
|
||||
}
|
||||
|
||||
detected = linSlope;
|
||||
|
||||
if(params[param_compression] != NULL) {
|
||||
*params[param_compression] = compression;
|
||||
}
|
||||
|
||||
if(params[param_clip] != NULL) {
|
||||
*params[param_clip] = clip;
|
||||
}
|
||||
|
||||
if(params[param_peak] != NULL) {
|
||||
*params[param_peak] = peak;
|
||||
}
|
||||
|
||||
return inputs_mask;
|
||||
}
|
||||
|
||||
|
||||
/// Multibandcompressor by Markus Schmidt
|
||||
///
|
||||
/// This module splits the signal in four different bands
|
||||
@@ -1050,6 +838,161 @@ int multibandcompressor_audio_module::get_changed_offsets(int index, int generat
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Compressor originally by Thor
|
||||
///
|
||||
/// This module provides Thor's original compressor without any sidechain or weighting
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
compressor_audio_module::compressor_audio_module()
|
||||
{
|
||||
is_active = false;
|
||||
srate = 0;
|
||||
last_generation = 0;
|
||||
}
|
||||
|
||||
void compressor_audio_module::activate()
|
||||
{
|
||||
is_active = true;
|
||||
// set all filters and strips
|
||||
compressor.activate();
|
||||
params_changed();
|
||||
meter_in = 0.f;
|
||||
meter_out = 0.f;
|
||||
clip_in = 0.f;
|
||||
clip_out = 0.f;
|
||||
}
|
||||
void compressor_audio_module::deactivate()
|
||||
{
|
||||
is_active = false;
|
||||
compressor.deactivate();
|
||||
}
|
||||
|
||||
void compressor_audio_module::params_changed()
|
||||
{
|
||||
compressor.set_params(*params[param_attack], *params[param_release], *params[param_threshold], *params[param_ratio], *params[param_knee], *params[param_makeup], *params[param_detection], *params[param_stereo_link], *params[param_bypass], 0.f);
|
||||
}
|
||||
|
||||
void compressor_audio_module::set_sample_rate(uint32_t sr)
|
||||
{
|
||||
srate = sr;
|
||||
compressor.set_sample_rate(srate);
|
||||
}
|
||||
|
||||
uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
|
||||
{
|
||||
bool bypass = *params[param_bypass] > 0.5f;
|
||||
numsamples += offset;
|
||||
if(bypass) {
|
||||
// everything bypassed
|
||||
while(offset < numsamples) {
|
||||
outs[0][offset] = ins[0][offset];
|
||||
outs[1][offset] = ins[1][offset];
|
||||
++offset;
|
||||
}
|
||||
// displays, too
|
||||
clip_in = 0.f;
|
||||
clip_out = 0.f;
|
||||
meter_in = 0.f;
|
||||
meter_out = 0.f;
|
||||
} else {
|
||||
// process
|
||||
|
||||
clip_in -= std::min(clip_in, numsamples);
|
||||
clip_out -= std::min(clip_out, numsamples);
|
||||
|
||||
while(offset < numsamples) {
|
||||
// cycle through samples
|
||||
float outL = 0.f;
|
||||
float outR = 0.f;
|
||||
float inL = ins[0][offset];
|
||||
float inR = ins[1][offset];
|
||||
// in level
|
||||
inR *= *params[param_level_in];
|
||||
inL *= *params[param_level_in];
|
||||
|
||||
float leftAC = inL;
|
||||
float rightAC = inR;
|
||||
float leftSC = inL;
|
||||
float rightSC = inR;
|
||||
|
||||
compressor.process(leftAC, rightAC, leftSC, rightSC);
|
||||
|
||||
outL = leftAC;
|
||||
outR = rightAC;
|
||||
|
||||
// send to output
|
||||
outs[0][offset] = outL;
|
||||
outs[1][offset] = outR;
|
||||
|
||||
// clip LED's
|
||||
if(std::max(fabs(inL), fabs(inR)) > 1.f) {
|
||||
clip_in = srate >> 3;
|
||||
}
|
||||
if(std::max(fabs(outL), fabs(outR)) > 1.f) {
|
||||
clip_out = srate >> 3;
|
||||
}
|
||||
// rise up out meter
|
||||
meter_in = std::max(fabs(inL), fabs(inR));;
|
||||
meter_out = std::max(fabs(outL), fabs(outR));;
|
||||
|
||||
// next sample
|
||||
++offset;
|
||||
} // cycle trough samples
|
||||
}
|
||||
// draw meters
|
||||
if(params[param_clip_in] != NULL) {
|
||||
*params[param_clip_in] = clip_in;
|
||||
}
|
||||
if(params[param_clip_out] != NULL) {
|
||||
*params[param_clip_out] = clip_out;
|
||||
}
|
||||
if(params[param_meter_in] != NULL) {
|
||||
*params[param_meter_in] = meter_in;
|
||||
}
|
||||
if(params[param_meter_out] != NULL) {
|
||||
*params[param_meter_out] = meter_out;
|
||||
}
|
||||
// draw strip meter
|
||||
if(bypass > 0.5f) {
|
||||
if(params[param_compression] != NULL) {
|
||||
*params[param_compression] = 1.0f;
|
||||
}
|
||||
} else {
|
||||
if(params[param_compression] != NULL) {
|
||||
*params[param_compression] = compressor.get_comp_level();
|
||||
}
|
||||
}
|
||||
// whatever has to be returned x)
|
||||
return outputs_mask;
|
||||
}
|
||||
bool compressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
|
||||
{
|
||||
if (!is_active)
|
||||
return false;
|
||||
return compressor.get_graph(subindex, data, points, context);
|
||||
}
|
||||
|
||||
bool compressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
|
||||
{
|
||||
if (!is_active)
|
||||
return false;
|
||||
return compressor.get_dot(subindex, x, y, size, context);
|
||||
}
|
||||
|
||||
bool compressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
|
||||
{
|
||||
if (!is_active)
|
||||
return false;
|
||||
return compressor.get_gridline(subindex, pos, vertical, legend, context);
|
||||
}
|
||||
|
||||
int compressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
|
||||
{
|
||||
if (!is_active)
|
||||
return false;
|
||||
return compressor.get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
|
||||
}
|
||||
|
||||
/// Sidecain Compressor by Markus Schmidt
|
||||
///
|
||||
/// This module splits the signal in a sidechain- and a process signal.
|
||||
|
||||
Reference in New Issue
Block a user