/* * CINELERRA * Copyright (C) 2008-2019 Adam Williams * * 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); void reset(); ArrayList levels; int solo; int bypass; // units of seconds // double readahead_len; double attack_len; double release_len; double mkup_gain; // 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 reset_base(); void reset_bands(); 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 gui_gains; // input levels to draw on the GUI ArrayList gui_levels; // which second in process() the gui_values came from ArrayList 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; }; #endif