From 6d2b91054bbf3365606ffaac1d3ba03406f289f4 Mon Sep 17 00:00:00 2001 From: dave Date: Sat, 15 Nov 2014 11:22:23 +0000 Subject: [PATCH 01/12] Tempo synced Delay Plugin --- data/locale/en.ts | 62 +++++++++++++- plugins/CMakeLists.txt | 1 + plugins/delay/CMakeLists.txt | 3 + plugins/delay/artwork.png | Bin 0 -> 1659 bytes plugins/delay/delaycontrols.cpp | 73 ++++++++++++++++ plugins/delay/delaycontrols.h | 72 ++++++++++++++++ plugins/delay/delaycontrolsdialog.cpp | 70 ++++++++++++++++ plugins/delay/delaycontrolsdialog.h | 41 +++++++++ plugins/delay/delayeffect.cpp | 115 ++++++++++++++++++++++++++ plugins/delay/delayeffect.h | 49 +++++++++++ plugins/delay/lfo.cpp | 79 ++++++++++++++++++ plugins/delay/lfo.h | 53 ++++++++++++ plugins/delay/logo.png | Bin 0 -> 3225 bytes plugins/delay/stereodelay.cpp | 100 ++++++++++++++++++++++ plugins/delay/stereodelay.h | 44 ++++++++++ 15 files changed, 760 insertions(+), 2 deletions(-) create mode 100644 plugins/delay/CMakeLists.txt create mode 100644 plugins/delay/artwork.png create mode 100644 plugins/delay/delaycontrols.cpp create mode 100644 plugins/delay/delaycontrols.h create mode 100644 plugins/delay/delaycontrolsdialog.cpp create mode 100644 plugins/delay/delaycontrolsdialog.h create mode 100644 plugins/delay/delayeffect.cpp create mode 100644 plugins/delay/delayeffect.h create mode 100644 plugins/delay/lfo.cpp create mode 100644 plugins/delay/lfo.h create mode 100644 plugins/delay/logo.png create mode 100644 plugins/delay/stereodelay.cpp create mode 100644 plugins/delay/stereodelay.h diff --git a/data/locale/en.ts b/data/locale/en.ts index b21db762d..736caf963 100644 --- a/data/locale/en.ts +++ b/data/locale/en.ts @@ -42,11 +42,11 @@ If you're interested in translating LMMS in another language or want to imp - <html><head/><body><p><a href="http://lmms.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.sourceforge.net</span></a></p></body></html> + LMMS - LMMS + <html><head/><body><p><a href="http://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.io</span></a></p></body></html> @@ -651,6 +651,60 @@ If you're interested in translating LMMS in another language or want to imp + + DelayControls + + Delay Samples + + + + Feedback + + + + Lfo Frequency + + + + Lfo Ammount + + + + + DelayControlsDialog + + Delay + + + + Delay Time Samples: + + + + Feedback + + + + Feedback Ammount: + + + + Lfo Hz + + + + Lfo Hz: + + + + Lfo Amt + + + + Lfo Amt: + + + DualFilterControlDialog @@ -7016,6 +7070,10 @@ This chip was used in the Commodore 64 computer. A NES-like synthesizer + + A native delay plugin + + projectNotes diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 8311c4fa6..1ba586768 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -5,6 +5,7 @@ ADD_SUBDIRECTORY(bit_invader) ADD_SUBDIRECTORY(carlabase) ADD_SUBDIRECTORY(carlapatchbay) ADD_SUBDIRECTORY(carlarack) +ADD_SUBDIRECTORY(delay) ADD_SUBDIRECTORY(DualFilter) ADD_SUBDIRECTORY(dynamics_processor) ADD_SUBDIRECTORY(flp_import) diff --git a/plugins/delay/CMakeLists.txt b/plugins/delay/CMakeLists.txt new file mode 100644 index 000000000..0663b9458 --- /dev/null +++ b/plugins/delay/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(delay delayeffect.cpp delaycontrols.cpp delaycontrolsdialog.cpp lfo.cpp stereodelay.cpp MOCFILES delaycontrols.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") diff --git a/plugins/delay/artwork.png b/plugins/delay/artwork.png new file mode 100644 index 0000000000000000000000000000000000000000..19b18740f259cdc70e3c8933ec4e57132ee97788 GIT binary patch literal 1659 zcmbW2dpOez7{`BdS(#i$RBp{J2_>g;DavLhmze8zbXc}C$t=uejS&i+j*a8muwv~g zwd9(Uq*lt@Mx?0R*-?|SCRsS^obx>AIscwNKJWK=FVFit-}j$4$H&`kv+{Oj001_- zBjG5S;$)<3RFXx1$EP5fY&wHP#{mFX^E-0D<+81^B8cqny-$V%JD zuEAs&iAcmplL1&P9!tjKb|ju6N9=HO_workr>X-0iV}DDQU9co`La~cf_S}Wp-;;- z2Y^j>S_*@H_wafg)F6t#;&$S+RTs(wGw9jXWJy>v@1ecsa8Yq1-8Ak>RjG&TRmic0 zzTCk$N?{t|%7%;e{vXCyrY1kaxlPT~OJCj_HVG+9B8pRul;%9PQ2*(Jl7jk$M+ywv zZ=9|b)4-af-{j=??P^Zp;a3d`x6B-c_D|N+hw}3CJ)@%3E;E@oZhS)B=N5c%{+2mA zJDZx!ns_N(YeOI#w*C-tM4D0Ji6f|)Ia2rD)xK1DCqjwPTQ(Q#H?#$jl#Qj_-FsGK z_p_k%cuI)LW#?lo?C_1 zof*|T86LieB1jCfBvAQgdNZc?@2==8sdj7#8@M2dvG3Y?mb*C(ngN=KEvo(W%W>0b z7dwjtxxSjvvA$aB&e3*FTLaSa0ZT(}k)p4opYBx*z z1K|8&81zu`I6Y-2X?i1Ik+8Z0s*`*r`jMM*S^aj_p;Jb{c~`m(9-{$NxxG#1OS{YV zGc~@3HvrDKPSm`te?I&a*ykO z(=tuIf@L57E)j#l*vW+UroK3+*t#lWMRPg%!BYA1Nc^oI*EO+yuxPl2?(EHaDir&Mj-@>w9yLColjUJ?fWe49G9J55UL^f7 zY+EFPX24b>79Om6(mrBS9CEZtR@Cwks&~Y?c=q*f$(%{`o~Q$HOCt0;-RdBm~n zS^W@@U0!L2}4a9)biA^Dh1{`?FN-_`wVVf zfjL24hL4ORGWN=7z~6? + * + * This file is part of LMMS - http://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 "delaycontrols.h" +#include "delayeffect.h" +#include "engine.h" +#include "song.h" + +DelayControls::DelayControls(DelayEffect* effect): + EffectControls( effect ), + m_effect ( effect ), + m_delayTimeModel( 2.0, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Delay Samples" )) , + m_feebackModel(0.0f,0.0f,1.0f,0.01f,this,tr( "Feedback" ) ), + m_lfoTimeModel(2.0, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Lfo Frequency" ) ), + m_lfoAmmountModel(0.0f,0.0f,0.5f,0.01f, this, tr ( "Lfo Ammount" ) ) +{ + +} + + + + +void DelayControls::changeControl() +{ + //engine::getSong()->setModified(); +} + + + + +void DelayControls::loadSettings(const QDomElement &_this) +{ + m_delayTimeModel.loadSettings(_this, "DelayTimeSamples" ); + m_feebackModel.loadSettings( _this, "FeebackAmmount" ); + m_lfoTimeModel.loadSettings( _this , "LfoFrequency"); + m_lfoAmmountModel.loadSettings( _this, "LfoAmmount"); +} + + + + +void DelayControls::saveSettings(QDomDocument& doc, QDomElement& _this) +{ + m_delayTimeModel.saveSettings( doc, _this, "DelayTimeSamples"); + m_feebackModel.saveSettings( doc, _this ,"FeebackAmmount"); + m_lfoTimeModel.saveSettings( doc, _this, "LfoFrequency"); + m_lfoAmmountModel.saveSettings( doc, _this ,"LfoAmmount"); +} + +#include "moc_delaycontrols.cxx" diff --git a/plugins/delay/delaycontrols.h b/plugins/delay/delaycontrols.h new file mode 100644 index 000000000..4947bf93e --- /dev/null +++ b/plugins/delay/delaycontrols.h @@ -0,0 +1,72 @@ +/* + * delaycontrols.h - declaration of DelayControl class. + * + * Copyright (c) 2014 David French + * + * This file is part of LMMS - http://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 DELAYCONTROLS_H +#define DELAYCONTROLS_H + +#include "EffectControls.h" +#include "knob.h" +#include "delaycontrolsdialog.h" + + + +class DelayEffect; + +class DelayControls : public EffectControls +{ + Q_OBJECT +public: + DelayControls( DelayEffect* effect ); + virtual ~DelayControls() + { + } + virtual void saveSettings( QDomDocument& doc, QDomElement& parent ); + virtual void loadSettings( const QDomElement& _this ); + inline virtual QString nodeName() const + { + return "Delay"; + } + virtual int controlCount(){ + return 4; + } + virtual EffectControlDialog* createView() + { + return new DelayControlsDialog( this ); + } + +private slots: + void changeControl(); + +private: + DelayEffect* m_effect; + TempoSyncKnobModel m_delayTimeModel; + FloatModel m_feebackModel; + TempoSyncKnobModel m_lfoTimeModel; + FloatModel m_lfoAmmountModel; + + friend class DelayControlsDialog; + friend class DelayEffect; +}; + +#endif // DELAYCONTROLS_H diff --git a/plugins/delay/delaycontrolsdialog.cpp b/plugins/delay/delaycontrolsdialog.cpp new file mode 100644 index 000000000..a27e4cdb2 --- /dev/null +++ b/plugins/delay/delaycontrolsdialog.cpp @@ -0,0 +1,70 @@ +/* + * delaycontrolsdialog.cpp - definition of DelayControlsDialog class. + * + * Copyright (c) 2014 David French + * + * This file is part of LMMS - http://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 "delaycontrolsdialog.h" +#include "delaycontrols.h" +#include "embed.h" +#include "TempoSyncKnob.h" + + + + +DelayControlsDialog::DelayControlsDialog(DelayControls *controls) : + EffectControlDialog( controls ) +{ + setAutoFillBackground( true ); + QPalette pal; + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); + setPalette( pal ); + setFixedSize( 100,125 ); + + TempoSyncKnob* sampleDelayKnob = new TempoSyncKnob( knobBright_26, this ); + sampleDelayKnob->move( 20,30 ); + sampleDelayKnob->setVolumeKnob( false ); + sampleDelayKnob->setModel( &controls->m_delayTimeModel ); + sampleDelayKnob->setLabel( tr( "Delay" ) ); + sampleDelayKnob->setHintText( tr( "Delay Time Samples:" ) + " ", "" ); + + knob * feedbackKnob = new knob( knobBright_26, this); + feedbackKnob->move( 60,30 ); + feedbackKnob->setVolumeKnob(true); + feedbackKnob->setModel( &controls->m_feebackModel); + feedbackKnob->setLabel( tr( "Feedback" ) ); + feedbackKnob->setHintText( tr ( "Feedback Ammount:" ) + " ", ""); + + TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this); + lfoFreqKnob->move( 20,80 ); + lfoFreqKnob->setVolumeKnob(false); + lfoFreqKnob->setModel( &controls->m_lfoTimeModel); + lfoFreqKnob->setLabel( tr( "Lfo Hz" ) ); + lfoFreqKnob->setHintText( tr ( "Lfo Hz:" ) + " ", ""); + + knob * lfoAmtKnob = new knob( knobBright_26, this); + lfoAmtKnob->move( 60,80 ); + lfoAmtKnob->setVolumeKnob(true); + lfoAmtKnob->setModel( &controls->m_lfoAmmountModel); + lfoAmtKnob->setLabel( tr( "Lfo Amt" ) ); + lfoAmtKnob->setHintText( tr ( "Lfo Amt:" ) + " ", ""); + +} diff --git a/plugins/delay/delaycontrolsdialog.h b/plugins/delay/delaycontrolsdialog.h new file mode 100644 index 000000000..1850c774b --- /dev/null +++ b/plugins/delay/delaycontrolsdialog.h @@ -0,0 +1,41 @@ +/* + * delaycontrolsdialog.h - declaration of DelayControlsDialog class. + * + * Copyright (c) 2014 David French + * + * This file is part of LMMS - http://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 DELAYCONTROLSDIALOG_H +#define DELAYCONTROLSDIALOG_H + +#include "EffectControlDialog.h" + +class DelayControls; + +class DelayControlsDialog : public EffectControlDialog +{ +public: + DelayControlsDialog(DelayControls* controls ); + virtual ~DelayControlsDialog() + { + } +}; + +#endif // DELAYCONTROLSDIALOG_H diff --git a/plugins/delay/delayeffect.cpp b/plugins/delay/delayeffect.cpp new file mode 100644 index 000000000..5da1a6299 --- /dev/null +++ b/plugins/delay/delayeffect.cpp @@ -0,0 +1,115 @@ +/* + * delayeffect.cpp - definition of the DelayEffect class. The Delay Plugin + * + * Copyright (c) 2014 David French + * + * This file is part of LMMS - http://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 "delayeffect.h" +#include "engine.h" +#include "embed.cpp" + + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT delay_plugin_descriptor = +{ + STRINGIFY( PLUGIN_NAME ), + "Delay", + QT_TRANSLATE_NOOP( "pluginBrowser", "A native delay plugin" ), + "Dave French ", + 0x0100, + Plugin::Effect, + new PluginPixmapLoader( "logo" ), + NULL, + NULL +} ; + + + + +DelayEffect::DelayEffect( Model* parent, const Plugin::Descriptor::SubPluginFeatures::Key* key ) : + Effect( &delay_plugin_descriptor, parent, key ), + m_delayControls( this ) +{ + m_delay = 0; + m_delay = new StereoDelay( engine::mixer()->processingSampleRate()* 20 ); + m_lfo = new Lfo( engine::mixer()->processingSampleRate() ); +} + + + +DelayEffect::~DelayEffect() +{ + if( m_delay ) + { + delete m_delay; + } + if( m_lfo ) + { + delete m_lfo; + } +} + + + + +bool DelayEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) +{ + if( !isEnabled() || !isRunning () ) + { + return( false ); + } + double outSum = 0.0; + const float d = dryLevel(); + const float w = wetLevel(); + sample_t dryS[2]; + for( fpp_t f = 0; f < frames; ++f ) + { + dryS[0] = buf[f][0]; + dryS[1] = buf[f][1]; + m_lfo->setAmplitude( m_delayControls.m_lfoAmmountModel.value( f ) ); + m_lfo->setFrequency( 1.0 / m_delayControls.m_lfoTimeModel.value( f ) ); + m_delay->setLength( m_delayControls.m_delayTimeModel.value(f) * engine::mixer()->processingSampleRate() * m_lfo->tick() ); + m_delay->setFeedback( m_delayControls.m_feebackModel.value( f ) ); + m_delay->tick( &buf[f][0], &buf[f][1] ); + + buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] ); + buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] ); + outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; + } + checkGate( outSum / frames ); + return isRunning(); +} + + + +extern "C" +{ + +//needed for getting plugin out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model* parent, void* data ) +{ + return new DelayEffect( parent , static_cast( data ) ); +} + +}} + diff --git a/plugins/delay/delayeffect.h b/plugins/delay/delayeffect.h new file mode 100644 index 000000000..58de87329 --- /dev/null +++ b/plugins/delay/delayeffect.h @@ -0,0 +1,49 @@ +/* + * delayeffect.h - declaration of DelayEffect class, the Delay plugin + * + * Copyright (c) 2014 David French + * + * This file is part of LMMS - http://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 DELAYEFFECT_H +#define DELAYEFFECT_H + +#include "Effect.h" +#include "delaycontrols.h" +#include "lfo.h" +#include "stereodelay.h" + +class DelayEffect : public Effect +{ +public: + DelayEffect(Model* parent , const Descriptor::SubPluginFeatures::Key* key ); + virtual ~DelayEffect(); + virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames); + virtual EffectControls* controls() + { + return &m_delayControls; + } +private: + DelayControls m_delayControls; + StereoDelay* m_delay; + Lfo* m_lfo; +}; + +#endif // DELAYEFFECT_H diff --git a/plugins/delay/lfo.cpp b/plugins/delay/lfo.cpp new file mode 100644 index 000000000..b93e9ad46 --- /dev/null +++ b/plugins/delay/lfo.cpp @@ -0,0 +1,79 @@ +/* + * lfo.cpp - defination of Lfo class. + * + * Copyright (c) 2014 David French + * + * This file is part of LMMS - http://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 "lfo.h" +#include + + + + +Lfo::Lfo( int samplerate ) +{ + m_samplerate = samplerate; + m_twoPiOverSr = TWOPI / samplerate; +} + + + +void Lfo::setFrequency( double frequency ) +{ + if( frequency < 0 || frequency > ( m_samplerate / 2.0 ) || frequency == m_frequency ) + { + return; + } + m_frequency = frequency; + m_increment = m_frequency * m_twoPiOverSr; +} + + + + +void Lfo::setAmplitude( float amplitude ) +{ + if( amplitude < 0.0 || amplitude > 1.0 ) + { + return; + } + m_amplitude = amplitude; +} + + + + +float Lfo::tick() +{ + float output = ( float )sin( m_phase ); + m_phase += m_increment; + if( m_phase >= TWOPI ) + { + m_phase -= TWOPI; + } + if( m_amplitude > 0.0001 ) + { + return ( ( output + 1.0 ) / 2.0 ) * m_amplitude; + } else + { + return 1; + } +} diff --git a/plugins/delay/lfo.h b/plugins/delay/lfo.h new file mode 100644 index 000000000..b561bbafa --- /dev/null +++ b/plugins/delay/lfo.h @@ -0,0 +1,53 @@ +/* + * lfo.h - declaration of Lfo class, a simple sine lfo + * + * Copyright (c) 2014 David French + * + * This file is part of LMMS - http://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 LFO_H +#define LFO_H + +#ifndef M_PI +#define M_PI (3.14159265358979321 ) +#endif +#define TWOPI ( 2.0 * M_PI ) + +class Lfo +{ +public: + Lfo( int samplerate ); + ~Lfo() + { + } + void setFrequency( double frequency ); + void setAmplitude( float amplitude ); + float tick(); + +private: + double m_frequency; + double m_phase; + double m_increment; + double m_amplitude; + double m_twoPiOverSr; + int m_samplerate; +}; + +#endif // LFO_H diff --git a/plugins/delay/logo.png b/plugins/delay/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..89e9f3680118931dd86f065a8f6bc0b4c631a585 GIT binary patch literal 3225 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 + * + * This file is part of LMMS - http://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 "stereodelay.h" +#include + + +StereoDelay::StereoDelay(int maxLength) +{ + m_buffer = 0; + m_buffer = ( float* )malloc(maxLength*2*sizeof( float ) ); + m_maxLength = maxLength; + m_length = m_maxLength; + m_index = 0; + m_feedback = 0.0f; + setLength( 0 ); +} + + + + +StereoDelay::~StereoDelay() +{ + if( m_buffer ) + { + free( m_buffer ); + } +} + + + + +void StereoDelay::setLength( int length ) +{ + if( length <= m_maxLength && length >= 0 ) + { + if( length < m_length ) + { + for( int i = length * 2; i < m_length *2; i++) + { + m_buffer[i] = 0.0f; + } + } + m_length = length; + } +} + + + + +void StereoDelay::setFeedback( float feedback ) +{ + m_feedback = feedback; +} + + + +float m_oldLeft; +float m_oldRight; +void StereoDelay::tick( float* left, float* right ) +{ + m_oldLeft = m_buffer[m_index]; + m_oldRight = m_buffer[m_index+1]; + m_buffer[m_index] = *left + ( m_oldLeft * m_feedback ); + m_buffer[m_index+1] = *right + ( m_oldRight * m_feedback ); + *left = m_oldLeft; + *right = m_oldRight; + m_index++; m_index++; + if( m_index > m_length ) + { + m_index = 0; + } +} + + + + + + diff --git a/plugins/delay/stereodelay.h b/plugins/delay/stereodelay.h new file mode 100644 index 000000000..f4e4431b7 --- /dev/null +++ b/plugins/delay/stereodelay.h @@ -0,0 +1,44 @@ +/* + * stereodelay.h - declaration of StereoDelay class. + * + * Copyright (c) 2014 David French + * + * This file is part of LMMS - http://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 STEREODELAY_H +#define STEREODELAY_H + +class StereoDelay +{ +public: + StereoDelay( int maxLength ); + ~StereoDelay(); + void setLength( int length ); + void setFeedback( float feedback ); + void tick( float* left, float* right ); +private: + float *m_buffer; + int m_maxLength; + int m_length; + int m_index; + float m_feedback; +}; + +#endif // STEREODELAY_H From 4c82ba22a9b4e55aa8c0680d466312c803ae8b00 Mon Sep 17 00:00:00 2001 From: dave Date: Sun, 16 Nov 2014 15:02:15 +0000 Subject: [PATCH 02/12] Fixed issues with original verion, as directed in pull request. corrected the typeo's, Used sampleFrame instead of float* making the code cleaner. Set up a socket to change the samplerate where required. Stopped using malloc ( yeah that was bad practice on my part ). Now using lmms_Math.h and the predefined versions of F_PI and F_2PI, I didn't know data from the knobs etc. was not updated over the course of a buffer, so have moved outside the processing loop, made appropriate functions inline, used sinf. Multiplication has replaced division where possible, zeroing of the buffer has been removed, as redundant. --- data/locale/en.ts | 4 +- plugins/delay/delaycontrols.cpp | 14 +++---- plugins/delay/delaycontrols.h | 4 +- plugins/delay/delaycontrolsdialog.cpp | 6 +-- plugins/delay/delayeffect.cpp | 21 +++++++--- plugins/delay/delayeffect.h | 4 ++ plugins/delay/lfo.cpp | 37 +++-------------- plugins/delay/lfo.h | 51 +++++++++++++++++++++--- plugins/delay/stereodelay.cpp | 57 +++++++-------------------- plugins/delay/stereodelay.h | 21 ++++++++-- 10 files changed, 115 insertions(+), 104 deletions(-) diff --git a/data/locale/en.ts b/data/locale/en.ts index 736caf963..9ed59949f 100644 --- a/data/locale/en.ts +++ b/data/locale/en.ts @@ -666,7 +666,7 @@ If you're interested in translating LMMS in another language or want to imp - Lfo Ammount + Lfo Amount @@ -685,7 +685,7 @@ If you're interested in translating LMMS in another language or want to imp - Feedback Ammount: + Feedback Amount: diff --git a/plugins/delay/delaycontrols.cpp b/plugins/delay/delaycontrols.cpp index 32a7a793a..85f1ac810 100644 --- a/plugins/delay/delaycontrols.cpp +++ b/plugins/delay/delaycontrols.cpp @@ -33,11 +33,11 @@ DelayControls::DelayControls(DelayEffect* effect): EffectControls( effect ), m_effect ( effect ), m_delayTimeModel( 2.0, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Delay Samples" )) , - m_feebackModel(0.0f,0.0f,1.0f,0.01f,this,tr( "Feedback" ) ), + m_feedbackModel(0.0f,0.0f,1.0f,0.01f,this,tr( "Feedback" ) ), m_lfoTimeModel(2.0, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Lfo Frequency" ) ), - m_lfoAmmountModel(0.0f,0.0f,0.5f,0.01f, this, tr ( "Lfo Ammount" ) ) + m_lfoAmountModel(0.0f,0.0f,0.5f,0.01f, this, tr ( "Lfo Amount" ) ) { - + //used to setup the controls } @@ -54,9 +54,9 @@ void DelayControls::changeControl() void DelayControls::loadSettings(const QDomElement &_this) { m_delayTimeModel.loadSettings(_this, "DelayTimeSamples" ); - m_feebackModel.loadSettings( _this, "FeebackAmmount" ); + m_feedbackModel.loadSettings( _this, "FeebackAmount" ); m_lfoTimeModel.loadSettings( _this , "LfoFrequency"); - m_lfoAmmountModel.loadSettings( _this, "LfoAmmount"); + m_lfoAmountModel.loadSettings( _this, "LfoAmount"); } @@ -65,9 +65,9 @@ void DelayControls::loadSettings(const QDomElement &_this) void DelayControls::saveSettings(QDomDocument& doc, QDomElement& _this) { m_delayTimeModel.saveSettings( doc, _this, "DelayTimeSamples"); - m_feebackModel.saveSettings( doc, _this ,"FeebackAmmount"); + m_feedbackModel.saveSettings( doc, _this ,"FeebackAmount"); m_lfoTimeModel.saveSettings( doc, _this, "LfoFrequency"); - m_lfoAmmountModel.saveSettings( doc, _this ,"LfoAmmount"); + m_lfoAmountModel.saveSettings( doc, _this ,"LfoAmount"); } #include "moc_delaycontrols.cxx" diff --git a/plugins/delay/delaycontrols.h b/plugins/delay/delaycontrols.h index 4947bf93e..e01c5fe05 100644 --- a/plugins/delay/delaycontrols.h +++ b/plugins/delay/delaycontrols.h @@ -61,9 +61,9 @@ private slots: private: DelayEffect* m_effect; TempoSyncKnobModel m_delayTimeModel; - FloatModel m_feebackModel; + FloatModel m_feedbackModel; TempoSyncKnobModel m_lfoTimeModel; - FloatModel m_lfoAmmountModel; + FloatModel m_lfoAmountModel; friend class DelayControlsDialog; friend class DelayEffect; diff --git a/plugins/delay/delaycontrolsdialog.cpp b/plugins/delay/delaycontrolsdialog.cpp index a27e4cdb2..a55ce33b3 100644 --- a/plugins/delay/delaycontrolsdialog.cpp +++ b/plugins/delay/delaycontrolsdialog.cpp @@ -49,9 +49,9 @@ DelayControlsDialog::DelayControlsDialog(DelayControls *controls) : knob * feedbackKnob = new knob( knobBright_26, this); feedbackKnob->move( 60,30 ); feedbackKnob->setVolumeKnob(true); - feedbackKnob->setModel( &controls->m_feebackModel); + feedbackKnob->setModel( &controls->m_feedbackModel); feedbackKnob->setLabel( tr( "Feedback" ) ); - feedbackKnob->setHintText( tr ( "Feedback Ammount:" ) + " ", ""); + feedbackKnob->setHintText( tr ( "Feedback Amount:" ) + " ", ""); TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this); lfoFreqKnob->move( 20,80 ); @@ -63,7 +63,7 @@ DelayControlsDialog::DelayControlsDialog(DelayControls *controls) : knob * lfoAmtKnob = new knob( knobBright_26, this); lfoAmtKnob->move( 60,80 ); lfoAmtKnob->setVolumeKnob(true); - lfoAmtKnob->setModel( &controls->m_lfoAmmountModel); + lfoAmtKnob->setModel( &controls->m_lfoAmountModel); lfoAmtKnob->setLabel( tr( "Lfo Amt" ) ); lfoAmtKnob->setHintText( tr ( "Lfo Amt:" ) + " ", ""); diff --git a/plugins/delay/delayeffect.cpp b/plugins/delay/delayeffect.cpp index 5da1a6299..3a51e7b87 100644 --- a/plugins/delay/delayeffect.cpp +++ b/plugins/delay/delayeffect.cpp @@ -51,12 +51,14 @@ DelayEffect::DelayEffect( Model* parent, const Plugin::Descriptor::SubPluginFeat m_delayControls( this ) { m_delay = 0; - m_delay = new StereoDelay( engine::mixer()->processingSampleRate()* 20 ); + m_delay = new StereoDelay( 192000 * 20 ); m_lfo = new Lfo( engine::mixer()->processingSampleRate() ); + connect( engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) ); } + DelayEffect::~DelayEffect() { if( m_delay ) @@ -81,16 +83,16 @@ bool DelayEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); + m_lfo->setAmplitude( m_delayControls.m_lfoAmountModel.value() ); + m_lfo->setFrequency( 1.0 / m_delayControls.m_lfoTimeModel.value() ); + m_delay->setFeedback( m_delayControls.m_feedbackModel.value() ); sample_t dryS[2]; for( fpp_t f = 0; f < frames; ++f ) { dryS[0] = buf[f][0]; dryS[1] = buf[f][1]; - m_lfo->setAmplitude( m_delayControls.m_lfoAmmountModel.value( f ) ); - m_lfo->setFrequency( 1.0 / m_delayControls.m_lfoTimeModel.value( f ) ); m_delay->setLength( m_delayControls.m_delayTimeModel.value(f) * engine::mixer()->processingSampleRate() * m_lfo->tick() ); - m_delay->setFeedback( m_delayControls.m_feebackModel.value( f ) ); - m_delay->tick( &buf[f][0], &buf[f][1] ); + m_delay->tick( buf[f] ); buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] ); buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] ); @@ -102,6 +104,15 @@ bool DelayEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) + +void DelayEffect::sampleRateChanged() +{ + m_lfo->setSamplerate(engine::mixer()->processingSampleRate()); +} + + + + extern "C" { diff --git a/plugins/delay/delayeffect.h b/plugins/delay/delayeffect.h index 58de87329..1b1318e09 100644 --- a/plugins/delay/delayeffect.h +++ b/plugins/delay/delayeffect.h @@ -40,6 +40,10 @@ public: { return &m_delayControls; } + +private slots: + void sampleRateChanged(); + private: DelayControls m_delayControls; StereoDelay* m_delay; diff --git a/plugins/delay/lfo.cpp b/plugins/delay/lfo.cpp index b93e9ad46..6fb5472c2 100644 --- a/plugins/delay/lfo.cpp +++ b/plugins/delay/lfo.cpp @@ -23,7 +23,7 @@ */ #include "lfo.h" -#include +#include "lmms_math.h" @@ -31,31 +31,7 @@ Lfo::Lfo( int samplerate ) { m_samplerate = samplerate; - m_twoPiOverSr = TWOPI / samplerate; -} - - - -void Lfo::setFrequency( double frequency ) -{ - if( frequency < 0 || frequency > ( m_samplerate / 2.0 ) || frequency == m_frequency ) - { - return; - } - m_frequency = frequency; - m_increment = m_frequency * m_twoPiOverSr; -} - - - - -void Lfo::setAmplitude( float amplitude ) -{ - if( amplitude < 0.0 || amplitude > 1.0 ) - { - return; - } - m_amplitude = amplitude; + m_twoPiOverSr = F_2PI / samplerate; } @@ -63,15 +39,12 @@ void Lfo::setAmplitude( float amplitude ) float Lfo::tick() { - float output = ( float )sin( m_phase ); + float output = sinf( m_phase ); m_phase += m_increment; - if( m_phase >= TWOPI ) - { - m_phase -= TWOPI; - } + if( m_amplitude > 0.0001 ) { - return ( ( output + 1.0 ) / 2.0 ) * m_amplitude; + return ( ( output + 1.0 ) * 0.5 ) * m_amplitude; } else { return 1; diff --git a/plugins/delay/lfo.h b/plugins/delay/lfo.h index b561bbafa..e340abeb5 100644 --- a/plugins/delay/lfo.h +++ b/plugins/delay/lfo.h @@ -25,10 +25,7 @@ #ifndef LFO_H #define LFO_H -#ifndef M_PI -#define M_PI (3.14159265358979321 ) -#endif -#define TWOPI ( 2.0 * M_PI ) +#include "lmms_math.h" class Lfo { @@ -37,8 +34,50 @@ public: ~Lfo() { } - void setFrequency( double frequency ); - void setAmplitude( float amplitude ); + + + + + inline void setFrequency( double frequency ) + { + if( frequency < 0 || frequency > ( m_samplerate / 2.0 ) || frequency == m_frequency ) + { + return; + } + m_frequency = frequency; + m_increment = m_frequency * m_twoPiOverSr; + + if( m_phase >= F_2PI ) + { + m_phase -= F_2PI; + } + } + + + + + inline void setAmplitude( float amplitude ) + { + if( amplitude < 0.0 || amplitude > 1.0 ) + { + return; + } + m_amplitude = amplitude; + } + + + + + inline void setSamplerate ( int samplerate ) + { + m_samplerate = samplerate; + m_twoPiOverSr = F_2PI / samplerate; + m_increment = m_frequency * m_twoPiOverSr; + } + + + + float tick(); private: diff --git a/plugins/delay/stereodelay.cpp b/plugins/delay/stereodelay.cpp index 8344e2869..c2d0dc254 100644 --- a/plugins/delay/stereodelay.cpp +++ b/plugins/delay/stereodelay.cpp @@ -24,17 +24,18 @@ #include "stereodelay.h" #include +#include "lmms_basics.h" -StereoDelay::StereoDelay(int maxLength) +StereoDelay::StereoDelay( int maxLength ) { m_buffer = 0; - m_buffer = ( float* )malloc(maxLength*2*sizeof( float ) ); + m_buffer = new sampleFrame[maxLength]; m_maxLength = maxLength; m_length = m_maxLength; m_index = 0; m_feedback = 0.0f; - setLength( 0 ); +// setLength( 0 ); } @@ -44,53 +45,23 @@ StereoDelay::~StereoDelay() { if( m_buffer ) { - free( m_buffer ); + delete m_buffer; } } -void StereoDelay::setLength( int length ) +sampleFrame oldFrame; +void StereoDelay::tick( sampleFrame frame ) { - if( length <= m_maxLength && length >= 0 ) - { - if( length < m_length ) - { - for( int i = length * 2; i < m_length *2; i++) - { - m_buffer[i] = 0.0f; - } - } - m_length = length; - } -} - - - - -void StereoDelay::setFeedback( float feedback ) -{ - m_feedback = feedback; -} - - - -float m_oldLeft; -float m_oldRight; -void StereoDelay::tick( float* left, float* right ) -{ - m_oldLeft = m_buffer[m_index]; - m_oldRight = m_buffer[m_index+1]; - m_buffer[m_index] = *left + ( m_oldLeft * m_feedback ); - m_buffer[m_index+1] = *right + ( m_oldRight * m_feedback ); - *left = m_oldLeft; - *right = m_oldRight; - m_index++; m_index++; - if( m_index > m_length ) - { - m_index = 0; - } + oldFrame[0] = m_buffer[m_index][0]; + oldFrame[1] = m_buffer[m_index][1]; + m_buffer[m_index][0] = frame[0] + ( oldFrame[0] * m_feedback ); + m_buffer[m_index][1] = frame[1] + ( oldFrame[1] * m_feedback ); + frame[0] = oldFrame[0]; + frame[1] = oldFrame[1]; + m_index = m_index + 1 < m_length ? m_index + 1 : 0; } diff --git a/plugins/delay/stereodelay.h b/plugins/delay/stereodelay.h index f4e4431b7..6d9697948 100644 --- a/plugins/delay/stereodelay.h +++ b/plugins/delay/stereodelay.h @@ -25,16 +25,29 @@ #ifndef STEREODELAY_H #define STEREODELAY_H +#include "lmms_basics.h" + class StereoDelay { public: StereoDelay( int maxLength ); ~StereoDelay(); - void setLength( int length ); - void setFeedback( float feedback ); - void tick( float* left, float* right ); + inline void setLength( int length ) + { + if( length <= m_maxLength && length >= 0 ) + { + m_length = length; + } + } + + inline void setFeedback( float feedback ) + { + m_feedback = feedback; + } + + void tick( sampleFrame frame ); private: - float *m_buffer; + sampleFrame* m_buffer; int m_maxLength; int m_length; int m_index; From 9bd758951a74be62c5233e369f0ff165b5640048 Mon Sep 17 00:00:00 2001 From: dave Date: Sun, 16 Nov 2014 15:20:26 +0000 Subject: [PATCH 03/12] removed unused socket and empty function in delaycontrols --- plugins/delay/delaycontrols.cpp | 8 -------- plugins/delay/delaycontrols.h | 3 --- 2 files changed, 11 deletions(-) diff --git a/plugins/delay/delaycontrols.cpp b/plugins/delay/delaycontrols.cpp index 85f1ac810..09ccb22d6 100644 --- a/plugins/delay/delaycontrols.cpp +++ b/plugins/delay/delaycontrols.cpp @@ -43,14 +43,6 @@ DelayControls::DelayControls(DelayEffect* effect): -void DelayControls::changeControl() -{ - //engine::getSong()->setModified(); -} - - - - void DelayControls::loadSettings(const QDomElement &_this) { m_delayTimeModel.loadSettings(_this, "DelayTimeSamples" ); diff --git a/plugins/delay/delaycontrols.h b/plugins/delay/delaycontrols.h index e01c5fe05..5f808354f 100644 --- a/plugins/delay/delaycontrols.h +++ b/plugins/delay/delaycontrols.h @@ -55,9 +55,6 @@ public: return new DelayControlsDialog( this ); } -private slots: - void changeControl(); - private: DelayEffect* m_effect; TempoSyncKnobModel m_delayTimeModel; From 2f58d7135bccc6b3bc9698553aba1f36e26ee154 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 17 Nov 2014 01:11:17 +0000 Subject: [PATCH 04/12] moved call to delayTimeModel.value() outside of process loop --- plugins/delay/delayeffect.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/delay/delayeffect.cpp b/plugins/delay/delayeffect.cpp index 3a51e7b87..fbd12b4a7 100644 --- a/plugins/delay/delayeffect.cpp +++ b/plugins/delay/delayeffect.cpp @@ -83,6 +83,7 @@ bool DelayEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); + const float length = m_delayControls.m_delayTimeModel.value() * engine::mixer()->processingSampleRate(); m_lfo->setAmplitude( m_delayControls.m_lfoAmountModel.value() ); m_lfo->setFrequency( 1.0 / m_delayControls.m_lfoTimeModel.value() ); m_delay->setFeedback( m_delayControls.m_feedbackModel.value() ); @@ -91,7 +92,7 @@ bool DelayEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) { dryS[0] = buf[f][0]; dryS[1] = buf[f][1]; - m_delay->setLength( m_delayControls.m_delayTimeModel.value(f) * engine::mixer()->processingSampleRate() * m_lfo->tick() ); + m_delay->setLength( length * m_lfo->tick() ); m_delay->tick( buf[f] ); buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] ); From 932d7905bae2a0b5e1805ae76a98c4dbe078d899 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 17 Nov 2014 20:10:34 +0000 Subject: [PATCH 05/12] The delay buffer now resizes on sample rate change. tidy up formatting --- plugins/delay/delaycontrols.cpp | 25 ++++++++++++++++--------- plugins/delay/delaycontrols.h | 3 +++ plugins/delay/delaycontrolsdialog.cpp | 24 ++++++++++++------------ plugins/delay/delaycontrolsdialog.h | 2 +- plugins/delay/delayeffect.cpp | 13 +++++-------- plugins/delay/delayeffect.h | 6 ++---- plugins/delay/lfo.cpp | 2 +- plugins/delay/lfo.h | 2 +- plugins/delay/stereodelay.cpp | 22 ++++++++++++++++++---- plugins/delay/stereodelay.h | 4 +++- 10 files changed, 62 insertions(+), 41 deletions(-) diff --git a/plugins/delay/delaycontrols.cpp b/plugins/delay/delaycontrols.cpp index 09ccb22d6..fb86834c7 100644 --- a/plugins/delay/delaycontrols.cpp +++ b/plugins/delay/delaycontrols.cpp @@ -29,21 +29,21 @@ #include "engine.h" #include "song.h" -DelayControls::DelayControls(DelayEffect* effect): +DelayControls::DelayControls( DelayEffect* effect ): EffectControls( effect ), m_effect ( effect ), m_delayTimeModel( 2.0, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Delay Samples" )) , m_feedbackModel(0.0f,0.0f,1.0f,0.01f,this,tr( "Feedback" ) ), m_lfoTimeModel(2.0, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Lfo Frequency" ) ), - m_lfoAmountModel(0.0f,0.0f,0.5f,0.01f, this, tr ( "Lfo Amount" ) ) + m_lfoAmountModel(0.0f,0.0f,0.1f,0.0001f, this, tr ( "Lfo Amount" ) ) { - //used to setup the controls + connect( engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( changeSampleRate() ) ); } -void DelayControls::loadSettings(const QDomElement &_this) +void DelayControls::loadSettings( const QDomElement &_this ) { m_delayTimeModel.loadSettings(_this, "DelayTimeSamples" ); m_feedbackModel.loadSettings( _this, "FeebackAmount" ); @@ -54,12 +54,19 @@ void DelayControls::loadSettings(const QDomElement &_this) -void DelayControls::saveSettings(QDomDocument& doc, QDomElement& _this) +void DelayControls::saveSettings( QDomDocument& doc, QDomElement& _this ) { - m_delayTimeModel.saveSettings( doc, _this, "DelayTimeSamples"); - m_feedbackModel.saveSettings( doc, _this ,"FeebackAmount"); - m_lfoTimeModel.saveSettings( doc, _this, "LfoFrequency"); - m_lfoAmountModel.saveSettings( doc, _this ,"LfoAmount"); + m_delayTimeModel.saveSettings( doc, _this, "DelayTimeSamples" ); + m_feedbackModel.saveSettings( doc, _this ,"FeebackAmount" ); + m_lfoTimeModel.saveSettings( doc, _this, "LfoFrequency" ); + m_lfoAmountModel.saveSettings( doc, _this ,"LfoAmount" ); +} + + + +void DelayControls::changeSampleRate() +{ + m_effect->changeSampleRate(); } #include "moc_delaycontrols.cxx" diff --git a/plugins/delay/delaycontrols.h b/plugins/delay/delaycontrols.h index 5f808354f..fe7b3c3e9 100644 --- a/plugins/delay/delaycontrols.h +++ b/plugins/delay/delaycontrols.h @@ -55,6 +55,9 @@ public: return new DelayControlsDialog( this ); } +private slots: + void changeSampleRate(); + private: DelayEffect* m_effect; TempoSyncKnobModel m_delayTimeModel; diff --git a/plugins/delay/delaycontrolsdialog.cpp b/plugins/delay/delaycontrolsdialog.cpp index a55ce33b3..3dab5b1fc 100644 --- a/plugins/delay/delaycontrolsdialog.cpp +++ b/plugins/delay/delaycontrolsdialog.cpp @@ -30,7 +30,7 @@ -DelayControlsDialog::DelayControlsDialog(DelayControls *controls) : +DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) : EffectControlDialog( controls ) { setAutoFillBackground( true ); @@ -46,25 +46,25 @@ DelayControlsDialog::DelayControlsDialog(DelayControls *controls) : sampleDelayKnob->setLabel( tr( "Delay" ) ); sampleDelayKnob->setHintText( tr( "Delay Time Samples:" ) + " ", "" ); - knob * feedbackKnob = new knob( knobBright_26, this); + knob * feedbackKnob = new knob( knobBright_26, this ); feedbackKnob->move( 60,30 ); - feedbackKnob->setVolumeKnob(true); + feedbackKnob->setVolumeKnob( true) ; feedbackKnob->setModel( &controls->m_feedbackModel); feedbackKnob->setLabel( tr( "Feedback" ) ); - feedbackKnob->setHintText( tr ( "Feedback Amount:" ) + " ", ""); + feedbackKnob->setHintText( tr ( "Feedback Amount:" ) + " ", "" ); - TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this); + TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this ); lfoFreqKnob->move( 20,80 ); - lfoFreqKnob->setVolumeKnob(false); - lfoFreqKnob->setModel( &controls->m_lfoTimeModel); + lfoFreqKnob->setVolumeKnob( false ); + lfoFreqKnob->setModel( &controls->m_lfoTimeModel ); lfoFreqKnob->setLabel( tr( "Lfo Hz" ) ); - lfoFreqKnob->setHintText( tr ( "Lfo Hz:" ) + " ", ""); + lfoFreqKnob->setHintText( tr ( "Lfo Hz:" ) + " ", "" ); - knob * lfoAmtKnob = new knob( knobBright_26, this); + knob * lfoAmtKnob = new knob( knobBright_26, this ); lfoAmtKnob->move( 60,80 ); - lfoAmtKnob->setVolumeKnob(true); - lfoAmtKnob->setModel( &controls->m_lfoAmountModel); + lfoAmtKnob->setVolumeKnob( true ); + lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); lfoAmtKnob->setLabel( tr( "Lfo Amt" ) ); - lfoAmtKnob->setHintText( tr ( "Lfo Amt:" ) + " ", ""); + lfoAmtKnob->setHintText( tr ( "Lfo Amt:" ) + " ", "" ); } diff --git a/plugins/delay/delaycontrolsdialog.h b/plugins/delay/delaycontrolsdialog.h index 1850c774b..ae3730098 100644 --- a/plugins/delay/delaycontrolsdialog.h +++ b/plugins/delay/delaycontrolsdialog.h @@ -32,7 +32,7 @@ class DelayControls; class DelayControlsDialog : public EffectControlDialog { public: - DelayControlsDialog(DelayControls* controls ); + DelayControlsDialog( DelayControls* controls ); virtual ~DelayControlsDialog() { } diff --git a/plugins/delay/delayeffect.cpp b/plugins/delay/delayeffect.cpp index fbd12b4a7..f011151a5 100644 --- a/plugins/delay/delayeffect.cpp +++ b/plugins/delay/delayeffect.cpp @@ -51,9 +51,8 @@ DelayEffect::DelayEffect( Model* parent, const Plugin::Descriptor::SubPluginFeat m_delayControls( this ) { m_delay = 0; - m_delay = new StereoDelay( 192000 * 20 ); + m_delay = new StereoDelay( 20, engine::mixer()->processingSampleRate() ); m_lfo = new Lfo( engine::mixer()->processingSampleRate() ); - connect( engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) ); } @@ -74,7 +73,7 @@ DelayEffect::~DelayEffect() -bool DelayEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) +bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) { if( !isEnabled() || !isRunning () ) { @@ -103,12 +102,10 @@ bool DelayEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) return isRunning(); } - - - -void DelayEffect::sampleRateChanged() +void DelayEffect::changeSampleRate() { - m_lfo->setSamplerate(engine::mixer()->processingSampleRate()); + m_lfo->setSampleRate( engine::mixer()->processingSampleRate() ); + m_delay->setSampleRate( engine::mixer()->processingSampleRate() ); } diff --git a/plugins/delay/delayeffect.h b/plugins/delay/delayeffect.h index 1b1318e09..aa0d6e697 100644 --- a/plugins/delay/delayeffect.h +++ b/plugins/delay/delayeffect.h @@ -35,14 +35,12 @@ class DelayEffect : public Effect public: DelayEffect(Model* parent , const Descriptor::SubPluginFeatures::Key* key ); virtual ~DelayEffect(); - virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames); + virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ); virtual EffectControls* controls() { return &m_delayControls; } - -private slots: - void sampleRateChanged(); + void changeSampleRate(); private: DelayControls m_delayControls; diff --git a/plugins/delay/lfo.cpp b/plugins/delay/lfo.cpp index 6fb5472c2..f0b84a089 100644 --- a/plugins/delay/lfo.cpp +++ b/plugins/delay/lfo.cpp @@ -44,7 +44,7 @@ float Lfo::tick() if( m_amplitude > 0.0001 ) { - return ( ( output + 1.0 ) * 0.5 ) * m_amplitude; + return ( ( output * m_amplitude + 1.0 ) * 0.5 ) ; } else { return 1; diff --git a/plugins/delay/lfo.h b/plugins/delay/lfo.h index e340abeb5..105c137b7 100644 --- a/plugins/delay/lfo.h +++ b/plugins/delay/lfo.h @@ -68,7 +68,7 @@ public: - inline void setSamplerate ( int samplerate ) + inline void setSampleRate ( int samplerate ) { m_samplerate = samplerate; m_twoPiOverSr = F_2PI / samplerate; diff --git a/plugins/delay/stereodelay.cpp b/plugins/delay/stereodelay.cpp index c2d0dc254..4a7c5b081 100644 --- a/plugins/delay/stereodelay.cpp +++ b/plugins/delay/stereodelay.cpp @@ -27,15 +27,15 @@ #include "lmms_basics.h" -StereoDelay::StereoDelay( int maxLength ) +StereoDelay::StereoDelay( int maxLength, int sampleRate ) { m_buffer = 0; - m_buffer = new sampleFrame[maxLength]; - m_maxLength = maxLength; + m_maxLength = maxLength * sampleRate; m_length = m_maxLength; + m_index = 0; m_feedback = 0.0f; -// setLength( 0 ); + setSampleRate( sampleRate ); } @@ -67,5 +67,19 @@ void StereoDelay::tick( sampleFrame frame ) +void StereoDelay::setSampleRate( int sampleRate ) +{ + if( m_buffer ) + { + delete m_buffer; + } + + + m_buffer = new sampleFrame[sampleRate * m_maxLength]; +} + + + + diff --git a/plugins/delay/stereodelay.h b/plugins/delay/stereodelay.h index 6d9697948..cc174e32b 100644 --- a/plugins/delay/stereodelay.h +++ b/plugins/delay/stereodelay.h @@ -30,7 +30,7 @@ class StereoDelay { public: - StereoDelay( int maxLength ); + StereoDelay( int maxLength, int sampleRate ); ~StereoDelay(); inline void setLength( int length ) { @@ -46,6 +46,8 @@ public: } void tick( sampleFrame frame ); + void setSampleRate( int sampleRate ); + private: sampleFrame* m_buffer; int m_maxLength; From 7df8878cc3526ad43fb604ba1e31410d767b6c7c Mon Sep 17 00:00:00 2001 From: DeRobyJ Date: Tue, 18 Nov 2014 17:06:43 +0100 Subject: [PATCH 06/12] Italian Loca - Grammar Fix 01 Corrected one text: "Export Tracks" had a typo --- data/locale/it.qm | Bin 293009 -> 293007 bytes data/locale/it.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/data/locale/it.qm b/data/locale/it.qm index 3b28aa03ce2abf41df0d669e7f2184798595b068..a65af6f4e2515b2855a0bf7b81787872b3703e77 100644 GIT binary patch delta 12863 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 VKtDS;L{kK50 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 diff --git a/data/locale/it.ts b/data/locale/it.ts index af3a1d55b..4d29871d6 100644 --- a/data/locale/it.ts +++ b/data/locale/it.ts @@ -2745,7 +2745,7 @@ Visitare http://lmms.sf.net/wiki per la documentazione di LMMS. E&xport tracks... - E&sporta traccie... + E&sporta tracce... LMMS (*.mmp *.mmpz) From e0c10e030b3cfcc245d22b921fa2bc108b991801 Mon Sep 17 00:00:00 2001 From: dave Date: Tue, 18 Nov 2014 20:38:39 +0000 Subject: [PATCH 07/12] Added linear interpolation , with help from Vesa --- plugins/delay/delayeffect.cpp | 2 +- plugins/delay/stereodelay.cpp | 35 ++++++++++++++++++++++++----------- plugins/delay/stereodelay.h | 5 +++-- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/plugins/delay/delayeffect.cpp b/plugins/delay/delayeffect.cpp index f011151a5..939cae7e2 100644 --- a/plugins/delay/delayeffect.cpp +++ b/plugins/delay/delayeffect.cpp @@ -91,7 +91,7 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) { dryS[0] = buf[f][0]; dryS[1] = buf[f][1]; - m_delay->setLength( length * m_lfo->tick() ); + m_delay->setLength( ( float )length * ( float )m_lfo->tick() ); m_delay->tick( buf[f] ); buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] ); diff --git a/plugins/delay/stereodelay.cpp b/plugins/delay/stereodelay.cpp index 4a7c5b081..5c641c087 100644 --- a/plugins/delay/stereodelay.cpp +++ b/plugins/delay/stereodelay.cpp @@ -25,12 +25,15 @@ #include "stereodelay.h" #include #include "lmms_basics.h" +#include "interpolation.h" +#include "lmms_math.h" -StereoDelay::StereoDelay( int maxLength, int sampleRate ) +StereoDelay::StereoDelay( int maxTime, int sampleRate ) { m_buffer = 0; - m_maxLength = maxLength * sampleRate; + m_maxTime = maxTime; + m_maxLength = maxTime * sampleRate; m_length = m_maxLength; m_index = 0; @@ -52,16 +55,26 @@ StereoDelay::~StereoDelay() -sampleFrame oldFrame; void StereoDelay::tick( sampleFrame frame ) { - oldFrame[0] = m_buffer[m_index][0]; - oldFrame[1] = m_buffer[m_index][1]; - m_buffer[m_index][0] = frame[0] + ( oldFrame[0] * m_feedback ); - m_buffer[m_index][1] = frame[1] + ( oldFrame[1] * m_feedback ); - frame[0] = oldFrame[0]; - frame[1] = oldFrame[1]; - m_index = m_index + 1 < m_length ? m_index + 1 : 0; + m_buffer[m_index][0] = frame[0]; + m_buffer[m_index][1] = frame[1]; + + int readIndex = m_index - ( int )m_length; + if( readIndex < 0 ) + { + readIndex += m_maxLength; + } + float fract = fraction( m_length ); + frame[0] = linearInterpolate( m_buffer[readIndex][0] , + m_buffer[( readIndex+1) % m_maxLength][0], fract ); + frame[1] = linearInterpolate( m_buffer[readIndex][1] , + m_buffer[( readIndex+1) % m_maxLength][1], fract ); + + m_buffer[m_index][0] += frame[0] * m_feedback; + m_buffer[m_index][1] += frame[1] * m_feedback; + + m_index = ( m_index + 1) % m_maxLength; } @@ -75,7 +88,7 @@ void StereoDelay::setSampleRate( int sampleRate ) } - m_buffer = new sampleFrame[sampleRate * m_maxLength]; + m_buffer = new sampleFrame[( int )( sampleRate * m_maxTime )]; } diff --git a/plugins/delay/stereodelay.h b/plugins/delay/stereodelay.h index cc174e32b..d1d7457ae 100644 --- a/plugins/delay/stereodelay.h +++ b/plugins/delay/stereodelay.h @@ -32,7 +32,7 @@ class StereoDelay public: StereoDelay( int maxLength, int sampleRate ); ~StereoDelay(); - inline void setLength( int length ) + inline void setLength( float length ) { if( length <= m_maxLength && length >= 0 ) { @@ -51,9 +51,10 @@ public: private: sampleFrame* m_buffer; int m_maxLength; - int m_length; + float m_length; int m_index; float m_feedback; + float m_maxTime; }; #endif // STEREODELAY_H From 941ed33248f926b3cb1f7e73b1629ef8606d02cf Mon Sep 17 00:00:00 2001 From: Lukas W Date: Thu, 20 Nov 2014 14:17:04 +0100 Subject: [PATCH 08/12] Travis: Install nsis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c75b12b7e..4dd7576f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ deploy: provider: releases api_key: secure: d4a+x4Gugpss7JK2DcHjyBZDmEFFh4iVfKDfITSD50T6Mc6At4LMgojvEu+6qT6IyOY2vm3UVT6fhyeuWDTRDwW9tfFlaHVA0h8aTRD+eAXOA7pQ8rEMwQO3+WCKuKTfEqUkpL4wxhww8dpkv54tqeIs0S4TBqz9tk8UhzU7XbE= - file: lmms-*-win*.exe + file: lmms-${TRAVIS_TAG:1}-$TARGET_OS.exe on: tags: true all_branches: true From 22ec15f2d738388aba55b116cbbd836bdf43fb70 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Fri, 21 Nov 2014 14:41:31 +0100 Subject: [PATCH 09/12] PianoRoll arrow key behaviour tweaks * Ctrl + Left/Right moves selected notes by one bar (Old behaviour was to move the playnote) Closes #811 * Shift + Up/Down moves selected nodes by one semitone (Old behaviour was to ignore the Shift key and move the viewport) Closes #810 --- src/gui/PianoRoll.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/gui/PianoRoll.cpp b/src/gui/PianoRoll.cpp index 468631896..1444389b9 100644 --- a/src/gui/PianoRoll.cpp +++ b/src/gui/PianoRoll.cpp @@ -1232,6 +1232,11 @@ void PianoRoll::keyPressEvent( QKeyEvent* event ) // if nothing selected, shift _everything_ shiftSemiTone( +12 ); } + else if((event->modifiers() & Qt::ShiftModifier) && m_action == ActionNone) + { + // Move selected notes up by one semitone + shiftSemiTone( 1 ); + } else { // scroll @@ -1259,6 +1264,11 @@ void PianoRoll::keyPressEvent( QKeyEvent* event ) // if nothing selected, shift _everything_ shiftSemiTone( -12 ); } + else if((event->modifiers() & Qt::ShiftModifier) && m_action == ActionNone) + { + // Move selected notes down by one semitone + shiftSemiTone( -1 ); + } else { // scroll @@ -1282,12 +1292,8 @@ void PianoRoll::keyPressEvent( QKeyEvent* event ) case Qt::Key_Left: if( event->modifiers() & Qt::ControlModifier && m_action == ActionNone ) { - // move time ticker - if( ( m_timeLine->pos() -= 16 ) < 0 ) - { - m_timeLine->pos().setTicks( 0 ); - } - m_timeLine->updatePosition(); + // Move selected notes by one bar to the left + shiftPos( - MidiTime::ticksPerTact() ); } else if( event->modifiers() & Qt::ShiftModifier && m_action == ActionNone) { @@ -1320,9 +1326,8 @@ void PianoRoll::keyPressEvent( QKeyEvent* event ) case Qt::Key_Right: if( event->modifiers() & Qt::ControlModifier && m_action == ActionNone) { - // move time ticker - m_timeLine->pos() += 16; - m_timeLine->updatePosition(); + // Move selected notes by one bar to the right + shiftPos( MidiTime::ticksPerTact() ); } else if( event->modifiers() & Qt::ShiftModifier && m_action == ActionNone) { From 7e780fc057eb40cbe8ebdf8f52cebd15d70f7e97 Mon Sep 17 00:00:00 2001 From: dave Date: Sun, 23 Nov 2014 11:20:03 +0000 Subject: [PATCH 10/12] Improved ui --- plugins/delay/artwork.png | Bin 1659 -> 9620 bytes plugins/delay/delaycontrolsdialog.cpp | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/delay/artwork.png b/plugins/delay/artwork.png index 19b18740f259cdc70e3c8933ec4e57132ee97788..459c1c5441df100a14163542700c3f4ec6040b9e 100644 GIT binary patch literal 9620 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 20,30 ); + sampleDelayKnob->move( 20,10 ); sampleDelayKnob->setVolumeKnob( false ); sampleDelayKnob->setModel( &controls->m_delayTimeModel ); sampleDelayKnob->setLabel( tr( "Delay" ) ); - sampleDelayKnob->setHintText( tr( "Delay Time Samples:" ) + " ", "" ); + sampleDelayKnob->setHintText( tr( "Delay Time Seconds:" ) + " ", "" ); knob * feedbackKnob = new knob( knobBright_26, this ); - feedbackKnob->move( 60,30 ); + feedbackKnob->move( 63,10 ); feedbackKnob->setVolumeKnob( true) ; feedbackKnob->setModel( &controls->m_feedbackModel); - feedbackKnob->setLabel( tr( "Feedback" ) ); + feedbackKnob->setLabel( tr( "Regen" ) ); feedbackKnob->setHintText( tr ( "Feedback Amount:" ) + " ", "" ); TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this ); - lfoFreqKnob->move( 20,80 ); + lfoFreqKnob->move( 106,10 ); lfoFreqKnob->setVolumeKnob( false ); lfoFreqKnob->setModel( &controls->m_lfoTimeModel ); - lfoFreqKnob->setLabel( tr( "Lfo Hz" ) ); - lfoFreqKnob->setHintText( tr ( "Lfo Hz:" ) + " ", "" ); + lfoFreqKnob->setLabel( tr( "Rate" ) ); + lfoFreqKnob->setHintText( tr ( "Lfo Seconds:" ) + " ", "" ); knob * lfoAmtKnob = new knob( knobBright_26, this ); - lfoAmtKnob->move( 60,80 ); + lfoAmtKnob->move( 150,10 ); lfoAmtKnob->setVolumeKnob( true ); lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); - lfoAmtKnob->setLabel( tr( "Lfo Amt" ) ); + lfoAmtKnob->setLabel( tr( "Lfo" ) ); lfoAmtKnob->setHintText( tr ( "Lfo Amt:" ) + " ", "" ); } From d1e50b9f32123f7b3fdd461a682ae27a4b481304 Mon Sep 17 00:00:00 2001 From: pascal Date: Sun, 23 Nov 2014 15:24:42 -0500 Subject: [PATCH 11/12] Bug #1335 Hide Size and Maximize options from the intrument dialog system menu since its size is fixed. --- src/tracks/InstrumentTrack.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 66dbb29fb..eb5275d35 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -1272,7 +1272,14 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : flags |= Qt::MSWindowsFixedSizeDialogHint; flags &= ~Qt::WindowMaximizeButtonHint; subWin->setWindowFlags( flags ); - subWin->setWindowIcon( embed::getIconPixmap( "instrument_track" ) ); + + // Hide the Size and Maximize options from the system menu + // since the dialog size is fixed. + QMenu * systemMenu = subWin->systemMenu(); + systemMenu->actions().at( 2 )->setVisible( false ); // Size + systemMenu->actions().at( 4 )->setVisible( false ); // Maximize + + subWin->setWindowIcon( embed::getIconPixmap( "instrument_track" ) ); subWin->setFixedSize( subWin->size() ); subWin->hide(); } From e47c1242b897638aeb7f10da5e9e02108cdc7514 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 25 Nov 2014 00:35:47 +0100 Subject: [PATCH 12/12] Add scrollbar to instrument plugin browser Fixes #959 --- include/plugin_browser.h | 32 +++++++++++------ src/gui/MainWindow.cpp | 2 +- src/gui/plugin_browser.cpp | 72 ++++++++++++++++++++++++-------------- 3 files changed, 67 insertions(+), 39 deletions(-) diff --git a/include/plugin_browser.h b/include/plugin_browser.h index 46c890bf2..00fd8ab41 100644 --- a/include/plugin_browser.h +++ b/include/plugin_browser.h @@ -35,30 +35,40 @@ class trackContainer; -class pluginBrowser : public SideBarWidget +class PluginBrowser : public SideBarWidget { Q_OBJECT public: - pluginBrowser( QWidget * _parent ); - virtual ~pluginBrowser(); + PluginBrowser( QWidget * _parent ); + virtual ~PluginBrowser(); private: - Plugin::DescriptorList m_pluginDescriptors; - QWidget * m_view; - -} ; +}; -class pluginDescWidget : public QWidget +class PluginDescList : public QWidget { Q_OBJECT public: - pluginDescWidget( const Plugin::Descriptor & _pd, QWidget * _parent ); - virtual ~pluginDescWidget(); + PluginDescList(QWidget* parent); + +private: + Plugin::DescriptorList m_pluginDescriptors; +}; + + + + +class PluginDescWidget : public QWidget +{ + Q_OBJECT +public: + PluginDescWidget( const Plugin::Descriptor & _pd, QWidget * _parent ); + virtual ~PluginDescWidget(); protected: @@ -81,7 +91,7 @@ private: bool m_mouseOver; int m_targetHeight; -} ; +}; #endif diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 5338cf7a9..f476ec70d 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -94,7 +94,7 @@ MainWindow::MainWindow() : splitter->setChildrenCollapsible( FALSE ); QString wdir = configManager::inst()->workingDir(); - sideBar->appendTab( new pluginBrowser( splitter ) ); + sideBar->appendTab( new PluginBrowser( splitter ) ); sideBar->appendTab( new FileBrowser( configManager::inst()->userProjectsDir() + "*" + configManager::inst()->factoryProjectsDir(), diff --git a/src/gui/plugin_browser.cpp b/src/gui/plugin_browser.cpp index af243027c..9827ce2e7 100644 --- a/src/gui/plugin_browser.cpp +++ b/src/gui/plugin_browser.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "plugin_browser.h" #include "embed.h" @@ -43,7 +44,7 @@ bool pluginBefore( const Plugin::Descriptor& d1, const Plugin::Descriptor& d2 ) -pluginBrowser::pluginBrowser( QWidget * _parent ) : +PluginBrowser::PluginBrowser( QWidget * _parent ) : SideBarWidget( tr( "Instrument plugins" ), embed::getIconPixmap( "plugins" ).transformed( QTransform().rotate( 90 ) ), _parent ) { @@ -65,29 +66,20 @@ pluginBrowser::pluginBrowser( QWidget * _parent ) : m_view ); hint->setFont( pointSize<8>( hint->font() ) ); hint->setWordWrap( true ); - view_layout->addWidget( hint ); - Plugin::getDescriptorsOfAvailPlugins( m_pluginDescriptors ); - qSort( m_pluginDescriptors.begin(), m_pluginDescriptors.end(), pluginBefore ); + QScrollArea* scrollarea = new QScrollArea( m_view ); + PluginDescList* descList = new PluginDescList( m_view ); + scrollarea->setWidget(descList); + scrollarea->setWidgetResizable(true); - for( Plugin::DescriptorList::ConstIterator it = m_pluginDescriptors.begin(); - it != m_pluginDescriptors.end(); ++it ) - { - if( it->type == Plugin::Instrument ) - { - pluginDescWidget * p = new pluginDescWidget( *it, m_view ); - p->show(); - view_layout->addWidget( p ); - } - } - view_layout->addStretch(); - show(); + view_layout->addWidget(hint); + view_layout->addWidget(scrollarea); } -pluginBrowser::~pluginBrowser() +PluginBrowser::~PluginBrowser() { } @@ -96,8 +88,36 @@ pluginBrowser::~pluginBrowser() +PluginDescList::PluginDescList(QWidget *parent) : + QWidget(parent) +{ + QVBoxLayout* layout = new QVBoxLayout(this); -pluginDescWidget::pluginDescWidget( const Plugin::Descriptor & _pd, + Plugin::getDescriptorsOfAvailPlugins( m_pluginDescriptors ); + std::sort(m_pluginDescriptors.begin(), m_pluginDescriptors.end(), pluginBefore); + + + for(Plugin::DescriptorList::const_iterator it = m_pluginDescriptors.constBegin(); + it != m_pluginDescriptors.constEnd(); it++) + { + if( it->type == Plugin::Instrument ) + { + PluginDescWidget* p = new PluginDescWidget( *it, this ); + p->show(); + layout->addWidget(p); + } + } + + setLayout(layout); + layout->addStretch(); +} + + + + + + +PluginDescWidget::PluginDescWidget( const Plugin::Descriptor & _pd, QWidget * _parent ) : QWidget( _parent ), m_updateTimer( this ), @@ -115,14 +135,14 @@ pluginDescWidget::pluginDescWidget( const Plugin::Descriptor & _pd, -pluginDescWidget::~pluginDescWidget() +PluginDescWidget::~PluginDescWidget() { } -void pluginDescWidget::paintEvent( QPaintEvent * ) +void PluginDescWidget::paintEvent( QPaintEvent * ) { const QColor fill_color = m_mouseOver ? QColor( 224, 224, 224 ) : QColor( 192, 192, 192 ); @@ -152,7 +172,7 @@ void pluginDescWidget::paintEvent( QPaintEvent * ) QRect br; p.drawText( 10 + logo_size.width(), 20, width() - 58 - 5, 999, Qt::TextWordWrap, - pluginBrowser::tr( m_pluginDescriptor.description ), + PluginBrowser::tr( m_pluginDescriptor.description ), &br ); if( m_mouseOver ) { @@ -165,7 +185,7 @@ void pluginDescWidget::paintEvent( QPaintEvent * ) -void pluginDescWidget::enterEvent( QEvent * _e ) +void PluginDescWidget::enterEvent( QEvent * _e ) { m_mouseOver = true; m_targetHeight = height() + 1; @@ -176,7 +196,7 @@ void pluginDescWidget::enterEvent( QEvent * _e ) -void pluginDescWidget::leaveEvent( QEvent * _e ) +void PluginDescWidget::leaveEvent( QEvent * _e ) { m_mouseOver = false; m_targetHeight = 24; @@ -187,7 +207,7 @@ void pluginDescWidget::leaveEvent( QEvent * _e ) -void pluginDescWidget::mousePressEvent( QMouseEvent * _me ) +void PluginDescWidget::mousePressEvent( QMouseEvent * _me ) { if( _me->button() == Qt::LeftButton ) { @@ -200,7 +220,7 @@ void pluginDescWidget::mousePressEvent( QMouseEvent * _me ) -void pluginDescWidget::updateHeight() +void PluginDescWidget::updateHeight() { if( m_targetHeight > height() ) { @@ -225,5 +245,3 @@ void pluginDescWidget::updateHeight() #include "moc_plugin_browser.cxx" - -