remove whitespace at eol
[goodguy/history.git] / cinelerra-5.1 / plugins / echocancel / echocancel.h
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #ifndef ECHOCANCEL_H
23 #define ECHOCANCEL_H
24
25
26
27
28
29
30 #include "bchash.inc"
31 #include "bctimer.inc"
32 #include "fourier.h"
33 #include "guicast.h"
34 #include "mutex.h"
35 #include "pluginaclient.h"
36 #include "vframe.inc"
37
38
39
40
41 class EchoCancel;
42
43 #define MIN_XZOOM 1
44 #define MAX_XZOOM 6
45 #define MIN_PEAKS 1
46 #define MAX_PEAKS 8
47 #define MIN_DAMP 1
48 #define MAX_DAMP 8
49 #define MIN_CUTOFF 10
50 #define MAX_CUTOFF 1000
51 #define MIN_WINDOW 1024
52 #define MAX_WINDOW 262144
53 #define DIVISIONS 10
54 #define DIVISION_W 60
55 #define MARGIN 10
56 #define MAX_HISTORY 32
57 #define MIN_HISTORY 1
58 #define MIN_FREQ 1
59 #define MAX_FREQ 30000
60
61 #define CANCEL_OFF 0
62 #define CANCEL_ON  1
63 #define CANCEL_MAN 2
64
65 class EchoCancelLevel : public BC_FPot
66 {
67 public:
68         EchoCancelLevel(EchoCancel *plugin, int x, int y);
69         int handle_event();
70         EchoCancel *plugin;
71 };
72
73 class EchoCancelMode : public BC_PopupMenu
74 {
75 public:
76         EchoCancelMode(EchoCancel *plugin, int x, int y);
77         int handle_event();
78         static const char *to_text(int mode);
79         static int to_mode(const char *text);
80         void create_objects();
81         EchoCancel *plugin;
82 };
83
84 class EchoCancelHistory : public BC_IPot
85 {
86 public:
87         EchoCancelHistory(EchoCancel *plugin, int x, int y);
88         int handle_event();
89         EchoCancel *plugin;
90 };
91
92 class EchoCancelWindowSize : public BC_PopupMenu
93 {
94 public:
95         EchoCancelWindowSize(EchoCancel *plugin, int x, int y, const char *text);
96         int handle_event();
97         static const char *to_text(int size);
98         static int to_size(const char *text);
99         EchoCancel *plugin;
100 };
101
102 class EchoCancelWindowSizeTumbler : public BC_Tumbler
103 {
104 public:
105         EchoCancelWindowSizeTumbler(EchoCancel *plugin, int x, int y);
106         int handle_up_event();
107         int handle_down_event();
108         EchoCancel *plugin;
109 };
110
111 class EchoCancelNormalize : public BC_CheckBox
112 {
113 public:
114         EchoCancelNormalize(EchoCancel *plugin, int x, int y);
115         int handle_event();
116         EchoCancel *plugin;
117 };
118
119 class EchoCancelXZoom : public BC_IPot
120 {
121 public:
122         EchoCancelXZoom(EchoCancel *plugin, int x, int y);
123         int handle_event();
124         EchoCancel *plugin;
125 };
126
127 class EchoCancelPeaks : public BC_IPot
128 {
129 public:
130         EchoCancelPeaks(EchoCancel *plugin, int x, int y);
131         int handle_event();
132         EchoCancel *plugin;
133 };
134
135 class EchoCancelDamp : public BC_IPot
136 {
137 public:
138         EchoCancelDamp(EchoCancel *plugin, int x, int y);
139         int handle_event();
140         EchoCancel *plugin;
141 };
142
143 class EchoCancelCutoff : public BC_IPot
144 {
145 public:
146         EchoCancelCutoff(EchoCancel *plugin, int x, int y);
147         int handle_event();
148         EchoCancel *plugin;
149 };
150
151 class EchoCancelCanvas : public BC_SubWindow
152 {
153 public:
154         EchoCancelCanvas(EchoCancel *plugin, int x, int y, int w, int h);
155         int button_press_event();
156         int button_release_event();
157         int cursor_motion_event();
158         void calculate_point(int do_overlay);
159         void draw_frame(float *data, int len, int hh);
160         void draw_overlay();
161         enum { NONE, DRAG };
162         int current_operation;
163         bool is_dragging() { return current_operation == DRAG; }
164         EchoCancel *plugin;
165 };
166
167
168 class EchoCancelPrefix {
169 public:
170         const char *prefix;
171         EchoCancelPrefix(const char *p) : prefix(p) {}
172         ~EchoCancelPrefix() {}
173 };
174
175 class EchoCancelTitle : public EchoCancelPrefix, public BC_Title {
176         char string[BCSTRLEN];
177         char *preset(int value) {
178                 sprintf(string, "%s%d", prefix, value);
179                 return string;
180         }
181         char *preset(double value) {
182                 sprintf(string, "%s%.3f", prefix, value);
183                 return string;
184         }
185 public:
186         void update(int value) { BC_Title::update(preset(value)); }
187         void update(double value) { BC_Title::update(preset(value)); }
188
189         EchoCancelTitle(int x, int y, const char *pfx, int value)
190                 : EchoCancelPrefix(pfx), BC_Title(x, y, preset(value)) {}
191         EchoCancelTitle(int x, int y, const char *pfx, double value)
192                 :  EchoCancelPrefix(pfx),BC_Title(x, y, preset(value)) {}
193         ~EchoCancelTitle() {}
194 };
195
196
197
198 class EchoCancelWindow : public PluginClientWindow
199 {
200 public:
201         EchoCancelWindow(EchoCancel *plugin);
202         ~EchoCancelWindow();
203
204         void create_objects();
205         void update_gui();
206         int resize_event(int w, int h);
207         void calculate_frequency(int x, int y, int do_overlay);
208
209         EchoCancelCanvas *canvas;
210
211         BC_Title *level_title;
212         EchoCancelLevel *level;
213         BC_Title *window_size_title;
214         EchoCancelWindowSize *window_size;
215         EchoCancelWindowSizeTumbler *window_size_tumbler;
216         BC_Title *mode_title;
217         EchoCancelMode *mode;
218         BC_Title *history_title;
219         EchoCancelHistory *history;
220
221         EchoCancelTitle *gain_title;
222         EchoCancelTitle *offset_title;
223         BC_Title *freq_title;
224         BC_Title *amplitude_title;
225
226         BC_Title *xzoom_title;
227         EchoCancelXZoom *xzoom;
228         BC_Title *peaks_title;
229         EchoCancelPeaks *peaks;
230         BC_Title *damp_title;
231         EchoCancelDamp *damp;
232         BC_Title *cutoff_title;
233         EchoCancelCutoff *cutoff;
234
235         EchoCancelNormalize *normalize;
236         EchoCancel *plugin;
237         int probe_x, probe_y;
238 };
239
240
241
242
243
244 class EchoCancelConfig
245 {
246 public:
247         EchoCancelConfig();
248         int equivalent(EchoCancelConfig &that);
249         void copy_from(EchoCancelConfig &that);
250         void interpolate(EchoCancelConfig &prev,
251                 EchoCancelConfig &next,
252                 int64_t prev_frame,
253                 int64_t next_frame,
254                 int64_t current_frame);
255         double level;
256         int normalize;
257         int xzoom;
258         int peaks;
259         int damp;
260         int cutoff;
261         double gain;
262         int offset;
263         int window_size;
264         int mode;
265         int history_size;
266 };
267
268 //unattributed data class
269 class DataHeader {
270 public:
271         int window_size;
272         int total_windows;     // Total windows in this buffer
273         int interrupted;       // playback stopped, config changed
274         int sample_rate;       // Samplerate
275         float level;           // Linearized user level
276         float samples[0];
277         int size() { return sizeof(DataHeader)+ window_size/2 * total_windows; }
278 };
279
280 // data buffer
281 class DataBuffer {
282         int allocated, data_len;
283         DataHeader *data_header;
284         float *sample_data;  // offset sample data
285 public:
286         void set_buffer(int ofs, int len);
287         float *get_buffer() { return sample_data; }
288         DataHeader *new_data_header(int data_size) {
289                 int size = sizeof(DataHeader) + data_size*sizeof(float);
290                 return (DataHeader*)(new char[size]);
291         }
292         DataHeader *get_header() { return data_header; }
293
294         DataBuffer(int len) : allocated(0),data_header(0) {
295                 //printf("DataBuffer new %p\n",this);
296                 set_buffer(0,len); }
297         ~DataBuffer() {
298                 //printf("DataBuffer delete %p\n",this);
299                 delete [] (char*) data_header; }
300 };
301
302 class AudioBuffer {
303         int allocated, data_len;
304         Samples *samples;
305         double *sample_data;
306 public:
307         double *get_buffer(int ofs=0) {
308                 return samples->get_data() + (ofs>=0 ? ofs : buffer_size()+ofs);
309         }
310         double *get_data(int ofs=0) { return sample_data + ofs; }
311         void set_buffer(int ofs, int len);
312         int buffer_size() { return get_data(data_len)-get_buffer(); }
313         int size() { return data_len; }
314         void append(double *bfr, int len);
315         void remove(int len);
316
317         AudioBuffer(int len) : allocated(0),samples(0) { set_buffer(0,len); }
318         ~AudioBuffer() { delete samples; }
319
320 };
321
322 class EchoCancelFrame {
323         float *data;
324         int len;
325 public:
326         int cut_offset;
327
328         EchoCancelFrame(int n);
329         ~EchoCancelFrame();
330         float scale() { return data[0]; }
331         float *samples() { return &data[1]; }
332         int size() { return len; }
333         void rescale(float s) {
334                 data[0] = s;
335                 for( int i=1; i<=len; ++i ) data[i] *= s;
336         }
337         void todb() {
338                 for( int i=1; i<=len; ++i ) data[i] = DB::todb(data[i]);
339         }
340 };
341
342 class EchoCancel : public PluginAClient
343 {
344 public:
345         EchoCancel(PluginServer *server);
346         ~EchoCancel();
347
348         PLUGIN_CLASS_MEMBERS2(EchoCancelConfig)
349         int is_realtime();
350         int process_buffer(int64_t size, Samples *buffer,
351                 int64_t start_position, int sample_rate);
352         void read_data(KeyFrame *keyframe);
353         void save_data(KeyFrame *keyframe);
354         void update_gui();
355         void render_gui(void *data, int size);
356         void render_stop();
357
358         void reset();
359         void cepstrum(double *audio);
360         void calculate_envelope(int sample_rate, int peaks, int bsz);
361         void create_envelope(int sample_rate);
362         int cancel_echo(double *bp, int size);
363         void delete_buffers();
364         void alloc_buffers(int fft_sz);
365
366         FFT *fft;
367 // Data buffer for frequency & magnitude
368         DataBuffer *data;
369 // time weighted data
370         float *time_frame;
371         int time_frames;
372 // envelope
373         double *envelope, *env_data;
374         double *env_real, *env_imag;
375 // correlation
376         double *cor, *aud_real, *aud_imag;
377 // Accumulate data for windowing
378         AudioBuffer *audio_buffer;
379 // Header from last data buffer
380         DataHeader header;
381 // Last window size rendered
382         int window_size, half_window;
383         int interrupted;
384 // Accumulates canvas pixels until the next update_gui
385         ArrayList<EchoCancelFrame*> frame_buffer;
386 // Probing data for horizontal mode
387         ArrayList<EchoCancelFrame*> frame_history;
388 // Time of last GUI update
389         Timer *timer;
390 // Window dimensions
391         int w, h;
392 // Help for the wicked
393         static void dfile_dump(const char *fn, double *dp, int n);
394         static void ffile_dump(const char *fn, float *dp, int n);
395 };
396
397
398 #endif