2 * Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
18 #include "lv2/lv2plug.in/ns/lv2core/lv2.h"
20 #define ACOMP_URI "urn:ardour:a-comp"
63 instantiate(const LV2_Descriptor* descriptor,
65 const char* bundle_path,
66 const LV2_Feature* const* features)
68 AComp* acomp = (AComp*)malloc(sizeof(AComp));
71 acomp->old_yl=acomp->old_y1=acomp->old_yg=0.f;
73 return (LV2_Handle)acomp;
77 connect_port(LV2_Handle instance,
81 AComp* acomp = (AComp*)instance;
83 switch ((PortIndex)port) {
85 acomp->attack = (float*)data;
88 acomp->release = (float*)data;
91 acomp->knee = (float*)data;
94 acomp->ratio = (float*)data;
97 acomp->thresdb = (float*)data;
100 acomp->makeup = (float*)data;
103 acomp->gainr = (float*)data;
106 acomp->outlevel = (float*)data;
108 case ACOMP_SIDECHAIN:
109 acomp->sidechain = (float*)data;
112 acomp->input0 = (float*)data;
115 acomp->input1 = (float*)data;
118 acomp->output = (float*)data;
123 // Force already-denormal float value to zero
125 sanitize_denormal(float value) {
126 if (!isnormal(value)) {
134 return (exp(gdb/20.f*log(10.f)));
139 return (20.f*log10(g));
143 activate(LV2_Handle instance)
145 AComp* acomp = (AComp*)instance;
147 *(acomp->gainr) = 0.0f;
148 *(acomp->outlevel) = -45.0f;
149 acomp->old_yl=acomp->old_y1=acomp->old_yg=0.f;
153 run(LV2_Handle instance, uint32_t n_samples)
155 AComp* acomp = (AComp*)instance;
157 const float* const input0 = acomp->input0;
158 const float* const input1 = acomp->input1;
159 float* const output = acomp->output;
161 float srate = acomp->srate;
162 float width = (6.f * *(acomp->knee)) + 0.01;
164 float attack_coeff = exp(-1000.f/(*(acomp->attack) * srate));
165 float release_coeff = exp(-1000.f/(*(acomp->release) * srate));
168 float lgaininp = 0.f;
170 float Lxg, Lxl, Lyg, Lyl, Ly1;
171 int usesidechain = (*(acomp->sidechain) < 0.5) ? 0 : 1;
176 float ratio = *(acomp->ratio);
177 float thresdb = *(acomp->thresdb);
179 for (i = 0; i < n_samples; i++) {
182 ingain = usesidechain ? in1 : in0;
184 Lxg = (ingain==0.f) ? -160.f : to_dB(fabs(ingain));
185 Lxg = sanitize_denormal(Lxg);
187 Lyg = Lxg + (1.f/ratio-1.f)*(Lxg-thresdb+width/2.f)*(Lxg-thresdb+width/2.f)/(2.f*width);
189 if (2.f*(Lxg-thresdb) < -width) {
192 Lyg = thresdb + (Lxg-thresdb)/ratio;
193 Lyg = sanitize_denormal(Lyg);
198 acomp->old_y1 = sanitize_denormal(acomp->old_y1);
199 acomp->old_yl = sanitize_denormal(acomp->old_yl);
200 Ly1 = fmaxf(Lxl, release_coeff * acomp->old_y1+(1.f-release_coeff)*Lxl);
201 Lyl = attack_coeff * acomp->old_yl+(1.f-attack_coeff)*Ly1;
202 Ly1 = sanitize_denormal(Ly1);
203 Lyl = sanitize_denormal(Lyl);
206 Lgain = from_dB(cdb);
208 *(acomp->gainr) = Lyl;
210 lgaininp = in0 * Lgain;
211 output[i] = lgaininp * from_dB(*(acomp->makeup));
213 max = (fabsf(output[i]) > max) ? fabsf(output[i]) : sanitize_denormal(max);
219 *(acomp->outlevel) = (max == 0.f) ? -45.f : to_dB(max);
223 deactivate(LV2_Handle instance)
229 cleanup(LV2_Handle instance)
235 extension_data(const char* uri)
240 static const LV2_Descriptor descriptor = {
252 const LV2_Descriptor*
253 lv2_descriptor(uint32_t index)