123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763 |
- /*
- * CompressorControlDialog.cpp
- *
- * Copyright (c) 2020 Lost Robot <r94231@gmail.com>
- *
- * This file is part of LMMS - https://lmms.io
- *
- * 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 (see COPYING); if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- */
- #include "Compressor.h"
- #include "CompressorControlDialog.h"
- #include "CompressorControls.h"
- #include <QLabel>
- #include <QLayout>
- #include <QPainter>
- #include "embed.h"
- #include "GuiApplication.h"
- #include "gui_templates.h"
- #include "interpolation.h"
- #include "MainWindow.h"
- #include "ToolTip.h"
- CompressorControlDialog::CompressorControlDialog(CompressorControls* controls) :
- EffectControlDialog(controls),
- m_controls(controls),
- m_inVolAreaColor(209, 216, 228, 17),
- m_inVolColor(209, 216, 228, 100),
- m_outVolAreaColor(209, 216, 228, 30),
- m_outVolColor(209, 216, 228, 240),
- m_gainReductionColor(180, 100, 100, 210),
- m_kneeColor(39, 171, 95, 255),
- m_kneeColor2(9, 171, 160, 255),
- m_threshColor(39, 171, 95, 100),
- m_textColor(209, 216, 228, 50),
- m_graphColor(209, 216, 228, 50),
- m_resetColor(200, 100, 15, 200)
- {
- setAutoFillBackground(true);
- QPalette pal;
- pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork"));
- setPalette(pal);
- setMinimumSize(MIN_COMP_SCREEN_X, MIN_COMP_SCREEN_Y);
- resize(COMP_SCREEN_X, COMP_SCREEN_Y);
- m_graphPixmap.fill(QColor("transparent"));
- m_visPixmap.fill(QColor("transparent"));
- m_kneePixmap.fill(QColor("transparent"));
- m_kneePixmap2.fill(QColor("transparent"));
- m_miscPixmap.fill(QColor("transparent"));
- m_controlsBoxLabel = new QLabel(this);
- m_controlsBoxLabel->setPixmap(PLUGIN_NAME::getIconPixmap("controlsBox"));
- m_controlsBoxLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
- m_rmsEnabledLabel = new QLabel(this);
- m_rmsEnabledLabel->setPixmap(PLUGIN_NAME::getIconPixmap("knob_enabled"));
- m_rmsEnabledLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
- m_blendEnabledLabel = new QLabel(this);
- m_blendEnabledLabel->setPixmap(PLUGIN_NAME::getIconPixmap("knob_enabled"));
- m_blendEnabledLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
- m_lookaheadEnabledLabel = new QLabel(this);
- m_lookaheadEnabledLabel->setPixmap(PLUGIN_NAME::getIconPixmap("knob_enabled"));
- m_lookaheadEnabledLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
- m_ratioEnabledLabel = new QLabel(this);
- m_ratioEnabledLabel->setPixmap(PLUGIN_NAME::getIconPixmap("knob_enabled_large"));
- m_ratioEnabledLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
- m_thresholdKnob = new Knob(knobStyled, this);
- makeLargeKnob(m_thresholdKnob, tr("Threshold:") , " dBFS");
- m_thresholdKnob->setModel(&controls->m_thresholdModel);
- ToolTip::add(m_thresholdKnob, tr("Volume at which the compression begins to take place"));
- m_ratioKnob = new Knob(knobStyled, this);
- makeLargeKnob(m_ratioKnob, tr("Ratio:") , ":1");
- m_ratioKnob->setModel(&controls->m_ratioModel);
- ToolTip::add(m_ratioKnob, tr("How far the compressor must turn the volume down after crossing the threshold"));
- m_attackKnob = new Knob(knobStyled, this);
- makeLargeKnob(m_attackKnob, tr("Attack:") , " ms");
- m_attackKnob->setModel(&controls->m_attackModel);
- ToolTip::add(m_attackKnob, tr("Speed at which the compressor starts to compress the audio"));
- m_releaseKnob = new Knob(knobStyled, this);
- makeLargeKnob(m_releaseKnob, tr("Release:") , " ms");
- m_releaseKnob->setModel(&controls->m_releaseModel);
- ToolTip::add(m_releaseKnob, tr("Speed at which the compressor ceases to compress the audio"));
- m_kneeKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_kneeKnob, tr("Knee:") , " dB");
- m_kneeKnob->setModel(&controls->m_kneeModel);
- ToolTip::add(m_kneeKnob, tr("Smooth out the gain reduction curve around the threshold"));
- m_rangeKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_rangeKnob, tr("Range:") , " dBFS");
- m_rangeKnob->setModel(&controls->m_rangeModel);
- ToolTip::add(m_rangeKnob, tr("Maximum gain reduction"));
- m_lookaheadLengthKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_lookaheadLengthKnob, tr("Lookahead Length:") , " ms");
- m_lookaheadLengthKnob->setModel(&controls->m_lookaheadLengthModel);
- ToolTip::add(m_lookaheadLengthKnob, tr("How long the compressor has to react to the sidechain signal ahead of time"));
- m_holdKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_holdKnob, tr("Hold:") , " ms");
- m_holdKnob->setModel(&controls->m_holdModel);
- ToolTip::add(m_holdKnob, tr("Delay between attack and release stages"));
- m_rmsKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_rmsKnob, tr("RMS Size:") , "");
- m_rmsKnob->setModel(&controls->m_rmsModel);
- ToolTip::add(m_rmsKnob, tr("Size of the RMS buffer"));
- m_inBalanceKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_inBalanceKnob, tr("Input Balance:") , "");
- m_inBalanceKnob->setModel(&controls->m_inBalanceModel);
- ToolTip::add(m_inBalanceKnob, tr("Bias the input audio to the left/right or mid/side"));
- m_outBalanceKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_outBalanceKnob, tr("Output Balance:") , "");
- m_outBalanceKnob->setModel(&controls->m_outBalanceModel);
- ToolTip::add(m_outBalanceKnob, tr("Bias the output audio to the left/right or mid/side"));
- m_stereoBalanceKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_stereoBalanceKnob, tr("Stereo Balance:") , "");
- m_stereoBalanceKnob->setModel(&controls->m_stereoBalanceModel);
- ToolTip::add(m_stereoBalanceKnob, tr("Bias the sidechain signal to the left/right or mid/side"));
- m_blendKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_blendKnob, tr("Stereo Link Blend:") , "");
- m_blendKnob->setModel(&controls->m_blendModel);
- ToolTip::add(m_blendKnob, tr("Blend between unlinked/maximum/average/minimum stereo linking modes"));
- m_tiltKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_tiltKnob, tr("Tilt Gain:") , " dB");
- m_tiltKnob->setModel(&controls->m_tiltModel);
- ToolTip::add(m_tiltKnob, tr("Bias the sidechain signal to the low or high frequencies. -6 db is lowpass, 6 db is highpass."));
- m_tiltFreqKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_tiltFreqKnob, tr("Tilt Frequency:") , " Hz");
- m_tiltFreqKnob->setModel(&controls->m_tiltFreqModel);
- ToolTip::add(m_tiltFreqKnob, tr("Center frequency of sidechain tilt filter"));
- m_mixKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_mixKnob, tr("Mix:") , "%");
- m_mixKnob->setModel(&controls->m_mixModel);
- ToolTip::add(m_mixKnob, tr("Balance between wet and dry signals"));
- m_autoAttackKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_autoAttackKnob, tr("Auto Attack:") , "%");
- m_autoAttackKnob->setModel(&controls->m_autoAttackModel);
- ToolTip::add(m_autoAttackKnob, tr("Automatically control attack value depending on crest factor"));
- m_autoReleaseKnob = new Knob(knobStyled, this);
- makeSmallKnob(m_autoReleaseKnob, tr("Auto Release:") , "%");
- m_autoReleaseKnob->setModel(&controls->m_autoReleaseModel);
- ToolTip::add(m_autoReleaseKnob, tr("Automatically control release value depending on crest factor"));
- m_outFader = new EqFader(&controls->m_outGainModel,tr("Output gain"),
- this, &controls->m_outPeakL, &controls->m_outPeakR);
- m_outFader->setDisplayConversion(false);
- m_outFader->setHintText(tr("Gain"), "dBFS");
- ToolTip::add(m_outFader, tr("Output volume"));
- m_inFader = new EqFader(&controls->m_inGainModel,tr("Input gain"),
- this, &controls->m_inPeakL, &controls->m_inPeakR);
- m_inFader->setDisplayConversion(false);
- m_inFader->setHintText(tr("Gain"), "dBFS");
- ToolTip::add(m_inFader, tr("Input volume"));
- rmsButton = new PixmapButton(this, tr("Root Mean Square"));
- rmsButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("rms_sel"));
- rmsButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("rms_unsel"));
- ToolTip::add(rmsButton, tr("Use RMS of the input"));
- peakButton = new PixmapButton(this, tr("Peak"));
- peakButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("peak_sel"));
- peakButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("peak_unsel"));
- ToolTip::add(peakButton, tr("Use absolute value of the input"));
-
- rmsPeakGroup = new automatableButtonGroup(this);
- rmsPeakGroup->addButton(rmsButton);
- rmsPeakGroup->addButton(peakButton);
- rmsPeakGroup->setModel(&controls->m_peakmodeModel);
- leftRightButton = new PixmapButton(this, tr("Left/Right"));
- leftRightButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("leftright_sel"));
- leftRightButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("leftright_unsel"));
- ToolTip::add(leftRightButton, tr("Compress left and right audio"));
- midSideButton = new PixmapButton(this, tr("Mid/Side"));
- midSideButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("midside_sel"));
- midSideButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("midside_unsel"));
- ToolTip::add(midSideButton, tr("Compress mid and side audio"));
-
- leftRightMidSideGroup = new automatableButtonGroup(this);
- leftRightMidSideGroup->addButton(leftRightButton);
- leftRightMidSideGroup->addButton(midSideButton);
- leftRightMidSideGroup->setModel(&controls->m_midsideModel);
- compressButton = new PixmapButton(this, tr("Compressor"));
- compressButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("compressor_sel"));
- compressButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("compressor_unsel"));
- ToolTip::add(compressButton, tr("Compress the audio"));
- limitButton = new PixmapButton(this, tr("Limiter"));
- limitButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("limiter_sel"));
- limitButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("limiter_unsel"));
- ToolTip::add(limitButton, tr("Set Ratio to infinity (is not guaranteed to limit audio volume)"));
- compressLimitGroup = new automatableButtonGroup(this);
- compressLimitGroup->addButton(compressButton);
- compressLimitGroup->addButton(limitButton);
- compressLimitGroup->setModel(&controls->m_limiterModel);
- unlinkedButton = new PixmapButton(this, tr("Unlinked"));
- unlinkedButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("unlinked_sel"));
- unlinkedButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("unlinked_unsel"));
- ToolTip::add(unlinkedButton, tr("Compress each channel separately"));
- maximumButton = new PixmapButton(this, tr("Maximum"));
- maximumButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("maximum_sel"));
- maximumButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("maximum_unsel"));
- ToolTip::add(maximumButton, tr("Compress based on the loudest channel"));
- averageButton = new PixmapButton(this, tr("Average"));
- averageButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("average_sel"));
- averageButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("average_unsel"));
- ToolTip::add(averageButton, tr("Compress based on the averaged channel volume"));
- minimumButton = new PixmapButton(this, tr("Minimum"));
- minimumButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("minimum_sel"));
- minimumButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("minimum_unsel"));
- ToolTip::add(minimumButton, tr("Compress based on the quietest channel"));
- blendButton = new PixmapButton(this, tr("Blend"));
- blendButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("blend_sel"));
- blendButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("blend_unsel"));
- ToolTip::add(blendButton, tr("Blend between stereo linking modes"));
- stereoLinkGroup = new automatableButtonGroup(this);
- stereoLinkGroup->addButton(unlinkedButton);
- stereoLinkGroup->addButton(maximumButton);
- stereoLinkGroup->addButton(averageButton);
- stereoLinkGroup->addButton(minimumButton);
- stereoLinkGroup->addButton(blendButton);
- stereoLinkGroup->setModel(&controls->m_stereoLinkModel);
- autoMakeupButton = new PixmapButton(this, tr("Auto Makeup Gain"));
- autoMakeupButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("autogain_sel"));
- autoMakeupButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("autogain_unsel"));
- ToolTip::add(autoMakeupButton, tr("Automatically change makeup gain depending on threshold, knee, and ratio settings"));
- autoMakeupButton->setCheckable(true);
- autoMakeupButton->setModel(&controls->m_autoMakeupModel);
- auditionButton = new PixmapButton(this, tr("Soft Clip"));
- auditionButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("audition_sel"));
- auditionButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("audition_unsel"));
- ToolTip::add(auditionButton, tr("Play the delta signal"));
- auditionButton->setCheckable(true);
- auditionButton->setModel(&controls->m_auditionModel);
- feedbackButton = new PixmapButton(this, tr("Soft Clip"));
- feedbackButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("feedback_sel"));
- feedbackButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("feedback_unsel"));
- ToolTip::add(feedbackButton, tr("Use the compressor's output as the sidechain input"));
- feedbackButton->setCheckable(true);
- feedbackButton->setModel(&controls->m_feedbackModel);
- lookaheadButton = new PixmapButton(this, tr("Lookahead Enabled"));
- lookaheadButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("lookahead_sel"));
- lookaheadButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("lookahead_unsel"));
- ToolTip::add(lookaheadButton, tr("Enable Lookahead, which introduces 20 milliseconds of latency"));
- lookaheadButton->setCheckable(true);
- lookaheadButton->setModel(&controls->m_lookaheadModel);
- connect(gui->mainWindow(), SIGNAL(periodicUpdate()), this, SLOT(updateDisplay()));
- connect(&m_controls->m_peakmodeModel, SIGNAL(dataChanged()), this, SLOT(peakmodeChanged()));
- connect(&m_controls->m_stereoLinkModel, SIGNAL(dataChanged()), this, SLOT(stereoLinkChanged()));
- connect(&m_controls->m_lookaheadModel, SIGNAL(dataChanged()), this, SLOT(lookaheadChanged()));
- connect(&m_controls->m_limiterModel, SIGNAL(dataChanged()), this, SLOT(limiterChanged()));
- m_timeElapsed.start();
- peakmodeChanged();
- stereoLinkChanged();
- lookaheadChanged();
- limiterChanged();
- }
- void CompressorControlDialog::makeLargeKnob(Knob * knob, QString hint, QString unit)
- {
- knob->setHintText(hint, unit);
- knob->setFixedSize(56, 56);
- knob->setOuterRadius(23);
- knob->setInnerRadius(15);
- knob->setCenterPointX(28);
- knob->setCenterPointY(28);
- }
- void CompressorControlDialog::makeSmallKnob(Knob * knob, QString hint, QString unit)
- {
- knob->setHintText(hint, unit);
- knob->setFixedSize(30, 30);
- knob->setOuterRadius(10);
- knob->setInnerRadius(4);
- knob->setCenterPointX(15);
- knob->setCenterPointY(15);
- }
- void CompressorControlDialog::peakmodeChanged()
- {
- m_rmsKnob->setVisible(!m_controls->m_peakmodeModel.value());
- m_rmsEnabledLabel->setVisible(!m_controls->m_peakmodeModel.value());
- }
- void CompressorControlDialog::stereoLinkChanged()
- {
- m_blendKnob->setVisible(m_controls->m_stereoLinkModel.value() == 4);
- m_blendEnabledLabel->setVisible(m_controls->m_stereoLinkModel.value() == 4);
- }
- void CompressorControlDialog::lookaheadChanged()
- {
- m_lookaheadLengthKnob->setVisible(m_controls->m_lookaheadModel.value());
- m_lookaheadEnabledLabel->setVisible(m_controls->m_lookaheadModel.value());
- }
- void CompressorControlDialog::limiterChanged()
- {
- m_ratioKnob->setVisible(!m_controls->m_limiterModel.value());
- m_ratioEnabledLabel->setVisible(!m_controls->m_limiterModel.value());
- }
- void CompressorControlDialog::updateDisplay()
- {
- if (!isVisible())
- {
- m_timeElapsed.restart();
- return;
- }
- int elapsedMil = m_timeElapsed.elapsed();
- m_timeElapsed.restart();
- m_timeSinceLastUpdate += elapsedMil;
- m_compPixelMovement = int(m_timeSinceLastUpdate / COMP_MILLI_PER_PIXEL);
- m_timeSinceLastUpdate %= COMP_MILLI_PER_PIXEL;
- // Time Change / Daylight Savings Time protection
- if (!m_compPixelMovement || m_compPixelMovement <= 0)
- {
- return;
- }
- if (!m_controls->m_effect->isEnabled() || !m_controls->m_effect->isRunning())
- {
- m_controls->m_effect->m_displayPeak[0] = COMP_NOISE_FLOOR;
- m_controls->m_effect->m_displayPeak[1] = COMP_NOISE_FLOOR;
- m_controls->m_effect->m_displayGain[0] = 1;
- m_controls->m_effect->m_displayGain[1] = 1;
- }
- m_peakAvg = (m_controls->m_effect->m_displayPeak[0] + m_controls->m_effect->m_displayPeak[1]) * 0.5f;
- m_gainAvg = (m_controls->m_effect->m_displayGain[0] + m_controls->m_effect->m_displayGain[1]) * 0.5f;
- m_controls->m_effect->m_displayPeak[0] = m_controls->m_effect->m_yL[0];
- m_controls->m_effect->m_displayPeak[1] = m_controls->m_effect->m_yL[1];
- m_controls->m_effect->m_displayGain[0] = m_controls->m_effect->m_gainResult[0];
- m_controls->m_effect->m_displayGain[1] = m_controls->m_effect->m_gainResult[1];
- m_yPoint = dbfsToYPoint(ampToDbfs(m_peakAvg));
- m_yGainPoint = dbfsToYPoint(ampToDbfs(m_gainAvg));
- m_threshYPoint = dbfsToYPoint(m_controls->m_effect->m_thresholdVal);
- m_threshXPoint = m_kneeWindowSizeY - m_threshYPoint;
- drawVisPixmap();
- if (m_controls->m_effect->m_redrawKnee)
- {
- redrawKnee();
- }
- drawKneePixmap2();
- if (m_controls->m_effect->m_redrawThreshold)
- {
- drawMiscPixmap();
- }
- m_lastPoint = m_yPoint;
- m_lastGainPoint = m_yGainPoint;
- update();
- }
- void CompressorControlDialog::drawVisPixmap()
- {
- m_p.begin(&m_visPixmap);
- // Move entire display to the left
- m_p.setCompositionMode(QPainter::CompositionMode_Source);
- m_p.drawPixmap(-m_compPixelMovement, 0, m_visPixmap);
- m_p.fillRect(m_windowSizeX-m_compPixelMovement, 0, m_windowSizeX, m_windowSizeY, QColor("transparent"));
- m_p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- m_p.setRenderHint(QPainter::Antialiasing, true);
- // Draw translucent portion of input volume line
- m_p.setPen(QPen(m_inVolAreaColor, 1));
- for (int i = 0; i < m_compPixelMovement; ++i)
- {
- const int temp = linearInterpolate(m_lastPoint, m_yPoint, float(i) / float(m_compPixelMovement));
- m_p.drawLine(m_windowSizeX-m_compPixelMovement+i, temp, m_windowSizeX-m_compPixelMovement+i, m_windowSizeY);
- }
- // Draw input volume line
- m_p.setPen(QPen(m_inVolColor, 1));
- m_p.drawLine(m_windowSizeX-m_compPixelMovement-1, m_lastPoint, m_windowSizeX, m_yPoint);
- // Draw translucent portion of output volume line
- m_p.setPen(QPen(m_outVolAreaColor, 1));
- for (int i = 0; i < m_compPixelMovement; ++i)
- {
- const int temp = linearInterpolate(m_lastPoint+m_lastGainPoint, m_yPoint+m_yGainPoint, float(i) / float(m_compPixelMovement));
- m_p.drawLine(m_windowSizeX-m_compPixelMovement+i, temp, m_windowSizeX-m_compPixelMovement+i, m_windowSizeY);
- }
- // Draw output volume line
- m_p.setPen(QPen(m_outVolColor, 1));
- m_p.drawLine(m_windowSizeX-m_compPixelMovement-1, m_lastPoint+m_lastGainPoint, m_windowSizeX, m_yPoint+m_yGainPoint);
- // Draw gain reduction line
- m_p.setPen(QPen(m_gainReductionColor, 2));
- m_p.drawLine(m_windowSizeX-m_compPixelMovement-1, m_lastGainPoint, m_windowSizeX, m_yGainPoint);
- m_p.end();
- }
- void CompressorControlDialog::redrawKnee()
- {
- m_controls->m_effect->m_redrawKnee = false;
- // Start drawing knee visualizer
- m_p.begin(&m_kneePixmap);
- m_p.setRenderHint(QPainter::Antialiasing, false);
- // Clear display
- m_p.setCompositionMode(QPainter::CompositionMode_Source);
- m_p.fillRect(0, 0, m_windowSizeX, m_kneeWindowSizeY, QColor("transparent"));
- m_p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- m_p.setRenderHint(QPainter::Antialiasing, true);
- m_p.setPen(QPen(m_kneeColor, 3));
- // Limiter = infinite ratio
- float actualRatio = m_controls->m_limiterModel.value() ? 0 : m_controls->m_effect->m_ratioVal;
- // Calculate endpoints for the two straight lines
- float kneePoint1 = m_controls->m_effect->m_thresholdVal - m_controls->m_effect->m_kneeVal;
- float kneePoint2X = m_controls->m_effect->m_thresholdVal + m_controls->m_effect->m_kneeVal;
- float kneePoint2Y = (m_controls->m_effect->m_thresholdVal + (-m_controls->m_effect->m_thresholdVal * (actualRatio * (m_controls->m_effect->m_kneeVal / -m_controls->m_effect->m_thresholdVal))));
- float ratioPoint = m_controls->m_effect->m_thresholdVal + (-m_controls->m_effect->m_thresholdVal * actualRatio);
- // Draw two straight lines
- m_p.drawLine(0, m_kneeWindowSizeY, dbfsToXPoint(kneePoint1), dbfsToYPoint(kneePoint1));
- if (dbfsToXPoint(kneePoint2X) < m_kneeWindowSizeY)
- {
- m_p.drawLine(dbfsToXPoint(kneePoint2X), dbfsToYPoint(kneePoint2Y), m_kneeWindowSizeY, dbfsToYPoint(ratioPoint));
- }
- // Draw knee section
- if (m_controls->m_effect->m_kneeVal)
- {
- m_p.setPen(QPen(m_kneeColor2, 3));
- float prevPoint[2] = {kneePoint1, kneePoint1};
- float newPoint[2] = {0, 0};
- // Draw knee curve using many straight lines.
- for (int i = 0; i < COMP_KNEE_LINES; ++i)
- {
- newPoint[0] = linearInterpolate(kneePoint1, kneePoint2X, (i + 1) / (float)COMP_KNEE_LINES);
- const float temp = newPoint[0] - m_controls->m_effect->m_thresholdVal + m_controls->m_effect->m_kneeVal;
- newPoint[1] = (newPoint[0] + (actualRatio - 1) * temp * temp / (4 * m_controls->m_effect->m_kneeVal));
- m_p.drawLine(dbfsToXPoint(prevPoint[0]), dbfsToYPoint(prevPoint[1]), dbfsToXPoint(newPoint[0]), dbfsToYPoint(newPoint[1]));
- prevPoint[0] = newPoint[0];
- prevPoint[1] = newPoint[1];
- }
- }
- m_p.setRenderHint(QPainter::Antialiasing, false);
- // Erase right portion
- m_p.setCompositionMode(QPainter::CompositionMode_Source);
- m_p.fillRect(m_kneeWindowSizeX + 1, 0, m_windowSizeX, m_kneeWindowSizeY, QColor("transparent"));
- m_p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- m_p.end();
- m_p.begin(&m_kneePixmap2);
-
- m_p.setCompositionMode(QPainter::CompositionMode_Source);
- m_p.fillRect(0, 0, m_windowSizeX, m_kneeWindowSizeY, QColor("transparent"));
- m_p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- m_p.end();
- m_lastKneePoint = 0;
- }
- void CompressorControlDialog::drawKneePixmap2()
- {
- m_p.begin(&m_kneePixmap2);
- m_p.setRenderHint(QPainter::Antialiasing, false);
- int kneePoint = dbfsToXPoint(ampToDbfs(m_peakAvg));
- if (kneePoint > m_lastKneePoint)
- {
- QRectF knee2Rect = QRect(m_lastKneePoint, 0, kneePoint - m_lastKneePoint, m_kneeWindowSizeY);
- m_p.drawPixmap(knee2Rect, m_kneePixmap, knee2Rect);
- }
- else
- {
- m_p.setCompositionMode(QPainter::CompositionMode_Source);
- m_p.fillRect(kneePoint, 0, m_lastKneePoint, m_kneeWindowSizeY, QColor("transparent"));
- m_p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- }
- m_lastKneePoint = kneePoint;
- m_p.end();
- }
- void CompressorControlDialog::drawMiscPixmap()
- {
- m_p.begin(&m_miscPixmap);
- m_p.setCompositionMode(QPainter::CompositionMode_Source);
- m_p.fillRect(0, 0, m_windowSizeX, m_windowSizeY, QColor("transparent"));
- m_p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- m_p.setRenderHint(QPainter::Antialiasing, true);
- // Draw threshold lines
- m_p.setPen(QPen(m_threshColor, 2, Qt::DotLine));
- m_p.drawLine(0, m_threshYPoint, m_windowSizeX, m_threshYPoint);
- m_p.drawLine(m_threshXPoint, 0, m_threshXPoint, m_kneeWindowSizeY);
- m_p.end();
- m_controls->m_effect->m_redrawThreshold = false;
- }
- void CompressorControlDialog::paintEvent(QPaintEvent *event)
- {
- if (!isVisible())
- {
- return;
- }
- m_p.begin(this);
- m_p.setCompositionMode(QPainter::CompositionMode_Source);
- m_p.fillRect(0, 0, m_windowSizeX, m_windowSizeY, QColor("transparent"));
- m_p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- m_p.drawPixmap(0, 0, m_graphPixmap);
- m_p.drawPixmap(0, 0, m_visPixmap);
- m_p.setOpacity(0.25);
- m_p.drawPixmap(0, 0, m_kneePixmap);
- m_p.setOpacity(1);
- if (m_controls->m_effect->isEnabled() && m_controls->m_effect->isRunning())
- {
- m_p.drawPixmap(0, 0, m_kneePixmap2);
- }
- m_p.drawPixmap(0, 0, m_miscPixmap);
- m_p.end();
- }
- inline int CompressorControlDialog::dbfsToYPoint(float inDbfs)
- {
- return (-((inDbfs + m_dbRange) / m_dbRange) + 1) * m_windowSizeY;
- }
- inline int CompressorControlDialog::dbfsToXPoint(float inDbfs)
- {
- return m_kneeWindowSizeY - dbfsToYPoint(inDbfs);
- }
- void CompressorControlDialog::resizeEvent(QResizeEvent *event)
- {
- resetCompressorView();
- }
- void CompressorControlDialog::wheelEvent(QWheelEvent * event)
- {
- const float temp = m_dbRange;
- const float dbRangeNew = m_dbRange - copysignf(COMP_GRID_SPACING, event->delta());
- m_dbRange = round(qBound(COMP_GRID_SPACING, dbRangeNew, COMP_GRID_MAX) / COMP_GRID_SPACING) * COMP_GRID_SPACING;
- // Only reset view if the scolling had an effect
- if (m_dbRange != temp)
- {
- drawGraph();
- m_controls->m_effect->m_redrawKnee = true;
- m_controls->m_effect->m_redrawThreshold = true;
- }
- }
- void CompressorControlDialog::drawGraph()
- {
- m_p.begin(&m_graphPixmap);
- m_p.setRenderHint(QPainter::Antialiasing, false);
- m_p.setCompositionMode(QPainter::CompositionMode_Source);
- m_p.fillRect(0, 0, m_windowSizeX, m_windowSizeY, QColor("transparent"));
- m_p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- m_p.setPen(QPen(m_textColor, 1));
- // Arbitrary formula for increasing font size when window size increases
- m_p.setFont(QFont("Arial", qMax(int(m_windowSizeY / 1080.f * 24), 12)));
- // Redraw graph
- m_p.setPen(QPen(m_graphColor, 1));
- for (int i = 1; i < m_dbRange / COMP_GRID_SPACING + 1; ++i)
- {
- m_p.drawLine(0, dbfsToYPoint(-COMP_GRID_SPACING * i), m_windowSizeX, dbfsToYPoint(-COMP_GRID_SPACING * i));
- m_p.drawLine(dbfsToXPoint(-COMP_GRID_SPACING * i), 0, dbfsToXPoint(-COMP_GRID_SPACING * i), m_kneeWindowSizeY);
- m_p.drawText(QRectF(m_windowSizeX - 50, dbfsToYPoint(-COMP_GRID_SPACING * i), 50, 50), Qt::AlignRight | Qt::AlignTop, QString::number(i * -COMP_GRID_SPACING));
- }
- m_p.end();
- }
- void CompressorControlDialog::resetCompressorView()
- {
- m_windowSizeX = size().width();
- m_windowSizeY = size().height();
- m_kneeWindowSizeX = m_windowSizeY;
- m_kneeWindowSizeY = m_windowSizeY;
- m_controlsBoxX = (m_windowSizeX - COMP_BOX_X) * 0.5;
- m_controlsBoxY = m_windowSizeY - 40 - COMP_BOX_Y;
- m_controls->m_effect->m_redrawKnee = true;
- m_controls->m_effect->m_redrawThreshold = true;
- m_lastKneePoint = 0;
- drawGraph();
- m_p.begin(&m_visPixmap);
- m_p.setCompositionMode(QPainter::CompositionMode_Source);
- m_p.fillRect(0, 0, m_windowSizeX, m_windowSizeY, QColor("transparent"));
- m_p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- // Draw line at right side, so the sudden
- // content that the visualizer will display
- // later on won't look too ugly
- m_p.setPen(QPen(m_resetColor, 3));
- m_p.drawLine(m_windowSizeX, 0, m_windowSizeX, m_windowSizeY);
- m_p.end();
- m_controlsBoxLabel->move(m_controlsBoxX, m_controlsBoxY);
- m_rmsEnabledLabel->move(m_controlsBoxX + 429, m_controlsBoxY + 209);
- m_blendEnabledLabel->move(m_controlsBoxX + 587, m_controlsBoxY + 197);
- m_lookaheadEnabledLabel->move(m_controlsBoxX + 221, m_controlsBoxY + 135);
- m_ratioEnabledLabel->move(m_controlsBoxX + 267, m_controlsBoxY + 21);
- m_thresholdKnob->move(m_controlsBoxX + 137, m_controlsBoxY + 21);
- m_ratioKnob->move(m_controlsBoxX + 267, m_controlsBoxY + 21);
- m_attackKnob->move(m_controlsBoxX + 397, m_controlsBoxY + 21);
- m_releaseKnob->move(m_controlsBoxX + 527, m_controlsBoxY + 21);
- m_kneeKnob->move(m_controlsBoxX + 97, m_controlsBoxY + 135);
- m_rangeKnob->move(m_controlsBoxX + 159, m_controlsBoxY + 135);
- m_lookaheadLengthKnob->move(m_controlsBoxX + 221, m_controlsBoxY + 135);
- m_holdKnob->move(m_controlsBoxX + 283, m_controlsBoxY + 135);
- m_rmsKnob->move(m_controlsBoxX + 429, m_controlsBoxY + 209);
- m_inBalanceKnob->move(m_controlsBoxX + 27, m_controlsBoxY + 219);
- m_outBalanceKnob->move(m_controlsBoxX + 662, m_controlsBoxY + 219);
- m_stereoBalanceKnob->move(m_controlsBoxX + 522, m_controlsBoxY + 137);
- m_blendKnob->move(m_controlsBoxX + 587, m_controlsBoxY + 197);
- m_tiltKnob->move(m_controlsBoxX + 364, m_controlsBoxY + 138);
- m_tiltFreqKnob->move(m_controlsBoxX + 415, m_controlsBoxY + 138);
- m_mixKnob->move(m_controlsBoxX + 27, m_controlsBoxY + 13);
- m_outFader->move(m_controlsBoxX + 666, m_controlsBoxY + 91);
- m_inFader->move(m_controlsBoxX + 31, m_controlsBoxY + 91);
- rmsButton->move(m_controlsBoxX + 337, m_controlsBoxY + 231);
- peakButton->move(m_controlsBoxX + 337, m_controlsBoxY + 248);
- leftRightButton->move(m_controlsBoxX + 220, m_controlsBoxY + 231);
- midSideButton->move(m_controlsBoxX + 220, m_controlsBoxY + 248);
- compressButton->move(m_controlsBoxX + 98, m_controlsBoxY + 231);
- limitButton->move(m_controlsBoxX + 98, m_controlsBoxY + 248);
- unlinkedButton->move(m_controlsBoxX + 495, m_controlsBoxY + 180);
- maximumButton->move(m_controlsBoxX + 495, m_controlsBoxY + 197);
- averageButton->move(m_controlsBoxX + 495, m_controlsBoxY + 214);
- minimumButton->move(m_controlsBoxX + 495, m_controlsBoxY + 231);
- blendButton->move(m_controlsBoxX + 495, m_controlsBoxY + 248);
- autoMakeupButton->move(m_controlsBoxX + 220, m_controlsBoxY + 206);
- auditionButton->move(m_controlsBoxX + 658, m_controlsBoxY + 14);
- feedbackButton->move(m_controlsBoxX + 98, m_controlsBoxY + 206);
- m_autoAttackKnob->move(m_controlsBoxX + 460, m_controlsBoxY + 38);
- m_autoReleaseKnob->move(m_controlsBoxX + 590, m_controlsBoxY + 38);
- lookaheadButton->move(m_controlsBoxX + 202, m_controlsBoxY + 171);
- }
|