port 7.2 mods: align_edits foreground plugin refresh_frame tweak, rework soundlevel...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / compressortools.h
1 /*
2  * CINELERRA
3  * Copyright (C) 2008-2019 Adam Williams <broadcast at earthling dot net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program 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
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  * 
19  */
20
21
22 // Base classes for compressors
23
24 #ifndef COMPRESSORTOOLS_H
25 #define COMPRESSORTOOLS_H
26
27
28 #include "guicast.h"
29 #include "pluginaclient.h"
30 #include "samples.inc"
31
32
33 #define MIN_ATTACK -10
34 #define MAX_ATTACK 10
35 #define MIN_DECAY 0
36 #define MAX_DECAY 255
37 #define MIN_TRIGGER 0
38 #define MAX_TRIGGER 255
39 // range of the meter
40 #define MIN_GAIN_CHANGE -20
41 #define MAX_GAIN_CHANGE 20
42
43
44 class CompressorConfigBase;
45 class CompressorPopup;
46
47
48 // get sample from trigger buffer
49 #define GET_TRIGGER(buffer, offset) \
50 double sample = 0; \
51 switch(config->input) \
52 { \
53         case CompressorConfigBase::MAX: \
54         { \
55                 double max = 0; \
56                 for(int channel = 0; channel < channels; channel++) \
57                 { \
58                         sample = fabs((buffer)[offset]); \
59                         if(sample > max) max = sample; \
60                 } \
61                 sample = max; \
62                 break; \
63         } \
64  \
65         case CompressorConfigBase::TRIGGER: \
66                 sample = fabs(trigger_buffer[offset]); \
67                 break; \
68  \
69         case CompressorConfigBase::SUM: \
70         { \
71                 double max = 0; \
72                 for(int channel = 0; channel < channels; channel++) \
73                 { \
74                         sample = fabs((buffer)[offset]); \
75                         max += sample; \
76                 } \
77                 sample = max; \
78                 break; \
79         } \
80 }
81
82
83
84
85
86 typedef struct
87 {
88 // DB from min_db - 0
89         double x, y;
90 } compressor_point_t;
91
92 class BandConfig
93 {
94 public:
95         BandConfig();
96         virtual ~BandConfig();
97
98         void copy_from(BandConfig *src);
99         int equiv(BandConfig *src);
100         void boundaries(CompressorConfigBase *base);
101         void save_data(FileXML *xml, int number, int do_multiband);
102         void read_data(FileXML *xml, int do_multiband);
103         void reset();
104
105         ArrayList<compressor_point_t> levels;
106         int solo;
107         int bypass;
108 // units of seconds
109 //      double readahead_len;
110         double attack_len;
111         double release_len;
112         double mkup_gain;
113
114 // upper frequency in Hz
115         int freq;
116 };
117
118 class CompressorConfigBase
119 {
120 public:
121         CompressorConfigBase(int total_bands);
122         virtual ~CompressorConfigBase();
123
124         virtual void copy_from(CompressorConfigBase &that);
125         virtual int equivalent(CompressorConfigBase &that);
126         void boundaries();
127         
128         void reset_base();
129         void reset_bands();
130         void remove_point(int band, int number);
131         int set_point(int band, double x, double y);
132         double calculate_db(int band, double x);
133         double get_x(int band, int number);
134         double get_y(int band, int number);
135         double calculate_gain(int band, double input);
136
137 // Calculate linear output from linear input
138         double calculate_output(int band, double x);
139
140 // min DB of the graph
141         double min_db;
142 // max DB of the graph
143         double max_db;
144
145         BandConfig *bands;
146         int total_bands;
147         int current_band;
148         int trigger;
149         int input;
150         enum
151         {
152                 TRIGGER,
153                 MAX,
154                 SUM
155         };
156         
157         double min_value;
158 //      double min_x, min_y;
159 //      double max_x, max_y;
160         int smoothing_only;
161 };
162
163
164 class CompressorCanvasBase : public BC_SubWindow
165 {
166 public:
167         CompressorCanvasBase(CompressorConfigBase *config, PluginClient *plugin,
168                 PluginClientWindow *window, int x, int y, int w, int h);
169         virtual ~CompressorCanvasBase();
170         int is_dragging();
171         int button_press_event();
172         int button_release_event();
173         int cursor_motion_event();
174         void create_objects();
175         void draw_scales();
176         void update();
177         int x_to_y(int band, int x);
178         int db_to_x(double db);
179         int db_to_y(double db);
180         double x_to_db(int x);
181         double y_to_db(int y);
182
183         virtual void update_window();
184
185         enum { NONE, DRAG };
186
187 // clickable area of canvas
188         int graph_x, graph_y;
189         int graph_w, graph_h;
190         int current_point;
191         int current_operation;
192         int divisions;
193         int subdivisions;
194         CompressorConfigBase *config;
195         CompressorPopup *menu;
196         PluginClient *plugin;
197         PluginClientWindow *window;
198 };
199
200
201 #define FREQ_COMPRESSORFRAME 0
202 #define GAIN_COMPRESSORFRAME 1
203 // used in eqcanvas, compressortools,
204 //  plugins: compressor, compressormulti
205 class CompressorClientFrame : public PluginClientFrame
206 {
207 public:
208         CompressorClientFrame();
209         ~CompressorClientFrame();
210         int type, band;
211 };
212
213 class CompressorFreqFrame : public CompressorClientFrame
214 {
215 public:
216         CompressorFreqFrame();
217         ~CompressorFreqFrame();
218
219         double freq_max, time_max;
220         double *data;
221         int data_size;
222         int nyquist;
223 };
224
225 class CompressorGainFrame : public CompressorClientFrame
226 {
227 public:
228         CompressorGainFrame();
229         ~CompressorGainFrame();
230
231         double gain, level;
232 };
233
234 class CompressorEngine
235 {
236 public:
237         CompressorEngine(CompressorConfigBase *config,
238                 int band);
239         ~CompressorEngine();
240         
241         void reset();
242         void calculate_ranges(int *attack_samples,
243                 int *release_samples,
244                 int *preview_samples,
245                 int sample_rate);
246         void process(Samples **output_buffer,
247                 Samples **input_buffer,
248                 int size,
249                 int sample_rate,
250                 int channels,
251                 int64_t start_position);
252
253         CompressorConfigBase *config;
254         int band;
255 // the current line segment defining the smooth signal level
256 // starting input value of line segment
257         double slope_value1;
258 // ending input value of line segment
259         double slope_value2;
260 // samples comprising the line segment
261         int slope_samples;
262 // samples from the start of the line to the peak that determined the slope
263         int peak_samples;
264 // current sample from 0 to slope_samples
265         int slope_current_sample;
266 // current value in the line segment
267         double current_value;
268 // gain change values to draw on the GUI
269         ArrayList<double> gui_gains;
270 // input levels to draw on the GUI
271         ArrayList<double> gui_levels;
272 // which second in process() the gui_values came from
273         ArrayList<double> gui_offsets;
274 // samples between gui_values.  Set by the user.
275         int gui_frame_samples;
276 // temporaries
277         int gui_frame_counter;
278         double gui_max_gain;
279         double gui_max_level;
280 };
281
282
283 class CompressorCopy : public BC_MenuItem
284 {
285 public:
286         CompressorCopy(CompressorPopup *popup);
287         ~CompressorCopy();
288         int handle_event();
289         CompressorPopup *popup;
290 };
291
292 class CompressorPaste : public BC_MenuItem
293 {
294 public:
295         CompressorPaste(CompressorPopup *popup);
296         ~CompressorPaste();
297         int handle_event();
298         CompressorPopup *popup;
299 };
300
301 class CompressorClearGraph : public BC_MenuItem
302 {
303 public:
304         CompressorClearGraph(CompressorPopup *popup);
305         ~CompressorClearGraph();
306         int handle_event();
307         CompressorPopup *popup;
308 };
309
310 class CompressorPopup : public BC_PopupMenu
311 {
312 public:
313         CompressorPopup(CompressorCanvasBase *canvas);
314         ~CompressorPopup();
315         
316         void create_objects();
317         
318         
319         CompressorCanvasBase *canvas;
320 };
321
322 #endif
323
324
325
326