From 4a2194321149dec048b560d16ba507e7450d4368 Mon Sep 17 00:00:00 2001 From: Kjetil Matheussen Date: Fri, 8 Feb 2013 19:48:55 +0100 Subject: [PATCH] various, most importantly much faster graphics --- Makefile | 63 +- Qt/Qt_MyQCheckBox.h | 34 +- Qt/Qt_SliderPainter.cpp | 146 +-- Qt/Qt_SliderPainterPainter.h | 120 +++ Qt/Qt_compressor_widget.h | 44 +- Qt/Qt_compressor_widget_callbacks.h | 1175 ++++++------------------ Qt/compressor_vertical_sliders.cpp | 1128 +++++++++++++++++++++++ Qt/mQt_compressor_widget_callbacks.h | 27 +- Qt/qt4_compressor_widget.ui | 27 +- audio/SoundPlugin.h | 18 + audio/fast_log_exp.dsp | 89 ++ audio/system_compressor.cpp | 63 +- audio/system_compressor.dsp | 108 +-- audio/system_compressor_wrapper.cpp | 310 +++++++ audio/system_compressor_wrapper_proc.h | 45 + audio/typepunning.h | 2 +- common/nsmtracker.h | 7 + main.cpp | 242 ++--- myjack-dsp.h | 1 + 19 files changed, 2290 insertions(+), 1359 deletions(-) create mode 100644 Qt/Qt_SliderPainterPainter.h create mode 100644 Qt/compressor_vertical_sliders.cpp create mode 100644 audio/fast_log_exp.dsp create mode 100644 audio/system_compressor_wrapper.cpp create mode 100644 audio/system_compressor_wrapper_proc.h diff --git a/Makefile b/Makefile index 00d5383..2c2e208 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,8 @@ PREFIX ?= /usr/local bindir ?= $(PREFIX)/bin libdir ?= $(PREFIX)/lib +#FIX locally. Line below removed from dsp file. +#effect.bypass2(checkbox("[6] bypass"), compressor) # These two commands are used by me, since most of the source files are stored in the Radium tree. # You would normally just run "make" to compile the program. @@ -9,20 +11,29 @@ libdir ?= $(PREFIX)/lib # make copy_files && make all && ./radium_compressor # make copy_files && rm -f benchmark && make benchmark && ./benchmark && ./benchmark && ./benchmark +OPT = -O3 -ffast-math +OPT_DSP = -O3 -ffast-math #-funroll-loops +CPP = g++ -DDEBUG -Wall -msse -mfpmath=sse -DUSE_QT_REQTYPE -DUSE_QT4 -g -I. -IQt +# -fpredictive-commoning -ftree-vectorize +# -funroll-loops -fira-loop-pressure -fipa-cp-clone -ftree-loop-distribute-patterns -CPP = g++ -DDEBUG -O3 -Wall -msse -mfpmath=sse -DUSE_QT_REQTYPE -DUSE_QT4 -g -I. -ffast-math -IQt +#-finline-functions -#FAUST = /home/kjetil/faudiostream/compiler/faust -vec -FAUST = faust -vec +FAUST = /home/kjetil/faudiostream/compiler/faust -vec +#FAUST = faust -vec # only used for copy files RADIUM_PATH = /home/kjetil/radium-qt4 -all: audio/system_compressor.cpp +all: system_compressor_wrapper.o myladspa.o cd Qt && ./create_source_from_ui.sh `../find_moc_and_uic_paths.sh uic` `../find_moc_and_uic_paths.sh moc` compressor_widget - $(CPP) Qt/Qt_SliderPainter.cpp `pkg-config --cflags Qt3Support` -c - $(CPP) main.cpp Qt_SliderPainter.o -Iaudio/faudiostream/architecture/ `pkg-config --libs --cflags Qt3Support` -ljack -o radium_compressor + $(CPP) Qt/Qt_SliderPainter.cpp `pkg-config --cflags Qt3Support` -c $(OPT) + $(CPP) main.cpp Qt_SliderPainter.o system_compressor_wrapper.o myladspa.o -DCOMPILING_STANDALONE -Iaudio/faudiostream/architecture/ `pkg-config --libs --cflags Qt3Support` -ljack -o radium_compressor $(OPT) +# /usr/lib64/libprofiler.so.0 +# make copy_files && make all && CPUPROFILE=ls.prof ./radium_compressor +clean: + rm -f *.o install: install -d $(DESTDIR)$(bindir) @@ -32,9 +43,33 @@ install: uninstall: rm -f $(DESTDIR)$(bindir)/radium_compressor +# ladpa plugin +radium_compressor.so: audio/system_compressor.cpp myladspa.o system_compressor_wrapper_ladspa.o + $(CPP) Qt/Qt_SliderPainter.cpp `pkg-config --cflags Qt3Support` -c -fPIC $(OPT) + $(CPP) -DCOMPILING_LADSPA main.cpp -Iaudio/faudiostream/architecture/ `pkg-config --libs --cflags Qt3Support` -c -fPIC $(OPT) + $(CPP) `pkg-config --libs Qt3Support` myladspa.o system_compressor_wrapper_ladspa.o -shared -fPIC -o radium_compressor.so + +system_compressor_wrapper.o: audio/system_compressor_wrapper.cpp audio/system_compressor.cpp + $(CPP) -Ifaudiostream/architecture `pkg-config --cflags QtCore` -DCOMPILING_STANDALONE audio/system_compressor_wrapper.cpp -c -fPIC $(OPT_DSP) + +system_compressor_wrapper_ladspa.o: audio/system_compressor_wrapper.cpp audio/system_compressor.cpp + $(CPP) -Ifaudiostream/architecture `pkg-config --cflags QtCore` -DCOMPILING_LADSPA audio/system_compressor_wrapper.cpp -c -fPIC -o system_compressor_wrapper_ladspa.o $(OPT_DSP) + +myladspa.o: myladspa.cpp audio/system_compressor.cpp + $(CPP) -DCOMPILING_LADSPA -Ifaudiostream/architecture `pkg-config --cflags QtCore` myladspa.cpp -fPIC -c $(OPT_DSP) + +audio/system_compressor.cpp: audio/system_compressor.dsp standalone_compressor.dsp + cp standalone_compressor.dsp audio/ + $(FAUST) -cn Faust_system_compressor audio/standalone_compressor.dsp >audio/system_compressor.cpp + +#audio/system_compressor_ladspa.cpp: audio/system_compressor.dsp standalone_compressor.dsp +# cp standalone_compressor.dsp audio/ +# $(FAUST) -cn Faust_system_compressor -a myladspa.cpp audio/standalone_compressor.dsp >audio/system_compressor_ladspa.cpp + copy_files: cp $(RADIUM_PATH)/Qt/qt4_compressor_widget.ui Qt/ + cp $(RADIUM_PATH)/Qt/compressor_vertical_sliders.cpp Qt/ cp $(RADIUM_PATH)/Qt/Qt_compressor_widget_callbacks.h Qt/ cp $(RADIUM_PATH)/Qt/Qt_MyQCheckBox.h Qt/ cp $(RADIUM_PATH)/Qt/Qt_MyQButton.h Qt/ @@ -47,6 +82,9 @@ copy_files: cp $(RADIUM_PATH)/Qt/Qt_instruments_proc.h Qt/ cp $(RADIUM_PATH)/audio/system_compressor.dsp audio/ + cp $(RADIUM_PATH)/audio/fast_log_exp.dsp audio/ + cp $(RADIUM_PATH)/audio/system_compressor_wrapper_proc.h audio/ + cp $(RADIUM_PATH)/audio/system_compressor_wrapper.cpp audio/ cp $(RADIUM_PATH)/audio/typepunning.h audio/ cp $(RADIUM_PATH)/audio/undo_audio_effect_proc.h audio/ cp $(RADIUM_PATH)/audio/SoundPlugin.h audio/ @@ -75,9 +113,6 @@ copy_files: cp -a $(RADIUM_PATH)/audio/faudiostream audio/ -audio/system_compressor.cpp: audio/system_compressor.dsp - $(FAUST) audio/system_compressor.dsp >audio/system_compressor.cpp - # Note that 0.9.55 runs the benchmark program a bit faster than 0.9.46. # I guess it's because of more min/max functions in 0.9.55, but it could also # be because of some castings. @@ -94,3 +129,13 @@ benchmark: # Relative accuracy of faster pow2 / faster log: 0.0152579 / 0.0130367 # Relative accuracy of fast pow2 / fast log: 1.58868e-05 / 2.09348e-05 +#/home/kjetil/faudiostream/compiler/faust -a ladspa.cpp system_compressor.dsp >ladspa_compressor.cpp +#g++ ladspa_compressor.cpp -I /home/kjetil/faudiostream/architecture/ -shared -fPIC -o ladspa_compressor.so + +VSTPATH = /home/kjetil/Dropbox/radium_build/vstsdk2.4 +vst: + $(FAUST) audio/standalone_compressor.dsp >compressor_vst.cpp + $(CPP) Qt/Qt_SliderPainter.cpp `pkg-config --cflags Qt3Support` -c -fPIC + $(CPP) -DCOMPILING_VST main.cpp -Iaudio/faudiostream/architecture/ `pkg-config --libs --cflags Qt3Support` -c -fPIC + $(CPP) -I $(VSTPATH)/public.sdk/source/vst2.x/ -I $(VSTPATH)/pluginterfaces/vst2.x/ -I $(VSTPATH) `pkg-config --cflags QtGui` `pkg-config --libs QtGui` vstplugin.cpp -Iaudio $(VSTPATH)/public.sdk/source/vst2.x/audioeffectx.cpp $(VSTPATH)/public.sdk/source/vst2.x/audioeffect.cpp $(VSTPATH)/public.sdk/source/vst2.x/vstplugmain.cpp main.o Qt_SliderPainter.o -shared -o radium_compressor.so -fPIC + diff --git a/Qt/Qt_MyQCheckBox.h b/Qt/Qt_MyQCheckBox.h index 4b8c459..8e9676f 100644 --- a/Qt/Qt_MyQCheckBox.h +++ b/Qt/Qt_MyQCheckBox.h @@ -53,6 +53,11 @@ static QColor mix_colors(const QColor &c1, const QColor &c2, float how_much){ } } +static int get_text_width(QString text){ + const QFontMetrics fn = QFontMetrics(QFont()); + return fn.width(text); +} + inline static void CHECKBOX_paint(QPainter *painter, bool is_checked, bool is_enabled, int width, int height, QString text){ #ifdef COMPILING_RADIUM QColor *colors = static_cast(root->song->tracker_windows->os_visual.widget)->colors; @@ -101,10 +106,22 @@ inline static void CHECKBOX_paint(QPainter *painter, bool is_checked, bool is_en else black.setAlpha(120); painter->setPen(black); + if(text=="Loop") - painter->drawText(rect, Qt::AlignCenter, text + " " + QChar(8634)); - else + text = text + " " + QChar(8634); + + if(height>width){ + painter->save(); + painter->translate(0,0); + painter->rotate(90); + int text_width = get_text_width(text); + int pos = (height-text_width)/2; + painter->drawText(pos,-5, text); + painter->restore(); + }else{ painter->drawText(rect, Qt::AlignCenter, text); + } + } } @@ -114,6 +131,8 @@ struct MyQCheckBox : public QCheckBox{ int _effect_num; bool _undo_patchvoice; + QString vertical_text; + void init(){ _has_mouse=false; _patch = NULL; @@ -124,7 +143,6 @@ struct MyQCheckBox : public QCheckBox{ MyQCheckBox ( QWidget * parent = 0 ) : QCheckBox(parent) {init();} MyQCheckBox ( const QString & text, QWidget * parent = 0) : QCheckBox(text,parent) {init();} - void mousePressEvent ( QMouseEvent * event ) { if (event->button() == Qt::LeftButton){ @@ -137,7 +155,7 @@ struct MyQCheckBox : public QCheckBox{ #endif //handle_mouse_event(event); _has_mouse = true; - printf("Got it %p %d\n",_patch,_effect_num); + printf("Got it %p %d. Checked: %d\n",_patch,_effect_num,!isChecked()); setChecked(!isChecked()); }else QCheckBox::mousePressEvent(event); @@ -146,7 +164,13 @@ struct MyQCheckBox : public QCheckBox{ void paintEvent ( QPaintEvent * ev ){ QPainter p(this); - CHECKBOX_paint(&p, isChecked(), isEnabled(), width(), height(), text()); + + if(text().startsWith("V ")){ + vertical_text = text().right(text().size()-2); + setText(""); + } + + CHECKBOX_paint(&p, isChecked(), isEnabled(), width(), height(), vertical_text!="" ? vertical_text : text()); } }; diff --git a/Qt/Qt_SliderPainter.cpp b/Qt/Qt_SliderPainter.cpp index cdaaf85..48fc1f4 100644 --- a/Qt/Qt_SliderPainter.cpp +++ b/Qt/Qt_SliderPainter.cpp @@ -27,18 +27,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "Qt_SliderPainter_proc.h" +#include "Qt_SliderPainterPainter.h" -const int k_timer_interval = 50; - -#ifdef COMPILING_RADIUM -extern struct Root *root; -#else -extern QColor *g_colors; -#endif +const int k_timer_interval = 50; -static int scale(int x, int x1, int x2, int y1, int y2){ +static int scale_int(int x, int x1, int x2, int y1, int y2){ return (int)scale((float)x,(float)x1,(float)x2,(float)y1,(float)y2); } @@ -92,27 +87,6 @@ static float iec_scale(float db) { #endif -static QColor mix_colors(const QColor &c1, const QColor &c2, float how_much){ - - float a1 = how_much; - float a2 = 1.0f-a1; - - if(c1.red()==0 && c1.green()==0 && c1.blue()==0){ // some of the black lines doesn't look look very good. - int r = 74*a1 + c2.red()*a2; - int g = 74*a1 + c2.green()*a2; - int b = 74*a1 + c2.blue()*a2; - - return QColor(r,g,b); - }else{ - - int r = c1.red()*a1 + c2.red()*a2; - int g = c1.green()*a1 + c2.green()*a2; - int b = c1.blue()*a1 + c2.blue()*a2; - - return QColor(r,g,b); - } -} - #define MAX_CHANNELS 8 @@ -135,11 +109,11 @@ struct AutomationOrPeakData{ } static int DATA_get_y1(AutomationOrPeakData *data, int height){ - return scale(data->ch,0,data->num_ch,1,height-1); + return scale_int(data->ch,0,data->num_ch,1,height-1); } static int DATA_get_y2(AutomationOrPeakData *data, int height){ - return scale(data->ch+1,0,data->num_ch,1,height-1); + return scale_int(data->ch+1,0,data->num_ch,1,height-1); } struct SliderPainter{ @@ -200,7 +174,7 @@ struct SliderPainter{ } }; // struct Timer - std::vector _data; + std::vector_data; QSlider *_qslider; QGraphicsItem *_graphics_item; // Either widget or _graphics_item must be set. @@ -415,89 +389,11 @@ struct SliderPainter{ QColor *colors = g_colors; #endif - QColor col1; - QColor col1b; - QColor col2; - - int col1num = 11; - int col2num = 9; - //int col1num = qrand() % 15; - //int col2num = qrand() % 15; - - if(false && _qslider!=NULL){ - if(isEnabled()){ - QColor c1(70,70,33); - QColor c2(59,98,33); - col1 = mix_colors(c1,colors[col1num].light(90),0.5); - col1b = mix_colors(c2,col1,0.3); - ///col2 = mix_colors(editor->colors[col2num],editor->colors[col1num],0.8).light(95);//.light(90); - col2 = colors[15]; - }else{ - col1 = colors[col1num].light(105); - col1b = col1; - col2 = colors[col2num].light(102); - } - }else{ - if(isEnabled()){ - QColor c(98,59,33); - - int colnum = 8; - col1 = c.light(90); - col1b = colors[13].light(100); - //int colnum = 8; - //col1 = editor->colors[colnum].light(90); - //col1b = editor->colors[13].light(100); - - col2 = colors[colnum]; - }else{ - //col1 = editor->colors[col1num].light(105); - col1 = mix_colors(colors[col1num], Qt::gray, 0.8f); - col1b = mix_colors(colors[col1num].light(110), Qt::gray, 0.8f); - col2 = mix_colors(colors[col2num], Qt::gray, 0.8f); - //col2 = editor->colors[col2num].light(102); - } - - if(_alternative_color==true){ - col1 = QColor(200,200,200); - col2 = QColor(100,100,100); - } - - if(_qslider!=NULL){ - col1.setAlpha(80); - col1b.setAlpha(100); - }else{ - col1.setAlpha(120); - col1b.setAlpha(120); - } - col2.setAlpha(0); - } - - if(orientation() == Qt::Vertical){ - int pos=scale(value(),maximum(),minimum(),0,height()); - p->fillRect(0,0,width(),height(),col2); - p->fillRect(0,pos,width(),height()-pos,col1); - }else{ - int pos=scale(value(),minimum(),maximum(),0,width()); - { - QLinearGradient gradient(0,0,width(),height()*3/4); - if(_qslider!=NULL){ - //gradient.setColorAt(0,col1.light(90)); - //gradient.setColorAt(1,col1.light(110)); - gradient.setColorAt(0,col1.light(100)); - gradient.setColorAt(1,col1b); - }else{ - gradient.setColorAt(0,col1.light(150)); - gradient.setColorAt(1,col1b); - } - p->setPen(QPen(QColor(Qt::gray).light(50),1)); - p->setBrush(gradient); - //p->fillRect(0 ,0, pos ,height(),col1); - p->drawRect(0 ,0, pos, height()); - p->setBrush(QBrush()); - } - p->setPen(QPen(Qt::gray,1)); - p->fillRect(pos ,0, width()-pos ,height(),col2); - } + SLIDERPAINTERPAINTER_paint(p,0,0,width(),height(), + isEnabled(), + scale(value(),minimum(),maximum(),0.0f,1.0f), + _display_string, + _alternative_color); for(unsigned int i=0;i<_data.size();i++){ AutomationOrPeakData *data = _data.at(i); @@ -509,32 +405,12 @@ struct SliderPainter{ 2, height-1, colors[*data->color]); - //p->setPen(editor->colors[2].dark(10)); p->setPen(QPen(colors[11].light(120),1)); p->drawRect(data->requested_pos, y1, 3, height); data->last_drawn_pos = data->requested_pos; } - - if(1){ - p->setPen(QPen(colors[11].light(110),1)); - p->drawRect(0,0,width(),height()); - } - - QRect rect(5,2,width()-5,height()-2); - - if(_display_string!=""){ - QColor c(colors[1]); - if(isEnabled()){ - c.setAlpha(160); - p->setPen(QPen(c,1));//editor->colors[2].darker(500)); - }else{ - c.setAlpha(60); - p->setPen(QPen(c,1)); - } - p->drawText(rect, Qt::AlignLeft, _display_string); - } } }; diff --git a/Qt/Qt_SliderPainterPainter.h b/Qt/Qt_SliderPainterPainter.h new file mode 100644 index 0000000..56e1f1c --- /dev/null +++ b/Qt/Qt_SliderPainterPainter.h @@ -0,0 +1,120 @@ +/* Copyright 2012 Kjetil S. Matheussen + +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. */ + + + +#ifdef COMPILING_RADIUM +extern struct Root *root; +#else +extern QColor *g_colors; +#endif + + +static inline QColor mix_colors(const QColor &c1, const QColor &c2, float how_much){ + + float a1 = how_much; + float a2 = 1.0f-a1; + + if(c1.red()==0 && c1.green()==0 && c1.blue()==0){ // some of the black lines doesn't look look very good. + int r = 74*a1 + c2.red()*a2; + int g = 74*a1 + c2.green()*a2; + int b = 74*a1 + c2.blue()*a2; + + return QColor(r,g,b); + }else{ + + int r = c1.red()*a1 + c2.red()*a2; + int g = c1.green()*a1 + c2.green()*a2; + int b = c1.blue()*a1 + c2.blue()*a2; + + return QColor(r,g,b); + } +} + + +static inline void SLIDERPAINTERPAINTER_paint(QPainter *p, int x1, int y1, int x2, int y2, bool is_enabled, float val, QString text, bool alternative_color){ +#ifdef COMPILING_RADIUM + QColor *colors = static_cast(root->song->tracker_windows->os_visual.widget)->colors; +#else + QColor *colors = g_colors; +#endif + + int height = y2-y1; + int width = x2-x1; + + QColor col1; + QColor col1b; + + int col1num = 11; + + if(is_enabled){ + QColor c(98,59,33); + + col1 = c.light(90); + col1b = colors[13].light(100); + }else{ + col1 = mix_colors(colors[col1num], Qt::gray, 0.8f); + col1b = mix_colors(colors[col1num].light(110), Qt::gray, 0.8f); + } + + if(alternative_color==true) + col1 = QColor(200,200,200); + + if(alternative_color==false){ + col1.setAlpha(80); + col1b.setAlpha(100); + }else{ + col1.setAlpha(120); + col1b.setAlpha(120); + } + + if(height > width){ // i.e. vertical + int pos=scale(val,0,1,0,height); + p->fillRect(0,pos,width,height-pos,col1); + }else{ + int pos=scale(val,0,1,0,width); + QLinearGradient gradient(0,0,width,height*3/4); + if(alternative_color==false) + gradient.setColorAt(0,col1.light(100)); + else + gradient.setColorAt(0,col1.light(150)); + gradient.setColorAt(1,col1b); + + p->setPen(QPen(QColor(Qt::gray).light(50),1)); + p->setBrush(gradient); + p->drawRect(0 ,0, pos, height); + p->setBrush(QBrush()); + } + + p->setPen(QPen(colors[11].light(110),1)); + p->drawRect(0,0,width,height); + + QRect rect(5,2,width-5,height-2); + + if(text!=""){ + QColor c(colors[1]); + if(is_enabled){ + c.setAlpha(160); + p->setPen(QPen(c,1)); + }else{ + c.setAlpha(60); + p->setPen(QPen(c,1)); + } + p->drawText(rect, Qt::AlignLeft, text); + } + +} + diff --git a/Qt/Qt_compressor_widget.h b/Qt/Qt_compressor_widget.h index b1940e7..819148c 100644 --- a/Qt/Qt_compressor_widget.h +++ b/Qt/Qt_compressor_widget.h @@ -31,6 +31,7 @@ class Ui_Compressor_widget QHBoxLayout *horizontalLayout; QLabel *radium_url; MyQCheckBox *bypass; + MyQCheckBox *enable_checkbox; MyQButton *load_button; MyQButton *save_button; MyQSlider *attack_slider; @@ -41,6 +42,11 @@ class Ui_Compressor_widget if (Compressor_widget->objectName().isEmpty()) Compressor_widget->setObjectName(QString::fromUtf8("Compressor_widget")); Compressor_widget->resize(385, 412); + QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(1); + sizePolicy.setHeightForWidth(Compressor_widget->sizePolicy().hasHeightForWidth()); + Compressor_widget->setSizePolicy(sizePolicy); verticalLayout = new QVBoxLayout(Compressor_widget); verticalLayout->setSpacing(0); verticalLayout->setContentsMargins(0, 0, 0, 0); @@ -52,11 +58,11 @@ class Ui_Compressor_widget horizontalLayout->setContentsMargins(-1, -1, -1, 2); radium_url = new QLabel(Compressor_widget); radium_url->setObjectName(QString::fromUtf8("radium_url")); - QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - sizePolicy.setHorizontalStretch(0); - sizePolicy.setVerticalStretch(0); - sizePolicy.setHeightForWidth(radium_url->sizePolicy().hasHeightForWidth()); - radium_url->setSizePolicy(sizePolicy); + QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Fixed); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(radium_url->sizePolicy().hasHeightForWidth()); + radium_url->setSizePolicy(sizePolicy1); radium_url->setAlignment(Qt::AlignCenter); radium_url->setOpenExternalLinks(true); @@ -64,25 +70,32 @@ class Ui_Compressor_widget bypass = new MyQCheckBox(Compressor_widget); bypass->setObjectName(QString::fromUtf8("bypass")); - QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Minimum); - sizePolicy1.setHorizontalStretch(0); - sizePolicy1.setVerticalStretch(0); - sizePolicy1.setHeightForWidth(bypass->sizePolicy().hasHeightForWidth()); - bypass->setSizePolicy(sizePolicy1); + QSizePolicy sizePolicy2(QSizePolicy::Minimum, QSizePolicy::Fixed); + sizePolicy2.setHorizontalStretch(0); + sizePolicy2.setVerticalStretch(0); + sizePolicy2.setHeightForWidth(bypass->sizePolicy().hasHeightForWidth()); + bypass->setSizePolicy(sizePolicy2); horizontalLayout->addWidget(bypass); + enable_checkbox = new MyQCheckBox(Compressor_widget); + enable_checkbox->setObjectName(QString::fromUtf8("enable_checkbox")); + sizePolicy2.setHeightForWidth(enable_checkbox->sizePolicy().hasHeightForWidth()); + enable_checkbox->setSizePolicy(sizePolicy2); + + horizontalLayout->addWidget(enable_checkbox); + load_button = new MyQButton(Compressor_widget); load_button->setObjectName(QString::fromUtf8("load_button")); - sizePolicy.setHeightForWidth(load_button->sizePolicy().hasHeightForWidth()); - load_button->setSizePolicy(sizePolicy); + sizePolicy1.setHeightForWidth(load_button->sizePolicy().hasHeightForWidth()); + load_button->setSizePolicy(sizePolicy1); horizontalLayout->addWidget(load_button); save_button = new MyQButton(Compressor_widget); save_button->setObjectName(QString::fromUtf8("save_button")); - sizePolicy.setHeightForWidth(save_button->sizePolicy().hasHeightForWidth()); - save_button->setSizePolicy(sizePolicy); + sizePolicy1.setHeightForWidth(save_button->sizePolicy().hasHeightForWidth()); + save_button->setSizePolicy(sizePolicy1); horizontalLayout->addWidget(save_button); @@ -91,6 +104,7 @@ class Ui_Compressor_widget attack_slider = new MyQSlider(Compressor_widget); attack_slider->setObjectName(QString::fromUtf8("attack_slider")); + attack_slider->setEnabled(false); attack_slider->setMaximum(1000); attack_slider->setOrientation(Qt::Horizontal); @@ -98,6 +112,7 @@ class Ui_Compressor_widget release_slider = new MyQSlider(Compressor_widget); release_slider->setObjectName(QString::fromUtf8("release_slider")); + release_slider->setEnabled(false); release_slider->setMaximum(1000); release_slider->setOrientation(Qt::Horizontal); @@ -114,6 +129,7 @@ class Ui_Compressor_widget Compressor_widget->setWindowTitle(QApplication::translate("Compressor_widget", "Radium Compressor", 0, QApplication::UnicodeUTF8)); radium_url->setText(QApplication::translate("Compressor_widget", "Radium", 0, QApplication::UnicodeUTF8)); bypass->setText(QApplication::translate("Compressor_widget", "Bypass", 0, QApplication::UnicodeUTF8)); + enable_checkbox->setText(QApplication::translate("Compressor_widget", "Enable", 0, QApplication::UnicodeUTF8)); load_button->setText(QApplication::translate("Compressor_widget", "Load", 0, QApplication::UnicodeUTF8)); save_button->setText(QApplication::translate("Compressor_widget", "Save", 0, QApplication::UnicodeUTF8)); } // retranslateUi diff --git a/Qt/Qt_compressor_widget_callbacks.h b/Qt/Qt_compressor_widget_callbacks.h index 51ce3c9..1058aed 100644 --- a/Qt/Qt_compressor_widget_callbacks.h +++ b/Qt/Qt_compressor_widget_callbacks.h @@ -16,968 +16,337 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include +#include "Qt_compressor_widget.h" + #include #include #include #include #include -#include "Qt_compressor_widget.h" - -#define GLIDING_PEAK_AREA 0 - -const int min_db = -40; -const int max_db = 40; - -const int k_timer_interval = 35; - -const int max_attack_release = 500; - -const float def_threshold = 0.7f; -const float def_ratio = 0.3; -const float def_makeupgain = 0.3f; +#define INCLUDE_MYLINE_AND_MYRECT 1 +# include "compressor_vertical_sliders.cpp" +#undef INCLUDE_MYLINE_AND_MYRECT -namespace{ +namespace cvs{ -enum{ - RATIO=0, - THRESHOLD, - ATTACK, - RELEASE, - //INPUT_VOLUME, - OUTPUT_VOLUME, - BYPASS -}; - - -struct Comp : public QWidget, public QTimer{ - // All values have the value 0 at top, and 1 at bottom, and: - // 0 <= val1 <= val2 <= 1 - // (sometimes < instead of <=) - - // slider 1 - double in_val1; // 0 - double in_val2; // threshold + struct MyColor{ + QColor col; + MyColor(int r,int g,int b) + : col(r,g,b) + {} - // slider 2 - double out_val1; // used to calculate ratio ( ratio = in_val2/(out_val1-in_val2) ) - double out_val2; // threshold + MyColor(QColor col) + : col(col) + {} - // slider 3 - double vol_val1; // used to calculate volume ( volume = out_val1/vol_val1 ) - double vol_val2; // threshold * volume - - int curr_slider; + MyColor(int colnum) +#ifdef COMPILING_RADIUM + : col(static_cast(root->song->tracker_windows->os_visual.widget)->colors[colnum]) +#else + : col(g_colors[colnum]) +#endif + {} - struct Box{ - int x1,y1,x2,y2; - int p1,p2; + MyColor() +#ifdef COMPILING_RADIUM + : col(static_cast(root->song->tracker_windows->os_visual.widget)->colors[11]) +#else + : col(g_colors[11]) +#endif + {} - Box(int _x1, int _y1, int _x2, int _y2, float val1,float val2) - : x1(_x1) - , y1(_y1) - , x2(_x2) - , y2(_y2) - { - p1 = scale(val1,0,1,y1,y2); - p2 = scale(val2,0,1,y1,y2); + MyColor lighter(int p){ + return MyColor(col.light(80)); } - bool inside(int x,int y){ - return x>=x1 && xy1 && y=p; + + void setAlpha(int a){ + col.setAlpha(a); } }; - struct Peaks{ - const static int num_peaks = 30;//24; - - float peaks[num_peaks]; // in dB - int peak_pos; - float last_peak; + static inline MyColor mix_colors(const MyColor &c1, const MyColor &c2, float how_much){ + return MyColor(mix_colors(c1.col,c2.col,how_much)); + } -#if GLIDING_PEAK_AREA - float min_peak_db, max_peak_db; // in dB -#endif - int min_peak, max_peak; // in pixels - - Peaks() - : peak_pos(0) - , last_peak(0) -#if GLIDING_PEAK_AREA - , min_peak_db(0), max_peak_db(0) -#endif - , min_peak(0) - , max_peak(0) + struct MyImage{ + QImage image; + QPainter qp; + MyImage(int width,int height) + : image(width,height,QImage::Format_RGB32) + , qp(&image) { - for(int i=0;iret) - ret=peaks[i]; - return ret; + struct MyPainter{ + QPainter *p; + MyColor col; + QPen pen; + QLinearGradient gradient; + bool use_gradient; + int _thickness; + + MyPainter(QPainter *p) + : p(p) + , use_gradient(false) + , _thickness(1) + { + p->setPen(pen); } - -#if GLIDING_PEAK_AREA - // Trying gliding area instead of array. IMO it is less clear, and it also uses more CPU because of more gfx updates. - void update_peaks(const Box &box, float peak){ - const float inc = 0.25; - - if(peak>max_peak_db) - max_peak_db = peak; - else - max_peak_db = max_peak_db - inc; - - if(peak max_db) - max_peak_db = max_db; - - if(min_peak_db>max_peak_db) - min_peak_db=max_peak_db; - - //if(box.x1<50) - // printf("min_peak_db: %f\n",min_peak_db); - - min_peak = scale(min_peak_db,min_db,max_db, box.y2, box.y1); - max_peak = scale(max_peak_db,min_db,max_db, box.y2, box.y1); + MyPainter(MyImage *image) + : p(&image->qp) + , use_gradient(false) + , _thickness(1) + { + p->setPen(pen); } -#else - - void set_min_max(const Box &box){ - min_peak = scale(get_min_peak(),min_db,max_db, box.y2, box.y1); - max_peak = scale(get_max_peak(),min_db,max_db, box.y2, box.y1); + void setGradient(int x1, int y1, int x2, int y2, const MyColor &c1, const MyColor &c2){ + gradient = QLinearGradient(x1,y1,x2,y2); + gradient.setColorAt(0,c1.col); + gradient.setColorAt(1,c2.col); + p->setPen(QPen(QBrush(gradient),_thickness)); + use_gradient = true; } -#endif - - const int get_y_pixel(const Box &box){ - return scale(last_peak,min_db,max_db, box.y2, box.y1); + void unsetGradient(){ + use_gradient=false; } - const QLine get_line_line(const Box &box){ - const int peak = get_y_pixel(box); - return QLine(box.x1,peak,box.x2,peak); + void drawImage(int x,int y,MyImage *image){ + p->drawImage(x,y,image->image); } - const QLine get_line_to_next_box(const Box &box1, Peaks *peaks2, const Box &box2){ - Peaks *peaks1 = this; - int x1=box1.x2; - int y1=peaks1->get_y_pixel(box1); - int x2=box2.x1; - int y2=peaks2->get_y_pixel(box2); - - if(y1 < box1.y1){ - x1=scale(box1.y1, y1,y2, x1,x2); - y1=box1.y1 - 10; // FIX. why is - 10 needed? - } - - if(y2 < box2.y1){ - x2=scale(box2.y1, y1,y2, x1,x2); - y2=box2.y1 - 10; - } - - if(y1 > box1.y2){ - x1=scale(box1.y2, y1,y2, x1,x2); - y1=box1.y2 + 10; - } - - if(y2 > box2.y2){ - x2=scale(box2.y2, y1,y2, x1,x2); - y2=box2.y2 + 10; + void drawRect(const int x1,const int y1,const int x2,const int y2, const MyColor &col){ + if(use_gradient==false){ + pen.setColor(col.col); + p->setPen(pen); } - - if(x1box2.x1) - x1=10000; - if(x2box2.x1) - x1=10000; - - - return QLine(x1,y1,x2,y2); - } - - // For lines in boxes (those lines are always horizontal) - const QRect get_line_rect(const Box &box){ - const int peak = get_y_pixel(box); - return QRect(box.x1,peak-2,box.x2-box.x1,5); - } - - // For the lines between boxes. - const QPolygon get_line_region(const Box &box1, Peaks *peaks2, const Box &box2){ - const QLine line = get_line_to_next_box(box1,peaks2,box2); - - int x1=line.x1(); - int y1=line.y1(); - int x2=line.x2(); - int y2=line.y2(); - - if(x1==10000) - return QPolygon(); // Line is not painted. - -#if 0 - double degree = 3.14159265359/2.0 - atan( (double)(line2.y1() - line1.y2()) / (double)(line2.x1() - line1.x2())); - int h = ceil( (4.0/sin(degree)) / 2.0); - //printf("degree: %f, h: %d\n",degree*57.2957795,h); -#else - // optimized: - int h_square = y2 - y1; - h_square *= h_square; - - int w_square = x2 - x1; - w_square *= w_square; - - int h = ceil(4.0/2.0 * sqrt((double)h_square/(double)w_square + 1.0)); // "4.0" is the pen width. -#endif - - QPolygon poly(4); - - poly.setPoint(0, x1, y1-h); - poly.setPoint(1, x1, y1+h); - poly.setPoint(2, x2, y2+h); - poly.setPoint(3, x2, y2-h); - - return poly; + p->drawRect(x1,y1,x2-x1,y2-y1); } - - const QRect get_area_rect(const Box &box){ - return QRect(box.x1,max_peak, - box.x2-box.x1, min_peak-max_peak); + void drawRect(const MyRect &rect,const MyColor &col){ + drawRect(rect.x1,rect.y1,rect.x2,rect.y2,col); } - void paint_peak_area(QPainter *p, const Box &box){ - QColor col(40,90,140); - col.setAlpha(80); - p->fillRect(get_area_rect(box),col); + void fillRect(const int x1,const int y1,const int x2,const int y2, const MyColor &col){ + if(use_gradient==false) + p->fillRect(x1,y1,x2-x1,y2-y1,col.col); + else + p->fillRect(x1,y1,x2-x1,y2-y1,QBrush(gradient)); } - void paint_peak_line(QPainter *p, const Box &box){ - p->drawLine(get_line_line(box)); + void fillRect(const MyRect &rect,const MyColor &col){ + fillRect(rect.x1,rect.y1,rect.x2,rect.y2,col); } - void paint_peak_line_between_boxes(QPainter *p, const Box &box1, Peaks *peaks2, const Box &box2){ - const QLine line = get_line_to_next_box(box1, peaks2, box2); - if(line.x1()==10000) - return; - - p->drawLine(line); + void setThickness(int thickness){ + _thickness=thickness; + pen.setWidth(thickness); } - QRegion add_peaks(const Box &box, float peak){ - - QRegion reg_before = get_area_rect(box); - - if(peak<-1000) - peak=-1000; - if(peak>1000) - peak=1000; - - last_peak = peak; - //printf("adding peak %.2f. ",peak); - peaks[peak_pos] = peak; - peak_pos++; - if(peak_pos==num_peaks) - peak_pos=0; - -#if USE_GLIDING_PEAK_AREA - update_peaks(box,peak); -#else - set_min_max(box); -#endif - - QRegion reg_after = get_area_rect(box); - - return reg_before.xored(reg_after); - } - }; - - Peaks peaks_in; - Peaks peaks_out; - Peaks peaks_vol; - - float in_peak_value; - float out_peak_value; - float vol_peak_value; - - void timerEvent(QTimerEvent * e){ // virtual method from QTimer - update_peaks(); - } - - Comp(QWidget *parent) - : QWidget(parent) - , in_val1(0.0) - , in_val2(def_threshold) - , out_val1(def_ratio) - , out_val2(def_threshold) - , vol_val1(def_makeupgain) - , vol_val2(def_threshold) - , curr_slider(0) - { - setInterval(k_timer_interval); // QTimer - start(); // QTimer - - set_threshold(def_threshold); - set_compressor_parameters(); - - update_peaks(); - } - - int get_box_width(){ - return (width()-1) / 4; - } - - int get_width_between_boxes(){ - return get_box_width() / 2; - } - - Box get_slider1_parms(){ - return Box( - 0,0, - get_box_width(), - height()-1, - in_val1,in_val2); - } - - Box get_slider2_parms(){ - return Box( - get_box_width() + get_width_between_boxes(), 0, - get_box_width() + get_width_between_boxes() + get_box_width(), - height()-1, - out_val1,out_val2); - } - - Box get_slider3_parms(){ - return Box( - get_box_width() + get_width_between_boxes() + get_box_width() + get_width_between_boxes(), 0, - get_box_width() + get_width_between_boxes() + get_box_width() + get_width_between_boxes() + get_box_width(), - height()-1, - vol_val1, vol_val2); - } - - double get_threshold(){ - return scale(in_val2, - in_val1,1, - max_db,min_db); - } - - void set_threshold_gui(){ - set_threshold(scale(get_compressor_parameter(THRESHOLD),max_db,min_db,in_val1,1)); - } - - double get_ratio(){ - double len_in = in_val2-in_val1; - double len_out = out_val2-out_val1; - - if(len_in==0.0 && len_out==0.0) - return 1.0; - - if(len_out==0.0) - return 60; - - double ratio = fabs(len_in-len_out)<0.00001 - ? 1.0 - : len_in / len_out; - - if(ratio>60) - ratio=60; - return ratio; - } - - void set_ratio_gui(){ - double ratio = get_compressor_parameter(RATIO); - if(ratio<1.0){ - set_ratio(scale(ratio,1,0,0,-1)); - }else - set_ratio(out_val2 - out_val2/ratio); - } - - double get_makeup_gain(){ - return scale(vol_val1,0,1,max_db,min_db) - scale(out_val1,0,1,max_db,min_db); - } - - // set_ratio must be called first. - void set_makeup_gain_gui(){ - float vol = get_compressor_parameter(OUTPUT_VOLUME); - float addvol = scale(out_val1,0,1,max_db,min_db) + vol; - set_makeupgain(scale(addvol,max_db,min_db,0,1)); - } - - // After loading. - void set_gui_parameters(){ - set_threshold_gui(); - set_ratio_gui(); - set_makeup_gain_gui(); - } - - void set_compressor_parameters(){ - //double input_volume = 1.0; - double threshold = get_threshold(); - double ratio = get_ratio(); - double output_volume = get_makeup_gain(); - - set_compressor_parameter(RATIO,ratio); - set_compressor_parameter(THRESHOLD, threshold); - //set_compressor_parameter(2,attack); - //set_compressor_parameter(3,release); - //set_compressor_parameter(4,input_volume); - set_compressor_parameter(OUTPUT_VOLUME,output_volume); - -#if 0 - printf("%f / %f\n%f / %f\n%f / %f\ninput_volume:\t\t %.2f\n" - "threshold:\t\t %f.2f\n" - "ratio:\t\t\t %f.2f\n" - "output_volume:\t\t %.2f\n\n",in_val2,out_val2,scale(vol_val1,0,1,max_db,min_db),scale(out_val1,0,1,max_db,min_db),vol_val1,out_val1, - input_volume, - threshold, - ratio, - output_volume); -#endif - } + void drawLine(const int x1,const int y1,const int x2,const int y2, const MyColor &col){ + if(use_gradient==false){ + pen.setColor(col.col); + p->setPen(pen); + } - enum{ - THRESHOLD_SLIDER = 1, - RATIO_SLIDER, - MAKEUPGAIN_SLIDER - }; + bool anti = x1!=x2 && y1!=y2; - double p_startpos; - int y_startpos; + if(anti) + p->setRenderHints(QPainter::Antialiasing,true); - void set_makeupgain(float val){ - //double old = vol_val2; - vol_val1=val; -#if 0 // allow this. - if(vol_val1<0.0) - vol_val1=0.0; -#endif - if(vol_val1>0.9999) - vol_val1=0.9999; - vol_val2 = vol_val1 + (out_val2-out_val1);// scale(out_val2, out_val1, 1.0, vol_val1, 1.0); - //printf("setting makeupgain to %f. old/new vol_val2: %f / %f\n",val,vol_val2,old); - } + p->drawLine(x1,y1,x2,y2); - void set_ratio(float val){ - double vol_diff = vol_val1 - out_val1; - out_val1=val; - // if(out_val1<0.0) - // out_val1=0.0; - - if(out_val1<0){ - double threshold=get_compressor_parameter(THRESHOLD); //get_threshold(); - double threshold_scaled=scale(threshold,max_db,min_db,0,1); - double ratio = scale(val,0,-1,1,0); //1.0 + val; // val is the out slider value, which goes from 0 to -1 when we are in expanding mode. - if(ratio<0.001) - ratio=0.001; - in_val1 = ((ratio-1)*threshold_scaled) / (ratio*threshold_scaled - ratio - threshold_scaled); // From: i1 = i2*(1-ratio), i2=scale(threshold_scaled,0,1,i1,1), i1=in_va1, i2=in_val2 - out_val1=0.0; - if(in_val1>0.999) - in_val1=0.999; - in_val2=scale(threshold,max_db,min_db,in_val1,1); - out_val2=in_val2; - }else{ - in_val1=0.0; + if(anti) + p->setRenderHints(QPainter::Antialiasing,false); } - if(out_val1>in_val2-0.0001) - out_val1=in_val2-0.0001; - - set_makeupgain(vol_diff + out_val1); - } - - void set_threshold(float val){ - //double bef=in_val2; - double old_inval1_scaled = scale(in_val1,0,in_val2,0,1); - double old_ratio_factor = out_val1 / (in_val2-in_val1); - in_val2 = val; - if(in_val2<=0.0) - in_val2=0.00001; - if(in_val2>0.9999) - in_val2=0.9999; - - out_val2 = in_val2; - - if(in_val1<=0.0){ - set_ratio(old_ratio_factor*in_val2); - }else{ - in_val1 = scale(old_inval1_scaled,0,1,0,in_val2); - set_makeupgain(vol_val1); - //printf("b %.2f - %.2f. Bef: %.2f, now: %.2f\n",in_val1,old_inval1_scaled,bef,in_val2); + void drawLine(const MyLine &l, const MyColor &col){ + drawLine(l.x1,l.y1,l.x2,l.y2, col); } - } - void handle_mouse_event ( QMouseEvent * event ){ - //printf("Got mouse press event %d / %d\n",(int)event->x(),(int)event->y()); - - double new_val = p_startpos + scale(event->y()-y_startpos,0,height(),0,1); - //printf("p_startpos: %f\n",p_startpos); - - switch(curr_slider){ - case THRESHOLD_SLIDER: - set_threshold(new_val); - break; - case RATIO_SLIDER: - set_ratio(new_val); - break; - case MAKEUPGAIN_SLIDER: - set_makeupgain(new_val); - break; + int getTextWidth(std::string text){ + const QFontMetrics fn = QFontMetrics(QFont()); + return fn.width(QString::fromStdString(text)); } - set_compressor_parameters(); - - update(); - - event->accept(); - } - - void mousePressEvent ( QMouseEvent * event ) - { - Box in_box = get_slider1_parms(); - Box out_box = get_slider2_parms(); - Box vol_box = get_slider3_parms(); - - int x = event->x(); - int y = event->y(); - - if(in_box.inside(x,y)){ - - curr_slider = THRESHOLD_SLIDER; - p_startpos = in_box.p2; - - }else if(out_box.inside(x,y)){ - - curr_slider = RATIO_SLIDER; - if(in_box.p1>0){ - p_startpos = scale(in_box.p1,0,in_box.p2,0,-height()); - }else{ - p_startpos = out_box.p1; + void drawText(const MyRect &rect, std::string text, const MyColor &col){ + if(use_gradient==false){ + pen.setColor(col.col); + p->setPen(pen); } - }else if(vol_box.inside(x,y)){ - - curr_slider = MAKEUPGAIN_SLIDER; - p_startpos = vol_box.p1; - + p->drawText(rect.x1,rect.y1,rect.width(),rect.height(), + Qt::AlignTop|Qt::AlignLeft, + QString::fromStdString(text)); } - p_startpos = scale(p_startpos,0,height(),0,1); - y_startpos = y; - } - - void mouseMoveEvent ( QMouseEvent * event ) - { - handle_mouse_event(event); - } - - void mouseReleaseEvent ( QMouseEvent * event ) - { - handle_mouse_event(event); - curr_slider = 0; - } - - void paint_slider(QPainter *p, const Box &b){ - p->drawRect(b.x1, b.y1, - b.x2-b.x1, b.y2-b.y1); - - p->drawLine(b.x1,b.p1, - b.x2,b.p1); - p->drawLine(b.x1,b.p2, - b.x2,b.p2); - } - - void paint_gradient(QPainter *p, const Box &in, const Box &out, const Box &vol){ - QColor col1(30,170,33); - QColor col2(159,58,33); - col2=col2.light(80); - - // in slider - { - QLinearGradient gradient(0,in.p1,0,in.y2); - gradient.setColorAt(0,col1); - gradient.setColorAt(1,col2); - p->fillRect(in.x1 ,in.p1, in.x2-in.x1 ,in.y2-in.p1,QBrush(gradient)); - } - - float in_val = scale(in_val2,in_val1,1.0f,0.0f,1.0f); - QColor col = mix_colors(col1,col2,1.0f-in_val); - - // out slider top - { - QLinearGradient gradient(0,out.p1,0,out.p2); - gradient.setColorAt(0,col1); - gradient.setColorAt(1,col); - p->fillRect(out.x1, out.p1, - out.x2-out.x1, - out.p2-out.p1, - QBrush(gradient)); - } - - // out slider bot. - { - QLinearGradient gradient(0,out.p2,0,out.y2); - gradient.setColorAt(0,col); - gradient.setColorAt(1,col2); - p->fillRect(out.x1, out.p2, - out.x2-out.x1, - out.y2-out.p2, - QBrush(gradient)); + void drawVerticalText(int x, int y, std::string text, const MyColor &col){ + if(use_gradient==false){ + pen.setColor(col.col); + p->setPen(pen); + } + p->save(); + QPoint point(x,y); + p->translate(x,0);//point);//x, y); + p->rotate(90); // or 270 + //p->scale((box.x2-box.x1)/12,1.0); + //point = p->xFormDev(point); + p->drawText(5,-5,QString::fromStdString(text)); + p->restore(); } + }; - // area between in slider and out slider, below threshold - { - QLinearGradient gradient(0,out.p2, - 0,out.y2); - gradient.setColorAt(0,col); - gradient.setColorAt(1,col2); - p->fillRect(in.x2, out.p2, - out.x1-in.x2, - out.y2-out.p2, - QBrush(gradient)); - } + struct MyWidget{ + struct MyQWidget : public QWidget{ - // area between in slider and out slider, above threshold - for(int x=in.x2;xsetPen(QPen(QBrush(gradient),1)); - p->drawLine(x,y1,x,y2); - } + MyWidget *mywidget; + MyQWidget(QWidget *parent, MyWidget *mywidget) : QWidget(parent),mywidget(mywidget){ + } - // volume slider - { - int p1 = vol.p1; - int p2 = vol.p2;//scale(out.p2, out.p1, out.y2, vol.p1, vol.y2); - int p3 = p2 + (out.y2-out.p2); - - // top - { - QLinearGradient gradient(0,p1,0,p2); - gradient.setColorAt(0,col1); - gradient.setColorAt(1,col); - p->fillRect(vol.x1, p1, - vol.x2-vol.x1, - p2-p1, - QBrush(gradient)); + void mousePressEvent ( QMouseEvent * event ){ + if(mywidget->mousePress(event->x(),event->y())) + event->accept(); } - - // bot. - { - QLinearGradient gradient(0,p2,0,p3); - gradient.setColorAt(0,col); - gradient.setColorAt(1,col2); - p->fillRect(vol.x1, p2, - vol.x2-vol.x1, - p3-p2, - QBrush(gradient)); + void mouseMoveEvent ( QMouseEvent * event ){ + if(mywidget->mouseMove(event->x(),event->y())) + event->accept(); } - - QColor col3=col2.light(scale(p3,vol.y2,vol.y1,100,40)); - - // below bot. - { - QLinearGradient gradient(0,p3,0,vol.y2); - gradient.setColorAt(0,col2); - gradient.setColorAt(1,col3); - p->fillRect(vol.x1,p3, - vol.x2-vol.x1,vol.y2-p3, - QBrush(gradient)); + void mouseReleaseEvent ( QMouseEvent * event ){ + if(mywidget->mouseRelease(event->x(),event->y())) + event->accept(); } - - // area between out slider and vol slider, above threshold - for(int x=out.x2;xsetPen(QPen(QBrush(gradient),1)); - p->drawLine(x,y1,x,y2); + void paintEvent ( QPaintEvent * ev ){ + QPainter qp(this); + MyPainter p(&qp); + mywidget->repaint(&p); } - - // area between out slider and vol slider, below threshold - for(int x=out.x2;xsetPen(QPen(QBrush(gradient),1)); - p->drawLine(x,y1,x,y2); + virtual void resizeEvent ( QResizeEvent * event ){ + mywidget->resized(); } + }; - } - - //p->setBrush(QBrush()); - p->setPen(QPen()); - } - + MyQWidget w; - // Called regularly - void update_peaks(){ - Box in_box = get_slider1_parms(); - Box out_box = get_slider2_parms(); - Box vol_box = get_slider3_parms(); + MyWidget(void *parent) + : w(static_cast(parent),this) + {} - in_peak_value = get_graph_value(0); - out_peak_value = in_peak_value + get_graph_value(1); - vol_peak_value = out_peak_value + get_makeup_gain(); - - QRegion reg; + void update(int x1,int y1,int x2,int y2){ + w.update(x1,y1,x2-x1,y2-y1); + } + void update(const MyRect &r){ + update(r.x1,r.y1,r.x2,r.y2); + } - // update old line boxes - reg = peaks_in.get_line_rect(in_box); - reg = reg.united(peaks_out.get_line_rect(out_box)); - reg = reg.united(peaks_vol.get_line_rect(vol_box)); + void update(){ + w.update(); + } - // update old lines between boxes - reg = reg.united(peaks_in.get_line_region(in_box,&peaks_out,out_box)); - reg = reg.united(peaks_out.get_line_region(out_box,&peaks_vol,vol_box)); + int width(){return w.width();} + int height(){return w.height();} - // Add new peaks, and update areas in boxes (both old and new) - reg = reg.united(peaks_in.add_peaks(in_box, scale(scale(in_peak_value,max_db,min_db,in_val1,1),0,1,max_db,min_db))); - reg = reg.united(peaks_out.add_peaks(out_box,scale(scale(out_peak_value,max_db,min_db,in_val1,1),0,1,max_db,min_db))); - reg = reg.united(peaks_vol.add_peaks(vol_box,scale(scale(vol_peak_value,max_db,min_db,in_val1,1),0,1,max_db,min_db))); + bool isVisible(){return w.isVisible();} + bool isEnabled(){ + //printf("w is %s\n",w.isEnabled()?"enabled":"disabled"); + return w.isEnabled(); + } - // update new lines between boxes - reg = reg.united(peaks_in.get_line_region(in_box,&peaks_out,out_box)); - reg = reg.united(peaks_out.get_line_region(out_box,&peaks_vol,vol_box)); + virtual void resized() = 0; - // update new line boxes - reg = reg.united(peaks_in.get_line_rect(in_box)); - reg = reg.united(peaks_out.get_line_rect(out_box)); - reg = reg.united(peaks_vol.get_line_rect(vol_box)); + //virtual void repaint(MyPainter *p){} + virtual void repaint(MyPainter *p) = 0; - update(reg); - } + virtual bool mousePress(int x, int y) = 0; - void paintPeaks(QPainter *p, const Box &in_box, const Box &out_box, const Box &vol_box){ + virtual bool mouseMove(int x, int y) = 0; - { - QColor col(0,90,180); - col.setAlpha(80); - QPen pen(col); - pen.setWidth(4); - p->setPen(pen); - } + virtual bool mouseRelease(int x, int y) = 0; + }; - // paint lines - { - // in - peaks_in.paint_peak_line(p, in_box); - - // between in and out - peaks_in.paint_peak_line_between_boxes(p, in_box, &peaks_out, out_box); - - // out - peaks_out.paint_peak_line(p, out_box); - - // between out and vol - peaks_out.paint_peak_line_between_boxes(p, out_box, &peaks_vol, vol_box); - - // vol - peaks_vol.paint_peak_line(p, vol_box); - } + struct MyTimer{ - // paint areas - { - peaks_in.paint_peak_area(p,in_box); - peaks_out.paint_peak_area(p,out_box); - peaks_vol.paint_peak_area(p,vol_box); - } + struct MyQTimer : public QTimer{ + MyTimer *mytimer; -#if 0 // for checking that get_line_region returns correct value. - p->setPen(QPen()); - p->drawPolygon(peaks_in.get_line_region(in_box,&peaks_out,out_box)); - p->drawPolygon(peaks_out.get_line_region(out_box,&peaks_vol,vol_box)); -#endif - } + MyQTimer(MyTimer *mytimer) : mytimer(mytimer) {} - int get_text_width(QString text){ - const QFontMetrics fn = QFontMetrics(QFont()); - return fn.width(text); - } - - void paintSliderText(QPainter *p, const Box &box, QString text, double value, QString unit){ - QString value_text = QString::number(value,'g',3) + unit; - QString one_line = text + " " + value_text; - - QRect rect(QPoint(box.x1+2,box.y1+2),QPoint(box.x2-4,box.y2-4)); + void timerEvent(QTimerEvent * e){ // virtual method from QTimer + mytimer->timer(); + } + }; - if(get_text_width(text) < rect.width() && get_text_width(value_text) < rect.width()){ - // horizontal + MyQTimer qtimer; - p->drawText(rect,Qt::AlignTop|Qt::AlignLeft, - get_text_width(one_line)save(); - QPoint point(box.x1,box.y1); - p->translate(box.x1,0);//point);//x, y); - p->rotate(90); // or 270 - //p->scale((box.x2-box.x1)/12,1.0); - //point = p->xFormDev(point); - p->drawText(5,-5, one_line); - p->restore(); + virtual void timer() = 0; + void startTimer(int interval_in_milliseconds){ + qtimer.setInterval(interval_in_milliseconds); + qtimer.start(); } - //p->drawText(box.x1,box.y2-20,QString::number(value)); - } + }; - void paint_box_fill(QPainter *p, const Box &box){ - QColor col(150,190,10); - col.setAlpha(10); - - p->fillRect(box.x1, box.y1, - box.x2-box.x1, box.y2-box.y1, - col); - } +} // namespace cvs - void paintEvent ( QPaintEvent * ev ){ - QPainter p(this); - //printf("Paint\n"); - Box in_box = get_slider1_parms(); - Box out_box = get_slider2_parms(); - Box vol_box = get_slider3_parms(); +#include "../audio/system_compressor_wrapper_proc.h" - paint_gradient(&p,in_box,out_box,vol_box); - QColor black(0,0,0); - black.setAlpha(80); - QPen pen(black); - //pen.setWidth(2); +#ifdef COMPILING_RADIUM - p.setPen(pen); +// I'm pretty sure it's not necessary to test for plugin!=NULL in these three functons. +// Normally, I'm 100% sure it's safe, but these functions can also be called from a timer. +// +static void set_compressor_parameter(struct Patch *patch, int num,float value){ + SoundPlugin *plugin = (SoundPlugin*)patch->patchdata; + if(plugin!=NULL) + PLUGIN_set_effect_value(plugin, 0, plugin->type->num_effects+EFFNUM_COMP_RATIO+num, value, PLUGIN_NONSTORED_TYPE, PLUGIN_STORE_VALUE); +} - paint_slider(&p, in_box); - paint_slider(&p, out_box); - paint_slider(&p, vol_box); +#else // COMPILING_RADIUM - // bottom line between sliders - { - p.drawLine(in_box.x2,in_box.y2,out_box.x1,out_box.y2); - p.drawLine(out_box.x2,out_box.y2,vol_box.x1,vol_box.y2); - } +static void set_compressor_parameter(struct Patch *patch, int num,float value){ + SoundPlugin *plugin = (SoundPlugin*)patch->patchdata; + if(plugin!=NULL) + COMPRESSOR_set_parameter(plugin->compressor,num,value); +} - // threshold line between sliders - { - // between in and out - p.drawLine(in_box.x2,in_box.p2, - out_box.x1,out_box.p2); - - if(out_box.p2!=vol_box.p2) - p.setRenderHints(QPainter::Antialiasing,true); - - // between out and vol - p.drawLine(out_box.x2,out_box.p2, - vol_box.x1,vol_box.p2); - - if(out_box.p2!=vol_box.p2) - p.setRenderHints(QPainter::Antialiasing,false); - } +#endif // #else COMPILING_RADIUM - paint_box_fill(&p,in_box); - paint_box_fill(&p,out_box); - paint_box_fill(&p,vol_box); +static float get_compressor_parameter(struct Patch *patch, int num){ + SoundPlugin *plugin = (SoundPlugin*)patch->patchdata; + if(plugin!=NULL) + return COMPRESSOR_get_parameter(plugin->compressor,num); + else + return 0.0f; +} - paintPeaks(&p, in_box, out_box, vol_box); +static float get_graph_value(struct Patch *patch, int num){ + SoundPlugin *plugin = (SoundPlugin*)patch->patchdata; + if(plugin!=NULL) + return COMPRESSOR_get_graph_value(plugin->compressor,num); + else + return 0.0; +} - // border line between sliders - { - black.setAlpha(60); - QPen pen(black); - p.setPen(pen); - - // between in and out - { - if(in_box.p1!=out_box.p1){ - p.setRenderHints(QPainter::Antialiasing,true); - pen.setWidth(2); - } - - p.drawLine(in_box.x2,in_box.p1, - out_box.x1,out_box.p1); - - if(in_box.p1!=out_box.p1){ - p.setRenderHints(QPainter::Antialiasing,false); - pen.setWidth(1); - } - } - // between out and vol - { - if(out_box.p1!=vol_box.p1){ - p.setRenderHints(QPainter::Antialiasing,true); - pen.setWidth(2); - } - - p.drawLine(out_box.x2,out_box.p1, - vol_box.x1,vol_box.p1); - - if(out_box.p1!=vol_box.p1){ - p.setRenderHints(QPainter::Antialiasing,false); - pen.setWidth(1); - } - } - } +//#ifdef COMPILING_RADIUM +//namespace radium_comp{ // got an error trying to use anonymous namespace here. + //#endif - p.setPen(QPen()); - paintSliderText(&p,in_box,"Threshold: ",get_threshold(), "dB"); - paintSliderText(&p,out_box,"Ratio: ",get_ratio(),":1"); - paintSliderText(&p,vol_box,"Makeup Gain: ",get_makeup_gain(),"dB"); - } +#include "compressor_vertical_sliders.cpp" -}; static double OS_get_double_from_string(const char *s){ QLocale::setDefault(QLocale::C); @@ -993,20 +362,47 @@ static float read_float(FILE *file){ return OS_get_double_from_string(temp); } + class Compressor_widget : public QWidget, public Ui::Compressor_widget{ Q_OBJECT public: bool initing; - Comp *comp; + cvs::Comp *comp; + struct Patch *_patch; - Compressor_widget(QWidget *parent=NULL) + Compressor_widget(struct Patch *patch, QWidget *parent=NULL) : QWidget(parent) + , _patch(patch) { initing = true; setupUi(this); - comp = new Comp(this); - verticalLayout->insertWidget(1,comp); + + QWidget *parent_for_comp = this; + comp = new cvs::Comp(patch,parent_for_comp); + +#ifdef COMPILING_RADIUM + comp->w.setEnabled(false); +#else + attack_slider->setEnabled(true); + release_slider->setEnabled(true); + enable_checkbox->setVisible(false); +#endif + verticalLayout->insertWidget(1,&comp->w); + +#ifdef COMPILING_RADIUM + // Enable MyQSlider and MyQCheckBox to take care of undo/redo. + { + SoundPlugin *plugin = (SoundPlugin*)_patch->patchdata; + attack_slider->_patch = patch; + attack_slider->_effect_num = plugin->type->num_effects+EFFNUM_COMP_ATTACK; + release_slider->_patch = patch; + release_slider->_effect_num = plugin->type->num_effects+EFFNUM_COMP_RELEASE; + enable_checkbox->_patch = patch; + enable_checkbox->_effect_num = plugin->type->num_effects+EFFNUM_COMP_ONOFF; + } +#endif + update_gui(); initing = false; } @@ -1024,8 +420,15 @@ class Compressor_widget : public QWidget, public Ui::Compressor_widget{ void update_gui(){ comp->set_gui_parameters(); - attack_slider->setValue(get_exp_inverted_value(get_compressor_parameter(ATTACK),1000,0,max_attack_release)); - release_slider->setValue(get_exp_inverted_value(get_compressor_parameter(RELEASE),1000,0,max_attack_release)); + attack_slider->setValue(get_exp_inverted_value(get_compressor_parameter(_patch, COMP_EFF_ATTACK),1000,0,max_attack_release)); + release_slider->setValue(get_exp_inverted_value(get_compressor_parameter(_patch, COMP_EFF_RELEASE),1000,0,max_attack_release)); + + SoundPlugin *plugin = (SoundPlugin*)_patch->patchdata; + enable_checkbox->setChecked(plugin->comp.is_on); + + //paint_all=true; + //updateBackgroundImage(); + update(); } void load(QString filename){ @@ -1040,13 +443,13 @@ class Compressor_widget : public QWidget, public Ui::Compressor_widget{ return; } - set_compressor_parameter(RATIO,read_float(file)); // ratio - set_compressor_parameter(THRESHOLD,read_float(file)); // threshold - set_compressor_parameter(ATTACK,read_float(file)); // attack - set_compressor_parameter(RELEASE,read_float(file)); // release + set_compressor_parameter(_patch, COMP_EFF_RATIO,read_float(file)); // ratio + set_compressor_parameter(_patch, COMP_EFF_THRESHOLD,read_float(file)); // threshold + set_compressor_parameter(_patch, COMP_EFF_ATTACK,read_float(file)); // attack + set_compressor_parameter(_patch, COMP_EFF_RELEASE,read_float(file)); // release //set_compressor_parameter(INPUT_VOLUME,read_float(file)); // input volume (currently not used) read_float(file); // input volume (currently not used) - set_compressor_parameter(OUTPUT_VOLUME,read_float(file)); // output volume + set_compressor_parameter(_patch, COMP_EFF_OUTPUT_VOLUME,read_float(file)); // output volume fclose(file); @@ -1055,9 +458,21 @@ class Compressor_widget : public QWidget, public Ui::Compressor_widget{ public slots: +void on_enable_checkbox_toggled(bool val){ +#ifdef COMPILING_RADIUM + SoundPlugin *plugin = (SoundPlugin*)_patch->patchdata; + PLUGIN_set_effect_value(plugin, 0, plugin->type->num_effects+EFFNUM_COMP_ONOFF, val==true?1.0:0.0, PLUGIN_NONSTORED_TYPE, PLUGIN_STORE_VALUE); + + attack_slider->setEnabled(val); + release_slider->setEnabled(val); + comp->background_image_must_be_updated=true; + comp->w.setEnabled(val); +#endif +} + void on_attack_slider_valueChanged(int val){ float attack = get_exp_value(val,1000,0,max_attack_release); - set_compressor_parameter(ATTACK,attack); + set_compressor_parameter(_patch, COMP_EFF_ATTACK,attack); char temp[512]; sprintf(temp,"Attack: %.2fms",attack); SLIDERPAINTER_set_string(attack_slider->_painter, temp); @@ -1065,7 +480,7 @@ public slots: void on_release_slider_valueChanged(int val){ float release = get_exp_value(val,1000,0,max_attack_release); - set_compressor_parameter(RELEASE,release); + set_compressor_parameter(_patch, COMP_EFF_RELEASE,release); char temp[512]; sprintf(temp,"Release: %.2fms",release); SLIDERPAINTER_set_string(release_slider->_painter, temp); @@ -1073,7 +488,7 @@ public slots: void on_bypass_toggled(bool val){ printf("bypass: %d\n",(int)val); - set_compressor_parameter(BYPASS,val==true?1.0f:0.0f); + set_compressor_parameter(_patch, COMP_EFF_BYPASS,val==true?1.0f:0.0f); } void on_load_button_pressed(void){ @@ -1107,18 +522,20 @@ public slots: } fprintf(file,"%f\n%f\n%f\n%f\n%f\n%f\n", - get_compressor_parameter(RATIO), - get_compressor_parameter(THRESHOLD), - get_compressor_parameter(ATTACK), - get_compressor_parameter(RELEASE), + get_compressor_parameter(_patch, COMP_EFF_RATIO), + get_compressor_parameter(_patch, COMP_EFF_THRESHOLD), + get_compressor_parameter(_patch, COMP_EFF_ATTACK), + get_compressor_parameter(_patch, COMP_EFF_RELEASE), //get_compressor_parameter(INPUT_VOLUME), 0.0f, // input volume (in dB) - get_compressor_parameter(OUTPUT_VOLUME) + get_compressor_parameter(_patch, COMP_EFF_OUTPUT_VOLUME) ); fclose(file); } }; -} // anon. namespace + //#ifdef COMPILING_RADIUM + //} // radium_comp namespace + //#endif diff --git a/Qt/compressor_vertical_sliders.cpp b/Qt/compressor_vertical_sliders.cpp new file mode 100644 index 0000000..de5dd0e --- /dev/null +++ b/Qt/compressor_vertical_sliders.cpp @@ -0,0 +1,1128 @@ +/* Copyright 2013 Kjetil S. Matheussen + +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. */ + +#ifdef INCLUDE_MYLINE_AND_MYRECT + +namespace cvs{ + +struct MyLine{ + int x1,y1,x2,y2; + MyLine(int x1,int y1, int x2, int y2) + : x1(x1),y1(y1),x2(x2),y2(y2) + {} +}; + +struct MyRect{ + int x1,y1,x2,y2; + MyRect(int x1,int y1, int x2, int y2) + : x1(x1),y1(y1),x2(x2),y2(y2) + {} + int width() const {return x2-x1;} + int height() const {return y2-y1;} +}; +} + + + +#else // INCLUDE_MYLINE_AND_MYRECT + + + +#include + +#define GLIDING_PEAK_AREA 0 // Set to 1 to get gliding peaks area, which most meters use. Looks good, but I think it is slightly more confusing than the array used now. + +const int min_db = -40; +const int max_db = 40; + +const int k_timer_interval = 25; + +const int max_attack_release = 500; + +const float def_threshold = 0.7f; +const float def_ratio = 0.3; +const float def_makeupgain = 0.3f; + +namespace cvs{ + +struct Comp : public MyWidget, public MyTimer{ + struct Patch *_patch; + + // All values have the value 0 at top, and 1 at bottom, and: + // 0 <= val1 <= val2 <= 1 + // (sometimes < instead of <=) + + // slider 1 + double in_val1; // 0 + double in_val2; // threshold + + // slider 2 + double out_val1; // used to calculate ratio ( ratio = in_val2/(out_val1-in_val2) ) + double out_val2; // threshold + + // slider 3 + double vol_val1; // used to calculate volume ( volume = out_val1/vol_val1 ) + double vol_val2; // threshold * volume + + // attack/release sliders + double attack_val; + double release_val; + + int curr_slider; + + struct Box{ + int x1,y1,x2,y2; + int p1,p2; + + Box(int _x1, int _y1, int _x2, int _y2, float val1,float val2) + : x1(_x1) + , y1(_y1) + , x2(_x2) + , y2(_y2) + { + p1 = scale(val1,0,1,y1,y2); + p2 = scale(val2,0,1,y1,y2); + } + + bool inside(int x,int y){ + return x>=x1 && xy1 && y=p; + } + }; + + struct Slider : public Box{ + Slider(int _x1, int _y1, int _x2, int _y2, float val1,float val2) + : Box(_x1,_y1,_x2,_y2,val1,val2) + { + p1 = scale(val1,0,1,x1,x2); + } + }; + + struct Peaks{ + const static int num_peaks = 30;//24; + + float peaks[num_peaks]; // in dB + int peak_pos; + float last_peak; + +#if GLIDING_PEAK_AREA + float min_peak_db, max_peak_db; // in dB +#endif + int min_peak, max_peak; // in pixels + + Peaks() + : peak_pos(0) + , last_peak(0) +#if GLIDING_PEAK_AREA + , min_peak_db(0), max_peak_db(0) +#endif + , min_peak(0) + , max_peak(0) + { + for(int i=0;iret) + ret=peaks[i]; + return ret; + } + + +#if GLIDING_PEAK_AREA + // Trying gliding area instead of array. IMO it is less clear, and it also uses more CPU because of more gfx updates. + void update_peaks(const Box &box, float peak){ + const float inc = 0.1; + + if(peak>max_peak_db) + max_peak_db = peak; + else + max_peak_db = max_peak_db - inc; + + if(peak max_db) + max_peak_db = max_db; + + if(min_peak_db>max_peak_db) + min_peak_db=max_peak_db; + + //if(box.x1<50) + // printf("min_peak_db: %f\n",min_peak_db); + + min_peak = scale(min_peak_db,min_db,max_db, box.y2, box.y1); + max_peak = scale(max_peak_db,min_db,max_db, box.y2, box.y1); + } + +#else + + void set_min_max(const Box &box){ + min_peak = scale(get_min_peak(),min_db,max_db, box.y2, box.y1); + max_peak = scale(get_max_peak(),min_db,max_db, box.y2, box.y1); + } + +#endif + + const int get_y_pixel(const Box &box){ + return scale(last_peak,min_db,max_db, box.y2, box.y1); + } + + const MyLine get_line_line(const Box &box){ + const int peak = get_y_pixel(box); + return MyLine(box.x1,peak,box.x2,peak); + } + + const MyLine get_line_to_next_box(const Box &box1, Peaks *peaks2, const Box &box2){ + Peaks *peaks1 = this; + int x1=box1.x2; + int y1=peaks1->get_y_pixel(box1); + int x2=box2.x1; + int y2=peaks2->get_y_pixel(box2); + + if(y1 < box1.y1){ + x1=scale(box1.y1, y1,y2, x1,x2); + y1=box1.y1 - 10; // FIX. why is - 10 needed? + } + + if(y2 < box2.y1){ + x2=scale(box2.y1, y1,y2, x1,x2); + y2=box2.y1 - 10; + } + + if(y1 > box1.y2){ + x1=scale(box1.y2, y1,y2, x1,x2); + y1=box1.y2 + 10; + } + + if(y2 > box2.y2){ + x2=scale(box2.y2, y1,y2, x1,x2); + y2=box2.y2 + 10; + } + + if(x1box2.x1) + x1=10000; + if(x2box2.x1) + x1=10000; + + + return MyLine(x1,y1,x2,y2); + } + + // For lines in boxes (those lines are always horizontal) + const MyRect get_line_rect(const Box &box){ + const int peak = get_y_pixel(box); + return MyRect(box.x1,peak-2,box.x2,peak+3); + } + + void update_line_rect(MyWidget *widget, const Box &box){ + widget->update(get_line_rect(box)); + } + + // For the lines between boxes. + void update_line_region(MyWidget *widget, const Box &box1, Peaks *peaks2, const Box &box2){ + const MyLine line = get_line_to_next_box(box1,peaks2,box2); + + int x1=line.x1; + int y1=line.y1; + int x2=line.x2; + int y2=line.y2; + + if(x1==10000) + return; // Line is not painted. + + + int h_square = y2 - y1; + h_square *= h_square; + + int w_square = x2 - x1; + w_square *= w_square; + + int h = ceil(4.0/2.0 * sqrt((double)h_square/(double)w_square + 1.0)); // "4.0" is the pen width. + + int y1_1 = y1-h; + int y1_2 = y1+h; + int y2_1 = y2-h; + int y2_2 = y2+h; + + const int dx = 8; + + if(y1_1 < y2_1) + for(int x=x1;xupdate(x,y1,x+dx,y2); + } + else + for(int x=x1;xupdate(x,y1,x+dx,y2); + } + } + + const MyRect get_area_rect(const Box &box){ + return MyRect(box.x1,max_peak, + box.x2, min_peak); + } + + void paint_peak_area(MyPainter *p, const Box &box){ + MyColor col(40,90,140); + col = col.lighter(80); + col.setAlpha(120); + + p->fillRect(get_area_rect(box), col); + } + + void paint_peak_line(MyPainter *p, const Box &box, const MyColor &col){ + p->drawLine(get_line_line(box),col); + } + + void paint_peak_line_between_boxes(MyPainter *p, const Box &box1, Peaks *peaks2, const Box &box2, const MyColor &col){ + const MyLine line = get_line_to_next_box(box1, peaks2, box2); + if(line.x1==10000) + return; + + p->drawLine(line,col); + } + + // Only works if rect1.x1==rect2.x1 && rect2.x2==rect2.x2 + void update_xored_rects(MyWidget *widget, const MyRect &rect1, const MyRect &rect2){ + if(rect1.y1==rect2.y1 && rect1.y2==rect2.y2) + return; + + MyRect r1=rect1; + MyRect r2=rect2; + int x1=rect1.x1; + int x2=rect1.x2; + + if(r1.y1 > r2.y1){ + MyRect temp=r1; + r1=r2; + r2=temp; + } + +#if 0 // for testing + widget->update(x1,r1.y1,x2,r1.y2); + widget->update(x1,r2.y1,x2,r2.y2); + return; +#endif + + if(r1.y1==r2.y1 && r2.y2update(x1, r2.y2, x2, r1.y2); + return; + } + + if(r1.y1==r2.y1){ + widget->update(x1, r1.y2, x2, r2.y2); + return; + } + + if(r1.y2==r2.y2){ + widget->update(x1, r1.y1, x2, r2.y1); + return; + } + + if(r2.y2 < r1.y2){ + widget->update(x1, r1.y1, x2, r2.y1); + widget->update(x1, r2.y2, x2, r1.y2); + return; + } + + if(r2.y1 < r1.y2){ + widget->update(x1, r1.y1, x2, r2.y1); + widget->update(x1, r1.y2, x2, r2.y2); + } + + // i.e. they are non-overlapping + widget->update(x1, r1.y1, x2, r1.y2); + widget->update(x1, r2.y1, x2, r2.y2); + } + + void add_peaks_and_update_area(MyWidget *widget, const Box &box, float peak){ + + MyRect rect_before = get_area_rect(box); + + if(peak<-1000) + peak=-1000; + if(peak>1000) + peak=1000; + + last_peak = peak; + //printf("adding peak %.2f. ",peak); + peaks[peak_pos] = peak; + peak_pos++; + if(peak_pos==num_peaks) + peak_pos=0; + +#if GLIDING_PEAK_AREA + update_peaks(box,peak); +#else + set_min_max(box); +#endif + + MyRect rect_after = get_area_rect(box); + + update_xored_rects(widget, rect_before, rect_after); + } + }; + + Peaks peaks_in; + Peaks peaks_out; + Peaks peaks_vol; + + float in_peak_value; + float out_peak_value; + float vol_peak_value; + + bool background_image_must_be_updated; + + MyImage *background_image; + + void timer(){ // virtual method from MyTimer + if(isVisible()) + update_peaks(); + } + + ~Comp(){ + delete background_image; + } + + Comp(struct Patch *patch, void *parent) + : MyWidget(parent) + , _patch(patch) + , in_val1(0.0) + , in_val2(def_threshold) + , out_val1(def_ratio) + , out_val2(def_threshold) + , vol_val1(def_makeupgain) + , vol_val2(def_threshold) + , curr_slider(0) + , background_image_must_be_updated(true) + , background_image(NULL) + { + createBackgroundImage(); + + startTimer(k_timer_interval); // MyTimer + + set_threshold(def_threshold); + set_compressor_parameters(); + + update_peaks(); + } + + void createBackgroundImage(){ + delete background_image; + background_image = new MyImage(width(),height()); + updateBackgroundImage(); + } + + void resized(){ + createBackgroundImage(); + } + + int get_box_width(){ + return (width()-1) / 4; + } + + int get_slider_height(){ + return 20; + } + + int get_box_height(){ + //return height()-((get_slider_height()+1)*2); + return height()-1; + } + + int get_width_between_boxes(){ + return get_box_width() / 2; + } + + Box get_slider1_parms(){ + return Box( + 0,0, + get_box_width(), + get_box_height(), + in_val1,in_val2); + } + + Box get_slider2_parms(){ + return Box( + get_box_width() + get_width_between_boxes(), 0, + get_box_width() + get_width_between_boxes() + get_box_width(), + get_box_height(), + out_val1,out_val2); + } + + Box get_slider3_parms(){ + return Box( + get_box_width() + get_width_between_boxes() + get_box_width() + get_width_between_boxes(), 0, + get_box_width() + get_width_between_boxes() + get_box_width() + get_width_between_boxes() + get_box_width(), + get_box_height(), + vol_val1, vol_val2); + } + +#if 0 + Slider get_attack_slider_parms(){ + return Box( + 0,get_box_height() + 1, + width(), get_box_height() + get_slider_height() + attack_val,0.0f); + } + + Slider get_release_slider_parms(){ + return Box( + 0,get_box_height() + 1, + width(), get_box_height() + get_slider_height() + release_val,0.0f); + } +#endif + + double get_threshold(){ + return scale(in_val2, + in_val1,1, + max_db,min_db); + } + + void set_threshold_gui(){ + set_threshold(scale(get_compressor_parameter(_patch, COMP_EFF_THRESHOLD),max_db,min_db,in_val1,1)); + } + + double get_ratio(){ + double len_in = in_val2-in_val1; + double len_out = out_val2-out_val1; + + if(len_in==0.0 && len_out==0.0) + return 1.0; + + if(len_out==0.0) + return 60; + + double ratio = fabs(len_in-len_out)<0.00001 + ? 1.0 + : len_in / len_out; + + if(ratio>60) + ratio=60; + return ratio; + } + + void set_ratio_gui(){ + double ratio = get_compressor_parameter(_patch, COMP_EFF_RATIO); + if(ratio<1.0){ + set_ratio(scale(ratio,1,0,0,-1)); + }else + set_ratio(out_val2 - out_val2/ratio); + } + + double get_makeup_gain(){ + return scale(vol_val1,0,1,max_db,min_db) - scale(out_val1,0,1,max_db,min_db); + } + + // set_ratio must be called first. + void set_makeup_gain_gui(){ + float vol = get_compressor_parameter(_patch, COMP_EFF_OUTPUT_VOLUME); + float addvol = scale(out_val1,0,1,max_db,min_db) + vol; + set_makeupgain(scale(addvol,max_db,min_db,0,1)); + } + + // After loading. + void set_gui_parameters(){ + set_threshold_gui(); + set_ratio_gui(); + set_makeup_gain_gui(); + } + + void set_compressor_parameters(){ + //double input_volume = 1.0; + double threshold = get_threshold(); + double ratio = get_ratio(); + double output_volume = get_makeup_gain(); + + set_compressor_parameter(_patch, COMP_EFF_RATIO,ratio); + set_compressor_parameter(_patch, COMP_EFF_THRESHOLD, threshold); + //set_compressor_parameter(2,attack); + //set_compressor_parameter(3,release); + //set_compressor_parameter(4,input_volume); + set_compressor_parameter(_patch, COMP_EFF_OUTPUT_VOLUME,output_volume); + +#if 0 + printf("%f / %f\n%f / %f\n%f / %f\ninput_volume:\t\t %.2f\n" + "threshold:\t\t %f.2f\n" + "ratio:\t\t\t %f.2f\n" + "output_volume:\t\t %.2f\n\n",in_val2,out_val2,scale(vol_val1,0,1,max_db,min_db),scale(out_val1,0,1,max_db,min_db),vol_val1,out_val1, + input_volume, + threshold, + ratio, + output_volume); +#endif + } + + enum{ + THRESHOLD_SLIDER = 1, + RATIO_SLIDER, + MAKEUPGAIN_SLIDER + }; + + double p_startpos; + int y_startpos; + + void set_makeupgain(float val){ + //double old = vol_val2; + vol_val1=val; +#if 0 // allow this. + if(vol_val1<0.0) + vol_val1=0.0; +#endif + if(vol_val1>0.9999) + vol_val1=0.9999; + vol_val2 = vol_val1 + (out_val2-out_val1);// scale(out_val2, out_val1, 1.0, vol_val1, 1.0); + //printf("setting makeupgain to %f. old/new vol_val2: %f / %f\n",val,vol_val2,old); + } + + void set_ratio(float val){ + double vol_diff = vol_val1 - out_val1; + out_val1=val; + // if(out_val1<0.0) + // out_val1=0.0; + + if(out_val1<0){ + double threshold=get_compressor_parameter(_patch, COMP_EFF_THRESHOLD); //get_threshold(); + double threshold_scaled=scale(threshold,max_db,min_db,0,1); + double ratio = scale(val,0,-1,1,0); //1.0 + val; // val is the out slider value, which goes from 0 to -1 when we are in expanding mode. + if(ratio<0.001) + ratio=0.001; + in_val1 = ((ratio-1)*threshold_scaled) / (ratio*threshold_scaled - ratio - threshold_scaled); // From: i1 = i2*(1-ratio), i2=scale(threshold_scaled,0,1,i1,1), i1=in_va1, i2=in_val2 + out_val1=0.0; + if(in_val1>0.999) + in_val1=0.999; + in_val2=scale(threshold,max_db,min_db,in_val1,1); + out_val2=in_val2; + }else{ + in_val1=0.0; + } + if(out_val1>in_val2-0.0001) + out_val1=in_val2-0.0001; + + set_makeupgain(vol_diff + out_val1); + } + + void set_threshold(float val){ + //double bef=in_val2; + double old_inval1_scaled = scale(in_val1,0,in_val2,0,1); + double old_ratio_factor = out_val1 / (in_val2-in_val1); + + in_val2 = val; + if(in_val2<=0.0) + in_val2=0.00001; + if(in_val2>0.9999) + in_val2=0.9999; + + out_val2 = in_val2; + + if(in_val1<=0.0){ + set_ratio(old_ratio_factor*in_val2); + }else{ + in_val1 = scale(old_inval1_scaled,0,1,0,in_val2); + set_makeupgain(vol_val1); + //printf("b %.2f - %.2f. Bef: %.2f, now: %.2f\n",in_val1,old_inval1_scaled,bef,in_val2); + } + } + + void handle_mouse_event (int x, int y){ + //printf("Got mouse press event %d / %d\n",(int)event->x(),(int)event->y()); + + double new_val = p_startpos + scale(y-y_startpos,0,height(),0,1); + //printf("p_startpos: %f\n",p_startpos); + + switch(curr_slider){ + case THRESHOLD_SLIDER: + set_threshold(new_val); + break; + case RATIO_SLIDER: + set_ratio(new_val); + break; + case MAKEUPGAIN_SLIDER: + set_makeupgain(new_val); + break; + } + + set_compressor_parameters(); + + background_image_must_be_updated=true; + update(); + } + + bool mousePress(int x, int y){ + Box in_box = get_slider1_parms(); + Box out_box = get_slider2_parms(); + Box vol_box = get_slider3_parms(); + + if(in_box.inside(x,y)){ +#ifdef COMPILING_RADIUM + SoundPlugin *plugin = (SoundPlugin*)_patch->patchdata; + Undo_AudioEffect_CurrPos(_patch, plugin->type->num_effects+EFFNUM_COMP_THRESHOLD); +#endif + + curr_slider = THRESHOLD_SLIDER; + p_startpos = in_box.p2; + + }else if(out_box.inside(x,y)){ +#ifdef COMPILING_RADIUM + SoundPlugin *plugin = (SoundPlugin*)_patch->patchdata; + Undo_AudioEffect_CurrPos(_patch, plugin->type->num_effects+EFFNUM_COMP_RATIO); +#endif + + curr_slider = RATIO_SLIDER; + if(in_box.p1>0){ + p_startpos = scale(in_box.p1,0,in_box.p2,0,-height()); + }else{ + p_startpos = out_box.p1; + } + + }else if(vol_box.inside(x,y)){ +#ifdef COMPILING_RADIUM + SoundPlugin *plugin = (SoundPlugin*)_patch->patchdata; + Undo_AudioEffect_CurrPos(_patch, plugin->type->num_effects+EFFNUM_COMP_OUTPUT_VOLUME); +#endif + + curr_slider = MAKEUPGAIN_SLIDER; + p_startpos = vol_box.p1; + + } else { + return false; + } + + p_startpos = scale(p_startpos,0,height(),0,1); + y_startpos = y; + + return true; + } + + bool mouseMove (int x, int y) + { + handle_mouse_event(x,y); + return true; + } + + bool mouseRelease (int x, int y) + { + handle_mouse_event(x,y); + curr_slider = 0; + return true; + } + + void paint_box(MyPainter *p, const Box &b, const MyColor &col){ + p->drawRect(b.x1, b.y1, + b.x2, b.y2, + col); + p->drawLine(b.x1,b.p1, + b.x2,b.p1, + col); + p->drawLine(b.x1,b.p2, + b.x2,b.p2, + col); + } + +#if 0 + void paint_slider(MyPainter *p, const Slider &s, const MyColor &col){ + p->drawRect(s.x1, s.y1, + s.x2, s.y2); + p->drawLine(s.x1,s.p1, + s.x2,s.p1); + } +#endif + + void paint_gradient_rectangle(MyPainter *p, const int x1, const int y1, const int x2, const int y2, const MyColor &c1, const MyColor &c2){ +#if 0 + for(int y=y1;ysetPen(mix_colors(c1,c2,scale(y, y1, y2, 1.0f,0.0f))); + p->drawLine(x1,y,x2,y); + } +#else + p->setGradient(0,y1,0,y2,c1,c2); + p->fillRect(x1, y1, x2 ,y2, c1); + p->unsetGradient(); +#endif + } + + void paint_gradient_trapezoid(MyPainter *p, const int x1, const int y1_1, const int y1_2, const int x2, const int y2_1, const int y2_2, const int min_y, const int max_y, const MyColor &c1, const MyColor &c2){ +#if 0 + if(y1_2-y1_1 >= y2_2-y2_1) + for(int y1=y1_1;y1setPen(mix_colors(c1,c2,scale(y1, y1_1,y1_2, 1.0f,0.0f))); + p->drawLine(x1,y1,x2,y2); + } + else + for(int y2=y2_1;y2setPen(mix_colors(c1,c2,scale(y2, y2_1,y2_2, 1.0f,0.0f))); + p->drawLine(x1,y1,x2,y2); + } +#else + for(int x=x1;xsetGradient(x,y1,x,y2,c1,c2); + p->drawLine(x,R_BOUNDARIES(min_y,y1,max_y),x,R_BOUNDARIES(min_y,y2,max_y),c1); + } + p->unsetGradient(); +#endif + } + + void paint_gradient(MyPainter *p, const Box &in, const Box &out, const Box &vol){ +#if 0 // for testing if clipping is accurate + QColor col1(qrand()%255,qrand()%255,qrand()%255); + QColor col2(qrand()%255,qrand()%255,qrand()%255); +#else + MyColor col1(30,170,33); + MyColor col2(159,58,33); +#endif + col2=col2.lighter(80); + + col1 = col1.lighter(80); + col2 = col2.lighter(60); + + //col1.setAlpha(120); + //col2.setAlpha(180); + + if(!isEnabled()){ + //col1.setAlpha(40); + //col2.setAlpha(40); + col1 = mix_colors(col1, MyColor(), 0.4); + col2 = mix_colors(col2, MyColor(), 0.4); + }else{ + col1 = mix_colors(col1, MyColor(), 0.8); + col2 = mix_colors(col2, MyColor(), 0.8); + } + + // in slider + paint_gradient_rectangle(p, in.x1,in.p1, in.x2,in.y2, col1, col2); + + float in_val = scale(in_val2,in_val1,1.0f,0.0f,1.0f); + MyColor col = mix_colors(col1,col2,1.0f-in_val); + + // out slider top + paint_gradient_rectangle(p, out.x1,out.p1, out.x2,out.p2, col1,col); + + // out slider bot. + paint_gradient_rectangle(p, out.x1,out.p2, out.x2,out.y2, col, col2); + + // area between in slider and out slider, below threshold + paint_gradient_rectangle(p, in.x2,in.p2, out.x1,out.y2, col, col2); + + // area between in slider and out slider, above threshold + paint_gradient_trapezoid(p, in.x2,in.p1,in.p2, out.x1,out.p1,out.p2, out.y1, out.y2, col1, col); + + // volume slider + { + int p1 = vol.p1; + int p2 = vol.p2;//scale(out.p2, out.p1, out.y2, vol.p1, vol.y2); + int p3 = p2 + (out.y2-out.p2); + + // top + paint_gradient_rectangle(p, vol.x1,p1, vol.x2,p2, col1, col); + + // middle. + paint_gradient_rectangle(p, vol.x1,p2, vol.x2,p3, col, col2); + + //QColor col3=col2.light(scale(p3,vol.y2,vol.y1,100,40)); + MyColor col3=mix_colors(col2,MyColor(1,1,1),R_BOUNDARIES(0.0f, scale(p3,vol.y2,vol.y1,1.0f,0.0f), 1.0f)); + + // bot. + paint_gradient_rectangle(p, vol.x1,p3, vol.x2,vol.y2, col2, col3); + + // area between out slider and vol slider, above threshold + paint_gradient_trapezoid(p, + out.x2, out.p1, out.p2, + vol.x1, vol.p1, vol.p2, + vol.y1, vol.y2, + col1,col); + + // area between out slider and vol slider, below threshold, colors in the col-col2 range. + paint_gradient_trapezoid(p, + out.x2, out.p2,out.y2, + vol.x1, p2,p3, + vol.y1, vol.y2, + col,col2); + + // area between out slider and vol slider, further below threshold, colors in the col2-col3 range. + if(p3 < vol.y2) + paint_gradient_trapezoid(p, + out.x2, out.y2, out.y2 + (vol.y2-p2), + vol.x1, p3, vol.y2, + vol.y1, vol.y2, + col2,col3); + } + } + + + // Called regularly + void update_peaks(){ + Box in_box = get_slider1_parms(); + Box out_box = get_slider2_parms(); + Box vol_box = get_slider3_parms(); + + in_peak_value = get_graph_value(_patch, 0); + out_peak_value = in_peak_value + get_graph_value(_patch, 1); + vol_peak_value = out_peak_value + get_makeup_gain(); + + //printf("in_peak_value: %f. out: %f, vol: %f\n",in_peak_value,out_peak_value,vol_peak_value); + + // update old line boxes + peaks_in.update_line_rect(this,in_box); + peaks_out.update_line_rect(this,out_box); + peaks_vol.update_line_rect(this,vol_box); + + // update old lines between boxes + peaks_in.update_line_region(this,in_box,&peaks_out,out_box); + peaks_out.update_line_region(this,out_box,&peaks_vol,vol_box); + + // Add new peaks, and update areas in boxes (both old and new) + peaks_in.add_peaks_and_update_area(this,in_box, scale(scale(in_peak_value,max_db,min_db,in_val1,1),0,1,max_db,min_db)); + peaks_out.add_peaks_and_update_area(this,out_box,scale(scale(out_peak_value,max_db,min_db,in_val1,1),0,1,max_db,min_db)); + peaks_vol.add_peaks_and_update_area(this,vol_box,scale(scale(vol_peak_value,max_db,min_db,in_val1,1),0,1,max_db,min_db)); + + // update new lines between boxes + peaks_in.update_line_region(this,in_box,&peaks_out,out_box); + peaks_out.update_line_region(this,out_box,&peaks_vol,vol_box); + + // update new line boxes + peaks_in.update_line_rect(this,in_box); + peaks_out.update_line_rect(this,out_box); + peaks_vol.update_line_rect(this,vol_box); + } + + void paintPeaks(MyPainter *p, const Box &in_box, const Box &out_box, const Box &vol_box){ + + // peak lines + { + MyColor col(0,90,180); + col = col.lighter(60); + col.setAlpha(130); + + p->setThickness(4); + + // paint lines + { + // in + peaks_in.paint_peak_line(p, in_box, col); + + // between in and out + peaks_in.paint_peak_line_between_boxes(p, in_box, &peaks_out, out_box, col); + + // out + peaks_out.paint_peak_line(p, out_box, col); + + // between out and vol + peaks_out.paint_peak_line_between_boxes(p, out_box, &peaks_vol, vol_box, col); + + // vol + peaks_vol.paint_peak_line(p, vol_box, col); + } + + p->setThickness(1); + } + + // peak areas + { + peaks_in.paint_peak_area(p,in_box); + peaks_out.paint_peak_area(p,out_box); + peaks_vol.paint_peak_area(p,vol_box); + } + +#if 0 // for checking that get_line_region returns correct value. + p->setPen(QPen()); + p->drawPolygon(peaks_in.get_line_region(in_box,&peaks_out,out_box)); + p->drawPolygon(peaks_out.get_line_region(out_box,&peaks_vol,vol_box)); +#endif + } + + void paintSliderText(MyPainter *p, const Box &box, std::string text, double value, std::string unit){ + MyColor c(1); + c.setAlpha(160); + if(!isEnabled()) + c.setAlpha(80); + + char temp[32]; + sprintf(temp,"%.1f",value); + std::string value_text = temp + unit; + std::string one_line = text + " " + value_text; + + MyRect rect(box.x1+2,box.y1+2,box.x2-4,box.y2-4); + + if(p->getTextWidth(text) < rect.width() && p->getTextWidth(value_text) < rect.width()){ + // horizontal + + p->drawText(rect, p->getTextWidth(one_line)drawVerticalText(box.x1,box.y1,one_line,c); + + } + //p->drawText(box.x1,box.y2-20,QString::number(value)); + } + + void paint_box_fill(MyPainter *p, const Box &box){ + MyColor col(150,190,10); + col.setAlpha(10); + + if(box.p1>box.y1) + p->fillRect(box.x1, box.y1, + box.x2, box.p1, + col); + if(box.p2fillRect(box.x1, box.y2, + box.x2, box.p2, + col); + } + + void paintBackgroundImage(MyPainter *p){ + + p->fillRect(0,0,width(),height(),MyColor()); + + //printf("Paint\n"); + + Box in_box = get_slider1_parms(); + Box out_box = get_slider2_parms(); + Box vol_box = get_slider3_parms(); + + paint_gradient(p,in_box,out_box,vol_box); + + MyColor black(1,1,1); + black.setAlpha(80); + + paint_box(p, in_box, black); + paint_box(p, out_box, black); + paint_box(p, vol_box, black); + + // bottom line between sliders + if(1){ + MyColor c = mix_colors(MyColor(1,1,1), MyColor(), 0.4); // Alpha color will not look correct here since the color it's drawn over differs. + p->drawLine(in_box.x2,in_box.y2,vol_box.x1,out_box.y2,c); + p->drawLine(out_box.x2,out_box.y2,vol_box.x1,vol_box.y2,c); + } + + // threshold line between sliders + if(1){ + // between in and out + p->drawLine(in_box.x2,in_box.p2, + out_box.x1,out_box.p2, + black + ); + + // between out and vol + p->drawLine(out_box.x2,out_box.p2, + vol_box.x1,vol_box.p2, + black); + } + + paint_box_fill(p,in_box); + paint_box_fill(p,out_box); + paint_box_fill(p,vol_box); + + // // + + // border line between sliders + if(1){ + black.setAlpha(80); + + if(in_box.p1!=out_box.p1) + p->setThickness(1); + + // between in and out + p->drawLine(in_box.x2,in_box.p1, + out_box.x1,out_box.p1, + black); + + if(out_box.p1!=vol_box.p1) + p->setThickness(1); + else + p->setThickness(1); + + // between out and vol + p->drawLine(out_box.x2,out_box.p1, + vol_box.x1,vol_box.p1, + black); + + p->setThickness(1); + } + + paintSliderText(p,in_box,"Threshold: ",get_threshold(), "dB"); + paintSliderText(p,out_box,"Ratio: ",get_ratio(),":1"); + paintSliderText(p,vol_box,"Makeup Gain: ",get_makeup_gain(),"dB"); + + background_image_must_be_updated = false; + } + + void updateBackgroundImage(){ + MyPainter p(background_image); + //background_image->fill(colors[11]); + paintBackgroundImage(&p); + } + + void repaint(MyPainter *p){ + + if(background_image_must_be_updated==true) + updateBackgroundImage(); + + Box in_box = get_slider1_parms(); + Box out_box = get_slider2_parms(); + Box vol_box = get_slider3_parms(); + + //paintBackgroundImage(&p); + p->drawImage(0,0,background_image); + + paintPeaks(p, in_box, out_box, vol_box); + } + +}; +} + +#endif // INCLUDE_MYLINE_AND_MYRECT diff --git a/Qt/mQt_compressor_widget_callbacks.h b/Qt/mQt_compressor_widget_callbacks.h index 47aeba4..6d35004 100644 --- a/Qt/mQt_compressor_widget_callbacks.h +++ b/Qt/mQt_compressor_widget_callbacks.h @@ -22,7 +22,7 @@ static const uint qt_meta_data_Compressor_widget[] = { 6, // revision 0, // classname 0, 0, // classinfo - 5, 14, // methods + 6, 14, // methods 0, 0, // properties 0, 0, // enums/sets 0, 0, // constructors @@ -31,16 +31,18 @@ static const uint qt_meta_data_Compressor_widget[] = { // slots: signature, parameters, type, tag, flags 23, 19, 18, 18, 0x0a, - 58, 19, 18, 18, 0x0a, - 94, 19, 18, 18, 0x0a, - 118, 18, 18, 18, 0x0a, - 143, 18, 18, 18, 0x0a, + 56, 19, 18, 18, 0x0a, + 91, 19, 18, 18, 0x0a, + 127, 19, 18, 18, 0x0a, + 151, 18, 18, 18, 0x0a, + 176, 18, 18, 18, 0x0a, 0 // eod }; static const char qt_meta_stringdata_Compressor_widget[] = { "Compressor_widget\0\0val\0" + "on_enable_checkbox_toggled(bool)\0" "on_attack_slider_valueChanged(int)\0" "on_release_slider_valueChanged(int)\0" "on_bypass_toggled(bool)\0" @@ -54,11 +56,12 @@ void Compressor_widget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, in Q_ASSERT(staticMetaObject.cast(_o)); Compressor_widget *_t = static_cast(_o); switch (_id) { - case 0: _t->on_attack_slider_valueChanged((*reinterpret_cast< int(*)>(_a[1]))); break; - case 1: _t->on_release_slider_valueChanged((*reinterpret_cast< int(*)>(_a[1]))); break; - case 2: _t->on_bypass_toggled((*reinterpret_cast< bool(*)>(_a[1]))); break; - case 3: _t->on_load_button_pressed(); break; - case 4: _t->on_save_button_pressed(); break; + case 0: _t->on_enable_checkbox_toggled((*reinterpret_cast< bool(*)>(_a[1]))); break; + case 1: _t->on_attack_slider_valueChanged((*reinterpret_cast< int(*)>(_a[1]))); break; + case 2: _t->on_release_slider_valueChanged((*reinterpret_cast< int(*)>(_a[1]))); break; + case 3: _t->on_bypass_toggled((*reinterpret_cast< bool(*)>(_a[1]))); break; + case 4: _t->on_load_button_pressed(); break; + case 5: _t->on_save_button_pressed(); break; default: ; } } @@ -98,9 +101,9 @@ int Compressor_widget::qt_metacall(QMetaObject::Call _c, int _id, void **_a) if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { - if (_id < 5) + if (_id < 6) qt_static_metacall(this, _c, _id, _a); - _id -= 5; + _id -= 6; } return _id; } diff --git a/Qt/qt4_compressor_widget.ui b/Qt/qt4_compressor_widget.ui index c2681a5..5b413d4 100644 --- a/Qt/qt4_compressor_widget.ui +++ b/Qt/qt4_compressor_widget.ui @@ -10,6 +10,12 @@ 412 + + + 0 + 1 + + Radium Compressor @@ -53,7 +59,7 @@ - + 0 0 @@ -63,6 +69,19 @@ + + + + + 0 + 0 + + + + Enable + + + @@ -93,6 +112,9 @@ + + false + 1000 @@ -103,6 +125,9 @@ + + false + 1000 diff --git a/audio/SoundPlugin.h b/audio/SoundPlugin.h index eb12ff8..8655843 100644 --- a/audio/SoundPlugin.h +++ b/audio/SoundPlugin.h @@ -74,6 +74,17 @@ enum{ EFFNUM_HIGHSHELF_GAIN, EFFNUM_HIGHSHELF_ONOFF, + EFFNUM_EQ_SHOW_GUI, + + EFFNUM_COMP_RATIO, // Note that the order for the compressor parameters must be the same as the compressor parameters in system_compresssor_wrapper_proc.h + EFFNUM_COMP_THRESHOLD, + EFFNUM_COMP_ATTACK, + EFFNUM_COMP_RELEASE, + EFFNUM_COMP_OUTPUT_VOLUME, + EFFNUM_COMP_ONOFF, + + EFFNUM_COMP_SHOW_GUI, + EFFNUM_DELAY_TIME, EFFNUM_DELAY_ONOFF, @@ -262,6 +273,13 @@ typedef struct SoundPlugin{ SystemFilter delay; float delay_time; + bool show_equalizer_gui; + + SystemFilter comp; + void *compressor; + + bool show_compressor_gui; + float *volume_peak_values; float *volume_peak_values_for_chip; diff --git a/audio/fast_log_exp.dsp b/audio/fast_log_exp.dsp new file mode 100644 index 0000000..5b44171 --- /dev/null +++ b/audio/fast_log_exp.dsp @@ -0,0 +1,89 @@ +/* +displaygain(i) = _,_ <: _,_,(abs,*(0):+) : _,_,gainview(i) : _,attach; + +min_db = -100.0; // db2linear_from_table(-100) = 0 +min_linear_db = -80.0; // Between min_db and min_linear_db, there is a linear conversion + +max_linear_db = 40.0; // Between max_linear_db and max_db, there is a linear conversion +max_db = 80.0; // 10000.0 = db2linear_from_table(80) = db2linear_from_table(81) = db2linear_from_table(82) = ... + +db2linear_from_table(x) = select2(x>min_db, + 0.0, + select2(x>min_linear_db, + scale(x, + min_db, min_linear_db, + 0.0, db2linear(min_linear_db)), + select2(xmin_linear, + min_db, + select2(x>min_linear_linear, + scale(x, + 0.0, min_linear_db, + min_linear, min_linear_linear), + select2(x -#define FAUSTCLASS mydsp +#ifndef FAUSTCLASS +#define FAUSTCLASS Faust_system_compressor +#endif -class mydsp : public dsp { +class Faust_system_compressor : public dsp { private: FAUSTFLOAT fcheckbox0; int iConst0; @@ -41,18 +43,17 @@ class mydsp : public dsp { m->declare("music.lib/author", "GRAME"); m->declare("music.lib/copyright", "GRAME"); m->declare("music.lib/version", "1.0"); - m->declare("music.lib/license", "LGPL"); + m->declare("music.lib/license", "LGPL with exception"); m->declare("math.lib/name", "Math Library"); m->declare("math.lib/author", "GRAME"); m->declare("math.lib/copyright", "GRAME"); m->declare("math.lib/version", "1.0"); - m->declare("math.lib/license", "LGPL"); + m->declare("math.lib/license", "LGPL with exception"); m->declare("effect.lib/name", "Faust Audio Effect Library"); m->declare("effect.lib/author", "Julius O. Smith (jos at ccrma.stanford.edu)"); m->declare("effect.lib/copyright", "Julius O. Smith III"); m->declare("effect.lib/version", "1.33"); m->declare("effect.lib/license", "STK-4.3"); - m->declare("effect.lib/reference", "https://ccrma.stanford.edu/realsimple/faust_strings/"); } virtual int getNumInputs() { return 2; } @@ -63,12 +64,12 @@ class mydsp : public dsp { fSamplingFreq = samplingFreq; fcheckbox0 = 0.0; iConst0 = min(192000, max(1, fSamplingFreq)); - fConst1 = (1.0f / iConst0); + fConst1 = (1.0f / float(iConst0)); fslider0 = 100.237f; for (int i=0; i<4; i++) fRec2_perm[i]=0; fslider1 = 50.148f; for (int i=0; i<4; i++) fRec1_perm[i]=0; - fConst2 = (2.0f / iConst0); + fConst2 = (2.0f / float(iConst0)); fslider2 = -2e+01f; fslider3 = 2.0f; for (int i=0; i<4; i++) fRec0_perm[i]=0; @@ -79,7 +80,7 @@ class mydsp : public dsp { instanceInit(samplingFreq); } virtual void buildUserInterface(UI* interface) { - interface->openVerticalBox("system_compressor"); + interface->openVerticalBox("standalone_compressor"); interface->declare(&fslider3, "0", ""); interface->declare(&fslider3, "style", "slider"); interface->declare(&fslider3, "tooltip", "A compression Ratio of N means that for each N dB increase in input signal level above Threshold, the output level goes up 1 dB"); @@ -146,27 +147,27 @@ class mydsp : public dsp { FAUSTFLOAT* output0 = &output[0][index]; FAUSTFLOAT* output1 = &output[1][index]; // SECTION : 1 - // LOOP 0x2a67980 + // LOOP 0x2fd3000 // exec code for (int i=0; imin_db, - 0.0, - select2(x>min_linear_db, - scale(x, - min_db, min_linear_db, - 0.0, db2linear(min_linear_db)), - select2(xmin_linear, - min_db, - select2(x>min_linear_linear, - scale(x, - 0.0, min_linear_db, - min_linear, min_linear_linear), - select2(x +#include + +#include +#include + +#include "faudiostream/architecture/faust/gui/UI.h" +#include "faudiostream/architecture/faust/audio/dsp.h" +#ifdef COMPILING_STANDALONE +#include "myjack-dsp.h" +#endif + +#include "../common/nsmtracker.h" + +#include "system_compressor_wrapper_proc.h" + + + +#include + +inline int max (unsigned int a, unsigned int b) { return (a>b) ? a : b; } +inline int max (int a, int b) { return (a>b) ? a : b; } + +inline long max (long a, long b) { return (a>b) ? a : b; } +inline long max (int a, long b) { return (a>b) ? a : b; } +inline long max (long a, int b) { return (a>b) ? a : b; } + +inline float max (float a, float b) { return (a>b) ? a : b; } +inline float max (int a, float b) { return (a>b) ? a : b; } +inline float max (float a, int b) { return (a>b) ? a : b; } +inline float max (long a, float b) { return (a>b) ? a : b; } +inline float max (float a, long b) { return (a>b) ? a : b; } + +inline double max (double a, double b) { return (a>b) ? a : b; } +inline double max (int a, double b) { return (a>b) ? a : b; } +inline double max (double a, int b) { return (a>b) ? a : b; } +inline double max (long a, double b) { return (a>b) ? a : b; } +inline double max (double a, long b) { return (a>b) ? a : b; } +inline double max (float a, double b) { return (a>b) ? a : b; } +inline double max (double a, float b) { return (a>b) ? a : b; } + + +inline int min (int a, int b) { return (a _controllers; + std::vector _graphs; + + void remove_last_item(){ + printf("Popping last effect\n"); + _controllers.pop_back(); + } + + void addEffect(const char *name, float* control_port, float min_value, float default_value, float max_value){ + printf("Adding effect %s %p\n",name,control_port); + _controllers.push_back(control_port); + } + + void addButton(const char* label, float* zone) { + addEffect(label, zone, 0, 0, 1); + } + void addToggleButton(const char* label, float* zone) { + addEffect(label, zone, 0, 0, 1); + } + void addCheckButton(const char* label, float* zone) { + addEffect(label, zone, 0, 0, 1); + } + void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) { + addEffect(label, zone, min, init, max); + } + void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) { + addEffect(label, zone, min, init, max); + } + void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) { + addEffect(label, zone, min, init, max); // The INT effect format might not work. Need to go through the code first. + } + + // -- passive widgets + + void addNumDisplay(const char* label, float* zone, int precision) {remove_last_item();} + void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max) {remove_last_item();} + void addHorizontalBargraph(const char* label, float* zone, float min, float max) { + *zone = (min+max)/2; // init + _graphs.push_back(zone); + //remove_last_item(); // remove metadata + //next_peak = zone; + } + void addVerticalBargraph(const char* label, float* zone, float min, float max) { + *zone = (min+max)/2; // init + _graphs.push_back(zone); + //remove_last_item(); // remove metadata + //next_peak = zone; + } + +}; + +struct Compressor_wrapper : public Faust_system_compressor { + MyUI ui; + + QString key; // If not empty string, the memory for the object is placed in shared memory. + QSharedMemory *shared; + +#ifdef COMPILING_STANDALONE + jackaudio audio; +#endif + + Compressor_wrapper(float sample_rate){ + shared=NULL; + +#ifdef COMPILING_STANDALONE + printf("\n\nCREATING 1\n\n"); + audio.init(g_jack_client_name, this); + audio.start(g_autoconnect); +#endif + +#ifdef COMPILING_RADIUM + init(sample_rate); +#endif + + buildUserInterface(&ui); + } + + +#ifdef COMPILING_STANDALONE + ~Compressor_wrapper(){ + printf("Closing\n"); + audio.stop(); + } + +#endif + +#if 0 + void* operator new(size_t size){ + printf("Allocating %d bytes\n",(int)size); + return malloc(size); + } + void operator delete(void *p){ + printf("Freeing %p.\n",p); + free(p); + } +#endif + + //#endif + +}; + +} // anon. namespace + + +void *COMPRESSOR_create_shared(float sample_rate){ + QString key = "radium_crashreporter_" + QString::number(QDateTime::currentMSecsSinceEpoch()); + QSharedMemory *shared = new QSharedMemory(key); + if(shared->create(sizeof(Compressor_wrapper))==false){ + fprintf(stderr,"COMPRESSOR_create_shared: Couldn't create... Error: %s\n",shared->error()==QSharedMemory::NoError?"No error (?)":shared->errorString().toAscii().data()); + return NULL; + } + + void *memory = shared->data(); + + Compressor_wrapper *wrapper = new(memory) Compressor_wrapper(sample_rate); + printf("memory: %p, shared: %p\n",memory,shared); + wrapper->key = key; + wrapper->shared = shared; + + return wrapper; +} + +void *COMPRESSOR_create(float sample_rate){ + return new Compressor_wrapper(sample_rate); +} + + +void *COMPRESSOR_create_from_shared_mem_key(const char *key){ + QSharedMemory *shared = new QSharedMemory(key); + return shared->data(); +} + +const char *COMPRESSOR_get_shared_mem_key(void *das_wrapper){ + Compressor_wrapper *wrapper = (Compressor_wrapper*)das_wrapper; + return wrapper->key.toAscii(); +} + +#if COMPILING_STANDALONE +extern char *g_shared_mem_key; +#endif + +void COMPRESSOR_delete(void *das_wrapper){ +#if COMPILING_STANDALONE + if(g_shared_mem_key!=NULL){ + COMPRESSOR_delete_ladspa(das_wrapper); + return; + } +#endif + + Compressor_wrapper *wrapper = (Compressor_wrapper*)das_wrapper; + if(wrapper->key=="") + delete wrapper; + else + wrapper->shared->detach(); +} + +float COMPRESSOR_get_parameter(void *das_wrapper,int num){ +#if COMPILING_STANDALONE +if(g_shared_mem_key!=NULL) + return COMPRESSOR_get_ladspa_parameter(das_wrapper,num); +#endif + + Compressor_wrapper *wrapper = (Compressor_wrapper*)das_wrapper; + float *controller = wrapper->ui._controllers.at(num); + return *controller; +} + +void COMPRESSOR_set_parameter(void *das_wrapper,int num,float value){ +#if COMPILING_STANDALONE +if(g_shared_mem_key!=NULL){ +COMPRESSOR_set_ladspa_parameter(das_wrapper,num,value); +return; +} +#endif + + Compressor_wrapper *wrapper = (Compressor_wrapper*)das_wrapper; + float *controller = wrapper->ui._controllers.at(num); + *controller = value; + //printf("Setting controller %d (%p) to %f (%f)\n",num,controller,value,*controller); +} + +float COMPRESSOR_get_graph_value(void *das_wrapper, int num){ +#if COMPILING_STANDALONE +if(g_shared_mem_key!=NULL) + return COMPRESSOR_get_ladspa_graph_value(das_wrapper,num); +#endif + + Compressor_wrapper *wrapper = (Compressor_wrapper*)das_wrapper; + float *controller = wrapper->ui._graphs.at(num); + return *controller; +} + +void COMPRESSOR_process(void *das_wrapper, float **inputs, float **outputs, int num_frames){ + Compressor_wrapper *wrapper = (Compressor_wrapper*)das_wrapper; + wrapper->compute(num_frames, inputs, outputs); +} + diff --git a/audio/system_compressor_wrapper_proc.h b/audio/system_compressor_wrapper_proc.h new file mode 100644 index 0000000..5ea25ce --- /dev/null +++ b/audio/system_compressor_wrapper_proc.h @@ -0,0 +1,45 @@ +/* Copyright 2013 Kjetil S. Matheussen + +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. */ + +enum{ + COMP_EFF_RATIO=0, + COMP_EFF_THRESHOLD, + COMP_EFF_ATTACK, + COMP_EFF_RELEASE, + //INPUT_VOLUME, + COMP_EFF_OUTPUT_VOLUME, + COMP_EFF_BYPASS // only used by the standalone version of the compressor. +}; + + +extern LANGSPEC void *COMPRESSOR_create(float sample_rate); + +extern LANGSPEC void COMPRESSOR_delete(void *das_wrapper); + +extern LANGSPEC float COMPRESSOR_get_parameter(void *das_wrapper,int num); + +extern LANGSPEC void COMPRESSOR_set_parameter(void *das_wrapper,int num,float value); + +extern LANGSPEC float COMPRESSOR_get_graph_value(void *das_wrapper, int num); + +extern LANGSPEC void COMPRESSOR_process(void *das_wrapper, float **inputs, float **outputs, int num_frames); + +extern LANGSPEC void *COMPRESSOR_create_ladspa(const char *key); +extern LANGSPEC float COMPRESSOR_get_ladspa_parameter(void *Instance,int num); +extern LANGSPEC void COMPRESSOR_set_ladspa_parameter(void *Instance,int num,float value); +extern LANGSPEC float COMPRESSOR_get_ladspa_graph_value(void *Instance, int num); +extern LANGSPEC void COMPRESSOR_delete_ladspa(void *Instance); + diff --git a/audio/typepunning.h b/audio/typepunning.h index e5f9773..7468795 100644 --- a/audio/typepunning.h +++ b/audio/typepunning.h @@ -26,7 +26,7 @@ static inline int pun_float_to_int(float x){ } static inline float pun_int_to_float(int x){ - union { uint32_t i; float f; } mx = { .i=(uint32_t)x }; + union { uint32_t i; float f; } mx = { (uint32_t)x }; return mx.f; } diff --git a/common/nsmtracker.h b/common/nsmtracker.h index 354073e..20bb40c 100755 --- a/common/nsmtracker.h +++ b/common/nsmtracker.h @@ -103,6 +103,13 @@ enum{ #define R_ABS(a) ((a)<0?(-(a)):(a)) #define R_BOUNDARIES(a,b,c) (R_MIN(R_MAX((a),(b)),(c))) +static inline double scale_double(double x, double x1, double x2, double y1, double y2){ + return y1 + ( ((x-x1)*(y2-y1)) + / + (x2-x1) + ); +} + static inline float scale(float x, float x1, float x2, float y1, float y2){ return y1 + ( ((x-x1)*(y2-y1)) / diff --git a/main.cpp b/main.cpp index 8926235..5908bd3 100644 --- a/main.cpp +++ b/main.cpp @@ -18,9 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include -#include "audio/faudiostream/architecture/faust/audio/dsp.h" -#include "audio/faudiostream/architecture/faust/gui/UI.h" -#include "myjack-dsp.h" +//#include "audio/faudiostream/architecture/faust/gui/UI.h" #include @@ -37,154 +35,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define OPTARGS_ELSE() }else if(1){ #define OPTARGS_END }else{fprintf(stderr,"%s",usage);exit(-1);}}} - -struct Meta -{ - void declare (const char* key, const char* value) { } -}; - -inline int max (unsigned int a, unsigned int b) { return (a>b) ? a : b; } -inline int max (int a, int b) { return (a>b) ? a : b; } - -inline long max (long a, long b) { return (a>b) ? a : b; } -inline long max (int a, long b) { return (a>b) ? a : b; } -inline long max (long a, int b) { return (a>b) ? a : b; } - -inline float max (float a, float b) { return (a>b) ? a : b; } -inline float max (int a, float b) { return (a>b) ? a : b; } -inline float max (float a, int b) { return (a>b) ? a : b; } -inline float max (long a, float b) { return (a>b) ? a : b; } -inline float max (float a, long b) { return (a>b) ? a : b; } - -inline double max (double a, double b) { return (a>b) ? a : b; } -inline double max (int a, double b) { return (a>b) ? a : b; } -inline double max (double a, int b) { return (a>b) ? a : b; } -inline double max (long a, double b) { return (a>b) ? a : b; } -inline double max (double a, long b) { return (a>b) ? a : b; } -inline double max (float a, double b) { return (a>b) ? a : b; } -inline double max (double a, float b) { return (a>b) ? a : b; } - - -inline int min (int a, int b) { return (a _controllers; - std::vector _graphs; - - void remove_last_item(){ - printf("Popping last effect\n"); - _controllers.pop_back(); - } - - void addEffect(const char *name, float* control_port, float min_value, float default_value, float max_value){ - printf("Adding effect %s %p\n",name,control_port); - _controllers.push_back(control_port); - } - - void addButton(const char* label, float* zone) { - addEffect(label, zone, 0, 0, 1); - } - void addToggleButton(const char* label, float* zone) { - addEffect(label, zone, 0, 0, 1); - } - void addCheckButton(const char* label, float* zone) { - addEffect(label, zone, 0, 0, 1); - } - void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) { - addEffect(label, zone, min, init, max); - } - void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) { - addEffect(label, zone, min, init, max); - } - void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) { - addEffect(label, zone, min, init, max); // The INT effect format might not work. Need to go through the code first. - } - - // -- passive widgets - - void addNumDisplay(const char* label, float* zone, int precision) {remove_last_item();} - void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max) {remove_last_item();} - void addHorizontalBargraph(const char* label, float* zone, float min, float max) { - _graphs.push_back(zone); - //remove_last_item(); // remove metadata - //next_peak = zone; - } - void addVerticalBargraph(const char* label, float* zone, float min, float max) { - _graphs.push_back(zone); - //remove_last_item(); // remove metadata - //next_peak = zone; - } - -}; - -mydsp *d; -MyUI *ui; - -static void set_compressor_parameter(int num,float value){ - float *controller = ui->_controllers.at(num); - *controller = value; - //printf("Setting controller %d (%p) to %f (%f)\n",num,controller,value,*controller); -} - -static float get_compressor_parameter(int num){ - float *controller = ui->_controllers.at(num); - return *controller; -} - -static float get_graph_value(int num){ - float *controller = ui->_graphs.at(num); - return *controller; -} - #include "mQt_compressor_widget_callbacks.h" static void set_colors(void){ @@ -206,10 +64,61 @@ static void set_colors(void){ das_colors[15] = QColor("#7a7967"); } +bool g_autoconnect = false; +const char *g_jack_client_name = "radium_compressor"; +const char *g_settings_filename = NULL; +const char *g_shared_mem_key = NULL; + +QWidget *create_compressor_editor(QWidget *parent, void *compressor){ + // A minimal radium patch environment. + struct Patch *patch = new Patch; + SoundPlugin *plugin = new SoundPlugin; + patch->patchdata = plugin; + plugin->compressor = compressor; + + Compressor_widget *compressor_widget = new Compressor_widget(patch,parent); + + if(g_settings_filename!=NULL) + compressor_widget->load(g_settings_filename); + + set_colors(); + + QPalette pal = compressor_widget->palette(); + //pal.setColor(compressor.backgroundRole(), das_colors[11].light(200)); + pal.setColor(compressor_widget->backgroundRole(), das_colors[11].light(100)); + compressor_widget->setPalette(pal); + + return compressor_widget; +} + +void delete_compressor_editor(QWidget *widget){ + Compressor_widget *compressor = static_cast(widget); + struct Patch *patch=compressor->_patch; + struct SoundPlugin *plugin=(SoundPlugin*)patch->patchdata; + COMPRESSOR_delete(plugin->compressor); + //delete compressor; +} + +void start_program(int argc, char **argv, void *compressor){ + + QApplication app(argc, argv); + + { + QWidget *compressor_editor = create_compressor_editor(NULL, compressor); + + compressor_editor->show(); + + app.exec(); + + delete_compressor_editor(compressor_editor); + } +} + +#ifndef COMPILING_VST + +void *COMPRESSOR_create_ladspa(const char *key); + int main(int argc, char **argv){ - const char *settings_filename = NULL; - bool autoconnect = false; - const char *jack_client_name = "radium_compressor"; OPTARGS_BEGIN("radium_compressor [--autoconnect] [--client-name s] [--settings-filename s] [settings-filename]\n" " [ -ac ] [ -cn s] [ -sn s] [settings filename]\n" @@ -220,40 +129,23 @@ int main(int argc, char **argv){ ) { - OPTARG("--settings-filename","-sn") settings_filename=OPTARG_GETSTRING(); - OPTARG("--autoconnect","-ac") autoconnect=true; - OPTARG("--client-name","-cn") jack_client_name=OPTARG_GETSTRING(); - OPTARG_LAST() settings_filename=OPTARG_GETSTRING(); + OPTARG("--settings-filename","-sn") g_settings_filename=OPTARG_GETSTRING(); + OPTARG("--autoconnect","-ac") g_autoconnect=true; + OPTARG("--client-name","-cn") g_jack_client_name=OPTARG_GETSTRING(); + OPTARG("--ladspa-slave","-ls") g_shared_mem_key = OPTARG_GETSTRING(); + OPTARG_LAST() g_settings_filename=OPTARG_GETSTRING(); }OPTARGS_END; - QApplication app(argc, argv); - set_colors(); - - d = new mydsp; - //d->init(44100); // d->init is called in audio.init. - - jackaudio audio; - audio.init(jack_client_name, d); - //finterface->recallState(rcfilename); - audio.start(autoconnect); + if(g_shared_mem_key!=NULL){ - ui = new MyUI; - d->buildUserInterface(ui); + start_program(argc,argv,COMPRESSOR_create_ladspa(g_shared_mem_key)); - Compressor_widget compressor; - if(settings_filename!=NULL) - compressor.load(settings_filename); + }else{ - compressor.show(); - - QPalette pal = compressor.palette(); - //pal.setColor(compressor.backgroundRole(), das_colors[11].light(200)); - pal.setColor(compressor.backgroundRole(), das_colors[11].light(100)); - compressor.setPalette(pal); - - app.exec(); - - audio.stop(); + start_program(argc,argv, COMPRESSOR_create(0)); + } return 0; } + +#endif diff --git a/myjack-dsp.h b/myjack-dsp.h index d62188b..64e2f24 100644 --- a/myjack-dsp.h +++ b/myjack-dsp.h @@ -2,6 +2,7 @@ #ifndef __jack_dsp__ #define __jack_dsp__ +#include #include #include #include "faust/audio/audio.h"