1 /* abGate - LV2 Noise Gate Plugin
2  *
3  * Copyright 2011 Antanas Bružas
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 3 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 #include <stdlib.h>
20 #include <lv2.h>
21 #include <cmath>
22 
23 #include "gate_const.h"
24 
25 #define CLOSED 1
26 #define ATTACK 2
27 #define OPENED 3
28 #define DECAY 4
29 
30 static LV2_Descriptor *gateDescriptor = NULL;
31 
32 class Gate {
33 public:
Gate()34 	Gate() {
35 		state = CLOSED;
36 		gate = 0;
37 		holding = 0;
38 	}
~Gate()39 	~Gate() {
40 	}
41 
42 	float *switch_button, *threshold, *attack, *hold, *decay, *range, sample_rate, gate, *output;
43 	const float *input;
44 	int state, holding;
45 };
46 
instantiateGate(const LV2_Descriptor * descriptor,double s_rate,const char * path,const LV2_Feature * const * features)47 static LV2_Handle instantiateGate(const LV2_Descriptor *descriptor, double s_rate, const char *path, const LV2_Feature * const * features) {
48 	Gate *plugin_data = new Gate;
49 	plugin_data->sample_rate = s_rate;
50 	return (LV2_Handle) plugin_data;
51 }
52 
connectPortGate(LV2_Handle instance,uint32_t port,void * data)53 static void connectPortGate(LV2_Handle instance, uint32_t port, void *data) {
54 	Gate *plugin = (Gate *) instance;
55 
56 	switch (port) {
57 	case p_switch:
58 		plugin->switch_button = (float*) data;
59 		break;
60 	case p_threshold:
61 		plugin->threshold = (float*) data;
62 		break;
63 	case p_attack:
64 		plugin->attack = (float*) data;
65 		break;
66 	case p_hold:
67 		plugin->hold = (float*) data;
68 		break;
69 	case p_decay:
70 		plugin->decay = (float*) data;
71 		break;
72 	case p_gaterange:
73 		plugin->range = (float*) data;
74 		break;
75 	case p_input:
76 		plugin->input = (const float*) data;
77 		break;
78 	case p_output:
79 		plugin->output = (float*) data;
80 		break;
81 	}
82 }
83 
runGate(LV2_Handle instance,uint32_t sample_count)84 static void runGate(LV2_Handle instance, uint32_t sample_count) {
85 
86 	Gate *plugin_data = (Gate *) instance;
87 
88 	float * const output = plugin_data->output;
89 	const float * const input = plugin_data->input;
90 
91 	// Checking bypass state
92 	float switch_button = *(plugin_data->switch_button);
93 	switch_button = switch_button < 0 ? 0 : switch_button;
94 	switch_button = switch_button > 1 ? 1 : switch_button;
95 
96 	bool active = switch_button > 0;
97 	if (active) {
98 
99 		// Getting port values
100 		const float threshold = *(plugin_data->threshold);
101 		const float attack = *(plugin_data->attack);
102 		const float hold = *(plugin_data->hold);
103 		const float decay = *(plugin_data->decay);
104 		const float range = *(plugin_data->range);
105 
106 		const float sample_rate = plugin_data->sample_rate;
107 
108 		const float threshold_value = pow(10, threshold * 0.05);
109 		const float attack_coef = 1000 / (attack * sample_rate);
110 		const int hold_samples = round(hold * sample_rate * 0.001);
111 		const float decay_coef = 1000 / (decay * sample_rate);
112 		const float range_coef = range > -90 ? pow(10, range * 0.05) : 0;
113 
114 		int state = plugin_data->state;
115 		float gate = plugin_data->gate;
116 		int holding = plugin_data->holding;
117 
118 		for (uint32_t i = 0; i < sample_count; ++i) {
119 
120 			// Counting input dB
121 			float sample = input[i];
122 			float abs_sample = fabs(sample);
123 
124 			switch (state) {
125 			case CLOSED:
126 			case DECAY:
127 				if (abs_sample >= threshold_value) {
128 					state = ATTACK;
129 				}
130 				break;
131 			case ATTACK:
132 				break;
133 			case OPENED:
134 				if (abs_sample >= threshold_value) {
135 					holding = hold_samples;
136 				} else if (holding <= 0) {
137 					state = DECAY;
138 				} else {
139 					holding--;
140 				}
141 				break;
142 			default:
143 				// shouldn't happen
144 				state = CLOSED;
145 			}
146 
147 			// handle attack/decay in a second pass to avoid unnecessary one-sample delay
148 			switch (state) {
149 			case CLOSED:
150 				output[i] = sample * range_coef;
151 				break;
152 			case DECAY:
153 				gate -= decay_coef;
154 				if (gate <= 0) {
155 					gate = 0;
156 					state = CLOSED;
157 				}
158 				output[i] = sample * (range_coef * (1 - gate) + gate);
159 				break;
160 			case ATTACK:
161 				gate += attack_coef;
162 				if (gate >= 1) {
163 					gate = 1;
164 					state = OPENED;
165 					holding = hold_samples;
166 				}
167 				output[i] = sample * (range_coef * (1 - gate) + gate);
168 				break;
169 			case OPENED:
170 				output[i] = sample;
171 				break;
172 			}
173 		}
174 
175 		plugin_data->gate = gate;
176 		plugin_data->state = state;
177 		plugin_data->holding = holding;
178 	} else {
179 		// Bypassing
180 		if (output != input) {
181 			for (uint32_t i = 0; i < sample_count; ++i) {
182 				output[i] = input[i];
183 			}
184 		}
185 	}
186 }
187 
cleanupGate(LV2_Handle instance)188 static void cleanupGate(LV2_Handle instance) {
189 	Gate *plugin_data = (Gate *) instance;
190 	delete plugin_data;
191 }
192 
init()193 static void init() {
194 
195 	gateDescriptor = (LV2_Descriptor *) malloc(sizeof(LV2_Descriptor));
196 	gateDescriptor->URI = p_uri;
197 	gateDescriptor->instantiate = instantiateGate;
198 	gateDescriptor->connect_port = connectPortGate;
199 	gateDescriptor->activate = NULL;
200 	gateDescriptor->run = runGate;
201 	gateDescriptor->deactivate = NULL;
202 	gateDescriptor->cleanup = cleanupGate;
203 	gateDescriptor->extension_data = NULL;
204 }
205 
206 LV2_SYMBOL_EXPORT
lv2_descriptor(uint32_t index)207 const LV2_Descriptor *lv2_descriptor(uint32_t index) {
208 
209 	if (!gateDescriptor) {
210 		init();
211 	}
212 
213 	switch (index) {
214 	case 0:
215 		return gateDescriptor;
216 	default:
217 		return NULL;
218 	}
219 }
220