4 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
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.
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.
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
31 #include "bctimer.inc"
35 #include "pluginaclient.h"
50 #define MAX_CUTOFF 1000
51 #define MIN_WINDOW 1024
52 #define MAX_WINDOW 262144
56 #define MAX_HISTORY 32
59 #define MAX_FREQ 30000
65 class EchoCancelLevel : public BC_FPot
68 EchoCancelLevel(EchoCancel *plugin, int x, int y);
73 class EchoCancelMode : public BC_PopupMenu
76 EchoCancelMode(EchoCancel *plugin, int x, int y);
78 static const char *to_text(int mode);
79 static int to_mode(const char *text);
80 void create_objects();
84 class EchoCancelHistory : public BC_IPot
87 EchoCancelHistory(EchoCancel *plugin, int x, int y);
92 class EchoCancelWindowSize : public BC_PopupMenu
95 EchoCancelWindowSize(EchoCancel *plugin, int x, int y, const char *text);
97 static const char *to_text(int size);
98 static int to_size(const char *text);
102 class EchoCancelWindowSizeTumbler : public BC_Tumbler
105 EchoCancelWindowSizeTumbler(EchoCancel *plugin, int x, int y);
106 int handle_up_event();
107 int handle_down_event();
111 class EchoCancelNormalize : public BC_CheckBox
114 EchoCancelNormalize(EchoCancel *plugin, int x, int y);
119 class EchoCancelXZoom : public BC_IPot
122 EchoCancelXZoom(EchoCancel *plugin, int x, int y);
127 class EchoCancelPeaks : public BC_IPot
130 EchoCancelPeaks(EchoCancel *plugin, int x, int y);
135 class EchoCancelDamp : public BC_IPot
138 EchoCancelDamp(EchoCancel *plugin, int x, int y);
143 class EchoCancelCutoff : public BC_IPot
146 EchoCancelCutoff(EchoCancel *plugin, int x, int y);
151 class EchoCancelCanvas : public BC_SubWindow
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);
162 int current_operation;
163 bool is_dragging() { return current_operation == DRAG; }
168 class EchoCancelPrefix {
171 EchoCancelPrefix(const char *p) : prefix(p) {}
172 ~EchoCancelPrefix() {}
175 class EchoCancelTitle : public EchoCancelPrefix, public BC_Title {
176 char string[BCSTRLEN];
177 char *preset(int value) {
178 sprintf(string, "%s%d", prefix, value);
181 char *preset(double value) {
182 sprintf(string, "%s%.3f", prefix, value);
186 void update(int value) { BC_Title::update(preset(value)); }
187 void update(double value) { BC_Title::update(preset(value)); }
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() {}
198 class EchoCancelWindow : public PluginClientWindow
201 EchoCancelWindow(EchoCancel *plugin);
204 void create_objects();
206 int resize_event(int w, int h);
207 void calculate_frequency(int x, int y, int do_overlay);
209 EchoCancelCanvas *canvas;
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;
221 EchoCancelTitle *gain_title;
222 EchoCancelTitle *offset_title;
223 BC_Title *freq_title;
224 BC_Title *amplitude_title;
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;
235 EchoCancelNormalize *normalize;
237 int probe_x, probe_y;
244 class EchoCancelConfig
248 int equivalent(EchoCancelConfig &that);
249 void copy_from(EchoCancelConfig &that);
250 void interpolate(EchoCancelConfig &prev,
251 EchoCancelConfig &next,
254 int64_t current_frame);
268 //unattributed data class
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
277 int size() { return sizeof(DataHeader)+ window_size/2 * total_windows; }
282 int allocated, data_len;
283 DataHeader *data_header;
284 float *sample_data; // offset sample data
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]);
292 DataHeader *get_header() { return data_header; }
294 DataBuffer(int len) : allocated(0),data_header(0) {
295 //printf("DataBuffer new %p\n",this);
298 //printf("DataBuffer delete %p\n",this);
299 delete [] (char*) data_header; }
303 int allocated, data_len;
307 double *get_buffer(int ofs=0) {
308 return samples->get_data() + (ofs>=0 ? ofs : buffer_size()+ofs);
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);
317 AudioBuffer(int len) : allocated(0),samples(0) { set_buffer(0,len); }
318 ~AudioBuffer() { delete samples; }
322 class EchoCancelFrame {
328 EchoCancelFrame(int n);
330 float scale() { return data[0]; }
331 float *samples() { return &data[1]; }
332 int size() { return len; }
333 void rescale(float s) {
335 for( int i=1; i<=len; ++i ) data[i] *= s;
338 for( int i=1; i<=len; ++i ) data[i] = DB::todb(data[i]);
342 class EchoCancel : public PluginAClient
345 EchoCancel(PluginServer *server);
348 PLUGIN_CLASS_MEMBERS2(EchoCancelConfig)
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);
355 void render_gui(void *data, int size);
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);
367 // Data buffer for frequency & magnitude
369 // time weighted data
373 double *envelope, *env_data;
374 double *env_real, *env_imag;
376 double *cor, *aud_real, *aud_imag;
377 // Accumulate data for windowing
378 AudioBuffer *audio_buffer;
379 // Header from last data buffer
381 // Last window size rendered
382 int window_size, half_window;
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
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);