--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 2008-2019 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+// Base classes for compressors
+
+#ifndef COMPRESSORTOOLS_H
+#define COMPRESSORTOOLS_H
+
+
+#include "guicast.h"
+#include "pluginaclient.h"
+#include "samples.inc"
+
+
+#define MIN_ATTACK -10
+#define MAX_ATTACK 10
+#define MIN_DECAY 0
+#define MAX_DECAY 255
+#define MIN_TRIGGER 0
+#define MAX_TRIGGER 255
+// range of the meter
+#define MIN_GAIN_CHANGE -20
+#define MAX_GAIN_CHANGE 20
+
+
+class CompressorConfigBase;
+class CompressorPopup;
+
+
+// get sample from trigger buffer
+#define GET_TRIGGER(buffer, offset) \
+double sample = 0; \
+switch(config->input) \
+{ \
+ case CompressorConfigBase::MAX: \
+ { \
+ double max = 0; \
+ for(int channel = 0; channel < channels; channel++) \
+ { \
+ sample = fabs((buffer)[offset]); \
+ if(sample > max) max = sample; \
+ } \
+ sample = max; \
+ break; \
+ } \
+ \
+ case CompressorConfigBase::TRIGGER: \
+ sample = fabs(trigger_buffer[offset]); \
+ break; \
+ \
+ case CompressorConfigBase::SUM: \
+ { \
+ double max = 0; \
+ for(int channel = 0; channel < channels; channel++) \
+ { \
+ sample = fabs((buffer)[offset]); \
+ max += sample; \
+ } \
+ sample = max; \
+ break; \
+ } \
+}
+
+
+
+
+
+typedef struct
+{
+// DB from min_db - 0
+ double x, y;
+} compressor_point_t;
+
+class BandConfig
+{
+public:
+ BandConfig();
+ virtual ~BandConfig();
+
+ void copy_from(BandConfig *src);
+ int equiv(BandConfig *src);
+ void boundaries(CompressorConfigBase *base);
+ void save_data(FileXML *xml, int number, int do_multiband);
+ void read_data(FileXML *xml, int do_multiband);
+
+ ArrayList<compressor_point_t> levels;
+ int solo;
+ int bypass;
+// units of seconds
+// double readahead_len;
+ double attack_len;
+ double release_len;
+
+// upper frequency in Hz
+ int freq;
+};
+
+class CompressorConfigBase
+{
+public:
+ CompressorConfigBase(int total_bands);
+ virtual ~CompressorConfigBase();
+
+ virtual void copy_from(CompressorConfigBase &that);
+ virtual int equivalent(CompressorConfigBase &that);
+ void boundaries();
+
+ void remove_point(int band, int number);
+ int set_point(int band, double x, double y);
+ double calculate_db(int band, double x);
+ double get_x(int band, int number);
+ double get_y(int band, int number);
+ double calculate_gain(int band, double input);
+
+// Calculate linear output from linear input
+ double calculate_output(int band, double x);
+
+// min DB of the graph
+ double min_db;
+// max DB of the graph
+ double max_db;
+
+ BandConfig *bands;
+ int total_bands;
+ int current_band;
+ int trigger;
+ int input;
+ enum
+ {
+ TRIGGER,
+ MAX,
+ SUM
+ };
+
+ double min_value;
+// double min_x, min_y;
+// double max_x, max_y;
+ int smoothing_only;
+};
+
+
+class CompressorCanvasBase : public BC_SubWindow
+{
+public:
+ CompressorCanvasBase(CompressorConfigBase *config, PluginClient *plugin,
+ PluginClientWindow *window, int x, int y, int w, int h);
+ virtual ~CompressorCanvasBase();
+ int is_dragging();
+ int button_press_event();
+ int button_release_event();
+ int cursor_motion_event();
+ void create_objects();
+ void draw_scales();
+ void update();
+ int x_to_y(int band, int x);
+ int db_to_x(double db);
+ int db_to_y(double db);
+ double x_to_db(int x);
+ double y_to_db(int y);
+
+ virtual void update_window();
+
+ enum { NONE, DRAG };
+
+// clickable area of canvas
+ int graph_x, graph_y;
+ int graph_w, graph_h;
+ int current_point;
+ int current_operation;
+ int divisions;
+ int subdivisions;
+ CompressorConfigBase *config;
+ CompressorPopup *menu;
+ PluginClient *plugin;
+ PluginClientWindow *window;
+};
+
+
+#define FREQ_COMPRESSORFRAME 0
+#define GAIN_COMPRESSORFRAME 1
+// used in eqcanvas, compressortools,
+// plugins: compressor, compressormulti
+class CompressorClientFrame : public PluginClientFrame
+{
+public:
+ CompressorClientFrame();
+ ~CompressorClientFrame();
+ int type, band;
+};
+
+class CompressorFreqFrame : public CompressorClientFrame
+{
+public:
+ CompressorFreqFrame();
+ ~CompressorFreqFrame();
+
+ double freq_max, time_max;
+ double *data;
+ int data_size;
+ int nyquist;
+};
+
+class CompressorGainFrame : public CompressorClientFrame
+{
+public:
+ CompressorGainFrame();
+ ~CompressorGainFrame();
+
+ double gain, level;
+};
+
+class CompressorEngine
+{
+public:
+ CompressorEngine(CompressorConfigBase *config,
+ int band);
+ ~CompressorEngine();
+
+ void reset();
+ void calculate_ranges(int *attack_samples,
+ int *release_samples,
+ int *preview_samples,
+ int sample_rate);
+ void process(Samples **output_buffer,
+ Samples **input_buffer,
+ int size,
+ int sample_rate,
+ int channels,
+ int64_t start_position);
+
+ CompressorConfigBase *config;
+ int band;
+// the current line segment defining the smooth signal level
+// starting input value of line segment
+ double slope_value1;
+// ending input value of line segment
+ double slope_value2;
+// samples comprising the line segment
+ int slope_samples;
+// samples from the start of the line to the peak that determined the slope
+ int peak_samples;
+// current sample from 0 to slope_samples
+ int slope_current_sample;
+// current value in the line segment
+ double current_value;
+// gain change values to draw on the GUI
+ ArrayList<double> gui_gains;
+// input levels to draw on the GUI
+ ArrayList<double> gui_levels;
+// which second in process() the gui_values came from
+ ArrayList<double> gui_offsets;
+// samples between gui_values. Set by the user.
+ int gui_frame_samples;
+// temporaries
+ int gui_frame_counter;
+ double gui_max_gain;
+ double gui_max_level;
+};
+
+
+class CompressorCopy : public BC_MenuItem
+{
+public:
+ CompressorCopy(CompressorPopup *popup);
+ ~CompressorCopy();
+ int handle_event();
+ CompressorPopup *popup;
+};
+
+class CompressorPaste : public BC_MenuItem
+{
+public:
+ CompressorPaste(CompressorPopup *popup);
+ ~CompressorPaste();
+ int handle_event();
+ CompressorPopup *popup;
+};
+
+class CompressorClearGraph : public BC_MenuItem
+{
+public:
+ CompressorClearGraph(CompressorPopup *popup);
+ ~CompressorClearGraph();
+ int handle_event();
+ CompressorPopup *popup;
+};
+
+class CompressorPopup : public BC_PopupMenu
+{
+public:
+ CompressorPopup(CompressorCanvasBase *canvas);
+ ~CompressorPopup();
+
+ void create_objects();
+
+
+ CompressorCanvasBase *canvas;
+};
+
+#define GRAPH_BG_COLOR 0x559977
+#define GRAPH_BORDER1_COLOR 0xeeaa44
+#define GRAPH_BORDER2_COLOR 0xeeaaff
+#define GRAPH_GRID_COLOR 0xeeffcc
+#define GRAPH_ACTIVE_COLOR 0x99cc77
+#define GRAPH_INACTIVE_COLOR 0x666688
+
+#endif
+
+
+
+