From e83d44a56e6483b25f3a19bfb2558bacdfe1b4f4 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 29 Aug 2019 19:59:03 -0600 Subject: [PATCH] Add Disintegrator effect --- plugins/CMakeLists.txt | 1 + plugins/Disintegrator/CMakeLists.txt | 3 + plugins/Disintegrator/Disintegrator.cpp | 279 ++++++++++++++++++ plugins/Disintegrator/Disintegrator.h | 84 ++++++ .../DisintegratorControlDialog.cpp | 97 ++++++ .../DisintegratorControlDialog.h | 60 ++++ .../Disintegrator/DisintegratorControls.cpp | 73 +++++ plugins/Disintegrator/DisintegratorControls.h | 79 +++++ plugins/Disintegrator/OLD 1/CMakeLists.txt | 3 + plugins/Disintegrator/OLD 1/Disintegrator.cpp | 245 +++++++++++++++ plugins/Disintegrator/OLD 1/Disintegrator.h | 67 +++++ .../OLD 1/DisintegratorControlDialog.cpp | 70 +++++ .../OLD 1/DisintegratorControlDialog.h | 45 +++ .../OLD 1/DisintegratorControls.cpp | 69 +++++ .../OLD 1/DisintegratorControls.h | 78 +++++ plugins/Disintegrator/OLD 1/artwork.png | Bin 0 -> 7739 bytes plugins/Disintegrator/OLD 1/logo.png | Bin 0 -> 774 bytes plugins/Disintegrator/artwork.png | Bin 0 -> 7739 bytes plugins/Disintegrator/logo.png | Bin 0 -> 774 bytes 19 files changed, 1253 insertions(+) create mode 100644 plugins/Disintegrator/CMakeLists.txt create mode 100644 plugins/Disintegrator/Disintegrator.cpp create mode 100644 plugins/Disintegrator/Disintegrator.h create mode 100644 plugins/Disintegrator/DisintegratorControlDialog.cpp create mode 100644 plugins/Disintegrator/DisintegratorControlDialog.h create mode 100644 plugins/Disintegrator/DisintegratorControls.cpp create mode 100644 plugins/Disintegrator/DisintegratorControls.h create mode 100644 plugins/Disintegrator/OLD 1/CMakeLists.txt create mode 100644 plugins/Disintegrator/OLD 1/Disintegrator.cpp create mode 100644 plugins/Disintegrator/OLD 1/Disintegrator.h create mode 100644 plugins/Disintegrator/OLD 1/DisintegratorControlDialog.cpp create mode 100644 plugins/Disintegrator/OLD 1/DisintegratorControlDialog.h create mode 100644 plugins/Disintegrator/OLD 1/DisintegratorControls.cpp create mode 100644 plugins/Disintegrator/OLD 1/DisintegratorControls.h create mode 100644 plugins/Disintegrator/OLD 1/artwork.png create mode 100644 plugins/Disintegrator/OLD 1/logo.png create mode 100644 plugins/Disintegrator/artwork.png create mode 100644 plugins/Disintegrator/logo.png diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 4f139f8b3..e12783bab 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -49,6 +49,7 @@ IF("${PLUGIN_LIST}" STREQUAL "") carlarack CrossoverEQ Delay + Disintegrator DualFilter dynamics_processor Eq diff --git a/plugins/Disintegrator/CMakeLists.txt b/plugins/Disintegrator/CMakeLists.txt new file mode 100644 index 000000000..7642f8138 --- /dev/null +++ b/plugins/Disintegrator/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(disintegrator Disintegrator.cpp DisintegratorControls.cpp DisintegratorControlDialog.cpp MOCFILES DisintegratorControls.h DisintegratorControlDialog.h EMBEDDED_RESOURCES artwork.png logo.png) diff --git a/plugins/Disintegrator/Disintegrator.cpp b/plugins/Disintegrator/Disintegrator.cpp new file mode 100644 index 000000000..6531f9468 --- /dev/null +++ b/plugins/Disintegrator/Disintegrator.cpp @@ -0,0 +1,279 @@ +/* + * Disintegrator.cpp + * + * Copyright (c) 2019 Lost Robot + * + * 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 "Disintegrator.h" + +#include "embed.h" +#include "lmms_math.h" +#include "plugin_export.h" + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT disintegrator_plugin_descriptor = +{ + STRINGIFY(PLUGIN_NAME), + "Disintegrator", + QT_TRANSLATE_NOOP("pluginBrowser", "A delay modulation effect for creating very aggressive digital distortion."), + "Lost Robot ", + 0x0100, + Plugin::Effect, + new PluginPixmapLoader("logo"), + NULL, + NULL +} ; + +} + + + +DisintegratorEffect::DisintegratorEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key) : + Effect(&disintegrator_plugin_descriptor, parent, key), + m_disintegratorControls(this) +{ + for (int a = 0; a < 200; ++a) + { + for (int b = 0; b < 2; ++b) + { + m_inBuf[b].push_back(0); + } + } +} + + + + +DisintegratorEffect::~DisintegratorEffect() +{ +} + + + + +bool DisintegratorEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) +{ + if (!isEnabled() || !isRunning ()) + { + return false; + } + + double outSum = 0.0; + const float d = dryLevel(); + const float w = wetLevel(); + + const ValueBuffer * lowCutBuf = m_disintegratorControls.m_lowCutModel.valueBuffer(); + const ValueBuffer * highCutBuf = m_disintegratorControls.m_highCutModel.valueBuffer(); + const ValueBuffer * amountBuf = m_disintegratorControls.m_amountModel.valueBuffer(); + const ValueBuffer * typeBuf = m_disintegratorControls.m_typeModel.valueBuffer(); + const ValueBuffer * freqBuf = m_disintegratorControls.m_lowCutModel.valueBuffer(); + + sample_rate_t sample_rate = Engine::mixer()->processingSampleRate(); + + for (fpp_t f = 0; f < frames; ++f) + { + const float lowCut = lowCutBuf ? lowCutBuf->value(f) : m_disintegratorControls.m_lowCutModel.value(); + const float highCut = highCutBuf ? highCutBuf->value(f) : m_disintegratorControls.m_highCutModel.value(); + const float amount = amountBuf ? amountBuf->value(f) : m_disintegratorControls.m_amountModel.value(); + const int type = typeBuf ? typeBuf->value(f) : m_disintegratorControls.m_typeModel.value(); + const float freq = freqBuf ? freqBuf->value(f) : m_disintegratorControls.m_freqModel.value(); + + outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; + + sample_t s[2] = {buf[f][0], buf[f][1]}; + + ++m_inBufLoc; + if (m_inBufLoc >= 200) + { + m_inBufLoc = 0; + } + + m_inBuf[0][m_inBufLoc] = s[0]; + m_inBuf[1][m_inBufLoc] = s[1]; + + float newInBufLoc[2] = {0, 0}; + float newInBufLocFrac[2] = {0, 0}; + switch (type) + { + case 0:// Mono Noise + { + newInBufLoc[0] = fast_rand() / (float)FAST_RAND_MAX; + + calcHighpassFilter(newInBufLoc[0], newInBufLoc[0], 0, lowCut, 0.707, sample_rate); + calcLowpassFilter(newInBufLoc[0], newInBufLoc[0], 0, highCut, 0.707, sample_rate); + + newInBufLoc[0] = realfmod(m_inBufLoc - newInBufLoc[0] * amount, 200); + newInBufLoc[1] = newInBufLoc[0]; + + newInBufLocFrac[0] = fmod(newInBufLoc[0], 1); + newInBufLocFrac[1] = newInBufLocFrac[0]; + + break; + } + case 1:// Stereo Noise + { + newInBufLoc[0] = fast_rand() / (float)FAST_RAND_MAX; + newInBufLoc[1] = fast_rand() / (float)FAST_RAND_MAX; + + calcHighpassFilter(newInBufLoc[0], newInBufLoc[0], 0, lowCut, 0.707, sample_rate); + calcHighpassFilter(newInBufLoc[1], newInBufLoc[1], 1, lowCut, 0.707, sample_rate); + calcLowpassFilter(newInBufLoc[0], newInBufLoc[0], 0, highCut, 0.707, sample_rate); + calcLowpassFilter(newInBufLoc[1], newInBufLoc[1], 1, highCut, 0.707, sample_rate); + + newInBufLoc[0] = realfmod(m_inBufLoc - newInBufLoc[0] * amount, 200); + newInBufLoc[1] = realfmod(m_inBufLoc - newInBufLoc[1] * amount, 200); + + newInBufLocFrac[0] = fmod(newInBufLoc[0], 1); + newInBufLocFrac[1] = fmod(newInBufLoc[1], 1); + + break; + } + case 2:// Sine Wave + { + m_sineLoc = fmod(m_sineLoc + (freq / (float)sample_rate * F_2PI), F_2PI); + + newInBufLoc[0] = (sin(m_sineLoc) + 1) * 0.5f; + + newInBufLoc[0] = realfmod(m_inBufLoc - newInBufLoc[0] * amount, 200); + newInBufLoc[1] = newInBufLoc[0]; + + newInBufLocFrac[0] = fmod(newInBufLoc[0], 1); + newInBufLocFrac[1] = newInBufLocFrac[0]; + + break; + } + } + + for (int b = 0; b < 2; ++b) + { + if (fmod(newInBufLoc[b], 1) == 0) + { + s[b] = m_inBuf[b][newInBufLoc[b]]; + } + else + { + if (newInBufLoc[b] < 199) + { + s[b] = m_inBuf[b][floor(newInBufLoc[b])] * (1 - newInBufLocFrac[b]) + m_inBuf[b][ceil(newInBufLoc[b])] * newInBufLocFrac[b]; + } + else + { + s[b] = m_inBuf[b][199] * (1 - newInBufLocFrac[b]) + m_inBuf[b][0] * newInBufLocFrac[b]; + } + } + } + + buf[f][0] = d * buf[f][0] + w * s[0]; + buf[f][1] = d * buf[f][1] + w * s[1]; + } + + checkGate(outSum / frames); + + return isRunning(); +} + + + +inline void DisintegratorEffect::calcLowpassFilter(sample_t &outSamp, sample_t inSamp, int which, float lpCutoff, float resonance, sample_rate_t Fs) +{ + if (m_prevLPCutoff[which] != lpCutoff) + { + m_prevLPCutoff[which] = lpCutoff; + const float w0 = D_2PI * lpCutoff / Fs; + const float tempCosW0 = cos(w0); + const float alpha = sin(w0) / 0.3535f; + + m_LPa0 = 1 + alpha; + m_LPb0 = (1 - tempCosW0) * 0.5f; + m_LPb1 = 1 - tempCosW0; + m_LPa1 = -(2 * tempCosW0); + m_LPa2 = 1 - alpha; + } + + m_filtLPY[which][0] = (m_LPb0 * (inSamp + m_filtLPX[which][2]) + m_LPb1 * m_filtLPX[which][1] - m_LPa1 * m_filtLPY[which][1] - m_LPa2 * m_filtLPY[which][2]) / m_LPa0; + + m_filtLPX[which][2] = m_filtLPX[which][1]; + m_filtLPX[which][1] = inSamp; + m_filtLPY[which][2] = m_filtLPY[which][1]; + m_filtLPY[which][1] = m_filtLPY[which][0]; + + outSamp = m_filtLPY[which][0]; +} + + + +inline void DisintegratorEffect::calcHighpassFilter(sample_t &outSamp, sample_t inSamp, int which, float hpCutoff, float resonance, sample_rate_t Fs) +{ + if (m_prevHPCutoff[which] != hpCutoff) + { + m_prevHPCutoff[which] = hpCutoff; + const float w0 = D_2PI * hpCutoff / Fs; + const float tempCosW0 = cos(w0); + const float alpha = sin(w0) / 0.3535f; + + m_HPa0 = 1 + alpha; + m_HPb0 = (1 + tempCosW0) * 0.5f; + m_HPb1 = -(1 + tempCosW0); + m_HPa1 = -2 * tempCosW0; + m_HPa2 = 1 - alpha; + } + + m_filtHPY[which][0] = (m_HPb0 * (inSamp + m_filtHPX[which][2]) + m_HPb1 * m_filtHPX[which][1] - m_HPa1 * m_filtHPY[which][1] - m_HPa2 * m_filtHPY[which][2]) / m_HPa0; + + m_filtHPX[which][2] = m_filtHPX[which][1]; + m_filtHPX[which][1] = inSamp; + m_filtHPY[which][2] = m_filtHPY[which][1]; + m_filtHPY[which][1] = m_filtHPY[which][0]; + + outSamp = m_filtHPY[which][0]; +} + + + +// Takes input of original Hz and the number of cents to detune it by, and returns the detuned result in Hz. +inline float DisintegratorEffect::detuneWithOctaves(float pitchValue, float detuneValue) +{ + return pitchValue * std::exp2(detuneValue); +} + + + +// Handles negative values properly, unlike fmod. +inline float DisintegratorEffect::realfmod(float k, float n) +{ + return ((k = fmod(k,n)) < 0) ? k+n : k; +} + + + +extern "C" +{ + +// necessary for getting instance out of shared lib +PLUGIN_EXPORT Plugin * lmms_plugin_main(Model* parent, void* data) +{ + return new DisintegratorEffect(parent, static_cast(data)); +} + +} + diff --git a/plugins/Disintegrator/Disintegrator.h b/plugins/Disintegrator/Disintegrator.h new file mode 100644 index 000000000..a206e4304 --- /dev/null +++ b/plugins/Disintegrator/Disintegrator.h @@ -0,0 +1,84 @@ +/* + * Disintegrator.h + * + * Copyright (c) 2019 Lost Robot + * + * 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. + * + */ + + +#ifndef DISINTEGRATOR_H +#define DISINTEGRATOR_H + +#include "DisintegratorControls.h" + +#include "Effect.h" +#include "ValueBuffer.h" + +class DisintegratorEffect : public Effect +{ +public: + DisintegratorEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key); + virtual ~DisintegratorEffect(); + virtual bool processAudioBuffer(sampleFrame* buf, const fpp_t frames); + + virtual EffectControls* controls() + { + return &m_disintegratorControls; + } + + inline float realfmod(float k, float n); + inline float detuneWithOctaves(float pitchValue, float detuneValue); + + inline void calcLowpassFilter(sample_t &outSamp, sample_t inSamp, int which, float lpCutoff, float resonance, sample_rate_t Fs); + inline void calcHighpassFilter(sample_t &outSamp, sample_t inSamp, int which, float lpCutoff, float resonance, sample_rate_t Fs); + + float m_filtLPX[2][3] = {{0}};// [filter number][samples back in time] + float m_filtLPY[2][3] = {{0}};// [filter number][samples back in time] + float m_prevLPCutoff[2] = {0}; + + float m_LPa0; + float m_LPb0; + float m_LPb1; + float m_LPa1; + float m_LPa2; + + float m_filtHPX[2][3] = {{0}};// [filter number][samples back in time] + float m_filtHPY[2][3] = {{0}};// [filter number][samples back in time] + float m_prevHPCutoff[2] = {0}; + + float m_HPa0; + float m_HPb0; + float m_HPb1; + float m_HPa1; + float m_HPa2; + +private: + DisintegratorControls m_disintegratorControls; + + std::vector m_inBuf[2]; + int m_inBufLoc = 0; + + float m_sineLoc = 0; + + friend class DisintegratorControls; + +} ; + +#endif diff --git a/plugins/Disintegrator/DisintegratorControlDialog.cpp b/plugins/Disintegrator/DisintegratorControlDialog.cpp new file mode 100644 index 000000000..a680f3c33 --- /dev/null +++ b/plugins/Disintegrator/DisintegratorControlDialog.cpp @@ -0,0 +1,97 @@ +/* + * DisintegratorControlDialog.cpp + * + * Copyright (c) 2019 Lost Robot + * + * 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 + +#include "DisintegratorControlDialog.h" +#include "DisintegratorControls.h" + +#include "embed.h" +#include "gui_templates.h" + + + +DisintegratorControlDialog::DisintegratorControlDialog(DisintegratorControls* controls) : + EffectControlDialog(controls) +{ + m_controls = controls; + + setAutoFillBackground(true); + QPalette pal; + pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork")); + setPalette(pal); + setFixedSize(179, 97); + + m_lowCutKnob = new Knob(knobBright_26, this); + m_lowCutKnob -> move(70, 10); + m_lowCutKnob->setModel(&m_controls->m_lowCutModel); + m_lowCutKnob->setLabel(tr("LOW CUT")); + m_lowCutKnob->setHintText(tr("Low Cut:"), " Hz"); + + m_highCutKnob = new Knob(knobBright_26, this); + m_highCutKnob -> move(125, 10); + m_highCutKnob->setModel(&m_controls->m_highCutModel); + m_highCutKnob->setLabel(tr("HIGH CUT")); + m_highCutKnob->setHintText(tr("High Cut:"), " Hz"); + + m_amountKnob = new Knob(knobBright_26, this); + m_amountKnob -> move(15, 10); + m_amountKnob -> setVolumeKnob(true); + m_amountKnob->setModel(&m_controls->m_amountModel); + m_amountKnob->setLabel(tr("AMOUNT")); + m_amountKnob->setHintText(tr("Amount:"), " samples"); + + m_typeBox = new ComboBox(this); + m_typeBox->setGeometry(1000, 5, 149, 22); + m_typeBox->setFont(pointSize<8>(m_typeBox->font())); + m_typeBox->move(14, 65); + m_typeBox->setModel(&m_controls->m_typeModel); + + m_freqKnob = new Knob(knobBright_26, this); + m_freqKnob -> move(132, 10); + m_freqKnob->setModel(&m_controls->m_freqModel); + m_freqKnob->setLabel(tr("FREQ")); + m_freqKnob->setHintText(tr("Frequency:"), " Hz"); + + connect(&m_controls->m_typeModel, SIGNAL(dataChanged()), this, SLOT(updateKnobVisibility())); + emit m_controls->m_typeModel.dataChanged();// Needed to update knobs when view is opened +} + + + +void DisintegratorControlDialog::updateKnobVisibility() +{ + if (m_controls->m_typeModel.value() == 2) + { + m_lowCutKnob->hide(); + m_highCutKnob->hide(); + m_freqKnob->show(); + } + else + { + m_lowCutKnob->show(); + m_highCutKnob->show(); + m_freqKnob->hide(); + } +} diff --git a/plugins/Disintegrator/DisintegratorControlDialog.h b/plugins/Disintegrator/DisintegratorControlDialog.h new file mode 100644 index 000000000..2c9938318 --- /dev/null +++ b/plugins/Disintegrator/DisintegratorControlDialog.h @@ -0,0 +1,60 @@ +/* + * DisintegratorControlDialog.h + * + * Copyright (c) 2019 Lost Robot + * + * 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. + * + */ + +#ifndef DISINTEGRATOR_CONTROL_DIALOG_H +#define DISINTEGRATOR_CONTROL_DIALOG_H + +#include "ComboBox.h" +#include "EffectControlDialog.h" +#include "Knob.h" + + +class DisintegratorControls; + + +class DisintegratorControlDialog : public EffectControlDialog +{ + Q_OBJECT +public: + DisintegratorControlDialog(DisintegratorControls* controls); + DisintegratorControls * m_controls; + + virtual ~DisintegratorControlDialog() + { + } + +private slots: + void updateKnobVisibility(); + +private: + Knob * m_lowCutKnob; + Knob * m_highCutKnob; + Knob * m_amountKnob; + ComboBox * m_typeBox; + Knob * m_freqKnob; + + friend class DisintegratorControls; +}; + +#endif diff --git a/plugins/Disintegrator/DisintegratorControls.cpp b/plugins/Disintegrator/DisintegratorControls.cpp new file mode 100644 index 000000000..547b962b3 --- /dev/null +++ b/plugins/Disintegrator/DisintegratorControls.cpp @@ -0,0 +1,73 @@ +/* + * DisintegratorControls.cpp + * + * Copyright (c) 2019 Lost Robot + * + * 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 + +#include "DisintegratorControls.h" +#include "Disintegrator.h" + +#include "Engine.h" +#include "Song.h" + + +DisintegratorControls::DisintegratorControls(DisintegratorEffect* effect) : + EffectControls(effect), + m_effect(effect), + m_lowCutModel(2.0f, 2.0f, 21050.0f, 0.01f, this, tr("Low Cut")), + m_highCutModel(21050.0f, 2.0f, 21050.0f, 0.01f, this, tr("High Cut")), + m_amountModel(30.0f, 0.0f, 200.0f, 0.01f, this, tr("Amount")), + m_typeModel(this, tr("Type")), + m_freqModel(100.0f, 2.0f, 21050.0f, 0.01f, this, tr("Frequency")) +{ + m_lowCutModel.setScaleLogarithmic(true); + m_highCutModel.setScaleLogarithmic(true); + m_amountModel.setScaleLogarithmic(true); + m_freqModel.setScaleLogarithmic(true); + + m_typeModel.addItem(tr("Mono Noise")); + m_typeModel.addItem(tr("Stereo Noise")); + m_typeModel.addItem(tr("Sine Wave")); +} + + +void DisintegratorControls::saveSettings(QDomDocument& doc, QDomElement& _this) +{ + m_lowCutModel.saveSettings(doc, _this, "lowCut"); + m_highCutModel.saveSettings(doc, _this, "highCut"); + m_amountModel.saveSettings(doc, _this, "amount"); + m_typeModel.saveSettings(doc, _this, "type"); + m_freqModel.saveSettings(doc, _this, "freq"); +} + + + +void DisintegratorControls::loadSettings(const QDomElement& _this) +{ + m_lowCutModel.loadSettings(_this, "lowCut"); + m_highCutModel.loadSettings(_this, "highCut"); + m_amountModel.loadSettings(_this, "amount"); + m_typeModel.loadSettings(_this, "type"); + m_freqModel.loadSettings(_this, "freq"); +} diff --git a/plugins/Disintegrator/DisintegratorControls.h b/plugins/Disintegrator/DisintegratorControls.h new file mode 100644 index 000000000..c8611cf92 --- /dev/null +++ b/plugins/Disintegrator/DisintegratorControls.h @@ -0,0 +1,79 @@ +/* + * DisintegratorControls.h + * + * Copyright (c) 2019 Lost Robot + * + * 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. + * + */ + +#ifndef DISINTEGRATOR_CONTROLS_H +#define DISINTEGRATOR_CONTROLS_H + +#include "DisintegratorControlDialog.h" + +#include "ComboBox.h" +#include "EffectControls.h" +#include "Knob.h" + + +class DisintegratorEffect; + + +class DisintegratorControls : public EffectControls +{ + Q_OBJECT +public: + DisintegratorControls(DisintegratorEffect* effect); + virtual ~DisintegratorControls() + { + } + + virtual void saveSettings(QDomDocument & _doc, QDomElement & _parent); + virtual void loadSettings(const QDomElement & _this); + inline virtual QString nodeName() const + { + return "DisintegratorControls"; + } + + virtual int controlCount() + { + return 5; + } + + virtual EffectControlDialog* createView() + { + m_effectView = new DisintegratorControlDialog(this); + return m_effectView; + } + +private: + DisintegratorEffect* m_effect; + DisintegratorControlDialog * m_effectView; + + FloatModel m_lowCutModel; + FloatModel m_highCutModel; + FloatModel m_amountModel; + ComboBoxModel m_typeModel; + FloatModel m_freqModel; + + friend class DisintegratorControlDialog; + friend class DisintegratorEffect; +} ; + +#endif diff --git a/plugins/Disintegrator/OLD 1/CMakeLists.txt b/plugins/Disintegrator/OLD 1/CMakeLists.txt new file mode 100644 index 000000000..7642f8138 --- /dev/null +++ b/plugins/Disintegrator/OLD 1/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(disintegrator Disintegrator.cpp DisintegratorControls.cpp DisintegratorControlDialog.cpp MOCFILES DisintegratorControls.h DisintegratorControlDialog.h EMBEDDED_RESOURCES artwork.png logo.png) diff --git a/plugins/Disintegrator/OLD 1/Disintegrator.cpp b/plugins/Disintegrator/OLD 1/Disintegrator.cpp new file mode 100644 index 000000000..1f4139dc9 --- /dev/null +++ b/plugins/Disintegrator/OLD 1/Disintegrator.cpp @@ -0,0 +1,245 @@ +/* + * Disintegrator.cpp + * + * Copyright (c) 2019 Lost Robot + * + * 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 "Disintegrator.h" + +#include "embed.h" +#include "plugin_export.h" +#include "lmms_math.h" + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT disintegrator_plugin_descriptor = +{ + STRINGIFY( PLUGIN_NAME ), + "Disintegrator", + QT_TRANSLATE_NOOP( "pluginBrowser", "A plugin generated by Lost Robot's LMMS Development Package. This is your plugin description. You should change this." ), + "Lost Robot ", + 0x0100, + Plugin::Effect, + new PluginPixmapLoader("logo"), + NULL, + NULL +} ; + +} + + + +DisintegratorEffect::DisintegratorEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ) : + Effect( &disintegrator_plugin_descriptor, parent, key ), + m_disintegratorControls( this ) +{ + for( int a = 0; a < 100; ++a ) + { + for( int b = 0; b < 2; ++b ) + { + inBuf[b].push_back(0); + } + } +} + + + + +DisintegratorEffect::~DisintegratorEffect() +{ +} + + + + +bool DisintegratorEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) +{ + if( !isEnabled() || !isRunning () ) + { + return( false ); + } + + double outSum = 0.0; + const float d = dryLevel(); + const float w = wetLevel(); + + // ==TAG== MAKEVALUEBUFFERS ==TAG== // + const ValueBuffer * volBuf = m_disintegratorControls.m_volumeModel.valueBuffer(); + const ValueBuffer * panBuf = m_disintegratorControls.m_panModel.valueBuffer(); + const ValueBuffer * leftBuf = m_disintegratorControls.m_leftModel.valueBuffer(); + const ValueBuffer * rightBuf = m_disintegratorControls.m_rightModel.valueBuffer(); + // ==TAG== ENDMAKEVALUEBUFFERS ==TAG== // + + for( fpp_t f = 0; f < frames; ++f ) + { + // ==TAG== EVALUATEVALUEBUFFERS ==TAG== // + const float vol = volBuf ? volBuf->value( f ) : m_disintegratorControls.m_volumeModel.value(); + const float pan = panBuf ? panBuf->value( f ) : m_disintegratorControls.m_panModel.value(); + const float left = leftBuf ? leftBuf->value( f ) : m_disintegratorControls.m_leftModel.value(); + const float right = rightBuf ? rightBuf->value( f ) : m_disintegratorControls.m_rightModel.value(); + // ==TAG== ENDEVALUATEVALUEBUFFERS ==TAG== // + + outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; + + sample_t s[2] = { buf[f][0], buf[f][1] }; + + ++inBufLoc; + if( inBufLoc >= 100 ) + { + inBufLoc = 0; + } + + inBuf[0][inBufLoc] = s[0]; + inBuf[1][inBufLoc] = s[1]; + + float newInBufLoc[2]; + newInBufLoc[0] = fast_rand() / (float)FAST_RAND_MAX; + newInBufLoc[1] = fast_rand() / (float)FAST_RAND_MAX; + + calcHighpassFilter( newInBufLoc[0], newInBufLoc[0], 0, vol, 0.707, Engine::mixer()->processingSampleRate() ); + calcHighpassFilter( newInBufLoc[1], newInBufLoc[1], 1, vol, 0.707, Engine::mixer()->processingSampleRate() ); + calcLowpassFilter( newInBufLoc[0], newInBufLoc[0], 0, pan, 0.707, Engine::mixer()->processingSampleRate() ); + calcLowpassFilter( newInBufLoc[1], newInBufLoc[1], 1, pan, 0.707, Engine::mixer()->processingSampleRate() ); + + newInBufLoc[0] = realfmod(inBufLoc - newInBufLoc[0] * left, 100); + newInBufLoc[1] = realfmod(inBufLoc - newInBufLoc[1] * left, 100); + + float newInBufLocFrac[2]; + newInBufLocFrac[0] = fmod(newInBufLoc[0], 1); + newInBufLocFrac[1] = fmod(newInBufLoc[1], 1); + + if( newInBufLoc[0] < 99 ) + { + s[0] = inBuf[0][floor(newInBufLoc[0])] * (1 - newInBufLocFrac[0]) + inBuf[0][ceil(newInBufLoc[0])] * newInBufLocFrac[0]; + } + else + { + s[0] = inBuf[0][99] * (1 - newInBufLocFrac[0]) + inBuf[0][0] * newInBufLocFrac[0]; + } + + if( newInBufLoc[1] < 99 ) + { + s[1] = inBuf[1][floor(newInBufLoc[1])] * (1 - newInBufLocFrac[1]) + inBuf[1][ceil(newInBufLoc[1])] * newInBufLocFrac[1]; + } + else + { + s[1] = inBuf[1][99] * (1 - newInBufLocFrac[1]) + inBuf[1][0] * newInBufLocFrac[1]; + } + + buf[f][0] = d * buf[f][0] + w * s[0]; + buf[f][1] = d * buf[f][1] + w * s[1]; + } + + checkGate( outSum / frames ); + + return isRunning(); +} + + + +inline void DisintegratorEffect::calcLowpassFilter( sample_t &outSamp, sample_t inSamp, int which, float lpCutoff, float resonance, sample_rate_t Fs ) +{ + const float m_w0 = D_2PI * lpCutoff / Fs; + + const float m_tempCosW0 = cos(m_w0); + const float m_alpha = sin(m_w0) / ( resonance / 2.f ); + const float m_b0 = (1 - m_tempCosW0) * 0.5f; + const float m_b1 = 1 - m_tempCosW0; + const float m_b2 = m_b0; + const float m_a0 = 1 + m_alpha; + const float m_a1 = -2 * m_tempCosW0; + const float m_a2 = 1 - m_alpha; + + const float m_temp1 = m_b0/m_a0; + const float m_temp2 = m_b1/m_a0; + const float m_temp3 = m_b2/m_a0; + const float m_temp4 = m_a1/m_a0; + const float m_temp5 = m_a2/m_a0; + filtLPY[which][0] = m_temp1*inSamp + m_temp2*filtLPX[which][1] + m_temp3*filtLPX[which][2] - m_temp4*filtLPY[which][1] - m_temp5*filtLPY[which][2]; + + filtLPX[which][2] = filtLPX[which][1]; + filtLPX[which][1] = inSamp; + filtLPY[which][2] = filtLPY[which][1]; + filtLPY[which][1] = filtLPY[which][0]; + + outSamp = filtLPY[which][0]; +} + + + +inline void DisintegratorEffect::calcHighpassFilter( sample_t &outSamp, sample_t inSamp, int which, float hpCutoff, float resonance, sample_rate_t Fs ) +{ + const float m_w0 = D_2PI * hpCutoff / Fs; + + const float m_tempCosW0 = cos(m_w0); + const float m_alpha = sin(m_w0) / ( resonance / 2.f ); + const float m_b0 = (1 + m_tempCosW0) * 0.5f; + const float m_b1 = -(1 + m_tempCosW0); + const float m_b2 = m_b0; + const float m_a0 = 1 + m_alpha; + const float m_a1 = -2 * m_tempCosW0; + const float m_a2 = 1 - m_alpha; + + const float m_temp1 = m_b0/m_a0; + const float m_temp2 = m_b1/m_a0; + const float m_temp3 = m_b2/m_a0; + const float m_temp4 = m_a1/m_a0; + const float m_temp5 = m_a2/m_a0; + filtHPY[which][0] = m_temp1*inSamp + m_temp2*filtHPX[which][1] + m_temp3*filtHPX[which][2] - m_temp4*filtHPY[which][1] - m_temp5*filtHPY[which][2]; + + filtHPX[which][2] = filtHPX[which][1]; + filtHPX[which][1] = inSamp; + filtHPY[which][2] = filtHPY[which][1]; + filtHPY[which][1] = filtHPY[which][0]; + + outSamp = filtHPY[which][0]; +} + + + +// Takes input of original Hz and the number of cents to detune it by, and returns the detuned result in Hz. +inline float DisintegratorEffect::detuneWithOctaves(float pitchValue, float detuneValue) +{ + return pitchValue * std::exp2(detuneValue); +} + + + +// Handles negative values properly, unlike fmod. +inline float DisintegratorEffect::realfmod(float k, float n) +{ + return ((k = fmod(k,n)) < 0) ? k+n : k; +} + + + +extern "C" +{ + +// necessary for getting instance out of shared lib +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* parent, void* data ) +{ + return new DisintegratorEffect( parent, static_cast( data ) ); +} + +} + diff --git a/plugins/Disintegrator/OLD 1/Disintegrator.h b/plugins/Disintegrator/OLD 1/Disintegrator.h new file mode 100644 index 000000000..80b1ee3cc --- /dev/null +++ b/plugins/Disintegrator/OLD 1/Disintegrator.h @@ -0,0 +1,67 @@ +/* + * Disintegrator.h + * + * Copyright (c) 2019 Lost Robot + * + * 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. + * + */ + + +#ifndef DISINTEGRATOR_H +#define DISINTEGRATOR_H + +#include "Effect.h" +#include "DisintegratorControls.h" +#include "ValueBuffer.h" + +class DisintegratorEffect : public Effect +{ +public: + DisintegratorEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ); + virtual ~DisintegratorEffect(); + virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ); + + virtual EffectControls* controls() + { + return &m_disintegratorControls; + } + + inline float realfmod(float k, float n); + inline float detuneWithOctaves(float pitchValue, float detuneValue); + + inline void calcLowpassFilter( sample_t &outSamp, sample_t inSamp, int which, float lpCutoff, float resonance, sample_rate_t Fs ); + inline void calcHighpassFilter( sample_t &outSamp, sample_t inSamp, int which, float lpCutoff, float resonance, sample_rate_t Fs ); + + float filtLPX[2][3] = {0};// [filter number][samples back in time] + float filtLPY[2][3] = {0};// [filter number][samples back in time] + + float filtHPX[2][3] = {0};// [filter number][samples back in time] + float filtHPY[2][3] = {0};// [filter number][samples back in time] + +private: + DisintegratorControls m_disintegratorControls; + + std::vector inBuf[2]; + int inBufLoc = 0; + + friend class DisintegratorControls; + +} ; + +#endif diff --git a/plugins/Disintegrator/OLD 1/DisintegratorControlDialog.cpp b/plugins/Disintegrator/OLD 1/DisintegratorControlDialog.cpp new file mode 100644 index 000000000..3dbc63c8a --- /dev/null +++ b/plugins/Disintegrator/OLD 1/DisintegratorControlDialog.cpp @@ -0,0 +1,70 @@ +/* + * DisintegratorControlDialog.cpp + * + * Copyright (c) 2019 Lost Robot + * + * 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 + +#include "DisintegratorControlDialog.h" +#include "DisintegratorControls.h" +#include "embed.h" + + + +DisintegratorControlDialog::DisintegratorControlDialog( DisintegratorControls* controls ) : + EffectControlDialog( controls ) +{ + setAutoFillBackground( true ); + QPalette pal; + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); + setPalette( pal ); + setFixedSize( 100, 110 ); + + // ==TAG== INITIALIZEWIDGETS ==TAG== // + Knob * volumeKnob = new Knob( knobBright_26, this); + volumeKnob -> move( 16, 10 ); + volumeKnob -> setVolumeKnob( true ); + volumeKnob->setModel( &controls->m_volumeModel ); + volumeKnob->setLabel( tr( "VOL" ) ); + volumeKnob->setHintText( tr( "Volume:" ) , "%" ); + + Knob * panKnob = new Knob( knobBright_26, this); + panKnob -> move( 57, 10 ); + panKnob->setModel( &controls->m_panModel ); + panKnob->setLabel( tr( "PAN" ) ); + panKnob->setHintText( tr( "Panning:" ) , "" ); + + Knob * leftKnob = new Knob( knobBright_26, this); + leftKnob -> move( 16, 65 ); + leftKnob -> setVolumeKnob( true ); + leftKnob->setModel( &controls->m_leftModel ); + leftKnob->setLabel( tr( "LEFT" ) ); + leftKnob->setHintText( tr( "Left gain:" ) , "%" ); + + Knob * rightKnob = new Knob( knobBright_26, this); + rightKnob -> move( 57, 65 ); + rightKnob -> setVolumeKnob( true ); + rightKnob->setModel( &controls->m_rightModel ); + rightKnob->setLabel( tr( "RIGHT" ) ); + rightKnob->setHintText( tr( "Right gain:" ) , "%" ); + // ==TAG== ENDINITIALIZEWIDGETS ==TAG== // +} diff --git a/plugins/Disintegrator/OLD 1/DisintegratorControlDialog.h b/plugins/Disintegrator/OLD 1/DisintegratorControlDialog.h new file mode 100644 index 000000000..89d270130 --- /dev/null +++ b/plugins/Disintegrator/OLD 1/DisintegratorControlDialog.h @@ -0,0 +1,45 @@ +/* + * DisintegratorControlDialog.h + * + * Copyright (c) 2019 Lost Robot + * + * 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. + * + */ + +#ifndef DISINTEGRATOR_CONTROL_DIALOG_H +#define DISINTEGRATOR_CONTROL_DIALOG_H + +#include "EffectControlDialog.h" + + +class DisintegratorControls; + + +class DisintegratorControlDialog : public EffectControlDialog +{ + Q_OBJECT +public: + DisintegratorControlDialog( DisintegratorControls* controls ); + virtual ~DisintegratorControlDialog() + { + } + +} ; + +#endif diff --git a/plugins/Disintegrator/OLD 1/DisintegratorControls.cpp b/plugins/Disintegrator/OLD 1/DisintegratorControls.cpp new file mode 100644 index 000000000..47fc5d295 --- /dev/null +++ b/plugins/Disintegrator/OLD 1/DisintegratorControls.cpp @@ -0,0 +1,69 @@ +/* + * DisintegratorControls.cpp + * + * Copyright (c) 2019 Lost Robot + * + * 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 + +#include "DisintegratorControls.h" +#include "Disintegrator.h" +#include "Engine.h" +#include "Song.h" + + +DisintegratorControls::DisintegratorControls( DisintegratorEffect* effect ) : + EffectControls( effect ), + m_effect( effect ), + // ==TAG== INITIALIZEMODELS ==TAG== // + m_volumeModel( 20.0f, 20.0f, 21050.0f, 0.001f, this, tr( "Volume" ) ), + m_panModel( 20.0f, 20.0f, 21050.0f, 0.001f, this, tr( "Panning" ) ), + m_leftModel( 50.0f, 0.0f, 100.0f, 0.001f, this, tr( "Left gain" ) ), + m_rightModel( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Right gain" ) ) + // ==TAG== ENDINITIALIZEMODELS ==TAG== // +{ +} + + +void DisintegratorControls::saveSettings( QDomDocument& doc, QDomElement& _this ) +{ + // ==TAG== SAVESETTINGS ==TAG== // + m_volumeModel.saveSettings( doc, _this, "volume" ); + m_panModel.saveSettings( doc, _this, "pan" ); + m_leftModel.saveSettings( doc, _this, "left" ); + m_rightModel.saveSettings( doc, _this, "right" ); + // ==TAG== ENDSAVESETTINGS ==TAG== // +} + + + +void DisintegratorControls::loadSettings( const QDomElement& _this ) +{ + // ==TAG== LOADSETTINGS ==TAG== // + m_volumeModel.loadSettings( _this, "volume" ); + m_panModel.loadSettings( _this, "pan" ); + m_leftModel.loadSettings( _this, "left" ); + m_rightModel.loadSettings( _this, "right" ); + // ==TAG== ENDLOADSETTINGS ==TAG== // +} + + diff --git a/plugins/Disintegrator/OLD 1/DisintegratorControls.h b/plugins/Disintegrator/OLD 1/DisintegratorControls.h new file mode 100644 index 000000000..39f7f5b26 --- /dev/null +++ b/plugins/Disintegrator/OLD 1/DisintegratorControls.h @@ -0,0 +1,78 @@ +/* + * DisintegratorControls.h + * + * Copyright (c) 2019 Lost Robot + * + * 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. + * + */ + +#ifndef DISINTEGRATOR_CONTROLS_H +#define DISINTEGRATOR_CONTROLS_H + +#include "EffectControls.h" +#include "DisintegratorControlDialog.h" +#include "Knob.h" + + +class DisintegratorEffect; + + +class DisintegratorControls : public EffectControls +{ + Q_OBJECT +public: + DisintegratorControls( DisintegratorEffect* effect ); + virtual ~DisintegratorControls() + { + } + + virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); + virtual void loadSettings( const QDomElement & _this ); + inline virtual QString nodeName() const + { + return "DisintegratorControls"; + } + + virtual int controlCount() + { + // ==TAG== CONTROLCOUNT ==TAG== // + return 4; + } + + virtual EffectControlDialog* createView() + { + return new DisintegratorControlDialog( this ); + } + +private: + DisintegratorEffect* m_effect; + + // ==TAG== DEFINEMODELS ==TAG== // + FloatModel m_volumeModel; + FloatModel m_panModel; + FloatModel m_leftModel; + FloatModel m_rightModel; + // ==TAG== ENDDEFINEMODELS ==TAG== // + + friend class DisintegratorControlDialog; + friend class DisintegratorEffect; + +} ; + +#endif diff --git a/plugins/Disintegrator/OLD 1/artwork.png b/plugins/Disintegrator/OLD 1/artwork.png new file mode 100644 index 0000000000000000000000000000000000000000..5598b32db47134819b686a2f2e282c297fe78c06 GIT binary patch literal 7739 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 Bz%u{< literal 0 HcmV?d00001 diff --git a/plugins/Disintegrator/OLD 1/logo.png b/plugins/Disintegrator/OLD 1/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9340da708dd79ed97111eb535f51b81a91d6a15b GIT binary patch literal 774 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 Bz%u{< literal 0 HcmV?d00001 diff --git a/plugins/Disintegrator/logo.png b/plugins/Disintegrator/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9340da708dd79ed97111eb535f51b81a91d6a15b GIT binary patch literal 774 zcmV+h1Nr=kP)7WEc)VQ)zLm`B#lSD% z0Wg;#IH?7|3b0p&fj_`2;A{cm@zx+(Ge?s$@EN$6LtMjg>;+(boCbaXw;ja=b6mQ?gRp67Yf18(18niCN0v&eY^{Cr&#;#IcF{ks?!* z&o!_q>9xbSw`QytRI!M?zP_o#K-8ExJaV?vi znPt?~0KhTu23U+Gy8^Tw;^SzWSet9n