From 9635232b45bc4470097f4df3003be4f282f0b944 Mon Sep 17 00:00:00 2001 From: mikobuntu Date: Thu, 17 Jul 2014 20:10:25 +0100 Subject: [PATCH 01/51] Update globals.h --- plugins/zynaddsubfx/zynaddsubfx/src/globals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/zynaddsubfx/zynaddsubfx/src/globals.h b/plugins/zynaddsubfx/zynaddsubfx/src/globals.h index d98e8babd..279dda525 100644 --- a/plugins/zynaddsubfx/zynaddsubfx/src/globals.h +++ b/plugins/zynaddsubfx/zynaddsubfx/src/globals.h @@ -80,7 +80,7 @@ /* * Number of part's insertion effects */ -#define NUM_PART_EFX 3 +#define NUM_PART_EFX 8 /* * Maximum number of the instrument on a part From 2a6d6c2a7e2e56c5917e50dba288faec31cd1e60 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Fri, 7 Nov 2014 12:23:39 -0800 Subject: [PATCH 02/51] Fix Apple/Clang compilation for fmaf() --- include/interpolation.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/include/interpolation.h b/include/interpolation.h index 113058e4f..6ec234036 100644 --- a/include/interpolation.h +++ b/include/interpolation.h @@ -81,7 +81,11 @@ inline float cosinusInterpolate( float v0, float v1, float x ) { const float f = ( 1.0f - cosf( x * F_PI ) ) * 0.5f; #ifdef FP_FAST_FMAF - return fmaf( f, v1-v0, v0 ); + #ifndef __clang__ + return fmaf( f, v1-v0, v0 ); + #else + return fma( f, v1-v0, v0 ); + #endif #else return f * (v1-v0) + v0; #endif @@ -94,8 +98,11 @@ inline float linearInterpolate( float v0, float v1, float x ) // take advantage of fma function if present in hardware #ifdef FP_FAST_FMAF - return fmaf( x, v1-v0, v0 ); -#else + #ifndef __clang__ + return fmaf( x, v1-v0, v0 ); + #else + return fma( x, v1-v0, v0 ); + #endif return x * (v1-v0) + v0; #endif } From 4e5d4b95a0562f59f2ada3cd0c846e6f1a7a25ad Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Fri, 7 Nov 2014 12:39:00 -0800 Subject: [PATCH 03/51] Typo, add missing "else" --- include/interpolation.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/interpolation.h b/include/interpolation.h index 6ec234036..5dd98ea3f 100644 --- a/include/interpolation.h +++ b/include/interpolation.h @@ -103,6 +103,7 @@ inline float linearInterpolate( float v0, float v1, float x ) #else return fma( x, v1-v0, v0 ); #endif +#else return x * (v1-v0) + v0; #endif } From 828dd625fadac57a545d5561cabcf7a87b4f8cb3 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Sun, 30 Nov 2014 23:00:28 -0500 Subject: [PATCH 04/51] Bump version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c2c1be51d..5fbbd979a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ INCLUDE(FindPkgConfig) SET(VERSION_MAJOR "1") SET(VERSION_MINOR "0") -SET(VERSION_PATCH "98") +SET(VERSION_PATCH "99") #SET(VERSION_SUFFIX "") SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") IF(VERSION_SUFFIX) From c3c550139689f5e973396716d09e7a1c4a901c9d Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Mon, 1 Dec 2014 21:28:29 +0200 Subject: [PATCH 05/51] Master kill switch for journalling, useful when closing program. --- include/ProjectJournal.h | 2 +- src/core/JournallingObject.cpp | 17 +++++++++++------ src/core/ProjectJournal.cpp | 12 ++++++++++++ src/core/engine.cpp | 1 + 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/include/ProjectJournal.h b/include/ProjectJournal.h index 20ff70959..5cb7920f6 100644 --- a/include/ProjectJournal.h +++ b/include/ProjectJournal.h @@ -74,7 +74,7 @@ public: } void clearJournal(); - + void stopAllJournalling(); JournallingObject * journallingObject( const jo_id_t _id ) { if( m_joIDs.contains( _id ) ) diff --git a/src/core/JournallingObject.cpp b/src/core/JournallingObject.cpp index 4e5b20aad..90d597365 100644 --- a/src/core/JournallingObject.cpp +++ b/src/core/JournallingObject.cpp @@ -70,14 +70,19 @@ void JournallingObject::addJournalCheckPoint() QDomElement JournallingObject::saveState( QDomDocument & _doc, QDomElement & _parent ) { - QDomElement _this = SerializingObject::saveState( _doc, _parent ); + if( isJournalling() ) + { + QDomElement _this = SerializingObject::saveState( _doc, _parent ); - QDomElement journalNode = _doc.createElement( "journallingObject" ); - journalNode.setAttribute( "id", id() ); - journalNode.setAttribute( "metadata", true ); - _this.appendChild( journalNode ); + QDomElement journalNode = _doc.createElement( "journallingObject" ); + journalNode.setAttribute( "id", id() ); + journalNode.setAttribute( "metadata", true ); + _this.appendChild( journalNode ); - return _this; + return _this; + } else { + return QDomElement(); + } } diff --git a/src/core/ProjectJournal.cpp b/src/core/ProjectJournal.cpp index c04f81d26..511df4059 100644 --- a/src/core/ProjectJournal.cpp +++ b/src/core/ProjectJournal.cpp @@ -168,5 +168,17 @@ void ProjectJournal::clearJournal() } } +void ProjectJournal::stopAllJournalling() +{ + for( JoIdMap::Iterator it = m_joIDs.begin(); it != m_joIDs.end(); ++it) + { + if( it.value() != NULL ) + { + it.value()->setJournalling(false); + } + } + setJournalling(false); +} + diff --git a/src/core/engine.cpp b/src/core/engine.cpp index 4931b571d..f7864e46f 100644 --- a/src/core/engine.cpp +++ b/src/core/engine.cpp @@ -115,6 +115,7 @@ void engine::init( const bool _has_gui ) void engine::destroy() { + s_projectJournal->stopAllJournalling(); s_mixer->stopProcessing(); deleteHelper( &s_projectNotes ); From e7e8e79630d646def6382aff0980c96ee1635bef Mon Sep 17 00:00:00 2001 From: dave Date: Thu, 4 Dec 2014 02:39:26 +0000 Subject: [PATCH 06/51] Changed default delay time to 0.5 seconds from 2.0. --- plugins/delay/delaycontrols.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/delay/delaycontrols.cpp b/plugins/delay/delaycontrols.cpp index cc0aadbb5..afcb0f76d 100644 --- a/plugins/delay/delaycontrols.cpp +++ b/plugins/delay/delaycontrols.cpp @@ -32,7 +32,7 @@ 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_delayTimeModel( 0.5, 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.0, 0.0, 2.0, 0.0001, 2000.0, this, tr ( "Lfo Amount" ) ) From fc6374a07b576c3921c4f68acd83968e5337f887 Mon Sep 17 00:00:00 2001 From: mikobuntu Date: Thu, 4 Dec 2014 19:49:40 +0000 Subject: [PATCH 07/51] reverted changes to globals.h --- plugins/zynaddsubfx/zynaddsubfx/src/globals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/zynaddsubfx/zynaddsubfx/src/globals.h b/plugins/zynaddsubfx/zynaddsubfx/src/globals.h index 279dda525..d98e8babd 100644 --- a/plugins/zynaddsubfx/zynaddsubfx/src/globals.h +++ b/plugins/zynaddsubfx/zynaddsubfx/src/globals.h @@ -80,7 +80,7 @@ /* * Number of part's insertion effects */ -#define NUM_PART_EFX 8 +#define NUM_PART_EFX 3 /* * Maximum number of the instrument on a part From 762b667b4753e7db8452da68a849654b9b38dfca Mon Sep 17 00:00:00 2001 From: mikobuntu Date: Thu, 4 Dec 2014 19:56:54 +0000 Subject: [PATCH 08/51] Added TR909-RimShot preset to Kicker :///home/mikobuntu/lmms/presets/Kicker/RimShot4.xpf --- data/presets/Kicker/TR909-RimShot.xpf | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 data/presets/Kicker/TR909-RimShot.xpf diff --git a/data/presets/Kicker/TR909-RimShot.xpf b/data/presets/Kicker/TR909-RimShot.xpf new file mode 100644 index 000000000..415fd0cee --- /dev/null +++ b/data/presets/Kicker/TR909-RimShot.xpf @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + From 8c0ab4dfecfd861d00e3af06af3874eddc1284eb Mon Sep 17 00:00:00 2001 From: mikobuntu Date: Thu, 4 Dec 2014 20:55:39 +0000 Subject: [PATCH 09/51] Fixed naming of Kicker preset (RimShot to TR909-RimShot) --- data/presets/Kicker/TR909-RimShot.xpf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/presets/Kicker/TR909-RimShot.xpf b/data/presets/Kicker/TR909-RimShot.xpf index 415fd0cee..e8626db29 100644 --- a/data/presets/Kicker/TR909-RimShot.xpf +++ b/data/presets/Kicker/TR909-RimShot.xpf @@ -2,7 +2,7 @@ - + From cefee3a72100d77074ef85aa77fe287d3f992708 Mon Sep 17 00:00:00 2001 From: dave Date: Sat, 6 Dec 2014 18:28:19 +0000 Subject: [PATCH 10/51] added s postfix to knob values where applicable. --- plugins/delay/delaycontrolsdialog.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/delay/delaycontrolsdialog.cpp b/plugins/delay/delaycontrolsdialog.cpp index badc9f84f..88f253f78 100644 --- a/plugins/delay/delaycontrolsdialog.cpp +++ b/plugins/delay/delaycontrolsdialog.cpp @@ -44,27 +44,30 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) : sampleDelayKnob->setVolumeKnob( false ); sampleDelayKnob->setModel( &controls->m_delayTimeModel ); sampleDelayKnob->setLabel( tr( "Delay" ) ); - sampleDelayKnob->setHintText( tr( "Delay Time Seconds:" ) + " ", "" ); + sampleDelayKnob->setHintText( tr( "Delay Time" ) , " s" ); + knob * feedbackKnob = new knob( knobBright_26, this ); feedbackKnob->move( 63,10 ); feedbackKnob->setVolumeKnob( true) ; feedbackKnob->setModel( &controls->m_feedbackModel); feedbackKnob->setLabel( tr( "Regen" ) ); - feedbackKnob->setHintText( tr ( "Feedback Amount:" ) + " ", "" ); + feedbackKnob->setHintText( tr ( "Feedback Amount:" ) , "" ); TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this ); lfoFreqKnob->move( 106,10 ); lfoFreqKnob->setVolumeKnob( false ); lfoFreqKnob->setModel( &controls->m_lfoTimeModel ); lfoFreqKnob->setLabel( tr( "Rate" ) ); - lfoFreqKnob->setHintText( tr ( "Lfo Seconds:" ) + " ", "" ); + lfoFreqKnob->setHintText( tr ( "Lfo" ) + " ", " s" ); + TempoSyncKnob * lfoAmtKnob = new TempoSyncKnob( knobBright_26, this ); lfoAmtKnob->move( 150,10 ); lfoAmtKnob->setVolumeKnob( false ); lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); lfoAmtKnob->setLabel( tr( "Lfo" ) ); - lfoAmtKnob->setHintText( tr ( "Lfo Amt:" ) + " ", "" ); + lfoAmtKnob->setHintText( tr ( "Lfo Amt:" ) , " s" ); + } From 4a2a60255c39039c6ef49e7ca92e175a3b790f44 Mon Sep 17 00:00:00 2001 From: dave Date: Sat, 6 Dec 2014 18:34:24 +0000 Subject: [PATCH 11/51] Added postfix "s" to knobs where relevant, cleaned up unintentional white space --- plugins/delay/delaycontrolsdialog.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/delay/delaycontrolsdialog.cpp b/plugins/delay/delaycontrolsdialog.cpp index 88f253f78..019d7208a 100644 --- a/plugins/delay/delaycontrolsdialog.cpp +++ b/plugins/delay/delaycontrolsdialog.cpp @@ -46,7 +46,6 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) : sampleDelayKnob->setLabel( tr( "Delay" ) ); sampleDelayKnob->setHintText( tr( "Delay Time" ) , " s" ); - knob * feedbackKnob = new knob( knobBright_26, this ); feedbackKnob->move( 63,10 ); feedbackKnob->setVolumeKnob( true) ; @@ -59,8 +58,7 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) : lfoFreqKnob->setVolumeKnob( false ); lfoFreqKnob->setModel( &controls->m_lfoTimeModel ); lfoFreqKnob->setLabel( tr( "Rate" ) ); - lfoFreqKnob->setHintText( tr ( "Lfo" ) + " ", " s" ); - + lfoFreqKnob->setHintText( tr ( "Lfo" ) , " s" ); TempoSyncKnob * lfoAmtKnob = new TempoSyncKnob( knobBright_26, this ); lfoAmtKnob->move( 150,10 ); From decac202980c1f545053d7c65ace34d96933f743 Mon Sep 17 00:00:00 2001 From: dave Date: Sat, 6 Dec 2014 19:47:39 +0000 Subject: [PATCH 12/51] Replaced whitespace in knob definitions, for consistancy --- plugins/delay/delaycontrolsdialog.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/delay/delaycontrolsdialog.cpp b/plugins/delay/delaycontrolsdialog.cpp index 019d7208a..00c46b105 100644 --- a/plugins/delay/delaycontrolsdialog.cpp +++ b/plugins/delay/delaycontrolsdialog.cpp @@ -44,28 +44,28 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) : sampleDelayKnob->setVolumeKnob( false ); sampleDelayKnob->setModel( &controls->m_delayTimeModel ); sampleDelayKnob->setLabel( tr( "Delay" ) ); - sampleDelayKnob->setHintText( tr( "Delay Time" ) , " s" ); + sampleDelayKnob->setHintText( tr( "Delay Time" ) + " ", " s" ); knob * feedbackKnob = new knob( knobBright_26, this ); feedbackKnob->move( 63,10 ); feedbackKnob->setVolumeKnob( true) ; feedbackKnob->setModel( &controls->m_feedbackModel); feedbackKnob->setLabel( tr( "Regen" ) ); - feedbackKnob->setHintText( tr ( "Feedback Amount:" ) , "" ); + feedbackKnob->setHintText( tr ( "Feedback Amount" ) + " " , "" ); TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this ); lfoFreqKnob->move( 106,10 ); lfoFreqKnob->setVolumeKnob( false ); lfoFreqKnob->setModel( &controls->m_lfoTimeModel ); lfoFreqKnob->setLabel( tr( "Rate" ) ); - lfoFreqKnob->setHintText( tr ( "Lfo" ) , " s" ); + lfoFreqKnob->setHintText( tr ( "Lfo") + " ", " s" ); TempoSyncKnob * lfoAmtKnob = new TempoSyncKnob( knobBright_26, this ); lfoAmtKnob->move( 150,10 ); lfoAmtKnob->setVolumeKnob( false ); lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); lfoAmtKnob->setLabel( tr( "Lfo" ) ); - lfoAmtKnob->setHintText( tr ( "Lfo Amt:" ) , " s" ); + lfoAmtKnob->setHintText( tr ( "Lfo Amt" ) + " " , " s" ); } From f7428546428722aa013a86f70b724cf923b57b7b Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 7 Dec 2014 00:07:30 +0200 Subject: [PATCH 13/51] Bitcrush effect plugin --- include/lmms_math.h | 11 +- plugins/Bitcrush/Bitcrush.cpp | 245 +++++++++++++++++++++ plugins/Bitcrush/Bitcrush.h | 83 +++++++ plugins/Bitcrush/BitcrushControlDialog.cpp | 113 ++++++++++ plugins/Bitcrush/BitcrushControlDialog.h | 44 ++++ plugins/Bitcrush/BitcrushControls.cpp | 89 ++++++++ plugins/Bitcrush/BitcrushControls.h | 82 +++++++ plugins/Bitcrush/CMakeLists.txt | 3 + plugins/Bitcrush/artwork.png | Bin 0 -> 52367 bytes plugins/CMakeLists.txt | 1 + 10 files changed, 670 insertions(+), 1 deletion(-) create mode 100644 plugins/Bitcrush/Bitcrush.cpp create mode 100644 plugins/Bitcrush/Bitcrush.h create mode 100644 plugins/Bitcrush/BitcrushControlDialog.cpp create mode 100644 plugins/Bitcrush/BitcrushControlDialog.h create mode 100644 plugins/Bitcrush/BitcrushControls.cpp create mode 100644 plugins/Bitcrush/BitcrushControls.h create mode 100644 plugins/Bitcrush/CMakeLists.txt create mode 100644 plugins/Bitcrush/artwork.png diff --git a/include/lmms_math.h b/include/lmms_math.h index 1177c6921..5882739bd 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -130,7 +130,17 @@ static inline int fast_rand() return( (unsigned)( next / 65536 ) % 32768 ); } +static inline double fastRand( double range ) +{ + static const double fast_rand_ratio = 1.0f / FAST_RAND_MAX; + return fast_rand() * range * fast_rand_ratio; +} +static inline float fastRandf( float range ) +{ + static const float fast_rand_ratio = 1.0f / FAST_RAND_MAX; + return fast_rand() * range * fast_rand_ratio; +} // source: http://martin.ankerl.com/2007/10/04/optimized-pow-approximation-for-java-and-c-c/ static inline double fastPow( double a, double b ) @@ -241,5 +251,4 @@ static inline float fastSqrt( float n ) return u.f; } - #endif diff --git a/plugins/Bitcrush/Bitcrush.cpp b/plugins/Bitcrush/Bitcrush.cpp new file mode 100644 index 000000000..e9ab9639a --- /dev/null +++ b/plugins/Bitcrush/Bitcrush.cpp @@ -0,0 +1,245 @@ +/* + * Bitcrush.cpp - A native bitcrusher + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 "Bitcrush.h" +#include "embed.cpp" + +const int OS_RATE = 5; +const float OS_RATIO = 1.0f / OS_RATE; +const float CUTOFF_RATIO = 0.353553391f; +const int SILENCEFRAMES = 10; + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT bitcrush_plugin_descriptor = +{ + STRINGIFY( PLUGIN_NAME ), + "Bitcrush", + QT_TRANSLATE_NOOP( "pluginBrowser", "An oversampling bitcrusher" ), + "Vesa Kivimäki ", + 0x0100, + Plugin::Effect, + new PluginPixmapLoader( "logo" ), + NULL, + NULL +}; + +} + +BitcrushEffect::BitcrushEffect( Model * parent, const Descriptor::SubPluginFeatures::Key * key ) : + Effect( &bitcrush_plugin_descriptor, parent, key ), + m_controls( this ), + m_sampleRate( Engine::mixer()->processingSampleRate() ), + m_filter( m_sampleRate ) +{ + m_buffer = MM_ALLOC( sampleFrame, Engine::mixer()->framesPerPeriod() * OS_RATE ); + m_filter.setLowpass( m_sampleRate * ( CUTOFF_RATIO * OS_RATIO ) ); + m_needsUpdate = true; + + m_bitCounterL = 0.0f; + m_bitCounterR = 0.0f; + + m_left = 0.0f; + m_right = 0.0f; + + m_silenceCounter = 0; +} + +BitcrushEffect::~BitcrushEffect() +{ + MM_FREE( m_buffer ); +} + + +void BitcrushEffect::sampleRateChanged() +{ + m_sampleRate = Engine::mixer()->processingSampleRate(); + m_filter.setSampleRate( m_sampleRate ); + m_filter.setLowpass( m_sampleRate * CUTOFF_RATIO ); + m_needsUpdate = true; +} + + +inline float BitcrushEffect::depthCrush( float in ) +{ + return roundf( in * (float) m_levels ) * m_levelsRatio; +} + +inline float BitcrushEffect::noise( float amt ) +{ + return fastRandf( amt * 2.0f ) - amt; +} + +bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) +{ + // update values + if( m_needsUpdate || m_controls.m_rateEnabled.isValueChanged() ) + { + m_rateEnabled = m_controls.m_rateEnabled.value(); + m_bitCounterL = 0.0f; + m_bitCounterR = 0.0f; + } + if( m_needsUpdate || m_controls.m_depthEnabled.isValueChanged() ) + { + m_depthEnabled = m_controls.m_depthEnabled.value(); + } + if( m_needsUpdate || m_controls.m_rate.isValueChanged() || m_controls.m_stereoDiff.isValueChanged() ) + { + const float rate = m_controls.m_rate.value(); + const float diff = m_controls.m_stereoDiff.value() * 0.005 * rate; + + m_rateCoeffL = ( m_sampleRate * OS_RATE ) / ( rate - diff ); + m_rateCoeffR = ( m_sampleRate * OS_RATE ) / ( rate + diff ); + + m_bitCounterL = 0.0f; + m_bitCounterR = 0.0f; + } + if( m_needsUpdate || m_controls.m_levels.isValueChanged() ) + { + m_levels = m_controls.m_levels.value(); + m_levelsRatio = 1.0f / (float) m_levels; + } + if( m_needsUpdate || m_controls.m_inGain.isValueChanged() ) + { + m_inGain = dbvToAmp( m_controls.m_inGain.value() ); + } + if( m_needsUpdate || m_controls.m_outGain.isValueChanged() ) + { + m_outGain = dbvToAmp( m_controls.m_outGain.value() ); + } + if( m_needsUpdate || m_controls.m_outClip.isValueChanged() ) + { + m_outClip = dbvToAmp( m_controls.m_outClip.value() ); + } + m_needsUpdate = false; + + const float noiseAmt = m_controls.m_inNoise.value() * 0.01f; + + // read input buffer and write it to oversampled buffer + if( m_rateEnabled ) // rate crushing enabled so do that + { + for( int f = 0; f < frames; ++f ) + { + for( int o = 0; o < OS_RATE; ++o ) + { + m_buffer[f * OS_RATE + o][0] = m_left; + m_buffer[f * OS_RATE + o][1] = m_right; + m_bitCounterL += 1.0f; + m_bitCounterR += 1.0f; + if( m_bitCounterL > m_rateCoeffL ) + { + m_bitCounterL -= m_rateCoeffL; + m_left = m_depthEnabled + ? depthCrush( buf[f][0] * m_inGain + noise( buf[f][0] * noiseAmt ) ) + : buf[f][0] * m_inGain + noise( buf[f][0] * noiseAmt ); + } + if( m_bitCounterR > m_rateCoeffR ) + { + m_bitCounterR -= m_rateCoeffR; + m_right = m_depthEnabled + ? depthCrush( buf[f][1] * m_inGain + noise( buf[f][1] * noiseAmt ) ) + : buf[f][1] * m_inGain + noise( buf[f][1] * noiseAmt ); + } + } + } + } + else // rate crushing disabled: simply oversample with zero-order hold + { + for( int f = 0; f < frames; ++f ) + { + for( int o = 0; o < OS_RATE; ++o ) + { + m_buffer[f * OS_RATE + o][0] = m_depthEnabled + ? depthCrush( buf[f][0] * m_inGain + noise( buf[f][0] * noiseAmt ) ) + : buf[f][0] * m_inGain + noise( buf[f][0] * noiseAmt ); + m_buffer[f * OS_RATE + o][1] = m_depthEnabled + ? depthCrush( buf[f][1] * m_inGain + noise( buf[f][1] * noiseAmt ) ) + : buf[f][1] * m_inGain + noise( buf[f][1] * noiseAmt ); + } + } + } + + // the oversampled buffer is now written, so filter it to reduce aliasing + + for( int f = 0; f < frames * OS_RATE; ++f ) + { + if( qMax( qAbs( m_buffer[f][0] ), qAbs( m_buffer[f][1] ) ) >= 1.0e-10f ) + { + m_silenceCounter = 0; + m_buffer[f][0] = m_filter.update( m_buffer[f][0], 0 ); + m_buffer[f][1] = m_filter.update( m_buffer[f][1], 1 ); + } + else + { + if( m_silenceCounter > SILENCEFRAMES ) + { + m_buffer[f][0] = m_buffer[f][1] = 0.0f; + } + else + { + ++m_silenceCounter; + m_buffer[f][0] = m_filter.update( m_buffer[f][0], 0 ); + m_buffer[f][1] = m_filter.update( m_buffer[f][1], 1 ); + } + } + } + + + // now downsample and write it back to main buffer + + double outSum = 0.0; + const float d = dryLevel(); + const float w = wetLevel(); + for( int f = 0; f < frames; ++f ) + { + float lsum = 0.0f; + float rsum = 0.0f; + for( int o = 0; o < OS_RATE; ++o ) + { + lsum += m_buffer[f * OS_RATE + o][0] * OS_RATIO; + rsum += m_buffer[f * OS_RATE + o][1] * OS_RATIO; + } + buf[f][0] = d * buf[f][0] + w * qBound( -m_outClip, lsum, m_outClip ) * m_outGain; + buf[f][1] = d * buf[f][1] + w * qBound( -m_outClip, rsum, m_outClip ) * m_outGain; + outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; + } + + checkGate( outSum / frames ); + + return isRunning(); +} + + +extern "C" +{ + +// necessary for getting instance out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model* parent, void* data ) +{ + return new BitcrushEffect( parent, static_cast( data ) ); +} + +} diff --git a/plugins/Bitcrush/Bitcrush.h b/plugins/Bitcrush/Bitcrush.h new file mode 100644 index 000000000..0c599e107 --- /dev/null +++ b/plugins/Bitcrush/Bitcrush.h @@ -0,0 +1,83 @@ +/* + * Bitcrush.h - A native bitcrusher + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 BITCRUSH_H +#define BITCRUSH_H + +#include "Effect.h" +#include "BitcrushControls.h" +#include "ValueBuffer.h" +#include "lmms_math.h" +#include "BasicFilters.h" + +class BitcrushEffect : public Effect +{ +public: + BitcrushEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ); + virtual ~BitcrushEffect(); + virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ); + + virtual EffectControls* controls() + { + return &m_controls; + } + +private: + void sampleRateChanged(); + float depthCrush( float in ); + float noise( float amt ); + + BitcrushControls m_controls; + + sampleFrame * m_buffer; + float m_sampleRate; + StereoLinkwitzRiley m_filter; + + float m_bitCounterL; + float m_rateCoeffL; + float m_bitCounterR; + float m_rateCoeffR; + bool m_rateEnabled; + + float m_left; + float m_right; + + int m_levels; + float m_levelsRatio; + bool m_depthEnabled; + + float m_inGain; + float m_outGain; + float m_outClip; + + bool m_needsUpdate; + + int m_silenceCounter; + + friend class BitcrushControls; +}; + +#endif diff --git a/plugins/Bitcrush/BitcrushControlDialog.cpp b/plugins/Bitcrush/BitcrushControlDialog.cpp new file mode 100644 index 000000000..3faa7e52c --- /dev/null +++ b/plugins/Bitcrush/BitcrushControlDialog.cpp @@ -0,0 +1,113 @@ +/* + * BitcrushControlDialog.cpp - A native bitcrusher + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 + +#include "BitcrushControlDialog.h" +#include "BitcrushControls.h" +#include "embed.h" +#include "ToolTip.h" +#include "LedCheckbox.h" +#include "Knob.h" + +BitcrushControlDialog::BitcrushControlDialog( BitcrushControls * controls ) : + EffectControlDialog( controls ) +{ + setAutoFillBackground( true ); + QPalette pal; + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); + setPalette( pal ); + setFixedSize( 215, 120 ); + + // labels + QLabel * inLabel = new QLabel( tr( "IN" ), this ); + inLabel->move( 12, 10); + + QLabel * outLabel = new QLabel( tr( "OUT" ), this ); + outLabel->move( 176, 10 ); + + // input knobs + Knob * inGain = new Knob( knobBright_26, this ); + inGain->move( 12, 25 ); + inGain->setModel( & controls->m_inGain ); + inGain->setLabel( tr( "GAIN" ) ); + inGain->setHintText( tr( "Input Gain:" ) + " ", " dBV" ); + + Knob * inNoise = new Knob( knobBright_26, this ); + inNoise->move( 12, 70 ); + inNoise->setModel( & controls->m_inNoise ); + inNoise->setLabel( tr( "NOIS" ) ); + inNoise->setHintText( tr( "Input Noise:" ) + " ", "%" ); + + + // output knobs + Knob * outGain = new Knob( knobBright_26, this ); + outGain->move( 176, 25 ); + outGain->setModel( & controls->m_outGain ); + outGain->setLabel( tr( "GAIN" ) ); + outGain->setHintText( tr( "Output Gain:" ) + " ", " dBV" ); + + Knob * outClip = new Knob( knobBright_26, this ); + outClip->move( 176, 70 ); + outClip->setModel( & controls->m_outClip ); + outClip->setLabel( tr( "CLIP" ) ); + outClip->setHintText( tr( "Output Clip:" ) + " ", "%" ); + + + // leds + LedCheckBox * rateEnabled = new LedCheckBox( tr( "Rate" ), this, tr( "Rate Enabled" ), LedCheckBox::Green ); + rateEnabled->move( 50, 30 ); + rateEnabled->setModel( & controls->m_rateEnabled ); + ToolTip::add( rateEnabled, tr( "Enable samplerate-crushing" ) ); + + LedCheckBox * depthEnabled = new LedCheckBox( tr( "Depth" ), this, tr( "Depth Enabled" ), LedCheckBox::Green ); + depthEnabled->move( 50, 80 ); + depthEnabled->setModel( & controls->m_depthEnabled ); + ToolTip::add( depthEnabled, tr( "Enable bitdepth-crushing" ) ); + + + // rate crushing knobs + Knob * rate = new Knob( knobBright_26, this ); + rate->move( 100, 20 ); + rate->setModel( & controls->m_rate ); + rate->setLabel( tr( "Rate" ) ); + rate->setHintText( tr( "Sample rate:" ) + " ", " Hz" ); + + Knob * stereoDiff = new Knob( knobBright_26, this ); + stereoDiff->move( 140, 20 ); + stereoDiff->setModel( & controls->m_stereoDiff ); + stereoDiff->setLabel( tr( "STD" ) ); + stereoDiff->setHintText( tr( "Stereo difference:" ) + " ", "%" ); + + + // depth crushing knob + Knob * levels = new Knob( knobBright_26, this ); + levels->move( 140, 70 ); + levels->setModel( & controls->m_levels ); + levels->setLabel( tr( "Levels" ) ); + levels->setHintText( tr( "Levels:" ) + " ", "" ); +} diff --git a/plugins/Bitcrush/BitcrushControlDialog.h b/plugins/Bitcrush/BitcrushControlDialog.h new file mode 100644 index 000000000..69c4dd5f5 --- /dev/null +++ b/plugins/Bitcrush/BitcrushControlDialog.h @@ -0,0 +1,44 @@ +/* + * BitcrushControlDialog.h - A native bitcrusher + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 BITCRUSH_CONTROL_DIALOG_H +#define BITCRUSH_CONTROL_DIALOG_H + +#include "EffectControlDialog.h" + +class BitcrushControls; + +class BitcrushControlDialog : public EffectControlDialog +{ + Q_OBJECT +public: + BitcrushControlDialog( BitcrushControls * controls ); + virtual ~BitcrushControlDialog() + { + } +}; + +#endif diff --git a/plugins/Bitcrush/BitcrushControls.cpp b/plugins/Bitcrush/BitcrushControls.cpp new file mode 100644 index 000000000..e67cef0d1 --- /dev/null +++ b/plugins/Bitcrush/BitcrushControls.cpp @@ -0,0 +1,89 @@ +/* + * BitcrushControls.cpp - A native bitcrusher + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 "BitcrushControls.h" +#include "Bitcrush.h" +#include "lmms_math.h" + + +BitcrushControls::BitcrushControls( BitcrushEffect * eff ) : + EffectControls( eff ), + m_effect( eff ), + m_inGain( 0.0f, -20.0f, 20.0f, 0.1f, this, "Input gain" ), + m_inNoise( 0.0f, 0.0f, 100.0f, 0.1f, this, "Input noise" ), + m_outGain( 0.0f, -20.0f, 20.0f, 0.1f, this, "Output gain" ), + m_outClip( 0.0f, -20.0f, 20.0f, 0.1f, this, "Output clip" ), + m_rate( 44100.f, 20.f, 44100.f, 1.0f, this, "Samplerate" ), + m_stereoDiff( 0.f, 0.f, 50.f, 0.1f, this, "Stereo difference" ), + m_levels( 256.f, 1.f, 256.f, 1.0f, this, "Levels" ), + m_rateEnabled( true, this, "Rate enabled" ), + m_depthEnabled( true, this, "Depth enabled" ) +{ + m_rate.setStrictStepSize( true ); + m_levels.setStrictStepSize( true ); + + connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) ); +} + +BitcrushControls::~BitcrushControls() +{ +} + +void BitcrushControls::saveSettings( QDomDocument & doc, QDomElement & elem ) +{ + m_inGain.saveSettings( doc, elem, "ingain" ); + m_inNoise.saveSettings( doc, elem, "innoise" ); + m_outGain.saveSettings( doc, elem, "outgain" ); + m_outClip.saveSettings( doc, elem, "outclip" ); + m_rate.saveSettings( doc, elem, "rate" ); + m_stereoDiff.saveSettings( doc, elem, "stereodiff" ); + m_levels.saveSettings( doc, elem, "levels" ); + m_rateEnabled.saveSettings( doc, elem, "rateon" ); + m_depthEnabled.saveSettings( doc, elem, "depthon" ); +} + + +void BitcrushControls::loadSettings( const QDomElement & elem ) +{ + m_inGain.loadSettings( elem, "ingain" ); + m_inNoise.loadSettings( elem, "innoise" ); + m_outGain.loadSettings( elem, "outgain" ); + m_outClip.loadSettings( elem, "outclip" ); + m_rate.loadSettings( elem, "rate" ); + m_stereoDiff.loadSettings( elem, "stereodiff" ); + m_levels.loadSettings( elem, "levels" ); + m_rateEnabled.loadSettings( elem, "rateon" ); + m_depthEnabled.loadSettings( elem, "depthon" ); + + m_effect->m_needsUpdate = true; +} + +void BitcrushControls::sampleRateChanged() +{ + m_effect->sampleRateChanged(); +} diff --git a/plugins/Bitcrush/BitcrushControls.h b/plugins/Bitcrush/BitcrushControls.h new file mode 100644 index 000000000..42ec34e38 --- /dev/null +++ b/plugins/Bitcrush/BitcrushControls.h @@ -0,0 +1,82 @@ +/* + * BitcrushControls.h - A native bitcrusher + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 BITCRUSH_CONTROLS_H +#define BITCRUSH_CONTROLS_H + +#include "EffectControls.h" +#include "BitcrushControlDialog.h" + +class BitcrushEffect; + +class BitcrushControls : public EffectControls +{ + Q_OBJECT +public: + BitcrushControls( BitcrushEffect * eff ); + virtual ~BitcrushControls(); + + virtual void saveSettings( QDomDocument & doc, QDomElement & elem ); + virtual void loadSettings( const QDomElement & elem ); + inline virtual QString nodeName() const + { + return( "bitcrushcontrols" ); + } + + virtual int controlCount() + { + return( 9 ); + } + + virtual EffectControlDialog * createView() + { + return( new BitcrushControlDialog( this ) ); + } + +private slots: + void sampleRateChanged(); + +private: + BitcrushEffect * m_effect; + + FloatModel m_inGain; + FloatModel m_inNoise; + + FloatModel m_outGain; + FloatModel m_outClip; + + FloatModel m_rate; + FloatModel m_stereoDiff; + + FloatModel m_levels; + + BoolModel m_rateEnabled; + BoolModel m_depthEnabled; + + friend class BitcrushControlDialog; + friend class BitcrushEffect; +}; + +#endif diff --git a/plugins/Bitcrush/CMakeLists.txt b/plugins/Bitcrush/CMakeLists.txt new file mode 100644 index 000000000..ca70afceb --- /dev/null +++ b/plugins/Bitcrush/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(bitcrush Bitcrush.cpp BitcrushControls.cpp BitcrushControlDialog.cpp MOCFILES BitcrushControls.h BitcrushControlDialog.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") diff --git a/plugins/Bitcrush/artwork.png b/plugins/Bitcrush/artwork.png new file mode 100644 index 0000000000000000000000000000000000000000..c0c97bdd525f16d86aef5c1377154adae3c075a8 GIT binary patch literal 52367 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�f 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 literal 0 HcmV?d00001 diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index e6f3509ee..4df760ecd 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -2,6 +2,7 @@ ADD_SUBDIRECTORY(Amplifier) ADD_SUBDIRECTORY(audio_file_processor) ADD_SUBDIRECTORY(BassBooster) ADD_SUBDIRECTORY(bit_invader) +ADD_SUBDIRECTORY(Bitcrush) ADD_SUBDIRECTORY(carlabase) ADD_SUBDIRECTORY(carlapatchbay) ADD_SUBDIRECTORY(carlarack) From 68f5ccce64c82f8fcddd38a9e57f54037a19a139 Mon Sep 17 00:00:00 2001 From: Vesa V Date: Sun, 7 Dec 2014 00:12:19 +0200 Subject: [PATCH 14/51] Update lmms_math.h oops, extra f --- include/lmms_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 5882739bd..96e6fdcd2 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -132,7 +132,7 @@ static inline int fast_rand() static inline double fastRand( double range ) { - static const double fast_rand_ratio = 1.0f / FAST_RAND_MAX; + static const double fast_rand_ratio = 1.0 / FAST_RAND_MAX; return fast_rand() * range * fast_rand_ratio; } From e7b7cf54bb1327e1e993b12920c6cf7a8667fd5b Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 7 Dec 2014 21:11:11 +0200 Subject: [PATCH 15/51] Remove distortion from sv filters --- include/BasicFilters.h | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/include/BasicFilters.h b/include/BasicFilters.h index cd4687ef0..98c69474a 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -289,7 +289,6 @@ public: m_sampleRatio( 1.0f / m_sampleRate ), m_subFilter( NULL ) { - m_svsr = 1.0f - expf( -4646.39874051f / m_sampleRate ); clearHistory(); } @@ -326,7 +325,6 @@ public: m_delay2[_chnl] = 0.0f; m_delay3[_chnl] = 0.0f; m_delay4[_chnl] = 0.0f; - m_sva[_chnl] = 0.0f; } } @@ -409,7 +407,6 @@ public: case Lowpass_SV: case Bandpass_SV: { - m_sva[_chnl] += ( qAbs( _in0 ) - m_sva[_chnl] ) * m_svsr; float highpass; for( int i = 0; i < 2; ++i ) // 2x oversample @@ -425,14 +422,13 @@ public: /* mix filter output into output buffer */ return m_type == Lowpass_SV - ? atanf( 3.0f * m_delay4[_chnl] * m_sva[_chnl] ) - : atanf( 3.0f * m_delay3[_chnl] * m_sva[_chnl] ); + ? m_delay4[_chnl] + : m_delay3[_chnl]; break; } case Highpass_SV: { - m_sva[_chnl] += ( qAbs( _in0 ) - m_sva[_chnl] ) * m_svsr; float hp; for( int i = 0; i < 2; ++i ) // 2x oversample @@ -442,13 +438,12 @@ public: m_delay1[_chnl] = m_svf1 * hp + m_delay1[_chnl]; } - return atanf( 3.0f * hp * m_sva[_chnl] ); + return hp; break; } case Notch_SV: { - m_sva[_chnl] += ( qAbs( _in0 ) - m_sva[_chnl] ) * m_svsr; float hp1, hp2; for( int i = 0; i < 2; ++i ) // 2x oversample @@ -463,7 +458,7 @@ public: } /* mix filter output into output buffer */ - return atanf( 1.5f * ( m_delay4[_chnl] + hp1 ) * m_sva[_chnl] ); + return m_delay4[_chnl] + hp1; break; } @@ -899,7 +894,7 @@ private: float m_vfa[4], m_vfb[4], m_vfc[4], m_vfq; // coeffs for Lowpass_SV (state-variant lowpass) - float m_svf1, m_svf2, m_svq, m_svsr; + float m_svf1, m_svf2, m_svq; typedef sample_t frame[CHANNELS]; @@ -916,7 +911,7 @@ private: frame m_vfbp[6], m_vfhp[6], m_vflast[6]; // in/out history for Lowpass_SV (state-variant lowpass) - frame m_delay1, m_delay2, m_delay3, m_delay4, m_sva; + frame m_delay1, m_delay2, m_delay3, m_delay4; FilterTypes m_type; bool m_doubleFilter; From dbc404cca12e611e44fae08e054d3a399c75c6cf Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 7 Dec 2014 22:29:23 +0200 Subject: [PATCH 16/51] Fix FX mixer race condition --- src/core/FxMixer.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index b1494e00d..7169a25ee 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -104,7 +104,6 @@ void FxChannel::incrementDeps() { m_queued = true; MixerWorkerThread::addJob( this ); - m_dependenciesMet = 0; } } @@ -174,7 +173,7 @@ void FxChannel::doProcessing() // only start fxchain when we have input... m_fxChain.startRunning(); } - + m_stillRunning = m_fxChain.processAudioBuffer( m_buffer, fpp, m_hasInput ); m_peakLeft = qMax( m_peakLeft, Engine::mixer()->peakValueLeft( m_buffer, fpp ) * v ); @@ -184,8 +183,8 @@ void FxChannel::doProcessing() { m_peakLeft = m_peakRight = 0.0f; } - - // increment dependency counter of all receivers + + // increment dependency counter of all receivers processed(); } @@ -430,7 +429,7 @@ FxRoute * FxMixer::createRoute( FxChannel * from, FxChannel * to, float amount ) // add us to fxmixer's list Engine::fxMixer()->m_fxRoutes.append( route ); m_sendsMutex.unlock(); - + return route; } @@ -613,6 +612,7 @@ void FxMixer::masterMix( sampleFrame * _buf ) m_fxChannels[i]->m_queued = false; // also reset hasInput m_fxChannels[i]->m_hasInput = false; + m_fxChannels[i]->m_dependenciesMet = 0; } } @@ -688,7 +688,7 @@ void FxMixer::saveSettings( QDomDocument & _doc, QDomElement & _this ) ch->m_sends[si]->amount()->saveSettings( _doc, sendsDom, "amount" ); } } -} +} // make sure we have at least num channels void FxMixer::allocateChannelsTo(int num) From 2e8534955b5064da736b19ed08c6b0bd6358cbca Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 7 Dec 2014 22:29:23 +0200 Subject: [PATCH 17/51] Fix FX mixer race condition Conflicts: src/core/FxMixer.cpp --- src/core/FxMixer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 37a91b7d4..d47f34c8b 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -103,7 +103,6 @@ void FxChannel::incrementDeps() { m_queued = true; MixerWorkerThread::addJob( this ); - m_dependenciesMet = 0; } } @@ -164,8 +163,8 @@ void FxChannel::doProcessing( sampleFrame * _buf ) { m_peakLeft = m_peakRight = 0.0f; } - - // increment dependency counter of all receivers + + // increment dependency counter of all receivers processed(); } @@ -358,7 +357,7 @@ FxRoute * FxMixer::createRoute( FxChannel * from, FxChannel * to, float amount ) // add us to fxmixer's list engine::fxMixer()->m_fxRoutes.append( route ); m_sendsMutex.unlock(); - + return route; } @@ -527,6 +526,7 @@ void FxMixer::masterMix( sampleFrame * _buf ) m_fxChannels[i]->m_queued = false; // also reset hasInput m_fxChannels[i]->m_hasInput = false; + m_fxChannels[i]->m_dependenciesMet = 0; } } @@ -600,7 +600,7 @@ void FxMixer::saveSettings( QDomDocument & _doc, QDomElement & _this ) ch->m_sends[si]->amount()->saveSettings( _doc, sendsDom, "amount" ); } } -} +} // make sure we have at least num channels void FxMixer::allocateChannelsTo(int num) From 4993eba3c179876676e76a9b7bff0daf0b025bc1 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 8 Dec 2014 10:57:21 +0000 Subject: [PATCH 18/51] Remove unused and unnessary +" " in all knob.setHintText calls --- plugins/Amplifier/AmplifierControlDialog.cpp | 8 ++--- .../BassBooster/BassBoosterControlDialog.cpp | 6 ++-- .../DualFilter/DualFilterControlDialog.cpp | 2 +- .../MultitapEchoControlDialog.cpp | 6 ++-- .../audio_file_processor.cpp | 8 ++--- plugins/bit_invader/bit_invader.cpp | 2 +- .../dynamics_processor_control_dialog.cpp | 8 ++--- plugins/flanger/flangercontrolsdialog.cpp | 10 +++---- plugins/kicker/kicker.cpp | 20 ++++++------- plugins/lb302/lb302.cpp | 12 ++++---- plugins/monstro/Monstro.h | 4 +-- plugins/nes/Nes.h | 2 +- plugins/opl2/opl2instrument.cpp | 2 +- plugins/organic/organic.cpp | 16 +++++----- plugins/papu/papu_instrument.cpp | 30 +++++++++---------- .../peak_controller_effect_control_dialog.cpp | 12 ++++---- plugins/sid/sid_instrument.cpp | 18 +++++------ .../stereoenhancer_control_dialog.cpp | 2 +- .../stereomatrix_control_dialog.cpp | 8 ++--- .../triple_oscillator/TripleOscillator.cpp | 16 +++++----- plugins/vibed/vibed.cpp | 24 +++++++-------- plugins/watsyn/Watsyn.h | 4 +-- .../waveshaper/waveshaper_control_dialog.cpp | 4 +-- plugins/zynaddsubfx/ZynAddSubFx.cpp | 14 ++++----- src/gui/LfoControllerDialog.cpp | 8 ++--- src/gui/widgets/EnvelopeAndLfoView.cpp | 22 +++++++------- src/gui/widgets/InstrumentFunctionViews.cpp | 8 ++--- .../widgets/InstrumentSoundShapingView.cpp | 4 +-- src/gui/widgets/LadspaControlView.cpp | 2 +- src/tracks/InstrumentTrack.cpp | 10 +++---- src/tracks/SampleTrack.cpp | 2 +- 31 files changed, 147 insertions(+), 147 deletions(-) diff --git a/plugins/Amplifier/AmplifierControlDialog.cpp b/plugins/Amplifier/AmplifierControlDialog.cpp index 360458827..d5b17e4d1 100644 --- a/plugins/Amplifier/AmplifierControlDialog.cpp +++ b/plugins/Amplifier/AmplifierControlDialog.cpp @@ -45,26 +45,26 @@ AmplifierControlDialog::AmplifierControlDialog( AmplifierControls* controls ) : volumeKnob -> setVolumeKnob( true ); volumeKnob->setModel( &controls->m_volumeModel ); volumeKnob->setLabel( tr( "VOL" ) ); - volumeKnob->setHintText( tr( "Volume:" ) + " ", "%" ); + volumeKnob->setHintText( tr( "Volume:" ) , "%" ); Knob * panKnob = new Knob( knobBright_26, this); panKnob -> move( 60, 30 ); panKnob->setModel( &controls->m_panModel ); panKnob->setLabel( tr( "PAN" ) ); - panKnob->setHintText( tr( "Panning:" ) + " ", "" ); + panKnob->setHintText( tr( "Panning:" ) , "" ); Knob * leftKnob = new Knob( knobBright_26, this); leftKnob -> move( 20, 80 ); leftKnob -> setVolumeKnob( true ); leftKnob->setModel( &controls->m_leftModel ); leftKnob->setLabel( tr( "LEFT" ) ); - leftKnob->setHintText( tr( "Left gain:" ) + " ", "%" ); + leftKnob->setHintText( tr( "Left gain:" ) , "%" ); Knob * rightKnob = new Knob( knobBright_26, this); rightKnob -> move( 60, 80 ); rightKnob -> setVolumeKnob( true ); rightKnob->setModel( &controls->m_rightModel ); rightKnob->setLabel( tr( "RIGHT" ) ); - rightKnob->setHintText( tr( "Right gain:" ) + " ", "%" ); + rightKnob->setHintText( tr( "Right gain:" ) , "%" ); } diff --git a/plugins/BassBooster/BassBoosterControlDialog.cpp b/plugins/BassBooster/BassBoosterControlDialog.cpp index cd299fb6d..a589576dc 100644 --- a/plugins/BassBooster/BassBoosterControlDialog.cpp +++ b/plugins/BassBooster/BassBoosterControlDialog.cpp @@ -47,17 +47,17 @@ BassBoosterControlDialog::BassBoosterControlDialog( BassBoosterControls* control Knob * freqKnob = new Knob( knobBright_26, this); freqKnob->setModel( &controls->m_freqModel ); freqKnob->setLabel( tr( "FREQ" ) ); - freqKnob->setHintText( tr( "Frequency:" ) + " ", "Hz" ); + freqKnob->setHintText( tr( "Frequency:" ) , "Hz" ); Knob * gainKnob = new Knob( knobBright_26, this ); gainKnob->setModel( &controls->m_gainModel ); gainKnob->setLabel( tr( "GAIN" ) ); - gainKnob->setHintText( tr( "Gain:" ) + " ", "" ); + gainKnob->setHintText( tr( "Gain:" ) , "" ); Knob * ratioKnob = new Knob( knobBright_26, this ); ratioKnob->setModel( &controls->m_ratioModel ); ratioKnob->setLabel( tr( "RATIO" ) ); - ratioKnob->setHintText( tr( "Ratio:" ) + " ", "" ); + ratioKnob->setHintText( tr( "Ratio:" ) , "" ); l->addWidget( freqKnob ); l->addWidget( gainKnob ); diff --git a/plugins/DualFilter/DualFilterControlDialog.cpp b/plugins/DualFilter/DualFilterControlDialog.cpp index 368d9dd34..0e7f19807 100644 --- a/plugins/DualFilter/DualFilterControlDialog.cpp +++ b/plugins/DualFilter/DualFilterControlDialog.cpp @@ -38,7 +38,7 @@ name -> move( x, y ); \ name ->setModel( &controls-> model ); \ name ->setLabel( tr( label ) ); \ - name ->setHintText( tr( hint ) + " ", unit ); + name ->setHintText( tr( hint ) , unit ); diff --git a/plugins/MultitapEcho/MultitapEchoControlDialog.cpp b/plugins/MultitapEcho/MultitapEchoControlDialog.cpp index 7780bf94c..52fa2bdec 100644 --- a/plugins/MultitapEcho/MultitapEchoControlDialog.cpp +++ b/plugins/MultitapEcho/MultitapEchoControlDialog.cpp @@ -82,19 +82,19 @@ MultitapEchoControlDialog::MultitapEchoControlDialog( MultitapEchoControls * con stepLength->move( 100, 245 ); stepLength->setModel( & controls->m_stepLength ); stepLength->setLabel( tr( "Length" ) ); - stepLength->setHintText( tr( "Step length:" ) + " ", " ms" ); + stepLength->setHintText( tr( "Step length:" ) , " ms" ); Knob * dryGain = new Knob( knobBright_26, this ); dryGain->move( 150, 245 ); dryGain->setModel( & controls->m_dryGain ); dryGain->setLabel( tr( "Dry" ) ); - dryGain->setHintText( tr( "Dry Gain:" ) + " ", " dBV" ); + dryGain->setHintText( tr( "Dry Gain:" ) , " dBV" ); Knob * stages = new Knob( knobBright_26, this ); stages->move( 200, 245 ); stages->setModel( & controls->m_stages ); stages->setLabel( tr( "Stages" ) ); - stages->setHintText( tr( "Lowpass stages:" ) + " ", "x" ); + stages->setHintText( tr( "Lowpass stages:" ) , "x" ); // switch led LedCheckBox * swapInputs = new LedCheckBox( "Swap inputs", this, tr( "Swap inputs" ), LedCheckBox::Green ); diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index d18145b70..024494947 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -543,7 +543,7 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, m_ampKnob = new Knob( knobBright_26, this ); m_ampKnob->setVolumeKnob( true ); m_ampKnob->move( 5, 108 ); - m_ampKnob->setHintText( tr( "Amplify:" )+" ", "%" ); + m_ampKnob->setHintText( tr( "Amplify:" ), "%" ); m_ampKnob->setWhatsThis( tr( "With this knob you can set the amplify ratio. When you " "set a value of 100% your sample isn't changed. " @@ -552,21 +552,21 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, m_startKnob = new AudioFileProcessorWaveView::knob( this ); m_startKnob->move( 45, 108 ); - m_startKnob->setHintText( tr( "Startpoint:" )+" ", "" ); + m_startKnob->setHintText( tr( "Startpoint:" ), "" ); m_startKnob->setWhatsThis( tr( "With this knob you can set the point where " "AudioFileProcessor should begin playing your sample. " ) ); m_endKnob = new AudioFileProcessorWaveView::knob( this ); m_endKnob->move( 125, 108 ); - m_endKnob->setHintText( tr( "Endpoint:" )+" ", "" ); + m_endKnob->setHintText( tr( "Endpoint:" ), "" ); m_endKnob->setWhatsThis( tr( "With this knob you can set the point where " "AudioFileProcessor should stop playing your sample. " ) ); m_loopKnob = new AudioFileProcessorWaveView::knob( this ); m_loopKnob->move( 85, 108 ); - m_loopKnob->setHintText( tr( "Loopback point:" )+" ", "" ); + m_loopKnob->setHintText( tr( "Loopback point:" ), "" ); m_loopKnob->setWhatsThis( tr( "With this knob you can set the point where " "the loop starts. " ) ); diff --git a/plugins/bit_invader/bit_invader.cpp b/plugins/bit_invader/bit_invader.cpp index 9fc371ae9..09b5cda95 100644 --- a/plugins/bit_invader/bit_invader.cpp +++ b/plugins/bit_invader/bit_invader.cpp @@ -335,7 +335,7 @@ bitInvaderView::bitInvaderView( Instrument * _instrument, m_sampleLengthKnob = new Knob( knobDark_28, this ); m_sampleLengthKnob->move( 6, 201 ); - m_sampleLengthKnob->setHintText( tr( "Sample Length" ) + " ", "" ); + m_sampleLengthKnob->setHintText( tr( "Sample Length" ), "" ); m_graph = new Graph( this, Graph::NearestStyle, 204, 134 ); m_graph->move(23,59); // 55,120 - 2px border diff --git a/plugins/dynamics_processor/dynamics_processor_control_dialog.cpp b/plugins/dynamics_processor/dynamics_processor_control_dialog.cpp index 9b5037106..2ae1b8d78 100644 --- a/plugins/dynamics_processor/dynamics_processor_control_dialog.cpp +++ b/plugins/dynamics_processor/dynamics_processor_control_dialog.cpp @@ -63,7 +63,7 @@ dynProcControlDialog::dynProcControlDialog( inputKnob -> move( 14, 251 ); inputKnob->setModel( &_controls->m_inputModel ); inputKnob->setLabel( tr( "INPUT" ) ); - inputKnob->setHintText( tr( "Input gain:" ) + " ", "" ); + inputKnob->setHintText( tr( "Input gain:" ) , "" ); Knob * outputKnob = new Knob( knobBright_26, this ); outputKnob -> setVolumeKnob( true ); @@ -71,19 +71,19 @@ dynProcControlDialog::dynProcControlDialog( outputKnob -> move( 54, 251 ); outputKnob->setModel( &_controls->m_outputModel ); outputKnob->setLabel( tr( "OUTPUT" ) ); - outputKnob->setHintText( tr( "Output gain:" ) + " ", "" ); + outputKnob->setHintText( tr( "Output gain:" ) , "" ); Knob * attackKnob = new Knob( knobBright_26, this); attackKnob -> move( 11, 291 ); attackKnob->setModel( &_controls->m_attackModel ); attackKnob->setLabel( tr( "ATTACK" ) ); - attackKnob->setHintText( tr( "Peak attack time:" ) + " ", "ms" ); + attackKnob->setHintText( tr( "Peak attack time:" ) , "ms" ); Knob * releaseKnob = new Knob( knobBright_26, this ); releaseKnob -> move( 52, 291 ); releaseKnob->setModel( &_controls->m_releaseModel ); releaseKnob->setLabel( tr( "RELEASE" ) ); - releaseKnob->setHintText( tr( "Peak release time:" ) + " ", "ms" ); + releaseKnob->setHintText( tr( "Peak release time:" ) , "ms" ); //waveform control buttons diff --git a/plugins/flanger/flangercontrolsdialog.cpp b/plugins/flanger/flangercontrolsdialog.cpp index 971208771..b404ea39a 100644 --- a/plugins/flanger/flangercontrolsdialog.cpp +++ b/plugins/flanger/flangercontrolsdialog.cpp @@ -45,35 +45,35 @@ FlangerControlsDialog::FlangerControlsDialog( FlangerControls *controls ) : delayKnob->setVolumeKnob( false ); delayKnob->setModel( &controls->m_delayTimeModel ); delayKnob->setLabel( tr( "Delay" ) ); - delayKnob->setHintText( tr( "Delay Time :" ) + " ", "" ); + delayKnob->setHintText( tr( "Delay Time:" ) + " ", "" ); TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this ); lfoFreqKnob->move( 53,10 ); lfoFreqKnob->setVolumeKnob( false ); lfoFreqKnob->setModel( &controls->m_lfoFrequencyModel ); lfoFreqKnob->setLabel( tr( "Lfo Hz" ) ); - lfoFreqKnob->setHintText( tr ( "Lfo Hz:" ) + " ", "" ); + lfoFreqKnob->setHintText( tr ( "Lfo:" ) , "s" ); Knob * lfoAmtKnob = new Knob( knobBright_26, this ); lfoAmtKnob->move( 86,10 ); lfoAmtKnob->setVolumeKnob( false ); lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); lfoAmtKnob->setLabel( tr( "Amt" ) ); - lfoAmtKnob->setHintText( tr ( "Amt" ) + " ", "" ); + lfoAmtKnob->setHintText( tr ( "Amt:" ) , "" ); Knob * feedbackKnob = new Knob( knobBright_26, this ); feedbackKnob->move( 119,10 ); feedbackKnob->setVolumeKnob( true) ; feedbackKnob->setModel( &controls->m_feedbackModel ); feedbackKnob->setLabel( tr( "Regen" ) ); - feedbackKnob->setHintText( tr ( "Feedback Amount:" ) + " ", "" ); + feedbackKnob->setHintText( tr ( "Feedback Amount:" ) , "" ); Knob * whiteNoiseKnob = new Knob( knobBright_26, this ); whiteNoiseKnob->move( 150,10 ); whiteNoiseKnob->setVolumeKnob( true) ; whiteNoiseKnob->setModel( &controls->m_whiteNoiseAmountModel ); whiteNoiseKnob->setLabel( tr( "Noise" ) ); - whiteNoiseKnob->setHintText( tr ( "White Noise Amount:" ) + " ", "" ); + whiteNoiseKnob->setHintText( tr ( "White Noise Amount:" ) , "" ); LedCheckBox* invertCb = new LedCheckBox( tr( "" ), this ); invertCb->move( 15,55 ); diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index a3868a257..ddd68abc7 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -280,43 +280,43 @@ kickerInstrumentView::kickerInstrumentView( Instrument * _instrument, const int END_COL = COL1 + 48; m_startFreqKnob = new kickerLargeKnob( this ); - m_startFreqKnob->setHintText( tr( "Start frequency:" ) + " ", "Hz" ); + m_startFreqKnob->setHintText( tr( "Start frequency:" ), "Hz" ); m_startFreqKnob->move( COL1, ROW1 ); m_endFreqKnob = new kickerLargeKnob( this ); - m_endFreqKnob->setHintText( tr( "End frequency:" ) + " ", "Hz" ); + m_endFreqKnob->setHintText( tr( "End frequency:" ), "Hz" ); m_endFreqKnob->move( END_COL, ROW1 ); m_slopeKnob = new kickerKnob( this ); - m_slopeKnob->setHintText( tr( "Frequency Slope:" ) + " ", "" ); + m_slopeKnob->setHintText( tr( "Frequency Slope:" ), "" ); m_slopeKnob->move( COL3, ROW1 ); m_gainKnob = new kickerKnob( this ); - m_gainKnob->setHintText( tr( "Gain:" ) + " ", "" ); + m_gainKnob->setHintText( tr( "Gain:" ), "" ); m_gainKnob->move( COL1, ROW3 ); m_decayKnob = new kickerEnvKnob( this ); - m_decayKnob->setHintText( tr( "Envelope Length:" ) + " ", "ms" ); + m_decayKnob->setHintText( tr( "Envelope Length:" ), "ms" ); m_decayKnob->move( COL2, ROW3 ); m_envKnob = new kickerKnob( this ); - m_envKnob->setHintText( tr( "Envelope Slope:" ) + " ", "" ); + m_envKnob->setHintText( tr( "Envelope Slope:" ), "" ); m_envKnob->move( COL3, ROW3 ); m_clickKnob = new kickerKnob( this ); - m_clickKnob->setHintText( tr( "Click:" ) + " ", "" ); + m_clickKnob->setHintText( tr( "Click:" ), "" ); m_clickKnob->move( COL5, ROW1 ); m_noiseKnob = new kickerKnob( this ); - m_noiseKnob->setHintText( tr( "Noise:" ) + " ", "" ); + m_noiseKnob->setHintText( tr( "Noise:" ), "" ); m_noiseKnob->move( COL5, ROW3 ); m_distKnob = new kickerKnob( this ); - m_distKnob->setHintText( tr( "Distortion Start:" ) + " ", "" ); + m_distKnob->setHintText( tr( "Distortion Start:" ), "" ); m_distKnob->move( COL4, ROW2 ); m_distEndKnob = new kickerKnob( this ); - m_distEndKnob->setHintText( tr( "Distortion End:" ) + " ", "" ); + m_distEndKnob->setHintText( tr( "Distortion End:" ), "" ); m_distEndKnob->move( COL5, ROW2 ); m_startNoteToggle = new LedCheckBox( "", this, "", LedCheckBox::Green ); diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 46e7be982..d1d352d0b 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -824,22 +824,22 @@ lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) : // GUI m_vcfCutKnob = new Knob( knobBright_26, this ); m_vcfCutKnob->move( 75, 130 ); - m_vcfCutKnob->setHintText( tr( "Cutoff Freq:" ) + " ", "" ); + m_vcfCutKnob->setHintText( tr( "Cutoff Freq:" ), "" ); m_vcfCutKnob->setLabel( "" ); m_vcfResKnob = new Knob( knobBright_26, this ); m_vcfResKnob->move( 120, 130 ); - m_vcfResKnob->setHintText( tr( "Resonance:" ) + " ", "" ); + m_vcfResKnob->setHintText( tr( "Resonance:" ), "" ); m_vcfResKnob->setLabel( "" ); m_vcfModKnob = new Knob( knobBright_26, this ); m_vcfModKnob->move( 165, 130 ); - m_vcfModKnob->setHintText( tr( "Env Mod:" ) + " ", "" ); + m_vcfModKnob->setHintText( tr( "Env Mod:" ), "" ); m_vcfModKnob->setLabel( "" ); m_vcfDecKnob = new Knob( knobBright_26, this ); m_vcfDecKnob->move( 210, 130 ); - m_vcfDecKnob->setHintText( tr( "Decay:" ) + " ", "" ); + m_vcfDecKnob->setHintText( tr( "Decay:" ), "" ); m_vcfDecKnob->setLabel( "" ); m_slideToggle = new LedCheckBox( "", this ); @@ -860,12 +860,12 @@ lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) : m_slideDecKnob = new Knob( knobBright_26, this ); m_slideDecKnob->move( 210, 75 ); - m_slideDecKnob->setHintText( tr( "Slide Decay:" ) + " ", "" ); + m_slideDecKnob->setHintText( tr( "Slide Decay:" ), "" ); m_slideDecKnob->setLabel( ""); m_distKnob = new Knob( knobBright_26, this ); m_distKnob->move( 210, 190 ); - m_distKnob->setHintText( tr( "DIST:" ) + " ", "" ); + m_distKnob->setHintText( tr( "DIST:" ), "" ); m_distKnob->setLabel( tr( "")); diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index c041ffe38..b0bf366d0 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -46,14 +46,14 @@ #define makeknob( name, x, y, hint, unit, oname ) \ name = new Knob( knobStyled, view ); \ name ->move( x, y ); \ - name ->setHintText( tr( hint ) + " ", unit ); \ + name ->setHintText( tr( hint ), unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 20, 20 ); #define maketsknob( name, x, y, hint, unit, oname ) \ name = new TempoSyncKnob( knobStyled, view ); \ name ->move( x, y ); \ - name ->setHintText( tr( hint ) + " ", unit ); \ + name ->setHintText( tr( hint ), unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 20, 20 ); diff --git a/plugins/nes/Nes.h b/plugins/nes/Nes.h index 645a980dc..29db58b79 100644 --- a/plugins/nes/Nes.h +++ b/plugins/nes/Nes.h @@ -38,7 +38,7 @@ #define makeknob( name, x, y, hint, unit, oname ) \ name = new Knob( knobStyled, this ); \ name ->move( x, y ); \ - name ->setHintText( tr( hint ) + " ", unit ); \ + name ->setHintText( tr( hint ), unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 29, 29 ); diff --git a/plugins/opl2/opl2instrument.cpp b/plugins/opl2/opl2instrument.cpp index f99c38296..188a05323 100644 --- a/plugins/opl2/opl2instrument.cpp +++ b/plugins/opl2/opl2instrument.cpp @@ -586,7 +586,7 @@ opl2instrumentView::opl2instrumentView( Instrument * _instrument, #define KNOB_GEN(knobname, hinttext, hintunit,xpos,ypos) \ knobname = new Knob( knobStyled, this );\ - knobname->setHintText( tr(hinttext) + "", hintunit );\ + knobname->setHintText( tr(hinttext), hintunit );\ knobname->setFixedSize(22,22);\ knobname->setCenterPointX(11.0);\ knobname->setCenterPointY(11.0);\ diff --git a/plugins/organic/organic.cpp b/plugins/organic/organic.cpp index 08699d18d..2e45aa8e9 100644 --- a/plugins/organic/organic.cpp +++ b/plugins/organic/organic.cpp @@ -433,7 +433,7 @@ organicInstrumentView::organicInstrumentView( Instrument * _instrument, m_fx1Knob = new organicKnob( this ); m_fx1Knob->move( 15, 201 ); m_fx1Knob->setFixedSize( 37, 47 ); - m_fx1Knob->setHintText( tr( "Distortion:" ) + " ", QString() ); + m_fx1Knob->setHintText( tr( "Distortion:" ), QString() ); m_fx1Knob->setObjectName( "fx1Knob" ); m_fx1Knob->setWhatsThis( tr( "The distortion knob adds distortion to the output of the instrument. " ) ); @@ -442,7 +442,7 @@ organicInstrumentView::organicInstrumentView( Instrument * _instrument, m_volKnob->setVolumeKnob( true ); m_volKnob->move( 60, 201 ); m_volKnob->setFixedSize( 37, 47 ); - m_volKnob->setHintText( tr( "Volume:" ) + " ", "%" ); + m_volKnob->setHintText( tr( "Volume:" ), "%" ); m_volKnob->setObjectName( "volKnob" ); m_volKnob->setWhatsThis( tr( "The volume knob controls the volume of the output of the instrument. " "It is cumulative with the instrument window's volume control. " ) ); @@ -513,7 +513,7 @@ void organicInstrumentView::modelChanged() connect( &oi->m_osc[i]->m_oscModel, SIGNAL( dataChanged() ), this, SLOT( updateKnobHint() ) ); - oscKnob->setHintText( tr( "Osc %1 waveform:" ).arg( i + 1 ) + " ", QString() ); + oscKnob->setHintText( tr( "Osc %1 waveform:" ).arg( i + 1 ), QString() ); // setup volume-knob Knob * volKnob = new Knob( knobStyled, this ); @@ -521,19 +521,19 @@ void organicInstrumentView::modelChanged() volKnob->move( x + i * colWidth, y + rowHeight*1 ); volKnob->setFixedSize( 21, 21 ); volKnob->setHintText( tr( "Osc %1 volume:" ).arg( - i + 1 ) + " ", "%" ); + i + 1 ), "%" ); // setup panning-knob Knob * panKnob = new organicKnob( this ); panKnob->move( x + i * colWidth, y + rowHeight*2 ); panKnob->setHintText( tr("Osc %1 panning:").arg( - i + 1 ) + " ", "" ); + i + 1 ), "" ); // setup knob for fine-detuning Knob * detuneKnob = new organicKnob( this ); detuneKnob->move( x + i * colWidth, y + rowHeight*3 ); detuneKnob->setHintText( tr( "Osc %1 stereo detuning" ).arg( i + 1 ) - + " ", " " + + , " " + tr( "cents" ) ); m_oscKnobs[i] = OscillatorKnobs( harmKnob, volKnob, oscKnob, panKnob, detuneKnob ); @@ -557,9 +557,9 @@ void organicInstrumentView::updateKnobHint() const float harm = oi->m_osc[i]->m_harmModel.value(); const float wave = oi->m_osc[i]->m_oscModel.value(); - m_oscKnobs[i].m_harmKnob->setHintText( tr( "Osc %1 harmonic:" ) + " ", " (" + + m_oscKnobs[i].m_harmKnob->setHintText( tr( "Osc %1 harmonic:" ), " (" + HARMONIC_NAMES[ static_cast( harm ) ] + ")" ); - m_oscKnobs[i].m_oscKnob->setHintText( tr( "Osc %1 waveform:" ) + " ", " (" + + m_oscKnobs[i].m_oscKnob->setHintText( tr( "Osc %1 waveform:" ), " (" + WAVEFORM_NAMES[ static_cast( wave ) ] + ")" ); } } diff --git a/plugins/papu/papu_instrument.cpp b/plugins/papu/papu_instrument.cpp index 947c9d841..1af0da914 100644 --- a/plugins/papu/papu_instrument.cpp +++ b/plugins/papu/papu_instrument.cpp @@ -456,7 +456,7 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, setPalette( pal ); m_ch1SweepTimeKnob = new papuKnob( this ); - m_ch1SweepTimeKnob->setHintText( tr( "Sweep Time:" ) + " ", "" ); + m_ch1SweepTimeKnob->setHintText( tr( "Sweep Time:" ), "" ); m_ch1SweepTimeKnob->move( 5 + 4*32, 106 ); ToolTip::add( m_ch1SweepTimeKnob, tr( "Sweep Time" ) ); m_ch1SweepTimeKnob->setWhatsThis( tr( "The amount of increase or" @@ -464,7 +464,7 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch1SweepRtShiftKnob = new papuKnob( this ); m_ch1SweepRtShiftKnob->setHintText( tr( "Sweep RtShift amount:" ) - + " ", "" ); + , "" ); m_ch1SweepRtShiftKnob->move( 5 + 3*32, 106 ); ToolTip::add( m_ch1SweepRtShiftKnob, tr( "Sweep RtShift amount" ) ); m_ch1SweepRtShiftKnob->setWhatsThis( tr( "The rate at which increase or" @@ -472,7 +472,7 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch1WavePatternDutyKnob = new papuKnob( this ); m_ch1WavePatternDutyKnob->setHintText( tr( "Wave pattern duty:" ) - + " ", "" ); + , "" ); m_ch1WavePatternDutyKnob->move( 5 + 2*32, 106 ); ToolTip::add( m_ch1WavePatternDutyKnob, tr( "Wave Pattern Duty" ) ); m_ch1WavePatternDutyKnob->setWhatsThis( tr( "The duty cycle is the ratio of" @@ -481,14 +481,14 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch1VolumeKnob = new papuKnob( this ); m_ch1VolumeKnob->setHintText( tr( "Square Channel 1 Volume:" ) - + " ", "" ); + , "" ); m_ch1VolumeKnob->move( 5, 106 ); ToolTip::add( m_ch1VolumeKnob, tr( "Square Channel 1 Volume:" ) ); m_ch1VolumeKnob->setWhatsThis( tr( "Square Channel 1 Volume" ) ); m_ch1SweepStepLengthKnob = new papuKnob( this ); m_ch1SweepStepLengthKnob->setHintText( tr( "Length of each step in sweep:" ) - + " ", "" ); + , "" ); m_ch1SweepStepLengthKnob->move( 5 + 32, 106 ); ToolTip::add( m_ch1SweepStepLengthKnob, tr( "Length of each step in sweep" ) ); m_ch1SweepStepLengthKnob->setWhatsThis( tr( "The delay between step change" ) ); @@ -497,7 +497,7 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch2WavePatternDutyKnob = new papuKnob( this ); m_ch2WavePatternDutyKnob->setHintText( tr( "Wave pattern duty:" ) - + " ", "" ); + , "" ); m_ch2WavePatternDutyKnob->move( 5 + 2*32, 155 ); ToolTip::add( m_ch2WavePatternDutyKnob, tr( "Wave pattern duty" ) ); m_ch2WavePatternDutyKnob->setWhatsThis( tr( "The duty cycle is the ratio of" @@ -506,14 +506,14 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch2VolumeKnob = new papuKnob( this ); m_ch2VolumeKnob->setHintText( tr( "Square Channel 2 Volume:" ) - + " ", "" ); + , "" ); m_ch2VolumeKnob->move( 5, 155 ); ToolTip::add( m_ch2VolumeKnob, tr( "Square Channel 2 Volume" ) ); m_ch2VolumeKnob->setWhatsThis( tr( "Square Channel 2 Volume" ) ); m_ch2SweepStepLengthKnob = new papuKnob( this ); m_ch2SweepStepLengthKnob->setHintText( tr( "Length of each step in sweep:" ) - + " ", "" ); + , "" ); m_ch2SweepStepLengthKnob->move( 5 + 32, 155 ); ToolTip::add( m_ch2SweepStepLengthKnob, tr( "Length of each step in sweep" ) ); m_ch2SweepStepLengthKnob->setWhatsThis( tr( "The delay between step change" ) ); @@ -521,7 +521,7 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch3VolumeKnob = new papuKnob( this ); - m_ch3VolumeKnob->setHintText( tr( "Wave Channel Volume:" ) + " ", "" ); + m_ch3VolumeKnob->setHintText( tr( "Wave Channel Volume:" ), "" ); m_ch3VolumeKnob->move( 5, 204 ); ToolTip::add( m_ch3VolumeKnob, tr( "Wave Channel Volume" ) ); m_ch3VolumeKnob->setWhatsThis( tr( "Wave Channel Volume" ) ); @@ -529,14 +529,14 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch4VolumeKnob = new papuKnob( this ); - m_ch4VolumeKnob->setHintText( tr( "Noise Channel Volume:" ) + " ", "" ); + m_ch4VolumeKnob->setHintText( tr( "Noise Channel Volume:" ), "" ); m_ch4VolumeKnob->move( 144, 155 ); ToolTip::add( m_ch4VolumeKnob, tr( "Noise Channel Volume" ) ); m_ch4VolumeKnob->setWhatsThis( tr( "Noise Channel Volume" ) ); m_ch4SweepStepLengthKnob = new papuKnob( this ); m_ch4SweepStepLengthKnob->setHintText( tr( "Length of each step in sweep:" ) - + " ", "" ); + , "" ); m_ch4SweepStepLengthKnob->move( 144 + 32, 155 ); ToolTip::add( m_ch4SweepStepLengthKnob, tr( "Length of each step in sweep" ) ); m_ch4SweepStepLengthKnob->setWhatsThis( tr( "The delay between step change" ) ); @@ -544,22 +544,22 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_so1VolumeKnob = new papuKnob( this ); - m_so1VolumeKnob->setHintText( tr( "SO1 Volume (Right):" ) + " ", "" ); + m_so1VolumeKnob->setHintText( tr( "SO1 Volume (Right):" ), "" ); m_so1VolumeKnob->move( 5, 58 ); ToolTip::add( m_so1VolumeKnob, tr( "SO1 Volume (Right)" ) ); m_so2VolumeKnob = new papuKnob( this ); - m_so2VolumeKnob->setHintText( tr( "SO2 Volume (Left):" ) + " ", "" ); + m_so2VolumeKnob->setHintText( tr( "SO2 Volume (Left):" ), "" ); m_so2VolumeKnob->move( 5 + 32, 58 ); ToolTip::add( m_so2VolumeKnob, tr( "SO2 Volume (Left)" ) ); m_trebleKnob = new papuKnob( this ); - m_trebleKnob->setHintText( tr( "Treble:" ) + " ", "" ); + m_trebleKnob->setHintText( tr( "Treble:" ), "" ); m_trebleKnob->move( 5 + 2*32, 58 ); ToolTip::add( m_trebleKnob, tr( "Treble" ) ); m_bassKnob = new papuKnob( this ); - m_bassKnob->setHintText( tr( "Bass:" ) + " ", "" ); + m_bassKnob->setHintText( tr( "Bass:" ), "" ); m_bassKnob->move( 5 + 3*32, 58 ); ToolTip::add( m_bassKnob, tr( "Bass" ) ); diff --git a/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp b/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp index e1b76d31e..beda3759a 100644 --- a/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp @@ -53,32 +53,32 @@ PeakControllerEffectControlDialog::PeakControllerEffectControlDialog( m_baseKnob = new Knob( knobBright_26, this ); m_baseKnob->setLabel( tr( "BASE" ) ); m_baseKnob->setModel( &_controls->m_baseModel ); - m_baseKnob->setHintText( tr( "Base amount:" ) + " ", "" ); + m_baseKnob->setHintText( tr( "Base amount:" ) , "" ); m_amountKnob = new Knob( knobBright_26, this ); m_amountKnob->setLabel( tr( "AMNT" ) ); m_amountKnob->setModel( &_controls->m_amountModel ); - m_amountKnob->setHintText( tr( "Modulation amount:" ) + " ", "" ); + m_amountKnob->setHintText( tr( "Modulation amount:" ) , "" ); m_amountMultKnob = new Knob( knobBright_26, this ); m_amountMultKnob->setLabel( tr( "MULT" ) ); m_amountMultKnob->setModel( &_controls->m_amountMultModel ); - m_amountMultKnob->setHintText( tr( "Amount Multiplicator:" ) + " ", "" ); + m_amountMultKnob->setHintText( tr( "Amount Multiplicator:" ) , "" ); m_attackKnob = new Knob( knobBright_26, this ); m_attackKnob->setLabel( tr( "ATCK" ) ); m_attackKnob->setModel( &_controls->m_attackModel ); - m_attackKnob->setHintText( tr( "Attack:" ) + " ", "" ); + m_attackKnob->setHintText( tr( "Attack:" ) , "" ); m_decayKnob = new Knob( knobBright_26, this ); m_decayKnob->setLabel( tr( "DCAY" ) ); m_decayKnob->setModel( &_controls->m_decayModel ); - m_decayKnob->setHintText( tr( "Release:" ) + " ", "" ); + m_decayKnob->setHintText( tr( "Release:" ) , "" ); m_tresholdKnob = new Knob( knobBright_26, this ); m_tresholdKnob->setLabel( tr( "TRES" ) ); m_tresholdKnob->setModel( &_controls->m_tresholdModel ); - m_tresholdKnob->setHintText( tr( "Treshold:" ) + " ", "" ); + m_tresholdKnob->setHintText( tr( "Treshold:" ) , "" ); l->addWidget( m_baseKnob ); l->addWidget( m_amountKnob ); diff --git a/plugins/sid/sid_instrument.cpp b/plugins/sid/sid_instrument.cpp index 0e64e83d7..ce4acb680 100644 --- a/plugins/sid/sid_instrument.cpp +++ b/plugins/sid/sid_instrument.cpp @@ -487,15 +487,15 @@ sidInstrumentView::sidInstrumentView( Instrument * _instrument, setPalette( pal ); m_volKnob = new sidKnob( this ); - m_volKnob->setHintText( tr( "Volume:" ) + " ", "" ); + m_volKnob->setHintText( tr( "Volume:" ), "" ); m_volKnob->move( 7, 64 ); m_resKnob = new sidKnob( this ); - m_resKnob->setHintText( tr( "Resonance:" ) + " ", "" ); + m_resKnob->setHintText( tr( "Resonance:" ), "" ); m_resKnob->move( 7 + 28, 64 ); m_cutKnob = new sidKnob( this ); - m_cutKnob->setHintText( tr( "Cutoff frequency:" ) + " ", "Hz" ); + m_cutKnob->setHintText( tr( "Cutoff frequency:" ), "Hz" ); m_cutKnob->move( 7 + 2*28, 64 ); PixmapButton * hp_btn = new PixmapButton( this, NULL ); @@ -547,32 +547,32 @@ sidInstrumentView::sidInstrumentView( Instrument * _instrument, for( int i = 0; i < 3; i++ ) { Knob *ak = new sidKnob( this ); - ak->setHintText( tr("Attack:") + " ", "" ); + ak->setHintText( tr("Attack:"), "" ); ak->move( 7, 114 + i*50 ); ak->setWhatsThis( tr ( "Attack rate determines how rapidly the output " "of Voice %1 rises from zero to peak amplitude." ).arg( i+1 ) ); Knob *dk = new sidKnob( this ); - dk->setHintText( tr("Decay:") + " ", "" ); + dk->setHintText( tr("Decay:") , "" ); dk->move( 7 + 28, 114 + i*50 ); dk->setWhatsThis( tr ( "Decay rate determines how rapidly the output " "falls from the peak amplitude to the selected Sustain level." ) ); Knob *sk = new sidKnob( this ); - sk->setHintText( tr("Sustain:") + " ", "" ); + sk->setHintText( tr("Sustain:"), "" ); sk->move( 7 + 2*28, 114 + i*50 ); sk->setWhatsThis( tr ( "Output of Voice %1 will remain at the selected " "Sustain amplitude as long as the note is held." ).arg( i+1 ) ); Knob *rk = new sidKnob( this ); - rk->setHintText( tr("Release:") + " ", "" ); + rk->setHintText( tr("Release:"), "" ); rk->move( 7 + 3*28, 114 + i*50 ); rk->setWhatsThis( tr ( "The output of of Voice %1 will fall from " "Sustain amplitude to zero amplitude at the selected Release " "rate." ).arg( i+1 ) ); Knob *pwk = new sidKnob( this ); - pwk->setHintText( tr("Pulse Width:") + " ", "" ); + pwk->setHintText( tr("Pulse Width:"), "" ); pwk->move( 7 + 4*28, 114 + i*50 ); pwk->setWhatsThis( tr ( "The Pulse Width resolution allows the width " "to be smoothly swept with no discernable stepping. The Pulse " @@ -580,7 +580,7 @@ sidInstrumentView::sidInstrumentView( Instrument * _instrument, " effect." ).arg( i+1 ) ); Knob *crsk = new sidKnob( this ); - crsk->setHintText( tr("Coarse:") + " ", " semitones" ); + crsk->setHintText( tr("Coarse:"), " semitones" ); crsk->move( 147, 114 + i*50 ); crsk->setWhatsThis( tr ( "The Coarse detuning allows to detune Voice " "%1 one octave up or down." ).arg( i+1 ) ); diff --git a/plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp b/plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp index 42fabf427..34f1d7167 100644 --- a/plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp +++ b/plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp @@ -40,7 +40,7 @@ stereoEnhancerControlDialog::stereoEnhancerControlDialog( Knob * widthKnob = new Knob( knobBright_26, this ); widthKnob->setModel( &_controls->m_widthModel ); widthKnob->setLabel( tr( "WIDE" ) ); - widthKnob->setHintText( tr( "Width:" ) + " ", "samples" ); + widthKnob->setHintText( tr( "Width:" ) , "samples" ); l->addWidget( widthKnob ); diff --git a/plugins/stereo_matrix/stereomatrix_control_dialog.cpp b/plugins/stereo_matrix/stereomatrix_control_dialog.cpp index 3017973ea..4ed6d0bb9 100644 --- a/plugins/stereo_matrix/stereomatrix_control_dialog.cpp +++ b/plugins/stereo_matrix/stereomatrix_control_dialog.cpp @@ -49,22 +49,22 @@ stereoMatrixControlDialog::stereoMatrixControlDialog( Knob * llKnob = new Knob( knobSmall_17, this ); llKnob->setModel( &_controls->m_llModel ); - llKnob->setHintText( tr( "Left to Left Vol:" ) + " ", "" ); + llKnob->setHintText( tr( "Left to Left Vol:" ) , "" ); llKnob->move( 40, 60 ); Knob * lrKnob = new Knob( knobSmall_17, this ); lrKnob->setModel( &_controls->m_lrModel ); - lrKnob->setHintText( tr( "Left to Right Vol:" ) + " ", "" ); + lrKnob->setHintText( tr( "Left to Right Vol:" ) , "" ); lrKnob->move( 40+28, 60); Knob * rlKnob = new Knob( knobSmall_17, this ); rlKnob->setModel( &_controls->m_rlModel ); - rlKnob->setHintText( tr( "Right to Left Vol:" ) + " ", "" ); + rlKnob->setHintText( tr( "Right to Left Vol:" ) , "" ); rlKnob->move( 40, 60+28 ); Knob * rrKnob = new Knob( knobSmall_17, this ); rrKnob->setModel( &_controls->m_rrModel ); - rrKnob->setHintText( tr( "Right to Right Vol:" ) + " ", "" ); + rrKnob->setHintText( tr( "Right to Right Vol:" ) , "" ); rrKnob->move( 40+28, 60+28 ); } diff --git a/plugins/triple_oscillator/TripleOscillator.cpp b/plugins/triple_oscillator/TripleOscillator.cpp index 360b7ad24..e188e8693 100644 --- a/plugins/triple_oscillator/TripleOscillator.cpp +++ b/plugins/triple_oscillator/TripleOscillator.cpp @@ -555,7 +555,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, vk->setFixedSize( 28, 35 ); vk->move( 6, knob_y ); vk->setHintText( tr( "Osc %1 volume:" ).arg( - i+1 ) + " ", "%" ); + i+1 ), "%" ); vk->setWhatsThis( tr( "With this knob you can set the volume of " "oscillator %1. When setting a value of 0 the " @@ -566,7 +566,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, // setup panning-knob Knob * pk = new TripleOscKnob( this ); pk->move( 35, knob_y ); - pk->setHintText( tr("Osc %1 panning:").arg( i + 1 ) + " ", "" ); + pk->setHintText( tr("Osc %1 panning:").arg( i + 1 ), "" ); pk->setWhatsThis( tr( "With this knob you can set the panning of the " "oscillator %1. A value of -100 means 100% " @@ -576,8 +576,8 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, // setup coarse-knob Knob * ck = new TripleOscKnob( this ); ck->move( 82, knob_y ); - ck->setHintText( tr( "Osc %1 coarse detuning:" ).arg( i + 1 ) + - " ", " " + tr( "semitones" ) ); + ck->setHintText( tr( "Osc %1 coarse detuning:" ).arg( i + 1 ) + , " " + tr( "semitones" ) ); ck->setWhatsThis( tr( "With this knob you can set the coarse detuning of " "oscillator %1. You can detune the oscillator " @@ -590,7 +590,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, Knob * flk = new TripleOscKnob( this ); flk->move( 111, knob_y ); flk->setHintText( tr( "Osc %1 fine detuning left:" ). - arg( i + 1 ) + " ", + arg( i + 1 ), " " + tr( "cents" ) ); flk->setWhatsThis( tr( "With this knob you can set the fine detuning of " @@ -603,7 +603,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, Knob * frk = new TripleOscKnob( this ); frk->move( 140, knob_y ); frk->setHintText( tr( "Osc %1 fine detuning right:" ). - arg( i + 1 ) + " ", + arg( i + 1 ), " " + tr( "cents" ) ); frk->setWhatsThis( tr( "With this knob you can set the fine detuning of " @@ -617,7 +617,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, Knob * pok = new TripleOscKnob( this ); pok->move( 188, knob_y ); pok->setHintText( tr( "Osc %1 phase-offset:" ). - arg( i + 1 ) + " ", + arg( i + 1 ), " " + tr( "degrees" ) ); pok->setWhatsThis( tr( "With this knob you can set the phase-offset of " @@ -633,7 +633,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, Knob * spdk = new TripleOscKnob( this ); spdk->move( 217, knob_y ); spdk->setHintText( tr("Osc %1 stereo phase-detuning:" ). - arg( i + 1 ) + " ", + arg( i + 1 ), " " + tr( "degrees" ) ); spdk->setWhatsThis( tr( "With this knob you can set the stereo phase-" diff --git a/plugins/vibed/vibed.cpp b/plugins/vibed/vibed.cpp index d48297779..dbe201226 100644 --- a/plugins/vibed/vibed.cpp +++ b/plugins/vibed/vibed.cpp @@ -361,14 +361,14 @@ vibedView::vibedView( Instrument * _instrument, m_volumeKnob = new Knob( knobBright_26, this ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->move( 103, 142 ); - m_volumeKnob->setHintText( tr( "Volume:" ) + " ", "" ); + m_volumeKnob->setHintText( tr( "Volume:" ), "" ); m_volumeKnob->setWhatsThis( tr( "The 'V' knob sets the volume " "of the selected string." ) ); m_stiffnessKnob = new Knob( knobBright_26, this ); m_stiffnessKnob->move( 129, 142 ); - m_stiffnessKnob->setHintText( tr( "String stiffness:" ) + - " ", "" ); + m_stiffnessKnob->setHintText( tr( "String stiffness:" ) + , "" ); m_stiffnessKnob->setWhatsThis( tr( "The 'S' knob sets the stiffness of the selected string. The stiffness " "of the string affects how long the string will ring out. The lower " @@ -377,15 +377,15 @@ vibedView::vibedView( Instrument * _instrument, m_pickKnob = new Knob( knobBright_26, this ); m_pickKnob->move( 153, 142 ); - m_pickKnob->setHintText( tr( "Pick position:" ) + " ", "" ); + m_pickKnob->setHintText( tr( "Pick position:" ), "" ); m_pickKnob->setWhatsThis( tr( "The 'P' knob sets the position where the selected string will be 'picked'. " "The lower the setting the closer the pick is to the bridge." ) ); m_pickupKnob = new Knob( knobBright_26, this ); m_pickupKnob->move( 177, 142 ); - m_pickupKnob->setHintText( tr( "Pickup position:" ) + - " ", "" ); + m_pickupKnob->setHintText( tr( "Pickup position:" ) + , "" ); m_pickupKnob->setWhatsThis( tr( "The 'PU' knob sets the position where the vibrations will be monitored " "for the selected string. The lower the setting, the closer the " @@ -393,14 +393,14 @@ vibedView::vibedView( Instrument * _instrument, m_panKnob = new Knob( knobBright_26, this ); m_panKnob->move( 105, 187 ); - m_panKnob->setHintText( tr( "Pan:" ) + " ", "" ); + m_panKnob->setHintText( tr( "Pan:" ), "" ); m_panKnob->setWhatsThis( tr( "The Pan knob determines the location of the selected string in the stereo " "field." ) ); m_detuneKnob = new Knob( knobBright_26, this ); m_detuneKnob->move( 150, 187 ); - m_detuneKnob->setHintText( tr( "Detune:" ) + " ", "" ); + m_detuneKnob->setHintText( tr( "Detune:" ), "" ); m_detuneKnob->setWhatsThis( tr( "The Detune knob modifies the pitch of the selected string. Settings less " "than zero will cause the string to sound flat. Settings greater than zero " @@ -408,8 +408,8 @@ vibedView::vibedView( Instrument * _instrument, m_randomKnob = new Knob( knobBright_26, this ); m_randomKnob->move( 194, 187 ); - m_randomKnob->setHintText( tr( "Fuzziness:" ) + - " ", "" ); + m_randomKnob->setHintText( tr( "Fuzziness:" ) + , "" ); m_randomKnob->setWhatsThis( tr( "The Slap knob adds a bit of fuzz to the selected string which is most " "apparent during the attack, though it can also be used to make the string " @@ -417,8 +417,8 @@ vibedView::vibedView( Instrument * _instrument, m_lengthKnob = new Knob( knobBright_26, this ); m_lengthKnob->move( 23, 193 ); - m_lengthKnob->setHintText( tr( "Length:" ) + - " ", "" ); + m_lengthKnob->setHintText( tr( "Length:" ) + , "" ); m_lengthKnob->setWhatsThis( tr( "The Length knob sets the length of the selected string. Longer strings " "will both ring longer and sound brighter, however, they will also eat up " diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index b8413f7f8..05ca9e855 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -41,14 +41,14 @@ #define makeknob( name, x, y, hint, unit, oname ) \ name = new Knob( knobStyled, this ); \ name ->move( x, y ); \ - name ->setHintText( tr( hint ) + " ", unit ); \ + name ->setHintText( tr( hint ), unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 19, 19 ); #define maketsknob( name, x, y, hint, unit, oname ) \ name = new TempoSyncKnob( knobStyled, this ); \ name ->move( x, y ); \ - name ->setHintText( tr( hint ) + " ", unit ); \ + name ->setHintText( tr( hint ), unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 19, 19 ); diff --git a/plugins/waveshaper/waveshaper_control_dialog.cpp b/plugins/waveshaper/waveshaper_control_dialog.cpp index 236fc70d4..e831756e0 100644 --- a/plugins/waveshaper/waveshaper_control_dialog.cpp +++ b/plugins/waveshaper/waveshaper_control_dialog.cpp @@ -63,7 +63,7 @@ waveShaperControlDialog::waveShaperControlDialog( inputKnob -> move( 14, 251 ); inputKnob->setModel( &_controls->m_inputModel ); inputKnob->setLabel( tr( "INPUT" ) ); - inputKnob->setHintText( tr( "Input gain:" ) + " ", "" ); + inputKnob->setHintText( tr( "Input gain:" ) , "" ); Knob * outputKnob = new Knob( knobBright_26, this ); outputKnob -> setVolumeKnob( true ); @@ -71,7 +71,7 @@ waveShaperControlDialog::waveShaperControlDialog( outputKnob -> move( 54, 251 ); outputKnob->setModel( &_controls->m_outputModel ); outputKnob->setLabel( tr( "OUTPUT" ) ); - outputKnob->setHintText( tr( "Output gain:" ) + " ", "" ); + outputKnob->setHintText( tr( "Output gain:" ), "" ); PixmapButton * resetButton = new PixmapButton( this, tr("Reset waveform") ); resetButton -> move( 164, 251 ); diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index b4ba7f15a..e0fd50f65 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -498,31 +498,31 @@ ZynAddSubFxView::ZynAddSubFxView( Instrument * _instrument, QWidget * _parent ) l->setHorizontalSpacing( 10 ); m_portamento = new Knob( knobBright_26, this ); - m_portamento->setHintText( tr( "Portamento:" ) + "", "" ); + m_portamento->setHintText( tr( "Portamento:" ), "" ); m_portamento->setLabel( tr( "PORT" ) ); m_filterFreq = new Knob( knobBright_26, this ); - m_filterFreq->setHintText( tr( "Filter Frequency:" ) + "", "" ); + m_filterFreq->setHintText( tr( "Filter Frequency:" ), "" ); m_filterFreq->setLabel( tr( "FREQ" ) ); m_filterQ = new Knob( knobBright_26, this ); - m_filterQ->setHintText( tr( "Filter Resonance:" ) + "", "" ); + m_filterQ->setHintText( tr( "Filter Resonance:" ), "" ); m_filterQ->setLabel( tr( "RES" ) ); m_bandwidth = new Knob( knobBright_26, this ); - m_bandwidth->setHintText( tr( "Bandwidth:" ) + "", "" ); + m_bandwidth->setHintText( tr( "Bandwidth:" ), "" ); m_bandwidth->setLabel( tr( "BW" ) ); m_fmGain = new Knob( knobBright_26, this ); - m_fmGain->setHintText( tr( "FM Gain:" ) + "", "" ); + m_fmGain->setHintText( tr( "FM Gain:" ), "" ); m_fmGain->setLabel( tr( "FM GAIN" ) ); m_resCenterFreq = new Knob( knobBright_26, this ); - m_resCenterFreq->setHintText( tr( "Resonance center frequency:" ) + "", "" ); + m_resCenterFreq->setHintText( tr( "Resonance center frequency:" ), "" ); m_resCenterFreq->setLabel( tr( "RES CF" ) ); m_resBandwidth = new Knob( knobBright_26, this ); - m_resBandwidth->setHintText( tr( "Resonance bandwidth:" ) + "", "" ); + m_resBandwidth->setHintText( tr( "Resonance bandwidth:" ), "" ); m_resBandwidth->setLabel( tr( "RES BW" ) ); m_forwardMidiCC = new LedCheckBox( tr( "Forward MIDI Control Changes" ), this ); diff --git a/src/gui/LfoControllerDialog.cpp b/src/gui/LfoControllerDialog.cpp index 0c1ef5a20..6fb36d61b 100644 --- a/src/gui/LfoControllerDialog.cpp +++ b/src/gui/LfoControllerDialog.cpp @@ -75,14 +75,14 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent m_baseKnob = new Knob( knobBright_26, this ); m_baseKnob->setLabel( tr( "BASE" ) ); m_baseKnob->move( CD_LFO_BASE_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); - m_baseKnob->setHintText( tr( "Base amount:" ) + " ", "" ); + m_baseKnob->setHintText( tr( "Base amount:" ), "" ); m_baseKnob->setWhatsThis( tr("todo") ); m_speedKnob = new TempoSyncKnob( knobBright_26, this ); m_speedKnob->setLabel( tr( "SPD" ) ); m_speedKnob->move( CD_LFO_SPEED_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); - m_speedKnob->setHintText( tr( "LFO-speed:" ) + " ", "" ); + m_speedKnob->setHintText( tr( "LFO-speed:" ), "" ); m_speedKnob->setWhatsThis( tr( "Use this knob for setting speed of the LFO. The " "bigger this value the faster the LFO oscillates and " @@ -92,7 +92,7 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent m_amountKnob = new Knob( knobBright_26, this ); m_amountKnob->setLabel( tr( "AMT" ) ); m_amountKnob->move( CD_LFO_AMOUNT_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); - m_amountKnob->setHintText( tr( "Modulation amount:" ) + " ", "" ); + m_amountKnob->setHintText( tr( "Modulation amount:" ), "" ); m_amountKnob->setWhatsThis( tr( "Use this knob for setting modulation amount of the " "LFO. The bigger this value, the more the connected " @@ -102,7 +102,7 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent m_phaseKnob = new Knob( knobBright_26, this ); m_phaseKnob->setLabel( tr( "PHS" ) ); m_phaseKnob->move( CD_LFO_PHASE_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); - m_phaseKnob->setHintText( tr( "Phase offset:" ) + " ", "" + tr( "degrees" ) ); + m_phaseKnob->setHintText( tr( "Phase offset:" ) , "" + tr( "degrees" ) ); m_phaseKnob->setWhatsThis( tr( "With this knob you can set the phase offset of " "the LFO. That means you can move the " diff --git a/src/gui/widgets/EnvelopeAndLfoView.cpp b/src/gui/widgets/EnvelopeAndLfoView.cpp index 5143a42e2..7e3922f60 100644 --- a/src/gui/widgets/EnvelopeAndLfoView.cpp +++ b/src/gui/widgets/EnvelopeAndLfoView.cpp @@ -97,7 +97,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_predelayKnob = new Knob( knobBright_26, this ); m_predelayKnob->setLabel( tr( "DEL" ) ); m_predelayKnob->move( PREDELAY_KNOB_X, ENV_KNOBS_Y ); - m_predelayKnob->setHintText( tr( "Predelay:" ) + " ", "" ); + m_predelayKnob->setHintText( tr( "Predelay:" ), "" ); m_predelayKnob->setWhatsThis( tr( "Use this knob for setting predelay of the current " "envelope. The bigger this value the longer the time " @@ -107,7 +107,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_attackKnob = new Knob( knobBright_26, this ); m_attackKnob->setLabel( tr( "ATT" ) ); m_attackKnob->move( ATTACK_KNOB_X, ENV_KNOBS_Y ); - m_attackKnob->setHintText( tr( "Attack:" )+" ", "" ); + m_attackKnob->setHintText( tr( "Attack:" ), "" ); m_attackKnob->setWhatsThis( tr( "Use this knob for setting attack-time of the current " "envelope. The bigger this value the longer the " @@ -118,7 +118,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_holdKnob = new Knob( knobBright_26, this ); m_holdKnob->setLabel( tr( "HOLD" ) ); m_holdKnob->move( HOLD_KNOB_X, ENV_KNOBS_Y ); - m_holdKnob->setHintText( tr( "Hold:" ) + " ", "" ); + m_holdKnob->setHintText( tr( "Hold:" ), "" ); m_holdKnob->setWhatsThis( tr( "Use this knob for setting hold-time of the current " "envelope. The bigger this value the longer the " @@ -128,7 +128,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_decayKnob = new Knob( knobBright_26, this ); m_decayKnob->setLabel( tr( "DEC" ) ); m_decayKnob->move( DECAY_KNOB_X, ENV_KNOBS_Y ); - m_decayKnob->setHintText( tr( "Decay:" ) + " ", "" ); + m_decayKnob->setHintText( tr( "Decay:" ), "" ); m_decayKnob->setWhatsThis( tr( "Use this knob for setting decay-time of the current " "envelope. The bigger this value the longer the " @@ -140,7 +140,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_sustainKnob = new Knob( knobBright_26, this ); m_sustainKnob->setLabel( tr( "SUST" ) ); m_sustainKnob->move( SUSTAIN_KNOB_X, ENV_KNOBS_Y ); - m_sustainKnob->setHintText( tr( "Sustain:" ) + " ", "" ); + m_sustainKnob->setHintText( tr( "Sustain:" ), "" ); m_sustainKnob->setWhatsThis( tr( "Use this knob for setting sustain-level of the current " "envelope. The bigger this value the higher the level " @@ -151,7 +151,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_releaseKnob = new Knob( knobBright_26, this ); m_releaseKnob->setLabel( tr( "REL" ) ); m_releaseKnob->move( RELEASE_KNOB_X, ENV_KNOBS_Y ); - m_releaseKnob->setHintText( tr( "Release:" ) + " ", "" ); + m_releaseKnob->setHintText( tr( "Release:" ), "" ); m_releaseKnob->setWhatsThis( tr( "Use this knob for setting release-time of the current " "envelope. The bigger this value the longer the " @@ -163,7 +163,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_amountKnob = new Knob( knobBright_26, this ); m_amountKnob->setLabel( tr( "AMT" ) ); m_amountKnob->move( AMOUNT_KNOB_X, ENV_GRAPH_Y ); - m_amountKnob->setHintText( tr( "Modulation amount:" ) + " ", "" ); + m_amountKnob->setHintText( tr( "Modulation amount:" ), "" ); m_amountKnob->setWhatsThis( tr( "Use this knob for setting modulation amount of the " "current envelope. The bigger this value the more the " @@ -176,7 +176,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_lfoPredelayKnob = new Knob( knobBright_26, this ); m_lfoPredelayKnob->setLabel( tr( "DEL" ) ); m_lfoPredelayKnob->move( LFO_PREDELAY_KNOB_X, LFO_KNOB_Y ); - m_lfoPredelayKnob->setHintText( tr( "LFO predelay:" ) + " ", "" ); + m_lfoPredelayKnob->setHintText( tr( "LFO predelay:" ), "" ); m_lfoPredelayKnob->setWhatsThis( tr( "Use this knob for setting predelay-time of the current " "LFO. The bigger this value the the time until the " @@ -186,7 +186,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_lfoAttackKnob = new Knob( knobBright_26, this ); m_lfoAttackKnob->setLabel( tr( "ATT" ) ); m_lfoAttackKnob->move( LFO_ATTACK_KNOB_X, LFO_KNOB_Y ); - m_lfoAttackKnob->setHintText( tr( "LFO- attack:" ) + " ", "" ); + m_lfoAttackKnob->setHintText( tr( "LFO- attack:" ), "" ); m_lfoAttackKnob->setWhatsThis( tr( "Use this knob for setting attack-time of the current LFO. " "The bigger this value the longer the LFO needs to " @@ -196,7 +196,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_lfoSpeedKnob = new TempoSyncKnob( knobBright_26, this ); m_lfoSpeedKnob->setLabel( tr( "SPD" ) ); m_lfoSpeedKnob->move( LFO_SPEED_KNOB_X, LFO_KNOB_Y ); - m_lfoSpeedKnob->setHintText( tr( "LFO speed:" ) + " ", "" ); + m_lfoSpeedKnob->setHintText( tr( "LFO speed:" ), "" ); m_lfoSpeedKnob->setWhatsThis( tr( "Use this knob for setting speed of the current LFO. The " "bigger this value the faster the LFO oscillates and " @@ -206,7 +206,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_lfoAmountKnob = new Knob( knobBright_26, this ); m_lfoAmountKnob->setLabel( tr( "AMT" ) ); m_lfoAmountKnob->move( LFO_AMOUNT_KNOB_X, LFO_KNOB_Y ); - m_lfoAmountKnob->setHintText( tr( "Modulation amount:" ) + " ", "" ); + m_lfoAmountKnob->setHintText( tr( "Modulation amount:" ), "" ); m_lfoAmountKnob->setWhatsThis( tr( "Use this knob for setting modulation amount of the " "current LFO. The bigger this value the more the " diff --git a/src/gui/widgets/InstrumentFunctionViews.cpp b/src/gui/widgets/InstrumentFunctionViews.cpp index d0f55f2c3..df58d1708 100644 --- a/src/gui/widgets/InstrumentFunctionViews.cpp +++ b/src/gui/widgets/InstrumentFunctionViews.cpp @@ -60,7 +60,7 @@ InstrumentFunctionNoteStackingView::InstrumentFunctionNoteStackingView( Instrume chordLabel->setFont( pointSize<8>( chordLabel->font() ) ); m_chordRangeKnob->setLabel( tr( "RANGE" ) ); - m_chordRangeKnob->setHintText( tr( "Chord range:" ) + " ", " " + tr( "octave(s)" ) ); + m_chordRangeKnob->setHintText( tr( "Chord range:" ), " " + tr( "octave(s)" ) ); m_chordRangeKnob->setWhatsThis( tr( "Use this knob for setting the chord range in octaves. " "The selected chord will be played within specified " @@ -130,7 +130,7 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti m_arpRangeKnob->setLabel( tr( "RANGE" ) ); - m_arpRangeKnob->setHintText( tr( "Arpeggio range:" ) + " ", " " + tr( "octave(s)" ) ); + m_arpRangeKnob->setHintText( tr( "Arpeggio range:" ), " " + tr( "octave(s)" ) ); m_arpRangeKnob->setWhatsThis( tr( "Use this knob for setting the arpeggio range in octaves. " "The selected arpeggio will be played within specified " @@ -138,7 +138,7 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti m_arpTimeKnob->setLabel( tr( "TIME" ) ); - m_arpTimeKnob->setHintText( tr( "Arpeggio time:" ) + " ", " " + tr( "ms" ) ); + m_arpTimeKnob->setHintText( tr( "Arpeggio time:" ), " " + tr( "ms" ) ); m_arpTimeKnob->setWhatsThis( tr( "Use this knob for setting the arpeggio time in " "milliseconds. The arpeggio time specifies how long " @@ -146,7 +146,7 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti m_arpGateKnob->setLabel( tr( "GATE" ) ); - m_arpGateKnob->setHintText( tr( "Arpeggio gate:" ) + " ", tr( "%" ) ); + m_arpGateKnob->setHintText( tr( "Arpeggio gate:" ), tr( "%" ) ); m_arpGateKnob->setWhatsThis( tr( "Use this knob for setting the arpeggio gate. The " "arpeggio gate specifies the percent of a whole " diff --git a/src/gui/widgets/InstrumentSoundShapingView.cpp b/src/gui/widgets/InstrumentSoundShapingView.cpp index b5c923e21..406c5a7a9 100644 --- a/src/gui/widgets/InstrumentSoundShapingView.cpp +++ b/src/gui/widgets/InstrumentSoundShapingView.cpp @@ -99,7 +99,7 @@ InstrumentSoundShapingView::InstrumentSoundShapingView( QWidget * _parent ) : m_filterCutKnob = new Knob( knobBright_26, m_filterGroupBox ); m_filterCutKnob->setLabel( tr( "FREQ" ) ); m_filterCutKnob->move( 140, 18 ); - m_filterCutKnob->setHintText( tr( "cutoff frequency:" ) + " ", " " + tr( "Hz" ) ); + m_filterCutKnob->setHintText( tr( "cutoff frequency:" ), " " + tr( "Hz" ) ); m_filterCutKnob->setWhatsThis( tr( "Use this knob for setting the cutoff frequency for the " "selected filter. The cutoff frequency specifies the " @@ -112,7 +112,7 @@ InstrumentSoundShapingView::InstrumentSoundShapingView( QWidget * _parent ) : m_filterResKnob = new Knob( knobBright_26, m_filterGroupBox ); m_filterResKnob->setLabel( tr( "RESO" ) ); m_filterResKnob->move( 196, 18 ); - m_filterResKnob->setHintText( tr( "Resonance:" ) + " ", "" ); + m_filterResKnob->setHintText( tr( "Resonance:" ), "" ); m_filterResKnob->setWhatsThis( tr( "Use this knob for setting Q/Resonance for the selected " "filter. Q/Resonance tells the filter how much it " diff --git a/src/gui/widgets/LadspaControlView.cpp b/src/gui/widgets/LadspaControlView.cpp index 558237ba6..05823a441 100644 --- a/src/gui/widgets/LadspaControlView.cpp +++ b/src/gui/widgets/LadspaControlView.cpp @@ -100,7 +100,7 @@ LadspaControlView::LadspaControlView( QWidget * _parent, knb->setModel( m_ctl->tempoSyncKnobModel() ); } knb->setLabel( m_ctl->port()->name ); - knb->setHintText( tr( "Value:" ) + " ", "" ); + knb->setHintText( tr( "Value:" ), "" ); knb->setWhatsThis( tr( "Sorry, no help available." ) ); layout->addWidget( knb ); if( link != NULL ) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index c1ae4d0c2..73f53cdac 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -849,7 +849,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV tr( "Volume" ) ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->setModel( &_it->m_volumeModel ); - m_volumeKnob->setHintText( tr( "Volume:" ) + " ", "%" ); + m_volumeKnob->setHintText( tr( "Volume:" ), "%" ); m_volumeKnob->move( widgetWidth-2*24, 2 ); m_volumeKnob->setLabel( tr( "VOL" ) ); m_volumeKnob->show(); @@ -858,7 +858,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_panningKnob = new Knob( knobSmall_17, getTrackSettingsWidget(), tr( "Panning" ) ); m_panningKnob->setModel( &_it->m_panningModel ); - m_panningKnob->setHintText( tr( "Panning:" ) + " ", "%" ); + m_panningKnob->setHintText( tr( "Panning:" ), "%" ); m_panningKnob->move( widgetWidth-24, 2 ); m_panningKnob->setLabel( tr( "PAN" ) ); m_panningKnob->show(); @@ -1176,7 +1176,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // set up volume knob m_volumeKnob = new Knob( knobBright_26, NULL, tr( "Instrument volume" ) ); m_volumeKnob->setVolumeKnob( true ); - m_volumeKnob->setHintText( tr( "Volume:" ) + " ", "%" ); + m_volumeKnob->setHintText( tr( "Volume:" ), "%" ); m_volumeKnob->setLabel( tr( "VOL" ) ); m_volumeKnob->setWhatsThis( tr( volume_help ) ); @@ -1185,7 +1185,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // set up panning knob m_panningKnob = new Knob( knobBright_26, NULL, tr( "Panning" ) ); - m_panningKnob->setHintText( tr( "Panning:" ) + " ", "" ); + m_panningKnob->setHintText( tr( "Panning:" ), "" ); m_panningKnob->setLabel( tr( "PAN" ) ); basicControlsLayout->addWidget( m_panningKnob ); @@ -1193,7 +1193,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // set up pitch knob m_pitchKnob = new Knob( knobBright_26, NULL, tr( "Pitch" ) ); - m_pitchKnob->setHintText( tr( "Pitch:" ) + " ", " " + tr( "cents" ) ); + m_pitchKnob->setHintText( tr( "Pitch:" ), " " + tr( "cents" ) ); m_pitchKnob->setLabel( tr( "PITCH" ) ); basicControlsLayout->addWidget( m_pitchKnob ); diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index da5c8caf4..3f8fe4276 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -537,7 +537,7 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : tr( "Track volume" ) ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->setModel( &_t->m_volumeModel ); - m_volumeKnob->setHintText( tr( "Channel volume:" ) + " ", "%" ); + m_volumeKnob->setHintText( tr( "Channel volume:" ), "%" ); if( ConfigManager::inst()->value( "ui", "compacttrackbuttons" ).toInt() ) { From c997da29db6748c35df1e4b221fb797d9eb6f3c8 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 8 Dec 2014 11:02:41 +0000 Subject: [PATCH 19/51] missed a couple of + " ", all sored now --- src/gui/widgets/EffectView.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/widgets/EffectView.cpp b/src/gui/widgets/EffectView.cpp index 466b2b0fa..ce80f8b29 100644 --- a/src/gui/widgets/EffectView.cpp +++ b/src/gui/widgets/EffectView.cpp @@ -67,7 +67,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_wetDry->setLabel( tr( "W/D" ) ); m_wetDry->move( 27, 5 ); m_wetDry->setEnabled( isEnabled ); - m_wetDry->setHintText( tr( "Wet Level:" ) + " ", "" ); + m_wetDry->setHintText( tr( "Wet Level:" ), "" ); m_wetDry->setWhatsThis( tr( "The Wet/Dry knob sets the ratio between " "the input signal and the effect signal that " "forms the output." ) ); @@ -77,7 +77,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_autoQuit->setLabel( tr( "DECAY" ) ); m_autoQuit->move( 60, 5 ); m_autoQuit->setEnabled( isEnabled ); - m_autoQuit->setHintText( tr( "Time:" ) + " ", "ms" ); + m_autoQuit->setHintText( tr( "Time:" ), "ms" ); m_autoQuit->setWhatsThis( tr( "The Decay knob controls how many buffers of silence must pass before the " "plugin stops processing. Smaller values will reduce the CPU overhead but " @@ -88,7 +88,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_gate->setLabel( tr( "GATE" ) ); m_gate->move( 93, 5 ); m_gate->setEnabled( isEnabled ); - m_gate->setHintText( tr( "Gate:" ) + " ", "" ); + m_gate->setHintText( tr( "Gate:" ), "" ); m_gate->setWhatsThis( tr( "The Gate knob controls the signal level that is considered to be 'silence' " "while deciding when to stop processing signals." ) ); From 56d0910533efbcf8589a1e1fca967dbeefbba026 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 8 Dec 2014 12:20:47 -0500 Subject: [PATCH 20/51] Cleanup fmaf() usage, move to lmms_math.h --- include/interpolation.h | 24 +++--------------------- include/lmms_math.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/include/interpolation.h b/include/interpolation.h index 5dd98ea3f..cbe274d42 100644 --- a/include/interpolation.h +++ b/include/interpolation.h @@ -32,6 +32,7 @@ #include #include "lmms_constants.h" +#include "lmms_math.h" inline float hermiteInterpolate( float x0, float x1, float x2, float x3, float frac_pos ) @@ -80,32 +81,13 @@ inline float cubicInterpolate( float v0, float v1, float v2, float v3, float x ) inline float cosinusInterpolate( float v0, float v1, float x ) { const float f = ( 1.0f - cosf( x * F_PI ) ) * 0.5f; -#ifdef FP_FAST_FMAF - #ifndef __clang__ - return fmaf( f, v1-v0, v0 ); - #else - return fma( f, v1-v0, v0 ); - #endif -#else - return f * (v1-v0) + v0; -#endif -// return( v0*f + v1*( 1.0f-f ) ); + return fastFmaf( f, v1-v0, v0 ); } inline float linearInterpolate( float v0, float v1, float x ) { -// take advantage of fma function if present in hardware - -#ifdef FP_FAST_FMAF - #ifndef __clang__ - return fmaf( x, v1-v0, v0 ); - #else - return fma( x, v1-v0, v0 ); - #endif -#else - return x * (v1-v0) + v0; -#endif + return fastFmaf( x, v1-v0, v0 ); } diff --git a/include/lmms_math.h b/include/lmms_math.h index 47136ae94..c82d32ac5 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -130,7 +130,40 @@ static inline int fast_rand() return( (unsigned)( next / 65536 ) % 32768 ); } +//! @brief Takes advantage of fmal() function if present in hardware +static inline long fastFmal( long a, long b, long c) { +#ifdef FP_FAST_FMAF + #ifdef __clang__ + return fma(a, b, c); + #else + return fmal(a, b, c); + #endif +#else + return a * ( b - c ) + c; +#endif +} +//! @brief Takes advantage of fmaf() function if present in hardware +static inline float fastFmaf( float a, float b, float c) { +#ifdef FP_FAST_FMAF + #ifdef __clang__ + return fma(a, b, c); + #else + return fmaf(a, b, c); + #endif +#else + return a * ( b - c ) + c; +#endif +} + +//! @brief Takes advantage of fma() function if present in hardware +static inline int fastFma( int a, int b, int c) { +#ifdef FP_FAST_FMAF + return fma(a, b, c); +#else + return a * ( b - c ) + c; +#endif +} // source: http://martin.ankerl.com/2007/10/04/optimized-pow-approximation-for-java-and-c-c/ static inline double fastPow( double a, double b ) From 591acbf73264620de26bb90ec32a5c183be98c0d Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 8 Dec 2014 12:22:33 -0500 Subject: [PATCH 21/51] fastFmaf() formatting fixes --- include/lmms_math.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index c82d32ac5..8c7d07cb0 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -136,7 +136,7 @@ static inline long fastFmal( long a, long b, long c) { #ifdef __clang__ return fma(a, b, c); #else - return fmal(a, b, c); + return fmal( a, b, c ); #endif #else return a * ( b - c ) + c; @@ -147,9 +147,9 @@ static inline long fastFmal( long a, long b, long c) { static inline float fastFmaf( float a, float b, float c) { #ifdef FP_FAST_FMAF #ifdef __clang__ - return fma(a, b, c); + return fma( a, b, c ); #else - return fmaf(a, b, c); + return fmaf( a, b, c ); #endif #else return a * ( b - c ) + c; @@ -159,7 +159,7 @@ static inline float fastFmaf( float a, float b, float c) { //! @brief Takes advantage of fma() function if present in hardware static inline int fastFma( int a, int b, int c) { #ifdef FP_FAST_FMAF - return fma(a, b, c); + return fma( a, b, c ); #else return a * ( b - c ) + c; #endif From 76d766fe252f55668ab7d1a21bb889d2de8e110c Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 8 Dec 2014 12:30:16 -0500 Subject: [PATCH 22/51] fmaf() code cleanup, typos --- include/lmms_math.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 8c7d07cb0..393a16d8b 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -131,7 +131,7 @@ static inline int fast_rand() } //! @brief Takes advantage of fmal() function if present in hardware -static inline long fastFmal( long a, long b, long c) { +static inline long fastFmal( long a, long b, long c ) { #ifdef FP_FAST_FMAF #ifdef __clang__ return fma(a, b, c); @@ -139,12 +139,12 @@ static inline long fastFmal( long a, long b, long c) { return fmal( a, b, c ); #endif #else - return a * ( b - c ) + c; + return a * b + c; #endif } //! @brief Takes advantage of fmaf() function if present in hardware -static inline float fastFmaf( float a, float b, float c) { +static inline float fastFmaf( float a, float b, float c ) { #ifdef FP_FAST_FMAF #ifdef __clang__ return fma( a, b, c ); @@ -152,16 +152,16 @@ static inline float fastFmaf( float a, float b, float c) { return fmaf( a, b, c ); #endif #else - return a * ( b - c ) + c; + return a * b + c; #endif } //! @brief Takes advantage of fma() function if present in hardware -static inline int fastFma( int a, int b, int c) { +static inline int fastFma( int a, int b, int c ) { #ifdef FP_FAST_FMAF return fma( a, b, c ); #else - return a * ( b - c ) + c; + return a * b + c; #endif } From 5a0dfdd3c0b63704130f6ed287ccd8e3521c73e6 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 8 Dec 2014 12:45:31 -0500 Subject: [PATCH 23/51] minor fmaf() formatting fix. --- include/lmms_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 393a16d8b..ac8ab6fdc 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -134,7 +134,7 @@ static inline int fast_rand() static inline long fastFmal( long a, long b, long c ) { #ifdef FP_FAST_FMAF #ifdef __clang__ - return fma(a, b, c); + return fma( a, b, c ); #else return fmal( a, b, c ); #endif From ed8e30b4ee53e502c38cc5c2f2a01f4f341aa10b Mon Sep 17 00:00:00 2001 From: Lukas W Date: Mon, 8 Dec 2014 20:19:25 +0100 Subject: [PATCH 24/51] Small const fix --- include/Song.h | 4 ++-- include/Track.h | 2 +- src/core/Song.cpp | 2 +- src/core/Track.cpp | 2 +- src/gui/AutomationEditor.cpp | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/Song.h b/include/Song.h index d0dac5a9c..81f12303d 100644 --- a/include/Song.h +++ b/include/Song.h @@ -263,7 +263,7 @@ public slots: void playAndRecord(); void playTrack( Track * _trackToPlay ); void playBB(); - void playPattern( Pattern* patternToPlay, bool _loop = true ); + void playPattern(const Pattern* patternToPlay, bool _loop = true ); void togglePause(); void stop(); @@ -354,7 +354,7 @@ private: tact_t m_length; Track * m_trackToPlay; - Pattern* m_patternToPlay; + const Pattern* m_patternToPlay; bool m_loopPattern; double m_elapsedMilliSeconds; diff --git a/include/Track.h b/include/Track.h index 8c7e05f23..396c41e52 100644 --- a/include/Track.h +++ b/include/Track.h @@ -468,7 +468,7 @@ public: int numOfTCOs(); TrackContentObject * getTCO( int _tco_num ); - int getTCONum( TrackContentObject * _tco ); + int getTCONum(const TrackContentObject* _tco ); const tcoVector & getTCOs() const { diff --git a/src/core/Song.cpp b/src/core/Song.cpp index ce686e79f..c9ac56452 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -473,7 +473,7 @@ void Song::playBB() -void Song::playPattern( Pattern* patternToPlay, bool _loop ) +void Song::playPattern( const Pattern* patternToPlay, bool _loop ) { if( isStopped() == false ) { diff --git a/src/core/Track.cpp b/src/core/Track.cpp index 188d57e08..f12bdb069 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -2139,7 +2139,7 @@ TrackContentObject * Track::getTCO( int _tco_num ) * \param _tco The TrackContentObject to search for. * \return its number in our array. */ -int Track::getTCONum( TrackContentObject * _tco ) +int Track::getTCONum( const TrackContentObject * _tco ) { // for( int i = 0; i < getTrackContentWidget()->numOfTCOs(); ++i ) tcoVector::iterator it = qFind( m_trackContentObjects.begin(), diff --git a/src/gui/AutomationEditor.cpp b/src/gui/AutomationEditor.cpp index f47d8165b..dc14eca60 100644 --- a/src/gui/AutomationEditor.cpp +++ b/src/gui/AutomationEditor.cpp @@ -1934,7 +1934,7 @@ void AutomationEditor::play() if( Engine::getSong()->playMode() != Song::Mode_PlayPattern ) { Engine::getSong()->stop(); - Engine::getSong()->playPattern( (Pattern *) Engine::pianoRoll()->currentPattern() ); + Engine::getSong()->playPattern( Engine::pianoRoll()->currentPattern() ); } else if( Engine::getSong()->isStopped() == false ) { @@ -1942,7 +1942,7 @@ void AutomationEditor::play() } else { - Engine::getSong()->playPattern( (Pattern *) Engine::pianoRoll()->currentPattern() ); + Engine::getSong()->playPattern( Engine::pianoRoll()->currentPattern() ); } } else if( inBBEditor() ) From 7431e772294a6d5455cfd1a6d45750bd26ac4d4e Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 8 Dec 2014 14:42:19 -0500 Subject: [PATCH 25/51] More fmal() fixes --- include/lmms_math.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index ac8ab6fdc..156303136 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -131,7 +131,7 @@ static inline int fast_rand() } //! @brief Takes advantage of fmal() function if present in hardware -static inline long fastFmal( long a, long b, long c ) { +static inline long double fastFmal( long double a, long double b, long double c ) { #ifdef FP_FAST_FMAF #ifdef __clang__ return fma( a, b, c ); @@ -157,7 +157,7 @@ static inline float fastFmaf( float a, float b, float c ) { } //! @brief Takes advantage of fma() function if present in hardware -static inline int fastFma( int a, int b, int c ) { +static inline double fastFma( double a, double b, double c ) { #ifdef FP_FAST_FMAF return fma( a, b, c ); #else From 2295545ac6f440c0c7760956e77eae03ed553a62 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 8 Dec 2014 23:48:44 +0000 Subject: [PATCH 26/51] Remove whitespace from setHintText, change spaces to tabs --- plugins/Amplifier/AmplifierControlDialog.cpp | 8 +- .../BassBooster/BassBoosterControlDialog.cpp | 6 +- .../DualFilter/DualFilterControlDialog.cpp | 2 +- .../MultitapEchoControlDialog.cpp | 6 +- .../audio_file_processor.cpp | 8 +- plugins/bit_invader/bit_invader.cpp | 2 +- plugins/delay/delaycontrolsdialog.cpp | 60 +++++++-------- .../dynamics_processor_control_dialog.cpp | 8 +- plugins/flanger/flangercontrolsdialog.cpp | 76 +++++++++---------- plugins/kicker/kicker.cpp | 20 ++--- plugins/lb302/lb302.cpp | 12 +-- plugins/monstro/Monstro.h | 4 +- plugins/nes/Nes.h | 2 +- plugins/opl2/opl2instrument.cpp | 2 +- plugins/organic/organic.cpp | 16 ++-- plugins/papu/papu_instrument.cpp | 30 ++++---- .../peak_controller_effect_control_dialog.cpp | 12 +-- plugins/sf2_player/sf2_player.cpp | 18 ++--- plugins/sid/sid_instrument.cpp | 18 ++--- .../stereoenhancer_control_dialog.cpp | 2 +- .../stereomatrix_control_dialog.cpp | 8 +- plugins/stk/mallets/mallets.cpp | 30 ++++---- .../triple_oscillator/TripleOscillator.cpp | 16 ++-- plugins/vibed/vibed.cpp | 24 +++--- plugins/watsyn/Watsyn.h | 4 +- .../waveshaper/waveshaper_control_dialog.cpp | 4 +- plugins/zynaddsubfx/ZynAddSubFx.cpp | 14 ++-- src/gui/LfoControllerDialog.cpp | 8 +- src/gui/widgets/EffectView.cpp | 6 +- src/gui/widgets/EnvelopeAndLfoView.cpp | 20 ++--- src/gui/widgets/InstrumentFunctionViews.cpp | 8 +- .../widgets/InstrumentSoundShapingView.cpp | 4 +- src/gui/widgets/LadspaControlView.cpp | 2 +- src/tracks/InstrumentTrack.cpp | 8 +- src/tracks/SampleTrack.cpp | 2 +- 35 files changed, 235 insertions(+), 235 deletions(-) diff --git a/plugins/Amplifier/AmplifierControlDialog.cpp b/plugins/Amplifier/AmplifierControlDialog.cpp index d5b17e4d1..50396a551 100644 --- a/plugins/Amplifier/AmplifierControlDialog.cpp +++ b/plugins/Amplifier/AmplifierControlDialog.cpp @@ -45,26 +45,26 @@ AmplifierControlDialog::AmplifierControlDialog( AmplifierControls* controls ) : volumeKnob -> setVolumeKnob( true ); volumeKnob->setModel( &controls->m_volumeModel ); volumeKnob->setLabel( tr( "VOL" ) ); - volumeKnob->setHintText( tr( "Volume:" ) , "%" ); + volumeKnob->setHintText( tr( "Volume:" ) , "%" ); Knob * panKnob = new Knob( knobBright_26, this); panKnob -> move( 60, 30 ); panKnob->setModel( &controls->m_panModel ); panKnob->setLabel( tr( "PAN" ) ); - panKnob->setHintText( tr( "Panning:" ) , "" ); + panKnob->setHintText( tr( "Panning:" ) , "" ); Knob * leftKnob = new Knob( knobBright_26, this); leftKnob -> move( 20, 80 ); leftKnob -> setVolumeKnob( true ); leftKnob->setModel( &controls->m_leftModel ); leftKnob->setLabel( tr( "LEFT" ) ); - leftKnob->setHintText( tr( "Left gain:" ) , "%" ); + leftKnob->setHintText( tr( "Left gain:" ) , "%" ); Knob * rightKnob = new Knob( knobBright_26, this); rightKnob -> move( 60, 80 ); rightKnob -> setVolumeKnob( true ); rightKnob->setModel( &controls->m_rightModel ); rightKnob->setLabel( tr( "RIGHT" ) ); - rightKnob->setHintText( tr( "Right gain:" ) , "%" ); + rightKnob->setHintText( tr( "Right gain:" ) , "%" ); } diff --git a/plugins/BassBooster/BassBoosterControlDialog.cpp b/plugins/BassBooster/BassBoosterControlDialog.cpp index a589576dc..fa4eac97d 100644 --- a/plugins/BassBooster/BassBoosterControlDialog.cpp +++ b/plugins/BassBooster/BassBoosterControlDialog.cpp @@ -47,17 +47,17 @@ BassBoosterControlDialog::BassBoosterControlDialog( BassBoosterControls* control Knob * freqKnob = new Knob( knobBright_26, this); freqKnob->setModel( &controls->m_freqModel ); freqKnob->setLabel( tr( "FREQ" ) ); - freqKnob->setHintText( tr( "Frequency:" ) , "Hz" ); + freqKnob->setHintText( tr( "Frequency:" ) , "Hz" ); Knob * gainKnob = new Knob( knobBright_26, this ); gainKnob->setModel( &controls->m_gainModel ); gainKnob->setLabel( tr( "GAIN" ) ); - gainKnob->setHintText( tr( "Gain:" ) , "" ); + gainKnob->setHintText( tr( "Gain:" ) , "" ); Knob * ratioKnob = new Knob( knobBright_26, this ); ratioKnob->setModel( &controls->m_ratioModel ); ratioKnob->setLabel( tr( "RATIO" ) ); - ratioKnob->setHintText( tr( "Ratio:" ) , "" ); + ratioKnob->setHintText( tr( "Ratio:" ) , "" ); l->addWidget( freqKnob ); l->addWidget( gainKnob ); diff --git a/plugins/DualFilter/DualFilterControlDialog.cpp b/plugins/DualFilter/DualFilterControlDialog.cpp index 0e7f19807..4a769e410 100644 --- a/plugins/DualFilter/DualFilterControlDialog.cpp +++ b/plugins/DualFilter/DualFilterControlDialog.cpp @@ -38,7 +38,7 @@ name -> move( x, y ); \ name ->setModel( &controls-> model ); \ name ->setLabel( tr( label ) ); \ - name ->setHintText( tr( hint ) , unit ); + name ->setHintText( tr( hint ) , unit ); diff --git a/plugins/MultitapEcho/MultitapEchoControlDialog.cpp b/plugins/MultitapEcho/MultitapEchoControlDialog.cpp index 52fa2bdec..5ff5fa900 100644 --- a/plugins/MultitapEcho/MultitapEchoControlDialog.cpp +++ b/plugins/MultitapEcho/MultitapEchoControlDialog.cpp @@ -82,19 +82,19 @@ MultitapEchoControlDialog::MultitapEchoControlDialog( MultitapEchoControls * con stepLength->move( 100, 245 ); stepLength->setModel( & controls->m_stepLength ); stepLength->setLabel( tr( "Length" ) ); - stepLength->setHintText( tr( "Step length:" ) , " ms" ); + stepLength->setHintText( tr( "Step length:" ) , " ms" ); Knob * dryGain = new Knob( knobBright_26, this ); dryGain->move( 150, 245 ); dryGain->setModel( & controls->m_dryGain ); dryGain->setLabel( tr( "Dry" ) ); - dryGain->setHintText( tr( "Dry Gain:" ) , " dBV" ); + dryGain->setHintText( tr( "Dry Gain:" ) , " dBV" ); Knob * stages = new Knob( knobBright_26, this ); stages->move( 200, 245 ); stages->setModel( & controls->m_stages ); stages->setLabel( tr( "Stages" ) ); - stages->setHintText( tr( "Lowpass stages:" ) , "x" ); + stages->setHintText( tr( "Lowpass stages:" ) , "x" ); // switch led LedCheckBox * swapInputs = new LedCheckBox( "Swap inputs", this, tr( "Swap inputs" ), LedCheckBox::Green ); diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index 024494947..ce390192a 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -543,7 +543,7 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, m_ampKnob = new Knob( knobBright_26, this ); m_ampKnob->setVolumeKnob( true ); m_ampKnob->move( 5, 108 ); - m_ampKnob->setHintText( tr( "Amplify:" ), "%" ); + m_ampKnob->setHintText( tr( "Amplify:" ), "%" ); m_ampKnob->setWhatsThis( tr( "With this knob you can set the amplify ratio. When you " "set a value of 100% your sample isn't changed. " @@ -552,21 +552,21 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, m_startKnob = new AudioFileProcessorWaveView::knob( this ); m_startKnob->move( 45, 108 ); - m_startKnob->setHintText( tr( "Startpoint:" ), "" ); + m_startKnob->setHintText( tr( "Startpoint:" ), "" ); m_startKnob->setWhatsThis( tr( "With this knob you can set the point where " "AudioFileProcessor should begin playing your sample. " ) ); m_endKnob = new AudioFileProcessorWaveView::knob( this ); m_endKnob->move( 125, 108 ); - m_endKnob->setHintText( tr( "Endpoint:" ), "" ); + m_endKnob->setHintText( tr( "Endpoint:" ), "" ); m_endKnob->setWhatsThis( tr( "With this knob you can set the point where " "AudioFileProcessor should stop playing your sample. " ) ); m_loopKnob = new AudioFileProcessorWaveView::knob( this ); m_loopKnob->move( 85, 108 ); - m_loopKnob->setHintText( tr( "Loopback point:" ), "" ); + m_loopKnob->setHintText( tr( "Loopback point:" ), "" ); m_loopKnob->setWhatsThis( tr( "With this knob you can set the point where " "the loop starts. " ) ); diff --git a/plugins/bit_invader/bit_invader.cpp b/plugins/bit_invader/bit_invader.cpp index 09b5cda95..668a761c8 100644 --- a/plugins/bit_invader/bit_invader.cpp +++ b/plugins/bit_invader/bit_invader.cpp @@ -335,7 +335,7 @@ bitInvaderView::bitInvaderView( Instrument * _instrument, m_sampleLengthKnob = new Knob( knobDark_28, this ); m_sampleLengthKnob->move( 6, 201 ); - m_sampleLengthKnob->setHintText( tr( "Sample Length" ), "" ); + m_sampleLengthKnob->setHintText( tr( "Sample Length" ), "" ); m_graph = new Graph( this, Graph::NearestStyle, 204, 134 ); m_graph->move(23,59); // 55,120 - 2px border diff --git a/plugins/delay/delaycontrolsdialog.cpp b/plugins/delay/delaycontrolsdialog.cpp index fd4e6cfb9..832c01ca4 100644 --- a/plugins/delay/delaycontrolsdialog.cpp +++ b/plugins/delay/delaycontrolsdialog.cpp @@ -31,40 +31,40 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) : - EffectControlDialog( controls ) + EffectControlDialog( controls ) { - setAutoFillBackground( true ); - QPalette pal; - pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); - setPalette( pal ); - setFixedSize( 200, 75 ); + setAutoFillBackground( true ); + QPalette pal; + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); + setPalette( pal ); + setFixedSize( 200, 75 ); - TempoSyncKnob* sampleDelayKnob = new TempoSyncKnob( knobBright_26, this ); - sampleDelayKnob->move( 20,10 ); - sampleDelayKnob->setVolumeKnob( false ); - sampleDelayKnob->setModel( &controls->m_delayTimeModel ); - sampleDelayKnob->setLabel( tr( "Delay" ) ); - sampleDelayKnob->setHintText( tr( "Delay Time Seconds:" ) + " ", "" ); + TempoSyncKnob* sampleDelayKnob = new TempoSyncKnob( knobBright_26, this ); + sampleDelayKnob->move( 20,10 ); + sampleDelayKnob->setVolumeKnob( false ); + sampleDelayKnob->setModel( &controls->m_delayTimeModel ); + sampleDelayKnob->setLabel( tr( "Delay" ) ); + sampleDelayKnob->setHintText( tr( "Delay Time Seconds:" ) + " ", "" ); - Knob * feedbackKnob = new Knob( knobBright_26, this ); - feedbackKnob->move( 63,10 ); - feedbackKnob->setVolumeKnob( true) ; - feedbackKnob->setModel( &controls->m_feedbackModel); - feedbackKnob->setLabel( tr( "Regen" ) ); - feedbackKnob->setHintText( tr ( "Feedback Amount:" ) + " ", "" ); + Knob * feedbackKnob = new Knob( knobBright_26, this ); + feedbackKnob->move( 63,10 ); + feedbackKnob->setVolumeKnob( true) ; + feedbackKnob->setModel( &controls->m_feedbackModel); + feedbackKnob->setLabel( tr( "Regen" ) ); + feedbackKnob->setHintText( tr ( "Feedback Amount:" ) + " ", "" ); - TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this ); - lfoFreqKnob->move( 106,10 ); - lfoFreqKnob->setVolumeKnob( false ); - lfoFreqKnob->setModel( &controls->m_lfoTimeModel ); - lfoFreqKnob->setLabel( tr( "Rate" ) ); - lfoFreqKnob->setHintText( tr ( "Lfo Seconds:" ) + " ", "" ); + TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this ); + lfoFreqKnob->move( 106,10 ); + lfoFreqKnob->setVolumeKnob( false ); + lfoFreqKnob->setModel( &controls->m_lfoTimeModel ); + lfoFreqKnob->setLabel( tr( "Rate" ) ); + lfoFreqKnob->setHintText( tr ( "Lfo Seconds:" ) + " ", "" ); - TempoSyncKnob * lfoAmtKnob = new TempoSyncKnob( knobBright_26, this ); - lfoAmtKnob->move( 150,10 ); - lfoAmtKnob->setVolumeKnob( false ); - lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); - lfoAmtKnob->setLabel( tr( "Lfo" ) ); - lfoAmtKnob->setHintText( tr ( "Lfo Amt:" ) + " ", "" ); + TempoSyncKnob * lfoAmtKnob = new TempoSyncKnob( knobBright_26, this ); + lfoAmtKnob->move( 150,10 ); + lfoAmtKnob->setVolumeKnob( false ); + lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); + lfoAmtKnob->setLabel( tr( "Lfo" ) ); + lfoAmtKnob->setHintText( tr ( "Lfo Amt:" ) + " ", "" ); } diff --git a/plugins/dynamics_processor/dynamics_processor_control_dialog.cpp b/plugins/dynamics_processor/dynamics_processor_control_dialog.cpp index 2ae1b8d78..5b820e1fa 100644 --- a/plugins/dynamics_processor/dynamics_processor_control_dialog.cpp +++ b/plugins/dynamics_processor/dynamics_processor_control_dialog.cpp @@ -63,7 +63,7 @@ dynProcControlDialog::dynProcControlDialog( inputKnob -> move( 14, 251 ); inputKnob->setModel( &_controls->m_inputModel ); inputKnob->setLabel( tr( "INPUT" ) ); - inputKnob->setHintText( tr( "Input gain:" ) , "" ); + inputKnob->setHintText( tr( "Input gain:" ) , "" ); Knob * outputKnob = new Knob( knobBright_26, this ); outputKnob -> setVolumeKnob( true ); @@ -71,19 +71,19 @@ dynProcControlDialog::dynProcControlDialog( outputKnob -> move( 54, 251 ); outputKnob->setModel( &_controls->m_outputModel ); outputKnob->setLabel( tr( "OUTPUT" ) ); - outputKnob->setHintText( tr( "Output gain:" ) , "" ); + outputKnob->setHintText( tr( "Output gain:" ) , "" ); Knob * attackKnob = new Knob( knobBright_26, this); attackKnob -> move( 11, 291 ); attackKnob->setModel( &_controls->m_attackModel ); attackKnob->setLabel( tr( "ATTACK" ) ); - attackKnob->setHintText( tr( "Peak attack time:" ) , "ms" ); + attackKnob->setHintText( tr( "Peak attack time:" ) , "ms" ); Knob * releaseKnob = new Knob( knobBright_26, this ); releaseKnob -> move( 52, 291 ); releaseKnob->setModel( &_controls->m_releaseModel ); releaseKnob->setLabel( tr( "RELEASE" ) ); - releaseKnob->setHintText( tr( "Peak release time:" ) , "ms" ); + releaseKnob->setHintText( tr( "Peak release time:" ) , "ms" ); //waveform control buttons diff --git a/plugins/flanger/flangercontrolsdialog.cpp b/plugins/flanger/flangercontrolsdialog.cpp index b404ea39a..8b3c61df4 100644 --- a/plugins/flanger/flangercontrolsdialog.cpp +++ b/plugins/flanger/flangercontrolsdialog.cpp @@ -32,51 +32,51 @@ FlangerControlsDialog::FlangerControlsDialog( FlangerControls *controls ) : - EffectControlDialog( controls ) + EffectControlDialog( controls ) { - setAutoFillBackground( true ); - QPalette pal; - pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); - setPalette( pal ); - setFixedSize( 200, 75 ); + setAutoFillBackground( true ); + QPalette pal; + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); + setPalette( pal ); + setFixedSize( 200, 75 ); - Knob* delayKnob = new Knob( knobBright_26, this ); - delayKnob->move( 20,10 ); - delayKnob->setVolumeKnob( false ); - delayKnob->setModel( &controls->m_delayTimeModel ); - delayKnob->setLabel( tr( "Delay" ) ); - delayKnob->setHintText( tr( "Delay Time:" ) + " ", "" ); + Knob* delayKnob = new Knob( knobBright_26, this ); + delayKnob->move( 20,10 ); + delayKnob->setVolumeKnob( false ); + delayKnob->setModel( &controls->m_delayTimeModel ); + delayKnob->setLabel( tr( "Delay" ) ); + delayKnob->setHintText( tr( "Delay Time:" ) + " ", "" ); - TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this ); - lfoFreqKnob->move( 53,10 ); - lfoFreqKnob->setVolumeKnob( false ); - lfoFreqKnob->setModel( &controls->m_lfoFrequencyModel ); - lfoFreqKnob->setLabel( tr( "Lfo Hz" ) ); - lfoFreqKnob->setHintText( tr ( "Lfo:" ) , "s" ); + TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this ); + lfoFreqKnob->move( 53,10 ); + lfoFreqKnob->setVolumeKnob( false ); + lfoFreqKnob->setModel( &controls->m_lfoFrequencyModel ); + lfoFreqKnob->setLabel( tr( "Lfo Hz" ) ); + lfoFreqKnob->setHintText( tr ( "Lfo:" ) , "s" ); - Knob * lfoAmtKnob = new Knob( knobBright_26, this ); - lfoAmtKnob->move( 86,10 ); - lfoAmtKnob->setVolumeKnob( false ); - lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); - lfoAmtKnob->setLabel( tr( "Amt" ) ); - lfoAmtKnob->setHintText( tr ( "Amt:" ) , "" ); + Knob * lfoAmtKnob = new Knob( knobBright_26, this ); + lfoAmtKnob->move( 86,10 ); + lfoAmtKnob->setVolumeKnob( false ); + lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); + lfoAmtKnob->setLabel( tr( "Amt" ) ); + lfoAmtKnob->setHintText( tr ( "Amt:" ) , "" ); - Knob * feedbackKnob = new Knob( knobBright_26, this ); - feedbackKnob->move( 119,10 ); - feedbackKnob->setVolumeKnob( true) ; - feedbackKnob->setModel( &controls->m_feedbackModel ); - feedbackKnob->setLabel( tr( "Regen" ) ); - feedbackKnob->setHintText( tr ( "Feedback Amount:" ) , "" ); + Knob * feedbackKnob = new Knob( knobBright_26, this ); + feedbackKnob->move( 119,10 ); + feedbackKnob->setVolumeKnob( true) ; + feedbackKnob->setModel( &controls->m_feedbackModel ); + feedbackKnob->setLabel( tr( "Regen" ) ); + feedbackKnob->setHintText( tr ( "Feedback Amount:" ) , "" ); - Knob * whiteNoiseKnob = new Knob( knobBright_26, this ); - whiteNoiseKnob->move( 150,10 ); - whiteNoiseKnob->setVolumeKnob( true) ; - whiteNoiseKnob->setModel( &controls->m_whiteNoiseAmountModel ); - whiteNoiseKnob->setLabel( tr( "Noise" ) ); - whiteNoiseKnob->setHintText( tr ( "White Noise Amount:" ) , "" ); + Knob * whiteNoiseKnob = new Knob( knobBright_26, this ); + whiteNoiseKnob->move( 150,10 ); + whiteNoiseKnob->setVolumeKnob( true) ; + whiteNoiseKnob->setModel( &controls->m_whiteNoiseAmountModel ); + whiteNoiseKnob->setLabel( tr( "Noise" ) ); + whiteNoiseKnob->setHintText( tr ( "White Noise Amount:" ) , "" ); - LedCheckBox* invertCb = new LedCheckBox( tr( "" ), this ); - invertCb->move( 15,55 ); + LedCheckBox* invertCb = new LedCheckBox( tr( "" ), this ); + invertCb->move( 15,55 ); diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index ddd68abc7..38149519f 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -280,43 +280,43 @@ kickerInstrumentView::kickerInstrumentView( Instrument * _instrument, const int END_COL = COL1 + 48; m_startFreqKnob = new kickerLargeKnob( this ); - m_startFreqKnob->setHintText( tr( "Start frequency:" ), "Hz" ); + m_startFreqKnob->setHintText( tr( "Start frequency:" ), "Hz" ); m_startFreqKnob->move( COL1, ROW1 ); m_endFreqKnob = new kickerLargeKnob( this ); - m_endFreqKnob->setHintText( tr( "End frequency:" ), "Hz" ); + m_endFreqKnob->setHintText( tr( "End frequency:" ), "Hz" ); m_endFreqKnob->move( END_COL, ROW1 ); m_slopeKnob = new kickerKnob( this ); - m_slopeKnob->setHintText( tr( "Frequency Slope:" ), "" ); + m_slopeKnob->setHintText( tr( "Frequency Slope:" ), "" ); m_slopeKnob->move( COL3, ROW1 ); m_gainKnob = new kickerKnob( this ); - m_gainKnob->setHintText( tr( "Gain:" ), "" ); + m_gainKnob->setHintText( tr( "Gain:" ), "" ); m_gainKnob->move( COL1, ROW3 ); m_decayKnob = new kickerEnvKnob( this ); - m_decayKnob->setHintText( tr( "Envelope Length:" ), "ms" ); + m_decayKnob->setHintText( tr( "Envelope Length:" ), "ms" ); m_decayKnob->move( COL2, ROW3 ); m_envKnob = new kickerKnob( this ); - m_envKnob->setHintText( tr( "Envelope Slope:" ), "" ); + m_envKnob->setHintText( tr( "Envelope Slope:" ), "" ); m_envKnob->move( COL3, ROW3 ); m_clickKnob = new kickerKnob( this ); - m_clickKnob->setHintText( tr( "Click:" ), "" ); + m_clickKnob->setHintText( tr( "Click:" ), "" ); m_clickKnob->move( COL5, ROW1 ); m_noiseKnob = new kickerKnob( this ); - m_noiseKnob->setHintText( tr( "Noise:" ), "" ); + m_noiseKnob->setHintText( tr( "Noise:" ), "" ); m_noiseKnob->move( COL5, ROW3 ); m_distKnob = new kickerKnob( this ); - m_distKnob->setHintText( tr( "Distortion Start:" ), "" ); + m_distKnob->setHintText( tr( "Distortion Start:" ), "" ); m_distKnob->move( COL4, ROW2 ); m_distEndKnob = new kickerKnob( this ); - m_distEndKnob->setHintText( tr( "Distortion End:" ), "" ); + m_distEndKnob->setHintText( tr( "Distortion End:" ), "" ); m_distEndKnob->move( COL5, ROW2 ); m_startNoteToggle = new LedCheckBox( "", this, "", LedCheckBox::Green ); diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index d1d352d0b..8e8785d6e 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -824,22 +824,22 @@ lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) : // GUI m_vcfCutKnob = new Knob( knobBright_26, this ); m_vcfCutKnob->move( 75, 130 ); - m_vcfCutKnob->setHintText( tr( "Cutoff Freq:" ), "" ); + m_vcfCutKnob->setHintText( tr( "Cutoff Freq:" ), "" ); m_vcfCutKnob->setLabel( "" ); m_vcfResKnob = new Knob( knobBright_26, this ); m_vcfResKnob->move( 120, 130 ); - m_vcfResKnob->setHintText( tr( "Resonance:" ), "" ); + m_vcfResKnob->setHintText( tr( "Resonance:" ), "" ); m_vcfResKnob->setLabel( "" ); m_vcfModKnob = new Knob( knobBright_26, this ); m_vcfModKnob->move( 165, 130 ); - m_vcfModKnob->setHintText( tr( "Env Mod:" ), "" ); + m_vcfModKnob->setHintText( tr( "Env Mod:" ), "" ); m_vcfModKnob->setLabel( "" ); m_vcfDecKnob = new Knob( knobBright_26, this ); m_vcfDecKnob->move( 210, 130 ); - m_vcfDecKnob->setHintText( tr( "Decay:" ), "" ); + m_vcfDecKnob->setHintText( tr( "Decay:" ), "" ); m_vcfDecKnob->setLabel( "" ); m_slideToggle = new LedCheckBox( "", this ); @@ -860,12 +860,12 @@ lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) : m_slideDecKnob = new Knob( knobBright_26, this ); m_slideDecKnob->move( 210, 75 ); - m_slideDecKnob->setHintText( tr( "Slide Decay:" ), "" ); + m_slideDecKnob->setHintText( tr( "Slide Decay:" ), "" ); m_slideDecKnob->setLabel( ""); m_distKnob = new Knob( knobBright_26, this ); m_distKnob->move( 210, 190 ); - m_distKnob->setHintText( tr( "DIST:" ), "" ); + m_distKnob->setHintText( tr( "DIST:" ), "" ); m_distKnob->setLabel( tr( "")); diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index b0bf366d0..95dfa2933 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -46,14 +46,14 @@ #define makeknob( name, x, y, hint, unit, oname ) \ name = new Knob( knobStyled, view ); \ name ->move( x, y ); \ - name ->setHintText( tr( hint ), unit ); \ + name ->setHintText( tr( hint ), unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 20, 20 ); #define maketsknob( name, x, y, hint, unit, oname ) \ name = new TempoSyncKnob( knobStyled, view ); \ name ->move( x, y ); \ - name ->setHintText( tr( hint ), unit ); \ + name ->setHintText( tr( hint ), unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 20, 20 ); diff --git a/plugins/nes/Nes.h b/plugins/nes/Nes.h index 29db58b79..3a75a7c06 100644 --- a/plugins/nes/Nes.h +++ b/plugins/nes/Nes.h @@ -38,7 +38,7 @@ #define makeknob( name, x, y, hint, unit, oname ) \ name = new Knob( knobStyled, this ); \ name ->move( x, y ); \ - name ->setHintText( tr( hint ), unit ); \ + name ->setHintText( tr( hint ), unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 29, 29 ); diff --git a/plugins/opl2/opl2instrument.cpp b/plugins/opl2/opl2instrument.cpp index 188a05323..2a8867c66 100644 --- a/plugins/opl2/opl2instrument.cpp +++ b/plugins/opl2/opl2instrument.cpp @@ -586,7 +586,7 @@ opl2instrumentView::opl2instrumentView( Instrument * _instrument, #define KNOB_GEN(knobname, hinttext, hintunit,xpos,ypos) \ knobname = new Knob( knobStyled, this );\ - knobname->setHintText( tr(hinttext), hintunit );\ + knobname->setHintText( tr(hinttext), hintunit );\ knobname->setFixedSize(22,22);\ knobname->setCenterPointX(11.0);\ knobname->setCenterPointY(11.0);\ diff --git a/plugins/organic/organic.cpp b/plugins/organic/organic.cpp index 2e45aa8e9..95e229613 100644 --- a/plugins/organic/organic.cpp +++ b/plugins/organic/organic.cpp @@ -433,7 +433,7 @@ organicInstrumentView::organicInstrumentView( Instrument * _instrument, m_fx1Knob = new organicKnob( this ); m_fx1Knob->move( 15, 201 ); m_fx1Knob->setFixedSize( 37, 47 ); - m_fx1Knob->setHintText( tr( "Distortion:" ), QString() ); + m_fx1Knob->setHintText( tr( "Distortion:" ), QString() ); m_fx1Knob->setObjectName( "fx1Knob" ); m_fx1Knob->setWhatsThis( tr( "The distortion knob adds distortion to the output of the instrument. " ) ); @@ -442,7 +442,7 @@ organicInstrumentView::organicInstrumentView( Instrument * _instrument, m_volKnob->setVolumeKnob( true ); m_volKnob->move( 60, 201 ); m_volKnob->setFixedSize( 37, 47 ); - m_volKnob->setHintText( tr( "Volume:" ), "%" ); + m_volKnob->setHintText( tr( "Volume:" ), "%" ); m_volKnob->setObjectName( "volKnob" ); m_volKnob->setWhatsThis( tr( "The volume knob controls the volume of the output of the instrument. " "It is cumulative with the instrument window's volume control. " ) ); @@ -513,7 +513,7 @@ void organicInstrumentView::modelChanged() connect( &oi->m_osc[i]->m_oscModel, SIGNAL( dataChanged() ), this, SLOT( updateKnobHint() ) ); - oscKnob->setHintText( tr( "Osc %1 waveform:" ).arg( i + 1 ), QString() ); + oscKnob->setHintText( tr( "Osc %1 waveform:" ).arg( i + 1 ), QString() ); // setup volume-knob Knob * volKnob = new Knob( knobStyled, this ); @@ -521,19 +521,19 @@ void organicInstrumentView::modelChanged() volKnob->move( x + i * colWidth, y + rowHeight*1 ); volKnob->setFixedSize( 21, 21 ); volKnob->setHintText( tr( "Osc %1 volume:" ).arg( - i + 1 ), "%" ); + i + 1 ), "%" ); // setup panning-knob Knob * panKnob = new organicKnob( this ); panKnob->move( x + i * colWidth, y + rowHeight*2 ); panKnob->setHintText( tr("Osc %1 panning:").arg( - i + 1 ), "" ); + i + 1 ), "" ); // setup knob for fine-detuning Knob * detuneKnob = new organicKnob( this ); detuneKnob->move( x + i * colWidth, y + rowHeight*3 ); detuneKnob->setHintText( tr( "Osc %1 stereo detuning" ).arg( i + 1 ) - , " " + + , " " + tr( "cents" ) ); m_oscKnobs[i] = OscillatorKnobs( harmKnob, volKnob, oscKnob, panKnob, detuneKnob ); @@ -557,9 +557,9 @@ void organicInstrumentView::updateKnobHint() const float harm = oi->m_osc[i]->m_harmModel.value(); const float wave = oi->m_osc[i]->m_oscModel.value(); - m_oscKnobs[i].m_harmKnob->setHintText( tr( "Osc %1 harmonic:" ), " (" + + m_oscKnobs[i].m_harmKnob->setHintText( tr( "Osc %1 harmonic:" ), " (" + HARMONIC_NAMES[ static_cast( harm ) ] + ")" ); - m_oscKnobs[i].m_oscKnob->setHintText( tr( "Osc %1 waveform:" ), " (" + + m_oscKnobs[i].m_oscKnob->setHintText( tr( "Osc %1 waveform:" ), " (" + WAVEFORM_NAMES[ static_cast( wave ) ] + ")" ); } } diff --git a/plugins/papu/papu_instrument.cpp b/plugins/papu/papu_instrument.cpp index 1af0da914..9177d7283 100644 --- a/plugins/papu/papu_instrument.cpp +++ b/plugins/papu/papu_instrument.cpp @@ -456,7 +456,7 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, setPalette( pal ); m_ch1SweepTimeKnob = new papuKnob( this ); - m_ch1SweepTimeKnob->setHintText( tr( "Sweep Time:" ), "" ); + m_ch1SweepTimeKnob->setHintText( tr( "Sweep Time:" ), "" ); m_ch1SweepTimeKnob->move( 5 + 4*32, 106 ); ToolTip::add( m_ch1SweepTimeKnob, tr( "Sweep Time" ) ); m_ch1SweepTimeKnob->setWhatsThis( tr( "The amount of increase or" @@ -464,7 +464,7 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch1SweepRtShiftKnob = new papuKnob( this ); m_ch1SweepRtShiftKnob->setHintText( tr( "Sweep RtShift amount:" ) - , "" ); + , "" ); m_ch1SweepRtShiftKnob->move( 5 + 3*32, 106 ); ToolTip::add( m_ch1SweepRtShiftKnob, tr( "Sweep RtShift amount" ) ); m_ch1SweepRtShiftKnob->setWhatsThis( tr( "The rate at which increase or" @@ -472,7 +472,7 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch1WavePatternDutyKnob = new papuKnob( this ); m_ch1WavePatternDutyKnob->setHintText( tr( "Wave pattern duty:" ) - , "" ); + , "" ); m_ch1WavePatternDutyKnob->move( 5 + 2*32, 106 ); ToolTip::add( m_ch1WavePatternDutyKnob, tr( "Wave Pattern Duty" ) ); m_ch1WavePatternDutyKnob->setWhatsThis( tr( "The duty cycle is the ratio of" @@ -481,14 +481,14 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch1VolumeKnob = new papuKnob( this ); m_ch1VolumeKnob->setHintText( tr( "Square Channel 1 Volume:" ) - , "" ); + , "" ); m_ch1VolumeKnob->move( 5, 106 ); ToolTip::add( m_ch1VolumeKnob, tr( "Square Channel 1 Volume:" ) ); m_ch1VolumeKnob->setWhatsThis( tr( "Square Channel 1 Volume" ) ); m_ch1SweepStepLengthKnob = new papuKnob( this ); m_ch1SweepStepLengthKnob->setHintText( tr( "Length of each step in sweep:" ) - , "" ); + , "" ); m_ch1SweepStepLengthKnob->move( 5 + 32, 106 ); ToolTip::add( m_ch1SweepStepLengthKnob, tr( "Length of each step in sweep" ) ); m_ch1SweepStepLengthKnob->setWhatsThis( tr( "The delay between step change" ) ); @@ -497,7 +497,7 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch2WavePatternDutyKnob = new papuKnob( this ); m_ch2WavePatternDutyKnob->setHintText( tr( "Wave pattern duty:" ) - , "" ); + , "" ); m_ch2WavePatternDutyKnob->move( 5 + 2*32, 155 ); ToolTip::add( m_ch2WavePatternDutyKnob, tr( "Wave pattern duty" ) ); m_ch2WavePatternDutyKnob->setWhatsThis( tr( "The duty cycle is the ratio of" @@ -506,14 +506,14 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch2VolumeKnob = new papuKnob( this ); m_ch2VolumeKnob->setHintText( tr( "Square Channel 2 Volume:" ) - , "" ); + , "" ); m_ch2VolumeKnob->move( 5, 155 ); ToolTip::add( m_ch2VolumeKnob, tr( "Square Channel 2 Volume" ) ); m_ch2VolumeKnob->setWhatsThis( tr( "Square Channel 2 Volume" ) ); m_ch2SweepStepLengthKnob = new papuKnob( this ); m_ch2SweepStepLengthKnob->setHintText( tr( "Length of each step in sweep:" ) - , "" ); + , "" ); m_ch2SweepStepLengthKnob->move( 5 + 32, 155 ); ToolTip::add( m_ch2SweepStepLengthKnob, tr( "Length of each step in sweep" ) ); m_ch2SweepStepLengthKnob->setWhatsThis( tr( "The delay between step change" ) ); @@ -521,7 +521,7 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch3VolumeKnob = new papuKnob( this ); - m_ch3VolumeKnob->setHintText( tr( "Wave Channel Volume:" ), "" ); + m_ch3VolumeKnob->setHintText( tr( "Wave Channel Volume:" ), "" ); m_ch3VolumeKnob->move( 5, 204 ); ToolTip::add( m_ch3VolumeKnob, tr( "Wave Channel Volume" ) ); m_ch3VolumeKnob->setWhatsThis( tr( "Wave Channel Volume" ) ); @@ -529,14 +529,14 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_ch4VolumeKnob = new papuKnob( this ); - m_ch4VolumeKnob->setHintText( tr( "Noise Channel Volume:" ), "" ); + m_ch4VolumeKnob->setHintText( tr( "Noise Channel Volume:" ), "" ); m_ch4VolumeKnob->move( 144, 155 ); ToolTip::add( m_ch4VolumeKnob, tr( "Noise Channel Volume" ) ); m_ch4VolumeKnob->setWhatsThis( tr( "Noise Channel Volume" ) ); m_ch4SweepStepLengthKnob = new papuKnob( this ); m_ch4SweepStepLengthKnob->setHintText( tr( "Length of each step in sweep:" ) - , "" ); + , "" ); m_ch4SweepStepLengthKnob->move( 144 + 32, 155 ); ToolTip::add( m_ch4SweepStepLengthKnob, tr( "Length of each step in sweep" ) ); m_ch4SweepStepLengthKnob->setWhatsThis( tr( "The delay between step change" ) ); @@ -544,22 +544,22 @@ papuInstrumentView::papuInstrumentView( Instrument * _instrument, m_so1VolumeKnob = new papuKnob( this ); - m_so1VolumeKnob->setHintText( tr( "SO1 Volume (Right):" ), "" ); + m_so1VolumeKnob->setHintText( tr( "SO1 Volume (Right):" ), "" ); m_so1VolumeKnob->move( 5, 58 ); ToolTip::add( m_so1VolumeKnob, tr( "SO1 Volume (Right)" ) ); m_so2VolumeKnob = new papuKnob( this ); - m_so2VolumeKnob->setHintText( tr( "SO2 Volume (Left):" ), "" ); + m_so2VolumeKnob->setHintText( tr( "SO2 Volume (Left):" ), "" ); m_so2VolumeKnob->move( 5 + 32, 58 ); ToolTip::add( m_so2VolumeKnob, tr( "SO2 Volume (Left)" ) ); m_trebleKnob = new papuKnob( this ); - m_trebleKnob->setHintText( tr( "Treble:" ), "" ); + m_trebleKnob->setHintText( tr( "Treble:" ), "" ); m_trebleKnob->move( 5 + 2*32, 58 ); ToolTip::add( m_trebleKnob, tr( "Treble" ) ); m_bassKnob = new papuKnob( this ); - m_bassKnob->setHintText( tr( "Bass:" ), "" ); + m_bassKnob->setHintText( tr( "Bass:" ), "" ); m_bassKnob->move( 5 + 3*32, 58 ); ToolTip::add( m_bassKnob, tr( "Bass" ) ); diff --git a/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp b/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp index beda3759a..7675da5d0 100644 --- a/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp @@ -53,32 +53,32 @@ PeakControllerEffectControlDialog::PeakControllerEffectControlDialog( m_baseKnob = new Knob( knobBright_26, this ); m_baseKnob->setLabel( tr( "BASE" ) ); m_baseKnob->setModel( &_controls->m_baseModel ); - m_baseKnob->setHintText( tr( "Base amount:" ) , "" ); + m_baseKnob->setHintText( tr( "Base amount:" ) , "" ); m_amountKnob = new Knob( knobBright_26, this ); m_amountKnob->setLabel( tr( "AMNT" ) ); m_amountKnob->setModel( &_controls->m_amountModel ); - m_amountKnob->setHintText( tr( "Modulation amount:" ) , "" ); + m_amountKnob->setHintText( tr( "Modulation amount:" ) , "" ); m_amountMultKnob = new Knob( knobBright_26, this ); m_amountMultKnob->setLabel( tr( "MULT" ) ); m_amountMultKnob->setModel( &_controls->m_amountMultModel ); - m_amountMultKnob->setHintText( tr( "Amount Multiplicator:" ) , "" ); + m_amountMultKnob->setHintText( tr( "Amount Multiplicator:" ) , "" ); m_attackKnob = new Knob( knobBright_26, this ); m_attackKnob->setLabel( tr( "ATCK" ) ); m_attackKnob->setModel( &_controls->m_attackModel ); - m_attackKnob->setHintText( tr( "Attack:" ) , "" ); + m_attackKnob->setHintText( tr( "Attack:" ) , "" ); m_decayKnob = new Knob( knobBright_26, this ); m_decayKnob->setLabel( tr( "DCAY" ) ); m_decayKnob->setModel( &_controls->m_decayModel ); - m_decayKnob->setHintText( tr( "Release:" ) , "" ); + m_decayKnob->setHintText( tr( "Release:" ) , "" ); m_tresholdKnob = new Knob( knobBright_26, this ); m_tresholdKnob->setLabel( tr( "TRES" ) ); m_tresholdKnob->setModel( &_controls->m_tresholdModel ); - m_tresholdKnob->setHintText( tr( "Treshold:" ) , "" ); + m_tresholdKnob->setHintText( tr( "Treshold:" ) , "" ); l->addWidget( m_baseKnob ); l->addWidget( m_amountKnob ); diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 3de39524b..91d9d6e8f 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -870,7 +870,7 @@ sf2InstrumentView::sf2InstrumentView( Instrument * _instrument, QWidget * _paren // Gain m_gainKnob = new sf2Knob( this ); - m_gainKnob->setHintText( tr("Gain") + " ", "" ); + m_gainKnob->setHintText( tr("Gain"), "" ); m_gainKnob->move( 86, 55 ); // vl->addWidget( m_gainKnob ); @@ -891,19 +891,19 @@ sf2InstrumentView::sf2InstrumentView( Instrument * _instrument, QWidget * _paren m_reverbRoomSizeKnob = new sf2Knob( this ); - m_reverbRoomSizeKnob->setHintText( tr("Reverb Roomsize:") + " ", "" ); + m_reverbRoomSizeKnob->setHintText( tr("Reverb Roomsize:"), "" ); m_reverbRoomSizeKnob->move( 93, 160 ); m_reverbDampingKnob = new sf2Knob( this ); - m_reverbDampingKnob->setHintText( tr("Reverb Damping:") + " ", "" ); + m_reverbDampingKnob->setHintText( tr("Reverb Damping:"), "" ); m_reverbDampingKnob->move( 130, 160 ); m_reverbWidthKnob = new sf2Knob( this ); - m_reverbWidthKnob->setHintText( tr("Reverb Width:") + " ", "" ); + m_reverbWidthKnob->setHintText( tr("Reverb Width:"), "" ); m_reverbWidthKnob->move( 167, 160 ); m_reverbLevelKnob = new sf2Knob( this ); - m_reverbLevelKnob->setHintText( tr("Reverb Level:") + " ", "" ); + m_reverbLevelKnob->setHintText( tr("Reverb Level:"), "" ); m_reverbLevelKnob->move( 204, 160 ); /* hl->addWidget( m_reverbOnLed ); @@ -930,19 +930,19 @@ sf2InstrumentView::sf2InstrumentView( Instrument * _instrument, QWidget * _paren "files that support it." ) ); m_chorusNumKnob = new sf2Knob( this ); - m_chorusNumKnob->setHintText( tr("Chorus Lines:") + " ", "" ); + m_chorusNumKnob->setHintText( tr("Chorus Lines:"), "" ); m_chorusNumKnob->move( 93, 206 ); m_chorusLevelKnob = new sf2Knob( this ); - m_chorusLevelKnob->setHintText( tr("Chorus Level:") + " ", "" ); + m_chorusLevelKnob->setHintText( tr("Chorus Level:"), "" ); m_chorusLevelKnob->move( 130 , 206 ); m_chorusSpeedKnob = new sf2Knob( this ); - m_chorusSpeedKnob->setHintText( tr("Chorus Speed:") + " ", "" ); + m_chorusSpeedKnob->setHintText( tr("Chorus Speed:"), "" ); m_chorusSpeedKnob->move( 167 , 206 ); m_chorusDepthKnob = new sf2Knob( this ); - m_chorusDepthKnob->setHintText( tr("Chorus Depth:") + " ", "" ); + m_chorusDepthKnob->setHintText( tr("Chorus Depth:"), "" ); m_chorusDepthKnob->move( 204 , 206 ); /* hl->addWidget( m_chorusOnLed ); diff --git a/plugins/sid/sid_instrument.cpp b/plugins/sid/sid_instrument.cpp index ce4acb680..03090e94d 100644 --- a/plugins/sid/sid_instrument.cpp +++ b/plugins/sid/sid_instrument.cpp @@ -487,15 +487,15 @@ sidInstrumentView::sidInstrumentView( Instrument * _instrument, setPalette( pal ); m_volKnob = new sidKnob( this ); - m_volKnob->setHintText( tr( "Volume:" ), "" ); + m_volKnob->setHintText( tr( "Volume:" ), "" ); m_volKnob->move( 7, 64 ); m_resKnob = new sidKnob( this ); - m_resKnob->setHintText( tr( "Resonance:" ), "" ); + m_resKnob->setHintText( tr( "Resonance:" ), "" ); m_resKnob->move( 7 + 28, 64 ); m_cutKnob = new sidKnob( this ); - m_cutKnob->setHintText( tr( "Cutoff frequency:" ), "Hz" ); + m_cutKnob->setHintText( tr( "Cutoff frequency:" ), "Hz" ); m_cutKnob->move( 7 + 2*28, 64 ); PixmapButton * hp_btn = new PixmapButton( this, NULL ); @@ -547,32 +547,32 @@ sidInstrumentView::sidInstrumentView( Instrument * _instrument, for( int i = 0; i < 3; i++ ) { Knob *ak = new sidKnob( this ); - ak->setHintText( tr("Attack:"), "" ); + ak->setHintText( tr("Attack:"), "" ); ak->move( 7, 114 + i*50 ); ak->setWhatsThis( tr ( "Attack rate determines how rapidly the output " "of Voice %1 rises from zero to peak amplitude." ).arg( i+1 ) ); Knob *dk = new sidKnob( this ); - dk->setHintText( tr("Decay:") , "" ); + dk->setHintText( tr("Decay:") , "" ); dk->move( 7 + 28, 114 + i*50 ); dk->setWhatsThis( tr ( "Decay rate determines how rapidly the output " "falls from the peak amplitude to the selected Sustain level." ) ); Knob *sk = new sidKnob( this ); - sk->setHintText( tr("Sustain:"), "" ); + sk->setHintText( tr("Sustain:"), "" ); sk->move( 7 + 2*28, 114 + i*50 ); sk->setWhatsThis( tr ( "Output of Voice %1 will remain at the selected " "Sustain amplitude as long as the note is held." ).arg( i+1 ) ); Knob *rk = new sidKnob( this ); - rk->setHintText( tr("Release:"), "" ); + rk->setHintText( tr("Release:"), "" ); rk->move( 7 + 3*28, 114 + i*50 ); rk->setWhatsThis( tr ( "The output of of Voice %1 will fall from " "Sustain amplitude to zero amplitude at the selected Release " "rate." ).arg( i+1 ) ); Knob *pwk = new sidKnob( this ); - pwk->setHintText( tr("Pulse Width:"), "" ); + pwk->setHintText( tr("Pulse Width:"), "" ); pwk->move( 7 + 4*28, 114 + i*50 ); pwk->setWhatsThis( tr ( "The Pulse Width resolution allows the width " "to be smoothly swept with no discernable stepping. The Pulse " @@ -580,7 +580,7 @@ sidInstrumentView::sidInstrumentView( Instrument * _instrument, " effect." ).arg( i+1 ) ); Knob *crsk = new sidKnob( this ); - crsk->setHintText( tr("Coarse:"), " semitones" ); + crsk->setHintText( tr("Coarse:"), " semitones" ); crsk->move( 147, 114 + i*50 ); crsk->setWhatsThis( tr ( "The Coarse detuning allows to detune Voice " "%1 one octave up or down." ).arg( i+1 ) ); diff --git a/plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp b/plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp index 34f1d7167..9fc3daafa 100644 --- a/plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp +++ b/plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp @@ -40,7 +40,7 @@ stereoEnhancerControlDialog::stereoEnhancerControlDialog( Knob * widthKnob = new Knob( knobBright_26, this ); widthKnob->setModel( &_controls->m_widthModel ); widthKnob->setLabel( tr( "WIDE" ) ); - widthKnob->setHintText( tr( "Width:" ) , "samples" ); + widthKnob->setHintText( tr( "Width:" ) , "samples" ); l->addWidget( widthKnob ); diff --git a/plugins/stereo_matrix/stereomatrix_control_dialog.cpp b/plugins/stereo_matrix/stereomatrix_control_dialog.cpp index 4ed6d0bb9..587787dc0 100644 --- a/plugins/stereo_matrix/stereomatrix_control_dialog.cpp +++ b/plugins/stereo_matrix/stereomatrix_control_dialog.cpp @@ -49,22 +49,22 @@ stereoMatrixControlDialog::stereoMatrixControlDialog( Knob * llKnob = new Knob( knobSmall_17, this ); llKnob->setModel( &_controls->m_llModel ); - llKnob->setHintText( tr( "Left to Left Vol:" ) , "" ); + llKnob->setHintText( tr( "Left to Left Vol:" ) , "" ); llKnob->move( 40, 60 ); Knob * lrKnob = new Knob( knobSmall_17, this ); lrKnob->setModel( &_controls->m_lrModel ); - lrKnob->setHintText( tr( "Left to Right Vol:" ) , "" ); + lrKnob->setHintText( tr( "Left to Right Vol:" ) , "" ); lrKnob->move( 40+28, 60); Knob * rlKnob = new Knob( knobSmall_17, this ); rlKnob->setModel( &_controls->m_rlModel ); - rlKnob->setHintText( tr( "Right to Left Vol:" ) , "" ); + rlKnob->setHintText( tr( "Right to Left Vol:" ) , "" ); rlKnob->move( 40, 60+28 ); Knob * rrKnob = new Knob( knobSmall_17, this ); rrKnob->setModel( &_controls->m_rrModel ); - rrKnob->setHintText( tr( "Right to Right Vol:" ) , "" ); + rrKnob->setHintText( tr( "Right to Right Vol:" ) , "" ); rrKnob->move( 40+28, 60+28 ); } diff --git a/plugins/stk/mallets/mallets.cpp b/plugins/stk/mallets/mallets.cpp index 433a6883b..70d93d068 100644 --- a/plugins/stk/mallets/mallets.cpp +++ b/plugins/stk/mallets/mallets.cpp @@ -334,7 +334,7 @@ malletsInstrumentView::malletsInstrumentView( malletsInstrument * _instrument, m_spreadKnob = new Knob( knobVintage_32, this ); m_spreadKnob->setLabel( tr( "Spread" ) ); m_spreadKnob->move( 190, 140 ); - m_spreadKnob->setHintText( tr( "Spread:" ) + " ", "" ); + m_spreadKnob->setHintText( tr( "Spread:" ), "" ); } @@ -366,27 +366,27 @@ QWidget * malletsInstrumentView::setupModalBarControls( QWidget * _parent ) m_hardnessKnob = new Knob( knobVintage_32, widget ); m_hardnessKnob->setLabel( tr( "Hardness" ) ); m_hardnessKnob->move( 30, 90 ); - m_hardnessKnob->setHintText( tr( "Hardness:" ) + " ", "" ); + m_hardnessKnob->setHintText( tr( "Hardness:" ), "" ); m_positionKnob = new Knob( knobVintage_32, widget ); m_positionKnob->setLabel( tr( "Position" ) ); m_positionKnob->move( 110, 90 ); - m_positionKnob->setHintText( tr( "Position:" ) + " ", "" ); + m_positionKnob->setHintText( tr( "Position:" ), "" ); m_vibratoGainKnob = new Knob( knobVintage_32, widget ); m_vibratoGainKnob->setLabel( tr( "Vib Gain" ) ); m_vibratoGainKnob->move( 30, 140 ); - m_vibratoGainKnob->setHintText( tr( "Vib Gain:" ) + " ", "" ); + m_vibratoGainKnob->setHintText( tr( "Vib Gain:" ), "" ); m_vibratoFreqKnob = new Knob( knobVintage_32, widget ); m_vibratoFreqKnob->setLabel( tr( "Vib Freq" ) ); m_vibratoFreqKnob->move( 110, 140 ); - m_vibratoFreqKnob->setHintText( tr( "Vib Freq:" ) + " ", "" ); + m_vibratoFreqKnob->setHintText( tr( "Vib Freq:" ), "" ); m_stickKnob = new Knob( knobVintage_32, widget ); m_stickKnob->setLabel( tr( "Stick Mix" ) ); m_stickKnob->move( 190, 90 ); - m_stickKnob->setHintText( tr( "Stick Mix:" ) + " ", "" ); + m_stickKnob->setHintText( tr( "Stick Mix:" ), "" ); return( widget ); } @@ -402,27 +402,27 @@ QWidget * malletsInstrumentView::setupTubeBellControls( QWidget * _parent ) m_modulatorKnob = new Knob( knobVintage_32, widget ); m_modulatorKnob->setLabel( tr( "Modulator" ) ); m_modulatorKnob->move( 30, 90 ); - m_modulatorKnob->setHintText( tr( "Modulator:" ) + " ", "" ); + m_modulatorKnob->setHintText( tr( "Modulator:" ), "" ); m_crossfadeKnob = new Knob( knobVintage_32, widget ); m_crossfadeKnob->setLabel( tr( "Crossfade" ) ); m_crossfadeKnob->move( 110, 90 ); - m_crossfadeKnob->setHintText( tr( "Crossfade:" ) + " ", "" ); + m_crossfadeKnob->setHintText( tr( "Crossfade:" ), "" ); m_lfoSpeedKnob = new Knob( knobVintage_32, widget ); m_lfoSpeedKnob->setLabel( tr( "LFO Speed" ) ); m_lfoSpeedKnob->move( 30, 140 ); - m_lfoSpeedKnob->setHintText( tr( "LFO Speed:" ) + " ", "" ); + m_lfoSpeedKnob->setHintText( tr( "LFO Speed:" ), "" ); m_lfoDepthKnob = new Knob( knobVintage_32, widget ); m_lfoDepthKnob->setLabel( tr( "LFO Depth" ) ); m_lfoDepthKnob->move( 110, 140 ); - m_lfoDepthKnob->setHintText( tr( "LFO Depth:" ) + " ", "" ); + m_lfoDepthKnob->setHintText( tr( "LFO Depth:" ), "" ); m_adsrKnob = new Knob( knobVintage_32, widget ); m_adsrKnob->setLabel( tr( "ADSR" ) ); m_adsrKnob->move( 190, 90 ); - m_adsrKnob->setHintText( tr( "ADSR:" ) + " ", "" ); + m_adsrKnob->setHintText( tr( "ADSR:" ), "" ); return( widget ); } @@ -442,22 +442,22 @@ QWidget * malletsInstrumentView::setupBandedWGControls( QWidget * _parent ) m_pressureKnob = new Knob( knobVintage_32, widget ); m_pressureKnob->setLabel( tr( "Pressure" ) ); m_pressureKnob->move( 30, 90 ); - m_pressureKnob->setHintText( tr( "Pressure:" ) + " ", "" ); + m_pressureKnob->setHintText( tr( "Pressure:" ), "" ); m_motionKnob = new Knob( knobVintage_32, widget ); m_motionKnob->setLabel( tr( "Motion" ) ); m_motionKnob->move( 110, 90 ); - m_motionKnob->setHintText( tr( "Motion:" ) + " ", "" ); + m_motionKnob->setHintText( tr( "Motion:" ), "" ); m_velocityKnob = new Knob( knobVintage_32, widget ); m_velocityKnob->setLabel( tr( "Speed" ) ); m_velocityKnob->move( 30, 140 ); - m_velocityKnob->setHintText( tr( "Speed:" ) + " ", "" ); + m_velocityKnob->setHintText( tr( "Speed:" ), "" ); m_vibratoKnob = new Knob( knobVintage_32, widget, tr( "Vibrato" ) ); m_vibratoKnob->setLabel( tr( "Vibrato" ) ); m_vibratoKnob->move( 110, 140 ); - m_vibratoKnob->setHintText( tr( "Vibrato:" ) + " ", "" ); + m_vibratoKnob->setHintText( tr( "Vibrato:" ), "" ); return( widget ); } diff --git a/plugins/triple_oscillator/TripleOscillator.cpp b/plugins/triple_oscillator/TripleOscillator.cpp index e188e8693..cdb35606c 100644 --- a/plugins/triple_oscillator/TripleOscillator.cpp +++ b/plugins/triple_oscillator/TripleOscillator.cpp @@ -555,7 +555,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, vk->setFixedSize( 28, 35 ); vk->move( 6, knob_y ); vk->setHintText( tr( "Osc %1 volume:" ).arg( - i+1 ), "%" ); + i+1 ), "%" ); vk->setWhatsThis( tr( "With this knob you can set the volume of " "oscillator %1. When setting a value of 0 the " @@ -566,7 +566,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, // setup panning-knob Knob * pk = new TripleOscKnob( this ); pk->move( 35, knob_y ); - pk->setHintText( tr("Osc %1 panning:").arg( i + 1 ), "" ); + pk->setHintText( tr("Osc %1 panning:").arg( i + 1 ), "" ); pk->setWhatsThis( tr( "With this knob you can set the panning of the " "oscillator %1. A value of -100 means 100% " @@ -576,8 +576,8 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, // setup coarse-knob Knob * ck = new TripleOscKnob( this ); ck->move( 82, knob_y ); - ck->setHintText( tr( "Osc %1 coarse detuning:" ).arg( i + 1 ) - , " " + tr( "semitones" ) ); + ck->setHintText( tr( "Osc %1 coarse detuning:" ).arg( i + 1 ) + , " " + tr( "semitones" ) ); ck->setWhatsThis( tr( "With this knob you can set the coarse detuning of " "oscillator %1. You can detune the oscillator " @@ -590,7 +590,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, Knob * flk = new TripleOscKnob( this ); flk->move( 111, knob_y ); flk->setHintText( tr( "Osc %1 fine detuning left:" ). - arg( i + 1 ), + arg( i + 1 ), " " + tr( "cents" ) ); flk->setWhatsThis( tr( "With this knob you can set the fine detuning of " @@ -603,7 +603,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, Knob * frk = new TripleOscKnob( this ); frk->move( 140, knob_y ); frk->setHintText( tr( "Osc %1 fine detuning right:" ). - arg( i + 1 ), + arg( i + 1 ), " " + tr( "cents" ) ); frk->setWhatsThis( tr( "With this knob you can set the fine detuning of " @@ -617,7 +617,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, Knob * pok = new TripleOscKnob( this ); pok->move( 188, knob_y ); pok->setHintText( tr( "Osc %1 phase-offset:" ). - arg( i + 1 ), + arg( i + 1 ), " " + tr( "degrees" ) ); pok->setWhatsThis( tr( "With this knob you can set the phase-offset of " @@ -633,7 +633,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, Knob * spdk = new TripleOscKnob( this ); spdk->move( 217, knob_y ); spdk->setHintText( tr("Osc %1 stereo phase-detuning:" ). - arg( i + 1 ), + arg( i + 1 ), " " + tr( "degrees" ) ); spdk->setWhatsThis( tr( "With this knob you can set the stereo phase-" diff --git a/plugins/vibed/vibed.cpp b/plugins/vibed/vibed.cpp index dbe201226..d74b654e2 100644 --- a/plugins/vibed/vibed.cpp +++ b/plugins/vibed/vibed.cpp @@ -361,14 +361,14 @@ vibedView::vibedView( Instrument * _instrument, m_volumeKnob = new Knob( knobBright_26, this ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->move( 103, 142 ); - m_volumeKnob->setHintText( tr( "Volume:" ), "" ); + m_volumeKnob->setHintText( tr( "Volume:" ), "" ); m_volumeKnob->setWhatsThis( tr( "The 'V' knob sets the volume " "of the selected string." ) ); m_stiffnessKnob = new Knob( knobBright_26, this ); m_stiffnessKnob->move( 129, 142 ); - m_stiffnessKnob->setHintText( tr( "String stiffness:" ) - , "" ); + m_stiffnessKnob->setHintText( tr( "String stiffness:" ) + , "" ); m_stiffnessKnob->setWhatsThis( tr( "The 'S' knob sets the stiffness of the selected string. The stiffness " "of the string affects how long the string will ring out. The lower " @@ -377,15 +377,15 @@ vibedView::vibedView( Instrument * _instrument, m_pickKnob = new Knob( knobBright_26, this ); m_pickKnob->move( 153, 142 ); - m_pickKnob->setHintText( tr( "Pick position:" ), "" ); + m_pickKnob->setHintText( tr( "Pick position:" ), "" ); m_pickKnob->setWhatsThis( tr( "The 'P' knob sets the position where the selected string will be 'picked'. " "The lower the setting the closer the pick is to the bridge." ) ); m_pickupKnob = new Knob( knobBright_26, this ); m_pickupKnob->move( 177, 142 ); - m_pickupKnob->setHintText( tr( "Pickup position:" ) - , "" ); + m_pickupKnob->setHintText( tr( "Pickup position:" ) + , "" ); m_pickupKnob->setWhatsThis( tr( "The 'PU' knob sets the position where the vibrations will be monitored " "for the selected string. The lower the setting, the closer the " @@ -400,7 +400,7 @@ vibedView::vibedView( Instrument * _instrument, m_detuneKnob = new Knob( knobBright_26, this ); m_detuneKnob->move( 150, 187 ); - m_detuneKnob->setHintText( tr( "Detune:" ), "" ); + m_detuneKnob->setHintText( tr( "Detune:" ), "" ); m_detuneKnob->setWhatsThis( tr( "The Detune knob modifies the pitch of the selected string. Settings less " "than zero will cause the string to sound flat. Settings greater than zero " @@ -408,8 +408,8 @@ vibedView::vibedView( Instrument * _instrument, m_randomKnob = new Knob( knobBright_26, this ); m_randomKnob->move( 194, 187 ); - m_randomKnob->setHintText( tr( "Fuzziness:" ) - , "" ); + m_randomKnob->setHintText( tr( "Fuzziness:" ) + , "" ); m_randomKnob->setWhatsThis( tr( "The Slap knob adds a bit of fuzz to the selected string which is most " "apparent during the attack, though it can also be used to make the string " @@ -417,8 +417,8 @@ vibedView::vibedView( Instrument * _instrument, m_lengthKnob = new Knob( knobBright_26, this ); m_lengthKnob->move( 23, 193 ); - m_lengthKnob->setHintText( tr( "Length:" ) - , "" ); + m_lengthKnob->setHintText( tr( "Length:" ) + , "" ); m_lengthKnob->setWhatsThis( tr( "The Length knob sets the length of the selected string. Longer strings " "will both ring longer and sound brighter, however, they will also eat up " @@ -427,7 +427,7 @@ vibedView::vibedView( Instrument * _instrument, m_impulse = new LedCheckBox( "", this ); m_impulse->move( 23, 94 ); ToolTip::add( m_impulse, - tr( "Impulse or initial state" ) ); + tr( "Impulse or initial state" ) ); m_impulse->setWhatsThis( tr( "The 'Imp' selector determines whether the waveform in the graph is to be " "treated as an impulse imparted to the string by the pick or the initial " diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index 05ca9e855..31e3625db 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -41,14 +41,14 @@ #define makeknob( name, x, y, hint, unit, oname ) \ name = new Knob( knobStyled, this ); \ name ->move( x, y ); \ - name ->setHintText( tr( hint ), unit ); \ + name ->setHintText( tr( hint ), unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 19, 19 ); #define maketsknob( name, x, y, hint, unit, oname ) \ name = new TempoSyncKnob( knobStyled, this ); \ name ->move( x, y ); \ - name ->setHintText( tr( hint ), unit ); \ + name ->setHintText( tr( hint ), unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 19, 19 ); diff --git a/plugins/waveshaper/waveshaper_control_dialog.cpp b/plugins/waveshaper/waveshaper_control_dialog.cpp index e831756e0..90e1c964f 100644 --- a/plugins/waveshaper/waveshaper_control_dialog.cpp +++ b/plugins/waveshaper/waveshaper_control_dialog.cpp @@ -63,7 +63,7 @@ waveShaperControlDialog::waveShaperControlDialog( inputKnob -> move( 14, 251 ); inputKnob->setModel( &_controls->m_inputModel ); inputKnob->setLabel( tr( "INPUT" ) ); - inputKnob->setHintText( tr( "Input gain:" ) , "" ); + inputKnob->setHintText( tr( "Input gain:" ) , "" ); Knob * outputKnob = new Knob( knobBright_26, this ); outputKnob -> setVolumeKnob( true ); @@ -71,7 +71,7 @@ waveShaperControlDialog::waveShaperControlDialog( outputKnob -> move( 54, 251 ); outputKnob->setModel( &_controls->m_outputModel ); outputKnob->setLabel( tr( "OUTPUT" ) ); - outputKnob->setHintText( tr( "Output gain:" ), "" ); + outputKnob->setHintText( tr( "Output gain:" ), "" ); PixmapButton * resetButton = new PixmapButton( this, tr("Reset waveform") ); resetButton -> move( 164, 251 ); diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index e0fd50f65..bdb0c6e1f 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -498,31 +498,31 @@ ZynAddSubFxView::ZynAddSubFxView( Instrument * _instrument, QWidget * _parent ) l->setHorizontalSpacing( 10 ); m_portamento = new Knob( knobBright_26, this ); - m_portamento->setHintText( tr( "Portamento:" ), "" ); + m_portamento->setHintText( tr( "Portamento:" ), "" ); m_portamento->setLabel( tr( "PORT" ) ); m_filterFreq = new Knob( knobBright_26, this ); - m_filterFreq->setHintText( tr( "Filter Frequency:" ), "" ); + m_filterFreq->setHintText( tr( "Filter Frequency:" ), "" ); m_filterFreq->setLabel( tr( "FREQ" ) ); m_filterQ = new Knob( knobBright_26, this ); - m_filterQ->setHintText( tr( "Filter Resonance:" ), "" ); + m_filterQ->setHintText( tr( "Filter Resonance:" ), "" ); m_filterQ->setLabel( tr( "RES" ) ); m_bandwidth = new Knob( knobBright_26, this ); - m_bandwidth->setHintText( tr( "Bandwidth:" ), "" ); + m_bandwidth->setHintText( tr( "Bandwidth:" ), "" ); m_bandwidth->setLabel( tr( "BW" ) ); m_fmGain = new Knob( knobBright_26, this ); - m_fmGain->setHintText( tr( "FM Gain:" ), "" ); + m_fmGain->setHintText( tr( "FM Gain:" ), "" ); m_fmGain->setLabel( tr( "FM GAIN" ) ); m_resCenterFreq = new Knob( knobBright_26, this ); - m_resCenterFreq->setHintText( tr( "Resonance center frequency:" ), "" ); + m_resCenterFreq->setHintText( tr( "Resonance center frequency:" ), "" ); m_resCenterFreq->setLabel( tr( "RES CF" ) ); m_resBandwidth = new Knob( knobBright_26, this ); - m_resBandwidth->setHintText( tr( "Resonance bandwidth:" ), "" ); + m_resBandwidth->setHintText( tr( "Resonance bandwidth:" ), "" ); m_resBandwidth->setLabel( tr( "RES BW" ) ); m_forwardMidiCC = new LedCheckBox( tr( "Forward MIDI Control Changes" ), this ); diff --git a/src/gui/LfoControllerDialog.cpp b/src/gui/LfoControllerDialog.cpp index 6fb36d61b..b7c3eced7 100644 --- a/src/gui/LfoControllerDialog.cpp +++ b/src/gui/LfoControllerDialog.cpp @@ -75,14 +75,14 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent m_baseKnob = new Knob( knobBright_26, this ); m_baseKnob->setLabel( tr( "BASE" ) ); m_baseKnob->move( CD_LFO_BASE_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); - m_baseKnob->setHintText( tr( "Base amount:" ), "" ); + m_baseKnob->setHintText( tr( "Base amount:" ), "" ); m_baseKnob->setWhatsThis( tr("todo") ); m_speedKnob = new TempoSyncKnob( knobBright_26, this ); m_speedKnob->setLabel( tr( "SPD" ) ); m_speedKnob->move( CD_LFO_SPEED_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); - m_speedKnob->setHintText( tr( "LFO-speed:" ), "" ); + m_speedKnob->setHintText( tr( "LFO-speed:" ), "" ); m_speedKnob->setWhatsThis( tr( "Use this knob for setting speed of the LFO. The " "bigger this value the faster the LFO oscillates and " @@ -92,7 +92,7 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent m_amountKnob = new Knob( knobBright_26, this ); m_amountKnob->setLabel( tr( "AMT" ) ); m_amountKnob->move( CD_LFO_AMOUNT_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); - m_amountKnob->setHintText( tr( "Modulation amount:" ), "" ); + m_amountKnob->setHintText( tr( "Modulation amount:" ), "" ); m_amountKnob->setWhatsThis( tr( "Use this knob for setting modulation amount of the " "LFO. The bigger this value, the more the connected " @@ -102,7 +102,7 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent m_phaseKnob = new Knob( knobBright_26, this ); m_phaseKnob->setLabel( tr( "PHS" ) ); m_phaseKnob->move( CD_LFO_PHASE_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); - m_phaseKnob->setHintText( tr( "Phase offset:" ) , "" + tr( "degrees" ) ); + m_phaseKnob->setHintText( tr( "Phase offset:" ) , "" + tr( "degrees" ) ); m_phaseKnob->setWhatsThis( tr( "With this knob you can set the phase offset of " "the LFO. That means you can move the " diff --git a/src/gui/widgets/EffectView.cpp b/src/gui/widgets/EffectView.cpp index ce80f8b29..6214747d5 100644 --- a/src/gui/widgets/EffectView.cpp +++ b/src/gui/widgets/EffectView.cpp @@ -67,7 +67,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_wetDry->setLabel( tr( "W/D" ) ); m_wetDry->move( 27, 5 ); m_wetDry->setEnabled( isEnabled ); - m_wetDry->setHintText( tr( "Wet Level:" ), "" ); + m_wetDry->setHintText( tr( "Wet Level:" ), "" ); m_wetDry->setWhatsThis( tr( "The Wet/Dry knob sets the ratio between " "the input signal and the effect signal that " "forms the output." ) ); @@ -77,7 +77,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_autoQuit->setLabel( tr( "DECAY" ) ); m_autoQuit->move( 60, 5 ); m_autoQuit->setEnabled( isEnabled ); - m_autoQuit->setHintText( tr( "Time:" ), "ms" ); + m_autoQuit->setHintText( tr( "Time:" ), "ms" ); m_autoQuit->setWhatsThis( tr( "The Decay knob controls how many buffers of silence must pass before the " "plugin stops processing. Smaller values will reduce the CPU overhead but " @@ -88,7 +88,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_gate->setLabel( tr( "GATE" ) ); m_gate->move( 93, 5 ); m_gate->setEnabled( isEnabled ); - m_gate->setHintText( tr( "Gate:" ), "" ); + m_gate->setHintText( tr( "Gate:" ), "" ); m_gate->setWhatsThis( tr( "The Gate knob controls the signal level that is considered to be 'silence' " "while deciding when to stop processing signals." ) ); diff --git a/src/gui/widgets/EnvelopeAndLfoView.cpp b/src/gui/widgets/EnvelopeAndLfoView.cpp index 7e3922f60..5c364c19b 100644 --- a/src/gui/widgets/EnvelopeAndLfoView.cpp +++ b/src/gui/widgets/EnvelopeAndLfoView.cpp @@ -97,7 +97,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_predelayKnob = new Knob( knobBright_26, this ); m_predelayKnob->setLabel( tr( "DEL" ) ); m_predelayKnob->move( PREDELAY_KNOB_X, ENV_KNOBS_Y ); - m_predelayKnob->setHintText( tr( "Predelay:" ), "" ); + m_predelayKnob->setHintText( tr( "Predelay:" ), "" ); m_predelayKnob->setWhatsThis( tr( "Use this knob for setting predelay of the current " "envelope. The bigger this value the longer the time " @@ -107,7 +107,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_attackKnob = new Knob( knobBright_26, this ); m_attackKnob->setLabel( tr( "ATT" ) ); m_attackKnob->move( ATTACK_KNOB_X, ENV_KNOBS_Y ); - m_attackKnob->setHintText( tr( "Attack:" ), "" ); + m_attackKnob->setHintText( tr( "Attack:" ), "" ); m_attackKnob->setWhatsThis( tr( "Use this knob for setting attack-time of the current " "envelope. The bigger this value the longer the " @@ -118,7 +118,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_holdKnob = new Knob( knobBright_26, this ); m_holdKnob->setLabel( tr( "HOLD" ) ); m_holdKnob->move( HOLD_KNOB_X, ENV_KNOBS_Y ); - m_holdKnob->setHintText( tr( "Hold:" ), "" ); + m_holdKnob->setHintText( tr( "Hold:" ), "" ); m_holdKnob->setWhatsThis( tr( "Use this knob for setting hold-time of the current " "envelope. The bigger this value the longer the " @@ -128,7 +128,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_decayKnob = new Knob( knobBright_26, this ); m_decayKnob->setLabel( tr( "DEC" ) ); m_decayKnob->move( DECAY_KNOB_X, ENV_KNOBS_Y ); - m_decayKnob->setHintText( tr( "Decay:" ), "" ); + m_decayKnob->setHintText( tr( "Decay:" ), "" ); m_decayKnob->setWhatsThis( tr( "Use this knob for setting decay-time of the current " "envelope. The bigger this value the longer the " @@ -140,7 +140,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_sustainKnob = new Knob( knobBright_26, this ); m_sustainKnob->setLabel( tr( "SUST" ) ); m_sustainKnob->move( SUSTAIN_KNOB_X, ENV_KNOBS_Y ); - m_sustainKnob->setHintText( tr( "Sustain:" ), "" ); + m_sustainKnob->setHintText( tr( "Sustain:" ), "" ); m_sustainKnob->setWhatsThis( tr( "Use this knob for setting sustain-level of the current " "envelope. The bigger this value the higher the level " @@ -163,7 +163,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_amountKnob = new Knob( knobBright_26, this ); m_amountKnob->setLabel( tr( "AMT" ) ); m_amountKnob->move( AMOUNT_KNOB_X, ENV_GRAPH_Y ); - m_amountKnob->setHintText( tr( "Modulation amount:" ), "" ); + m_amountKnob->setHintText( tr( "Modulation amount:" ), "" ); m_amountKnob->setWhatsThis( tr( "Use this knob for setting modulation amount of the " "current envelope. The bigger this value the more the " @@ -176,7 +176,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_lfoPredelayKnob = new Knob( knobBright_26, this ); m_lfoPredelayKnob->setLabel( tr( "DEL" ) ); m_lfoPredelayKnob->move( LFO_PREDELAY_KNOB_X, LFO_KNOB_Y ); - m_lfoPredelayKnob->setHintText( tr( "LFO predelay:" ), "" ); + m_lfoPredelayKnob->setHintText( tr( "LFO predelay:" ), "" ); m_lfoPredelayKnob->setWhatsThis( tr( "Use this knob for setting predelay-time of the current " "LFO. The bigger this value the the time until the " @@ -186,7 +186,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_lfoAttackKnob = new Knob( knobBright_26, this ); m_lfoAttackKnob->setLabel( tr( "ATT" ) ); m_lfoAttackKnob->move( LFO_ATTACK_KNOB_X, LFO_KNOB_Y ); - m_lfoAttackKnob->setHintText( tr( "LFO- attack:" ), "" ); + m_lfoAttackKnob->setHintText( tr( "LFO- attack:" ), "" ); m_lfoAttackKnob->setWhatsThis( tr( "Use this knob for setting attack-time of the current LFO. " "The bigger this value the longer the LFO needs to " @@ -196,7 +196,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_lfoSpeedKnob = new TempoSyncKnob( knobBright_26, this ); m_lfoSpeedKnob->setLabel( tr( "SPD" ) ); m_lfoSpeedKnob->move( LFO_SPEED_KNOB_X, LFO_KNOB_Y ); - m_lfoSpeedKnob->setHintText( tr( "LFO speed:" ), "" ); + m_lfoSpeedKnob->setHintText( tr( "LFO speed:" ), "" ); m_lfoSpeedKnob->setWhatsThis( tr( "Use this knob for setting speed of the current LFO. The " "bigger this value the faster the LFO oscillates and " @@ -206,7 +206,7 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : m_lfoAmountKnob = new Knob( knobBright_26, this ); m_lfoAmountKnob->setLabel( tr( "AMT" ) ); m_lfoAmountKnob->move( LFO_AMOUNT_KNOB_X, LFO_KNOB_Y ); - m_lfoAmountKnob->setHintText( tr( "Modulation amount:" ), "" ); + m_lfoAmountKnob->setHintText( tr( "Modulation amount:" ), "" ); m_lfoAmountKnob->setWhatsThis( tr( "Use this knob for setting modulation amount of the " "current LFO. The bigger this value the more the " diff --git a/src/gui/widgets/InstrumentFunctionViews.cpp b/src/gui/widgets/InstrumentFunctionViews.cpp index df58d1708..632526a25 100644 --- a/src/gui/widgets/InstrumentFunctionViews.cpp +++ b/src/gui/widgets/InstrumentFunctionViews.cpp @@ -60,7 +60,7 @@ InstrumentFunctionNoteStackingView::InstrumentFunctionNoteStackingView( Instrume chordLabel->setFont( pointSize<8>( chordLabel->font() ) ); m_chordRangeKnob->setLabel( tr( "RANGE" ) ); - m_chordRangeKnob->setHintText( tr( "Chord range:" ), " " + tr( "octave(s)" ) ); + m_chordRangeKnob->setHintText( tr( "Chord range:" ), " " + tr( "octave(s)" ) ); m_chordRangeKnob->setWhatsThis( tr( "Use this knob for setting the chord range in octaves. " "The selected chord will be played within specified " @@ -130,7 +130,7 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti m_arpRangeKnob->setLabel( tr( "RANGE" ) ); - m_arpRangeKnob->setHintText( tr( "Arpeggio range:" ), " " + tr( "octave(s)" ) ); + m_arpRangeKnob->setHintText( tr( "Arpeggio range:" ), " " + tr( "octave(s)" ) ); m_arpRangeKnob->setWhatsThis( tr( "Use this knob for setting the arpeggio range in octaves. " "The selected arpeggio will be played within specified " @@ -138,7 +138,7 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti m_arpTimeKnob->setLabel( tr( "TIME" ) ); - m_arpTimeKnob->setHintText( tr( "Arpeggio time:" ), " " + tr( "ms" ) ); + m_arpTimeKnob->setHintText( tr( "Arpeggio time:" ), " " + tr( "ms" ) ); m_arpTimeKnob->setWhatsThis( tr( "Use this knob for setting the arpeggio time in " "milliseconds. The arpeggio time specifies how long " @@ -146,7 +146,7 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti m_arpGateKnob->setLabel( tr( "GATE" ) ); - m_arpGateKnob->setHintText( tr( "Arpeggio gate:" ), tr( "%" ) ); + m_arpGateKnob->setHintText( tr( "Arpeggio gate:" ), tr( "%" ) ); m_arpGateKnob->setWhatsThis( tr( "Use this knob for setting the arpeggio gate. The " "arpeggio gate specifies the percent of a whole " diff --git a/src/gui/widgets/InstrumentSoundShapingView.cpp b/src/gui/widgets/InstrumentSoundShapingView.cpp index 406c5a7a9..39637e7e7 100644 --- a/src/gui/widgets/InstrumentSoundShapingView.cpp +++ b/src/gui/widgets/InstrumentSoundShapingView.cpp @@ -99,7 +99,7 @@ InstrumentSoundShapingView::InstrumentSoundShapingView( QWidget * _parent ) : m_filterCutKnob = new Knob( knobBright_26, m_filterGroupBox ); m_filterCutKnob->setLabel( tr( "FREQ" ) ); m_filterCutKnob->move( 140, 18 ); - m_filterCutKnob->setHintText( tr( "cutoff frequency:" ), " " + tr( "Hz" ) ); + m_filterCutKnob->setHintText( tr( "cutoff frequency:" ), " " + tr( "Hz" ) ); m_filterCutKnob->setWhatsThis( tr( "Use this knob for setting the cutoff frequency for the " "selected filter. The cutoff frequency specifies the " @@ -112,7 +112,7 @@ InstrumentSoundShapingView::InstrumentSoundShapingView( QWidget * _parent ) : m_filterResKnob = new Knob( knobBright_26, m_filterGroupBox ); m_filterResKnob->setLabel( tr( "RESO" ) ); m_filterResKnob->move( 196, 18 ); - m_filterResKnob->setHintText( tr( "Resonance:" ), "" ); + m_filterResKnob->setHintText( tr( "Resonance:" ), "" ); m_filterResKnob->setWhatsThis( tr( "Use this knob for setting Q/Resonance for the selected " "filter. Q/Resonance tells the filter how much it " diff --git a/src/gui/widgets/LadspaControlView.cpp b/src/gui/widgets/LadspaControlView.cpp index 05823a441..75eaf64cb 100644 --- a/src/gui/widgets/LadspaControlView.cpp +++ b/src/gui/widgets/LadspaControlView.cpp @@ -100,7 +100,7 @@ LadspaControlView::LadspaControlView( QWidget * _parent, knb->setModel( m_ctl->tempoSyncKnobModel() ); } knb->setLabel( m_ctl->port()->name ); - knb->setHintText( tr( "Value:" ), "" ); + knb->setHintText( tr( "Value:" ), "" ); knb->setWhatsThis( tr( "Sorry, no help available." ) ); layout->addWidget( knb ); if( link != NULL ) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 73f53cdac..b32414a38 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -849,7 +849,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV tr( "Volume" ) ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->setModel( &_it->m_volumeModel ); - m_volumeKnob->setHintText( tr( "Volume:" ), "%" ); + m_volumeKnob->setHintText( tr( "Volume:" ), "%" ); m_volumeKnob->move( widgetWidth-2*24, 2 ); m_volumeKnob->setLabel( tr( "VOL" ) ); m_volumeKnob->show(); @@ -1176,7 +1176,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // set up volume knob m_volumeKnob = new Knob( knobBright_26, NULL, tr( "Instrument volume" ) ); m_volumeKnob->setVolumeKnob( true ); - m_volumeKnob->setHintText( tr( "Volume:" ), "%" ); + m_volumeKnob->setHintText( tr( "Volume:" ), "%" ); m_volumeKnob->setLabel( tr( "VOL" ) ); m_volumeKnob->setWhatsThis( tr( volume_help ) ); @@ -1185,7 +1185,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // set up panning knob m_panningKnob = new Knob( knobBright_26, NULL, tr( "Panning" ) ); - m_panningKnob->setHintText( tr( "Panning:" ), "" ); + m_panningKnob->setHintText( tr( "Panning:" ), "" ); m_panningKnob->setLabel( tr( "PAN" ) ); basicControlsLayout->addWidget( m_panningKnob ); @@ -1193,7 +1193,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // set up pitch knob m_pitchKnob = new Knob( knobBright_26, NULL, tr( "Pitch" ) ); - m_pitchKnob->setHintText( tr( "Pitch:" ), " " + tr( "cents" ) ); + m_pitchKnob->setHintText( tr( "Pitch:" ), " " + tr( "cents" ) ); m_pitchKnob->setLabel( tr( "PITCH" ) ); basicControlsLayout->addWidget( m_pitchKnob ); diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index 3f8fe4276..49d59f66c 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -537,7 +537,7 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : tr( "Track volume" ) ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->setModel( &_t->m_volumeModel ); - m_volumeKnob->setHintText( tr( "Channel volume:" ), "%" ); + m_volumeKnob->setHintText( tr( "Channel volume:" ), "%" ); if( ConfigManager::inst()->value( "ui", "compacttrackbuttons" ).toInt() ) { From bbe337bd03299a37b27320f3995f27739733aa60 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Tue, 9 Dec 2014 08:28:00 -0500 Subject: [PATCH 27/51] Use correct FMA_ macros --- include/lmms_math.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 156303136..3d23abcd3 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -132,7 +132,7 @@ static inline int fast_rand() //! @brief Takes advantage of fmal() function if present in hardware static inline long double fastFmal( long double a, long double b, long double c ) { -#ifdef FP_FAST_FMAF +#ifdef FP_FAST_FMAL #ifdef __clang__ return fma( a, b, c ); #else @@ -158,7 +158,7 @@ static inline float fastFmaf( float a, float b, float c ) { //! @brief Takes advantage of fma() function if present in hardware static inline double fastFma( double a, double b, double c ) { -#ifdef FP_FAST_FMAF +#ifdef FP_FAST_FMA return fma( a, b, c ); #else return a * b + c; From fbc6de857a5ddd4f863a2689ca528aa1949027c1 Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 10 Dec 2014 01:28:14 +0200 Subject: [PATCH 28/51] Fix master channel peak display Fix #1427 --- src/core/FxMixer.cpp | 3 --- src/gui/FxMixerView.cpp | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 7169a25ee..797463d0d 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -600,9 +600,6 @@ void FxMixer::masterMix( sampleFrame * _buf ) : m_fxChannels[0]->m_volumeModel.value(); MixHelpers::addSanitizedMultiplied( _buf, m_fxChannels[0]->m_buffer, v, fpp ); - m_fxChannels[0]->m_peakLeft *= Engine::mixer()->masterGain(); - m_fxChannels[0]->m_peakRight *= Engine::mixer()->masterGain(); - // clear all channel buffers and // reset channel process state for( int i = 0; i < numChannels(); ++i) diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 407c0bd59..90de3d000 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -503,6 +503,11 @@ void FxMixerView::clear() void FxMixerView::updateFaders() { FxMixer * m = Engine::fxMixer(); + + // apply master gain + m->m_fxChannels[0]->m_peakLeft *= Engine::mixer()->masterGain(); + m->m_fxChannels[0]->m_peakRight *= Engine::mixer()->masterGain(); + for( int i = 0; i < m_fxChannelViews.size(); ++i ) { const float opl = m_fxChannelViews[i]->m_fader->getPeak_L(); From 4a6257a47c8c2d44f817ac447e2656a9283a242e Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 10 Dec 2014 01:28:14 +0200 Subject: [PATCH 29/51] Fix master channel peak display Fix #1427 Conflicts: src/core/FxMixer.cpp src/gui/FxMixerView.cpp --- src/core/FxMixer.cpp | 3 --- src/gui/FxMixerView.cpp | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index d47f34c8b..7a21acb92 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -514,9 +514,6 @@ void FxMixer::masterMix( sampleFrame * _buf ) const float v = m_fxChannels[0]->m_volumeModel.value(); MixHelpers::addSanitizedMultiplied( _buf, m_fxChannels[0]->m_buffer, v, fpp ); - m_fxChannels[0]->m_peakLeft *= engine::mixer()->masterGain(); - m_fxChannels[0]->m_peakRight *= engine::mixer()->masterGain(); - // clear all channel buffers and // reset channel process state for( int i = 0; i < numChannels(); ++i) diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index bd7df6e2f..8948e8474 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -480,6 +480,11 @@ void FxMixerView::clear() void FxMixerView::updateFaders() { FxMixer * m = engine::fxMixer(); + + // apply master gain + m->m_fxChannels[0]->m_peakLeft *= engine::mixer()->masterGain(); + m->m_fxChannels[0]->m_peakRight *= engine::mixer()->masterGain(); + for( int i = 0; i < m_fxChannelViews.size(); ++i ) { const float opl = m_fxChannelViews[i]->m_fader->getPeak_L(); From 170f60c8e0deab0da58bd6d817f55c003dc7e3dc Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 10 Dec 2014 06:55:59 +0200 Subject: [PATCH 30/51] Fader: add a way to disable the x100 display conversion so the fader widget can be used with arbitrary values Also it can now be used with alternate pixmaps --- include/AutomatableSlider.h | 2 +- include/Fader.h | 12 ++++ include/lmms_math.h | 1 + plugins/delay/delaycontrolsdialog.cpp | 2 +- src/gui/widgets/AutomatableSlider.cpp | 2 +- src/gui/widgets/Fader.cpp | 97 ++++++++++++++++++++------- 6 files changed, 90 insertions(+), 26 deletions(-) diff --git a/include/AutomatableSlider.h b/include/AutomatableSlider.h index 1cd1405b1..7627ddd95 100644 --- a/include/AutomatableSlider.h +++ b/include/AutomatableSlider.h @@ -1,5 +1,5 @@ /* - * AutomatableSlider.h - class automatableSlider, a QSlider with automation + * AutomatableSlider.h - class AutomatableSlider, a QSlider with automation * * Copyright (c) 2006-2008 Javier Serrano Polo * diff --git a/include/Fader.h b/include/Fader.h index efbc4ebf1..f8048e98c 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -64,6 +64,7 @@ public: Q_PROPERTY( QColor peakGreen READ peakGreen WRITE setPeakGreen ) Q_PROPERTY( QColor peakRed READ peakRed WRITE setPeakRed ) Fader( FloatModel * _model, const QString & _name, QWidget * _parent ); + Fader( FloatModel * _model, const QString & _name, QWidget * _parent, QPixmap * back, QPixmap * leds, QPixmap * knob ); virtual ~Fader(); void setPeak_L( float fPeak ); @@ -76,6 +77,11 @@ public: QColor peakRed() const; void setPeakGreen( const QColor & c ); void setPeakRed( const QColor & c ); + + void setDisplayConversion( bool b ) + { + m_displayConversion = b; + } private: virtual void contextMenuEvent( QContextMenuEvent * _me ); @@ -112,6 +118,12 @@ private: static QPixmap * s_back; static QPixmap * s_leds; static QPixmap * s_knob; + + QPixmap * m_back; + QPixmap * m_leds; + QPixmap * m_knob; + + bool m_displayConversion; int m_moveStartPoint; float m_startValue; diff --git a/include/lmms_math.h b/include/lmms_math.h index 157ab70b7..016e1a49f 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -140,6 +140,7 @@ static inline float fastRandf( float range ) { static const float fast_rand_ratio = 1.0f / FAST_RAND_MAX; return fast_rand() * range * fast_rand_ratio; +} //! @brief Takes advantage of fmal() function if present in hardware static inline long double fastFmal( long double a, long double b, long double c ) diff --git a/plugins/delay/delaycontrolsdialog.cpp b/plugins/delay/delaycontrolsdialog.cpp index adb5f3420..80aeba068 100644 --- a/plugins/delay/delaycontrolsdialog.cpp +++ b/plugins/delay/delaycontrolsdialog.cpp @@ -46,7 +46,7 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) : sampleDelayKnob->setLabel( tr( "Delay" ) ); sampleDelayKnob->setHintText( tr( "Delay Time" ) + " ", " s" ); - knob * feedbackKnob = new knob( knobBright_26, this ); + Knob * feedbackKnob = new Knob( knobBright_26, this ); feedbackKnob->move( 63,10 ); feedbackKnob->setVolumeKnob( true) ; feedbackKnob->setModel( &controls->m_feedbackModel); diff --git a/src/gui/widgets/AutomatableSlider.cpp b/src/gui/widgets/AutomatableSlider.cpp index 6a3d10640..c6a36c939 100644 --- a/src/gui/widgets/AutomatableSlider.cpp +++ b/src/gui/widgets/AutomatableSlider.cpp @@ -1,5 +1,5 @@ /* - * AutomatableSlider.cpp - implementation of class automatableSlider + * AutomatableSlider.cpp - implementation of class AutomatableSlider * * Copyright (c) 2006-2007 Javier Serrano Polo * Copyright (c) 2007-2009 Tobias Doerffel diff --git a/src/gui/widgets/Fader.cpp b/src/gui/widgets/Fader.cpp index 3015d976f..7f1352a57 100644 --- a/src/gui/widgets/Fader.cpp +++ b/src/gui/widgets/Fader.cpp @@ -74,6 +74,7 @@ Fader::Fader( FloatModel * _model, const QString & _name, QWidget * _parent ) : m_persistentPeak_R( 0.0 ), m_fMinPeak( 0.01f ), m_fMaxPeak( 1.1 ), + m_displayConversion( true ), m_moveStartPoint( -1 ), m_startValue( 0 ), m_peakGreen( 0, 0, 0 ), @@ -95,7 +96,11 @@ Fader::Fader( FloatModel * _model, const QString & _name, QWidget * _parent ) : { s_knob = new QPixmap( embed::getIconPixmap( "fader_knob" ) ); } - + + m_back = s_back; + m_leds = s_leds; + m_knob = s_knob; + setWindowTitle( _name ); setAttribute( Qt::WA_OpaquePaintEvent, false ); setMinimumSize( 23, 116 ); @@ -105,6 +110,39 @@ Fader::Fader( FloatModel * _model, const QString & _name, QWidget * _parent ) : } +Fader::Fader( FloatModel * model, const QString & name, QWidget * parent, QPixmap * back, QPixmap * leds, QPixmap * knob ) : + QWidget( parent ), + FloatModelView( model, this ), + m_model( model ), + m_fPeakValue_L( 0.0 ), + m_fPeakValue_R( 0.0 ), + m_persistentPeak_L( 0.0 ), + m_persistentPeak_R( 0.0 ), + m_fMinPeak( 0.01f ), + m_fMaxPeak( 1.1 ), + m_displayConversion( false ), + m_moveStartPoint( -1 ), + m_startValue( 0 ), + m_peakGreen( 0, 0, 0 ), + m_peakRed( 0, 0, 0 ) +{ + if( s_textFloat == NULL ) + { + s_textFloat = new TextFloat; + } + + m_back = back; + m_leds = leds; + m_knob = knob; + + setWindowTitle( name ); + setAttribute( Qt::WA_OpaquePaintEvent, false ); + setMinimumSize( m_back->width(), m_back->height() ); + setMaximumSize( m_back->width(), m_back->height() ); + resize( m_back->width(), m_back->height() ); + setModel( model ); +} + Fader::~Fader() { @@ -172,19 +210,33 @@ void Fader::mousePressEvent( QMouseEvent* mouseEvent ) void Fader::mouseDoubleClickEvent( QMouseEvent* mouseEvent ) { bool ok; + float newValue; // TODO: dbV handling - int newValue = QInputDialog::getInt( this, windowTitle(), - tr( "Please enter a new value between %1 and %2:" ). - arg( model()->minValue()*100 ). - arg( model()->maxValue()*100 ), - model()->value()*100, - model()->minValue()*100, - model()->maxValue()*100, 1, &ok ); + if( m_displayConversion ) + { + newValue = QInputDialog::getDouble( this, windowTitle(), + tr( "Please enter a new value between %1 and %2:" ). + arg( model()->minValue() * 100 ). + arg( model()->maxValue() * 100 ), + model()->value() * 100, + model()->minValue() * 100, + model()->maxValue() * 100, 4, &ok ) * 0.01f; + } + else + { + newValue = QInputDialog::getDouble( this, windowTitle(), + tr( "Please enter a new value between %1 and %2:" ). + arg( model()->minValue() ). + arg( model()->maxValue() ), + model()->value(), + model()->minValue(), + model()->maxValue(), 4, &ok ); + } if( ok ) { - model()->setValue( newValue / 100.0f ); + model()->setValue( newValue ); } } @@ -265,25 +317,24 @@ void Fader::setPeak_R( float fPeak ) // update tooltip showing value and adjust position while changing fader value void Fader::updateTextFloat() { - if( ConfigManager::inst()->value( "app", "displaydbv" ).toInt() ) + if( ConfigManager::inst()->value( "app", "displaydbv" ).toInt() && m_displayConversion ) { s_textFloat->setText( QString("Volume: %1 dBV"). arg( 20.0 * log10( model()->value() ), 3, 'f', 2 ) ); } else { - s_textFloat->setText( QString("Volume: %1 %").arg( m_model->value() * 100 ) ); + s_textFloat->setText( QString("Volume: %1 %").arg( m_displayConversion ? m_model->value() * 100 : m_model->value() ) ); } - s_textFloat->moveGlobal( this, QPoint( width() - ( *s_knob ).width() - 5, knobPosY() - 46 ) ); + s_textFloat->moveGlobal( this, QPoint( width() - ( *m_knob ).width() - 5, knobPosY() - 46 ) ); } inline int Fader::calculateDisplayPeak( float fPeak ) { - int peak = (int)( 116 - ( fPeak / ( m_fMaxPeak - m_fMinPeak ) ) * 116.0 ); + int peak = (int)( m_back->height() - ( fPeak / ( m_fMaxPeak - m_fMinPeak ) ) * m_back->height() ); - if ( peak > 116 ) return 116; - else return peak; + return qMin( peak, m_back->height() ); } void Fader::paintEvent( QPaintEvent * ev) @@ -291,7 +342,7 @@ void Fader::paintEvent( QPaintEvent * ev) QPainter painter(this); // background - painter.drawPixmap( ev->rect(), *s_back, ev->rect() ); + painter.drawPixmap( ev->rect(), *m_back, ev->rect() ); // peak leds @@ -299,28 +350,28 @@ void Fader::paintEvent( QPaintEvent * ev) int peak_L = calculateDisplayPeak( m_fPeakValue_L - m_fMinPeak ); int persistentPeak_L = qMax( 3, calculateDisplayPeak( m_persistentPeak_L - m_fMinPeak ) ); - painter.drawPixmap( QRect( 0, peak_L, 11, 116 - peak_L ), *s_leds, QRect( 0, peak_L, 11, 116 - peak_L ) ); + painter.drawPixmap( QRect( 0, peak_L, 11, 116 - peak_L ), *m_leds, QRect( 0, peak_L, 11, 116 - peak_L ) ); if( m_persistentPeak_L > 0.05 ) { painter.fillRect( QRect( 2, persistentPeak_L, 7, 1 ), ( m_persistentPeak_L < 1.0 ) - ? peakGreen() + ? peakGreen() : peakRed() ); } int peak_R = calculateDisplayPeak( m_fPeakValue_R - m_fMinPeak ); int persistentPeak_R = qMax( 3, calculateDisplayPeak( m_persistentPeak_R - m_fMinPeak ) ); - painter.drawPixmap( QRect( 11, peak_R, 11, 116 - peak_R ), *s_leds, QRect( 11, peak_R, 11, 116 - peak_R ) ); + painter.drawPixmap( QRect( 11, peak_R, 11, 116 - peak_R ), *m_leds, QRect( 11, peak_R, 11, 116 - peak_R ) ); if( m_persistentPeak_R > 0.05 ) { painter.fillRect( QRect( 14, persistentPeak_R, 7, 1 ), ( m_persistentPeak_R < 1.0 ) - ? peakGreen() + ? peakGreen() : peakRed() ); } // knob - painter.drawPixmap( 0, knobPosY() - ( *s_knob ).height(), *s_knob ); + painter.drawPixmap( 0, knobPosY() - ( *m_knob ).height(), *s_knob ); } @@ -333,12 +384,12 @@ QColor Fader::peakRed() const { return m_peakRed; } - + void Fader::setPeakGreen( const QColor & c ) { m_peakGreen = c; } - + void Fader::setPeakRed( const QColor & c ) { m_peakRed = c; From 60ad2c8aa0582e4453aa4b4bac8e24e79c678871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stian=20J=C3=B8rgensrud?= Date: Thu, 11 Dec 2014 00:24:52 +0100 Subject: [PATCH 31/51] New SnareMarch preset and updated KickPower The snare sounds like it would be used for marching. If you can make it brighter without making it sound funny, please do... The kick was too dark for general purpose. Shortened it, raised it in the frequency range and added more noise. --- .../Kicker/{Kick power.xpf => KickPower.xpf} | 20 +-- data/presets/Kicker/SnareMarch.xpf | 161 ++++++++++++++++++ 2 files changed, 171 insertions(+), 10 deletions(-) rename data/presets/Kicker/{Kick power.xpf => KickPower.xpf} (54%) create mode 100644 data/presets/Kicker/SnareMarch.xpf diff --git a/data/presets/Kicker/Kick power.xpf b/data/presets/Kicker/KickPower.xpf similarity index 54% rename from data/presets/Kicker/Kick power.xpf rename to data/presets/Kicker/KickPower.xpf index b4e1daba3..27259ce25 100644 --- a/data/presets/Kicker/Kick power.xpf +++ b/data/presets/Kicker/KickPower.xpf @@ -1,20 +1,20 @@ - + - + - + - - - - + + + + - - - + + + diff --git a/data/presets/Kicker/SnareMarch.xpf b/data/presets/Kicker/SnareMarch.xpf new file mode 100644 index 000000000..d4d1ad0db --- /dev/null +++ b/data/presets/Kicker/SnareMarch.xpf @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4710360ce5d5299ee271ce890c87fefd17316711 Mon Sep 17 00:00:00 2001 From: dave Date: Wed, 10 Dec 2014 23:47:07 +0000 Subject: [PATCH 32/51] updated Fader to use setHintText enables setting of the display text. --- include/Fader.h | 6 ++++++ src/gui/widgets/Fader.cpp | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/Fader.h b/include/Fader.h index f8048e98c..96c3ae732 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -82,6 +82,12 @@ public: { m_displayConversion = b; } + inline void setHintText( const QString & _txt_before, + const QString & _txt_after ) + { + setDescription( _txt_before ); + setUnit( _txt_after ); + } private: virtual void contextMenuEvent( QContextMenuEvent * _me ); diff --git a/src/gui/widgets/Fader.cpp b/src/gui/widgets/Fader.cpp index 7f1352a57..1af7bb040 100644 --- a/src/gui/widgets/Fader.cpp +++ b/src/gui/widgets/Fader.cpp @@ -107,6 +107,7 @@ Fader::Fader( FloatModel * _model, const QString & _name, QWidget * _parent ) : setMaximumSize( 23, 116); resize( 23, 116 ); setModel( _model ); + setHintText( "Volume:","%"); } @@ -141,6 +142,7 @@ Fader::Fader( FloatModel * model, const QString & name, QWidget * parent, QPixma setMaximumSize( m_back->width(), m_back->height() ); resize( m_back->width(), m_back->height() ); setModel( model ); + setHintText( "Volume:","%"); } @@ -324,7 +326,7 @@ void Fader::updateTextFloat() } else { - s_textFloat->setText( QString("Volume: %1 %").arg( m_displayConversion ? m_model->value() * 100 : m_model->value() ) ); + s_textFloat->setText( m_description + " " + QString("%1 ").arg( m_displayConversion ? m_model->value() * 100 : m_model->value() ) + " " + m_unit ); } s_textFloat->moveGlobal( this, QPoint( width() - ( *m_knob ).width() - 5, knobPosY() - 46 ) ); } From 1ad5ef22d7c99dd171c80c21395d28c378d4b1fd Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 13 Dec 2014 11:26:15 +0200 Subject: [PATCH 33/51] Bitcrush: small improvement, also add some stuff to math & constants Constants: - calculate all in long double so as to improve the accuracy of our pre-calculated constants - add some possibly useful constants: reciprocal of pi, square of pi, and reciprocal of e Math: - new math convenience functions: absMax, absMin --- include/lmms_constants.h | 29 +++++++++++++++++++++-------- include/lmms_math.h | 14 ++++++++++++++ plugins/Bitcrush/Bitcrush.cpp | 6 ++++-- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/include/lmms_constants.h b/include/lmms_constants.h index 629db886c..6f50c6f8e 100644 --- a/include/lmms_constants.h +++ b/include/lmms_constants.h @@ -25,15 +25,28 @@ #ifndef LMMS_CONSTANTS_H #define LMMS_CONSTANTS_H -const double D_PI = 3.14159265358979323846; -const double D_2PI = D_PI * 2.0; -const double D_PI_2 = D_PI * 0.5; -const double D_E = 2.71828182845904523536; +const long double LD_PI = 3.14159265358979323846264338327950288419716939937510; +const long double LD_2PI = LD_PI * 2.0; +const long double LD_PI_2 = LD_PI * 0.5; +const long double LD_PI_R = 1.0 / LD_PI; +const long double LD_PI_SQR = LD_PI * LD_PI; +const long double LD_E = 2.71828182845904523536028747135266249775724709369995; +const long double LD_E_R = 1.0 / LD_E; -const float F_PI = (float) D_PI; -const float F_2PI = (float) D_2PI; -const float F_PI_2 = (float) D_PI_2; -const float F_E = (float) D_E; +const double D_PI = (double) LD_PI; +const double D_2PI = (double) LD_2PI; +const double D_PI_2 = (double) LD_PI_2; +const double D_PI_R = (double) LD_PI_R; +const double D_PI_SQR = (double) LD_PI_SQR; +const double D_E = (double) LD_E; +const double D_E_R = (double) LD_E_R; +const float F_PI = (float) LD_PI; +const float F_2PI = (float) LD_2PI; +const float F_PI_2 = (float) LD_PI_2; +const float F_PI_R = (float) LD_PI_R; +const float F_PI_SQR = (float) LD_PI_SQR; +const float F_E = (float) LD_E; +const float F_E_R = (float) LD_E_R; #endif diff --git a/include/lmms_math.h b/include/lmms_math.h index 016e1a49f..7cde29153 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -289,4 +289,18 @@ static inline float fastSqrt( float n ) return u.f; } +//! returns value furthest from zero +template +static inline T absMax( T a, T b ) +{ + return qAbs(a) > qAbs(b) ? a : b; +} + +//! returns value nearest to zero +template +static inline T absMin( T a, T b ) +{ + return qAbs(a) < qAbs(b) ? a : b; +} + #endif diff --git a/plugins/Bitcrush/Bitcrush.cpp b/plugins/Bitcrush/Bitcrush.cpp index e9ab9639a..8a2822d60 100644 --- a/plugins/Bitcrush/Bitcrush.cpp +++ b/plugins/Bitcrush/Bitcrush.cpp @@ -30,6 +30,8 @@ const int OS_RATE = 5; const float OS_RATIO = 1.0f / OS_RATE; const float CUTOFF_RATIO = 0.353553391f; const int SILENCEFRAMES = 10; +const float OS_RESAMPLE [5] = { 0.0001490062883964112, 0.1645978376763992, 0.6705063120704088, + 0.1645978376763992, 0.0001490062883964112 }; extern "C" { @@ -219,8 +221,8 @@ bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) float rsum = 0.0f; for( int o = 0; o < OS_RATE; ++o ) { - lsum += m_buffer[f * OS_RATE + o][0] * OS_RATIO; - rsum += m_buffer[f * OS_RATE + o][1] * OS_RATIO; + lsum += m_buffer[f * OS_RATE + o][0] * OS_RESAMPLE[o]; + rsum += m_buffer[f * OS_RATE + o][1] * OS_RESAMPLE[o]; } buf[f][0] = d * buf[f][0] + w * qBound( -m_outClip, lsum, m_outClip ) * m_outGain; buf[f][1] = d * buf[f][1] + w * qBound( -m_outClip, rsum, m_outClip ) * m_outGain; From 73cad09968d35ee6c7f2bb11dcad7e8428cb7188 Mon Sep 17 00:00:00 2001 From: Vesa V Date: Sat, 13 Dec 2014 13:05:50 +0200 Subject: [PATCH 34/51] Update FxMixer.cpp prevent double adding of jobs --- src/core/FxMixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 7a21acb92..7f78afc9f 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -99,7 +99,7 @@ inline void FxChannel::processed() void FxChannel::incrementDeps() { m_dependenciesMet.ref(); - if( m_dependenciesMet >= m_receives.size() ) + if( m_dependenciesMet >= m_receives.size() && ! m_queued ) { m_queued = true; MixerWorkerThread::addJob( this ); From 4266de78304ce5c6ffbde34601216f0878935ef9 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 13 Dec 2014 16:28:44 +0200 Subject: [PATCH 35/51] More fixes (Bitcrush, Linkwitz-Riley filter) --- include/BasicFilters.h | 20 ++++++++++---------- plugins/Bitcrush/Bitcrush.cpp | 7 ++++++- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/include/BasicFilters.h b/include/BasicFilters.h index 98c69474a..e09d40c42 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -75,34 +75,34 @@ public: inline void setCoeffs( float freq ) { // wc - const float wc = F_2PI * freq; + const float wc = F_2PI * freq / m_sampleRate; const float wc2 = wc * wc; const float wc3 = wc2 * wc; m_wc4 = wc2 * wc2; // k - const float k = wc / tanf( F_PI * freq / m_sampleRate ); + const float k = wc / tan( wc * 0.5 ); const float k2 = k * k; const float k3 = k2 * k; m_k4 = k2 * k2; // a - static const float sqrt2 = sqrtf( 2.0f ); + static const double sqrt2 = sqrt( 2.0 ); const float sq_tmp1 = sqrt2 * wc3 * k; const float sq_tmp2 = sqrt2 * wc * k3; - m_a = 4.0f * wc2 * k2 + 2.0f * sq_tmp1 + m_k4 + 2.0f * sq_tmp2 + m_wc4; + m_a = 1.0f / ( 4.0f * wc2 * k2 + 2.0f * sq_tmp1 + m_k4 + 2.0f * sq_tmp2 + m_wc4 ); // b - m_b1 = ( 4.0f * ( m_wc4 + sq_tmp1 - m_k4 - sq_tmp2 ) ) / m_a; - m_b2 = ( 6.0f * m_wc4 - 8.0f * wc2 * k2 + 6.0f * m_k4 ) / m_a; - m_b3 = ( 4.0f * ( m_wc4 - sq_tmp1 + sq_tmp2 - m_k4 ) ) / m_a; - m_b4 = ( m_k4 - 2.0f * sq_tmp1 + m_wc4 - 2.0f * sq_tmp2 + 4.0f * wc2 * k2 ) / m_a; + m_b1 = ( 4.0f * ( m_wc4 + sq_tmp1 - m_k4 - sq_tmp2 ) ) * m_a; + m_b2 = ( 6.0f * m_wc4 - 8.0f * wc2 * k2 + 6.0f * m_k4 ) * m_a; + m_b3 = ( 4.0f * ( m_wc4 - sq_tmp1 + sq_tmp2 - m_k4 ) ) * m_a; + m_b4 = ( m_k4 - 2.0f * sq_tmp1 + m_wc4 - 2.0f * sq_tmp2 + 4.0f * wc2 * k2 ) * m_a; } inline void setLowpass( float freq ) { setCoeffs( freq ); - m_a0 = m_wc4 / m_a; + m_a0 = m_wc4 * m_a; m_a1 = 4.0f * m_a0; m_a2 = 6.0f * m_a0; } @@ -110,7 +110,7 @@ public: inline void setHighpass( float freq ) { setCoeffs( freq ); - m_a0 = m_k4 / m_a; + m_a0 = m_k4 * m_a; m_a1 = 4.0f * m_a0; m_a2 = 6.0f * m_a0; } diff --git a/plugins/Bitcrush/Bitcrush.cpp b/plugins/Bitcrush/Bitcrush.cpp index 8a2822d60..84f5b45ba 100644 --- a/plugins/Bitcrush/Bitcrush.cpp +++ b/plugins/Bitcrush/Bitcrush.cpp @@ -80,7 +80,7 @@ void BitcrushEffect::sampleRateChanged() { m_sampleRate = Engine::mixer()->processingSampleRate(); m_filter.setSampleRate( m_sampleRate ); - m_filter.setLowpass( m_sampleRate * CUTOFF_RATIO ); + m_filter.setLowpass( m_sampleRate * ( CUTOFF_RATIO * OS_RATIO ) ); m_needsUpdate = true; } @@ -97,6 +97,11 @@ inline float BitcrushEffect::noise( float amt ) bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) { + if( !isEnabled() || !isRunning () ) + { + return( false ); + } + // update values if( m_needsUpdate || m_controls.m_rateEnabled.isValueChanged() ) { From a8924a34dd08b75d6020f5aea78242531120455e Mon Sep 17 00:00:00 2001 From: tresf Date: Sat, 13 Dec 2014 11:27:14 -0500 Subject: [PATCH 36/51] Check major/minor version before setting theme directory --- src/core/config_mgr.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/config_mgr.cpp b/src/core/config_mgr.cpp index 411de79d5..93f286345 100644 --- a/src/core/config_mgr.cpp +++ b/src/core/config_mgr.cpp @@ -289,7 +289,13 @@ void configManager::loadConfigFile() node = node.nextSibling(); } - if( value( "paths", "artwork" ) != "" ) + // don't use dated theme folders as they break the UI (i.e. 0.4 != 1.0, etc) + bool use_artwork_path = + root.attribute( "version" ).startsWith( + QString::number( LMMS_VERSION_MAJOR ) + "." + + QString::number( LMMS_VERSION_MINOR ) ); + + if( use_artwork_path && value( "paths", "artwork" ) != "" ) { m_artworkDir = value( "paths", "artwork" ); if( !QDir( m_artworkDir ).exists() ) From a182a3e8cc9c512906aee38f1b8e067f31447198 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Sat, 13 Dec 2014 12:11:31 -0500 Subject: [PATCH 37/51] Fix scroll bar gap Closes #1437 --- src/tracks/InstrumentTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index bc9728e36..20b737444 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -86,7 +86,7 @@ const char * volume_help = QT_TRANSLATE_NOOP( "InstrumentTrack", const int INSTRUMENT_WIDTH = 254; const int INSTRUMENT_HEIGHT = INSTRUMENT_WIDTH; -const int PIANO_HEIGHT = 84; +const int PIANO_HEIGHT = 82; const int INSTRUMENT_WINDOW_CACHE_SIZE = 8; From e6ae2be65a5f3cd55d055be52ad0348ec3586604 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Sat, 13 Dec 2014 12:19:20 -0500 Subject: [PATCH 38/51] Bump DualFilter high cutoff to 20k Closes #1395. --- plugins/DualFilter/DualFilterControls.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/DualFilter/DualFilterControls.cpp b/plugins/DualFilter/DualFilterControls.cpp index 344a34ca0..df295c39f 100644 --- a/plugins/DualFilter/DualFilterControls.cpp +++ b/plugins/DualFilter/DualFilterControls.cpp @@ -39,7 +39,7 @@ DualFilterControls::DualFilterControls( DualFilterEffect* effect ) : m_enabled1Model( true, this, tr( "Filter 1 enabled" ) ), m_filter1Model( this, tr( "Filter 1 type" ) ), - m_cut1Model( 7000.0f, 1.0f, 14000.0f, 1.0f, this, tr( "Cutoff 1 frequency" ) ), + m_cut1Model( 7000.0f, 1.0f, 20000.0f, 1.0f, this, tr( "Cutoff 1 frequency" ) ), m_res1Model( 0.5, basicFilters<0>::minQ(), 10.0, 0.01, this, tr( "Q/Resonance 1" ) ), m_gain1Model( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Gain 1" ) ), @@ -47,7 +47,7 @@ DualFilterControls::DualFilterControls( DualFilterEffect* effect ) : m_enabled2Model( true, this, tr( "Filter 2 enabled" ) ), m_filter2Model( this, tr( "Filter 2 type" ) ), - m_cut2Model( 7000.0f, 1.0f, 14000.0f, 1.0f, this, tr( "Cutoff 2 frequency" ) ), + m_cut2Model( 7000.0f, 1.0f, 20000.0f, 1.0f, this, tr( "Cutoff 2 frequency" ) ), m_res2Model( 0.5, basicFilters<0>::minQ(), 10.0, 0.01, this, tr( "Q/Resonance 2" ) ), m_gain2Model( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Gain 2" ) ) { From 0789bae53a7a58bb61cb18dc917f5723f376cba5 Mon Sep 17 00:00:00 2001 From: Vesa Date: Mon, 15 Dec 2014 10:41:43 +0200 Subject: [PATCH 39/51] Crossover EQ initial commit, also fix bugs in LR4 filter and Fader --- include/BasicFilters.h | 81 ++++--- include/Fader.h | 2 +- plugins/CMakeLists.txt | 1 + plugins/CrossoverEQ/CMakeLists.txt | 3 + plugins/CrossoverEQ/CrossoverEQ.cpp | 219 ++++++++++++++++++ plugins/CrossoverEQ/CrossoverEQ.h | 77 ++++++ .../CrossoverEQ/CrossoverEQControlDialog.cpp | 115 +++++++++ .../CrossoverEQ/CrossoverEQControlDialog.h | 50 ++++ plugins/CrossoverEQ/CrossoverEQControls.cpp | 116 ++++++++++ plugins/CrossoverEQ/CrossoverEQControls.h | 86 +++++++ plugins/CrossoverEQ/artwork.png | Bin 0 -> 52627 bytes plugins/CrossoverEQ/fader_bg.png | Bin 0 -> 234 bytes plugins/CrossoverEQ/fader_empty.png | Bin 0 -> 198 bytes plugins/CrossoverEQ/fader_knob2.png | Bin 0 -> 783 bytes src/gui/widgets/Fader.cpp | 15 +- 15 files changed, 728 insertions(+), 37 deletions(-) create mode 100644 plugins/CrossoverEQ/CMakeLists.txt create mode 100644 plugins/CrossoverEQ/CrossoverEQ.cpp create mode 100644 plugins/CrossoverEQ/CrossoverEQ.h create mode 100644 plugins/CrossoverEQ/CrossoverEQControlDialog.cpp create mode 100644 plugins/CrossoverEQ/CrossoverEQControlDialog.h create mode 100644 plugins/CrossoverEQ/CrossoverEQControls.cpp create mode 100644 plugins/CrossoverEQ/CrossoverEQControls.h create mode 100644 plugins/CrossoverEQ/artwork.png create mode 100644 plugins/CrossoverEQ/fader_bg.png create mode 100644 plugins/CrossoverEQ/fader_empty.png create mode 100644 plugins/CrossoverEQ/fader_knob2.png diff --git a/include/BasicFilters.h b/include/BasicFilters.h index e09d40c42..eda8d7b14 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -64,6 +64,7 @@ public: for( int i = 0; i < CHANNELS; ++i ) { m_z1[i] = m_z2[i] = m_z3[i] = m_z4[i] = 0.0f; + m_y1[i] = m_y2[i] = m_y3[i] = m_y4[i] = 0.0f; } } @@ -75,69 +76,89 @@ public: inline void setCoeffs( float freq ) { // wc - const float wc = F_2PI * freq / m_sampleRate; - const float wc2 = wc * wc; - const float wc3 = wc2 * wc; + const double wc = D_2PI * freq; + const double wc2 = wc * wc; + const double wc3 = wc2 * wc; m_wc4 = wc2 * wc2; // k - const float k = wc / tan( wc * 0.5 ); - const float k2 = k * k; - const float k3 = k2 * k; + const double k = wc / tan( D_PI * freq / m_sampleRate ); + const double k2 = k * k; + const double k3 = k2 * k; m_k4 = k2 * k2; // a static const double sqrt2 = sqrt( 2.0 ); - const float sq_tmp1 = sqrt2 * wc3 * k; - const float sq_tmp2 = sqrt2 * wc * k3; - m_a = 1.0f / ( 4.0f * wc2 * k2 + 2.0f * sq_tmp1 + m_k4 + 2.0f * sq_tmp2 + m_wc4 ); + const double sq_tmp1 = sqrt2 * wc3 * k; + const double sq_tmp2 = sqrt2 * wc * k3; + + m_a = 1.0 / ( 4.0 * wc2 * k2 + 2.0 * sq_tmp1 + m_k4 + 2.0 * sq_tmp2 + m_wc4 ); // b - m_b1 = ( 4.0f * ( m_wc4 + sq_tmp1 - m_k4 - sq_tmp2 ) ) * m_a; - m_b2 = ( 6.0f * m_wc4 - 8.0f * wc2 * k2 + 6.0f * m_k4 ) * m_a; - m_b3 = ( 4.0f * ( m_wc4 - sq_tmp1 + sq_tmp2 - m_k4 ) ) * m_a; - m_b4 = ( m_k4 - 2.0f * sq_tmp1 + m_wc4 - 2.0f * sq_tmp2 + 4.0f * wc2 * k2 ) * m_a; + m_b1 = ( 4.0 * ( m_wc4 + sq_tmp1 - m_k4 - sq_tmp2 ) ) * m_a; + m_b2 = ( 6.0 * m_wc4 - 8.0 * wc2 * k2 + 6.0 * m_k4 ) * m_a; + m_b3 = ( 4.0 * ( m_wc4 - sq_tmp1 + sq_tmp2 - m_k4 ) ) * m_a; + m_b4 = ( m_k4 - 2.0 * sq_tmp1 + m_wc4 - 2.0 * sq_tmp2 + 4.0 * wc2 * k2 ) * m_a; } inline void setLowpass( float freq ) { setCoeffs( freq ); m_a0 = m_wc4 * m_a; - m_a1 = 4.0f * m_a0; - m_a2 = 6.0f * m_a0; + m_a1 = 4.0 * m_a0; + m_a2 = 6.0 * m_a0; } inline void setHighpass( float freq ) { setCoeffs( freq ); m_a0 = m_k4 * m_a; - m_a1 = 4.0f * m_a0; - m_a2 = 6.0f * m_a0; + m_a1 = -4.0 * m_a0; + m_a2 = 6.0 * m_a0; } inline float update( float in, ch_cnt_t ch ) { - const float a0in = m_a0 * in; - const float a1in = m_a1 * in; - const float out = m_z1[ch] + a0in; + const double y = m_a0 * in + ( m_z1[ch] * m_a1 ) + ( m_z2[ch] * m_a2 ) + + ( m_z3[ch] * m_a1 ) + ( m_z4[ch] * m_a0 ) - + ( m_y1[ch] * m_b1 ) - ( m_y2[ch] * m_b2 ) - + ( m_y3[ch] * m_b3 ) - ( m_y4[ch] * m_b4 ); + + m_z4[ch] = m_z3[ch]; + m_z3[ch] = m_z2[ch]; + m_z2[ch] = m_z1[ch]; + m_z1[ch] = in; - m_z1[ch] = a1in + m_z2[ch] - ( m_b1 * out ); - m_z2[ch] = ( m_a2 * in ) + m_z3[ch] - ( m_b2 * out ); - m_z3[ch] = a1in + m_z4[ch] - ( m_b3 * out ); - m_z4[ch] = a0in - ( m_b4 * out ); + m_y4[ch] = m_y3[ch]; + m_y3[ch] = m_y2[ch]; + m_y2[ch] = m_y1[ch]; + m_y1[ch] = y; - return out; + return y; + +// for some reason converting to direct form 2 doesn't seem to work for this filter +/* const double x = in - ( m_z1[ch] * m_b1 ) - ( m_z2[ch] * m_b2 ) - + ( m_z3[ch] * m_b3 ) - ( m_z4[ch] * m_b4 ); + + m_z4[ch] = m_z3[ch]; + m_z3[ch] = m_z2[ch]; + m_z2[ch] = m_z1[ch]; + m_z1[ch] = x; + + return ( m_a0 * x ) + ( m_z1[ch] * m_a1 ) + ( m_z2[ch] * m_a2 ) + + ( m_z3[ch] * m_a1 ) + ( m_z4[ch] * m_a0 );*/ } private: float m_sampleRate; - float m_wc4; - float m_k4; - float m_a, m_a0, m_a1, m_a2; - float m_b1, m_b2, m_b3, m_b4; + double m_wc4; + double m_k4; + double m_a, m_a0, m_a1, m_a2; + double m_b1, m_b2, m_b3, m_b4; - typedef float frame[CHANNELS]; + typedef double frame[CHANNELS]; frame m_z1, m_z2, m_z3, m_z4; + frame m_y1, m_y2, m_y3, m_y4; }; typedef LinkwitzRiley<2> StereoLinkwitzRiley; diff --git a/include/Fader.h b/include/Fader.h index 96c3ae732..9e8f034ea 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -103,7 +103,7 @@ private: float fRange = m_model->maxValue() - m_model->minValue(); float realVal = m_model->value() - m_model->minValue(); - return height() - ( ( height() - ( *s_knob ).height() ) * ( realVal / fRange ) ); + return height() - ( ( height() - m_knob->height() ) * ( realVal / fRange ) ); } FloatModel * m_model; diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 4df760ecd..cf7a5a94e 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -6,6 +6,7 @@ ADD_SUBDIRECTORY(Bitcrush) ADD_SUBDIRECTORY(carlabase) ADD_SUBDIRECTORY(carlapatchbay) ADD_SUBDIRECTORY(carlarack) +ADD_SUBDIRECTORY(CrossoverEQ) ADD_SUBDIRECTORY(delay) ADD_SUBDIRECTORY(DualFilter) ADD_SUBDIRECTORY(dynamics_processor) diff --git a/plugins/CrossoverEQ/CMakeLists.txt b/plugins/CrossoverEQ/CMakeLists.txt new file mode 100644 index 000000000..fbc8407d9 --- /dev/null +++ b/plugins/CrossoverEQ/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(crossovereq CrossoverEQ.cpp CrossoverEQControls.cpp CrossoverEQControlDialog.cpp MOCFILES CrossoverEQControls.h CrossoverEQControlDialog.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") diff --git a/plugins/CrossoverEQ/CrossoverEQ.cpp b/plugins/CrossoverEQ/CrossoverEQ.cpp new file mode 100644 index 000000000..a50b6381f --- /dev/null +++ b/plugins/CrossoverEQ/CrossoverEQ.cpp @@ -0,0 +1,219 @@ +/* + * CrossoverEQ.cpp - A native 4-band Crossover Equalizer + * good for simulating tonestacks or simple peakless (flat-band) equalization + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 "CrossoverEQ.h" +#include "lmms_math.h" +#include "embed.cpp" + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT crossovereq_plugin_descriptor = +{ + STRINGIFY( PLUGIN_NAME ), + "Crossover Equalizer", + QT_TRANSLATE_NOOP( "pluginBrowser", "A 4-band Crossover Equalizer" ), + "Vesa Kivimäki ", + 0x0100, + Plugin::Effect, + new PluginPixmapLoader( "logo" ), + NULL, + NULL +}; + +} + + +CrossoverEQEffect::CrossoverEQEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ) : + Effect( &crossovereq_plugin_descriptor, parent, key ), + m_controls( this ), + m_sampleRate( Engine::mixer()->processingSampleRate() ), + m_lp1( m_sampleRate ), + m_lp2( m_sampleRate ), + m_lp3( m_sampleRate ), + m_hp2( m_sampleRate ), + m_hp3( m_sampleRate ), + m_hp4( m_sampleRate ), + m_needsUpdate( true ) +{ + m_tmp1 = MM_ALLOC( sampleFrame, Engine::mixer()->framesPerPeriod() ); + m_tmp2 = MM_ALLOC( sampleFrame, Engine::mixer()->framesPerPeriod() ); + m_work = MM_ALLOC( sampleFrame, Engine::mixer()->framesPerPeriod() ); +} + +CrossoverEQEffect::~CrossoverEQEffect() +{ + MM_FREE( m_tmp1 ); + MM_FREE( m_tmp2 ); + MM_FREE( m_work ); +} + +void CrossoverEQEffect::sampleRateChanged() +{ + m_sampleRate = Engine::mixer()->processingSampleRate(); + m_lp1.setSampleRate( m_sampleRate ); + m_lp2.setSampleRate( m_sampleRate ); + m_lp3.setSampleRate( m_sampleRate ); + m_hp2.setSampleRate( m_sampleRate ); + m_hp3.setSampleRate( m_sampleRate ); + m_hp4.setSampleRate( m_sampleRate ); + m_needsUpdate = true; +} + + +bool CrossoverEQEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) +{ + if( !isEnabled() || !isRunning () ) + { + return( false ); + } + + // filters update + if( m_needsUpdate || m_controls.m_xover12.isValueChanged() ) + { + m_lp1.setLowpass( m_controls.m_xover12.value() ); + m_lp1.clearHistory(); + m_hp2.setHighpass( m_controls.m_xover12.value() ); + m_hp2.clearHistory(); + } + if( m_needsUpdate || m_controls.m_xover23.isValueChanged() ) + { + m_lp2.setLowpass( m_controls.m_xover23.value() ); + m_lp2.clearHistory(); + m_hp3.setHighpass( m_controls.m_xover23.value() ); + m_hp3.clearHistory(); + } + if( m_needsUpdate || m_controls.m_xover34.isValueChanged() ) + { + m_lp3.setLowpass( m_controls.m_xover34.value() ); + m_lp3.clearHistory(); + m_hp4.setHighpass( m_controls.m_xover34.value() ); + m_hp4.clearHistory(); + } + + // gain values update + if( m_needsUpdate || m_controls.m_gain1.isValueChanged() ) + { + m_gain1 = dbvToAmp( m_controls.m_gain1.value() ); + } + if( m_needsUpdate || m_controls.m_gain2.isValueChanged() ) + { + m_gain2 = dbvToAmp( m_controls.m_gain2.value() ); + } + if( m_needsUpdate || m_controls.m_gain3.isValueChanged() ) + { + m_gain3 = dbvToAmp( m_controls.m_gain3.value() ); + } + if( m_needsUpdate || m_controls.m_gain4.isValueChanged() ) + { + m_gain4 = dbvToAmp( m_controls.m_gain4.value() ); + } + + // mute values update + const bool mute1 = m_controls.m_mute1.value(); + const bool mute2 = m_controls.m_mute2.value(); + const bool mute3 = m_controls.m_mute3.value(); + const bool mute4 = m_controls.m_mute4.value(); + + m_needsUpdate = false; + + memset( m_work, 0, sizeof( sampleFrame ) * frames ); + + // run temp bands + for( int f = 0; f < frames; ++f ) + { + m_tmp1[f][0] = m_lp2.update( buf[f][0], 0 ); + m_tmp1[f][1] = m_lp2.update( buf[f][1], 1 ); + m_tmp2[f][0] = m_hp3.update( buf[f][0], 0 ); + m_tmp2[f][1] = m_hp3.update( buf[f][1], 1 ); + } + + // run band 1 + if( ! mute1 ) + { + for( int f = 0; f < frames; ++f ) + { + m_work[f][0] += m_lp1.update( m_tmp1[f][0], 0 ) * m_gain1; + m_work[f][1] += m_lp1.update( m_tmp1[f][1], 1 ) * m_gain1; + } + } + + // run band 2 + if( ! mute2 ) + { + for( int f = 0; f < frames; ++f ) + { + m_work[f][0] += m_hp2.update( m_tmp1[f][0], 0 ) * m_gain2; + m_work[f][1] += m_hp2.update( m_tmp1[f][1], 1 ) * m_gain2; + } + } + + // run band 3 + if( ! mute3 ) + { + for( int f = 0; f < frames; ++f ) + { + m_work[f][0] += m_lp3.update( m_tmp2[f][0], 0 ) * m_gain3; + m_work[f][1] += m_lp3.update( m_tmp2[f][1], 1 ) * m_gain3; + } + } + + // run band 4 + if( ! mute4 ) + { + for( int f = 0; f < frames; ++f ) + { + m_work[f][0] += m_hp4.update( m_tmp2[f][0], 0 ) * m_gain4; + m_work[f][1] += m_hp4.update( m_tmp2[f][1], 1 ) * m_gain4; + } + } + + const float d = dryLevel(); + const float w = wetLevel(); + double outSum = 0.0; + for( int f = 0; f < frames; ++f ) + { + buf[f][0] = d * buf[f][0] + w * m_work[f][0]; + buf[f][1] = d * buf[f][1] + w * m_work[f][1]; + outSum = buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; + } + + checkGate( outSum ); + + return isRunning(); +} + + +extern "C" +{ + +// necessary for getting instance out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model* parent, void* data ) +{ + return new CrossoverEQEffect( parent, static_cast( data ) ); +} + +} diff --git a/plugins/CrossoverEQ/CrossoverEQ.h b/plugins/CrossoverEQ/CrossoverEQ.h new file mode 100644 index 000000000..36b3a6bc5 --- /dev/null +++ b/plugins/CrossoverEQ/CrossoverEQ.h @@ -0,0 +1,77 @@ +/* + * CrossoverEQ.h - A native 4-band Crossover Equalizer + * good for simulating tonestacks or simple peakless (flat-band) equalization + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 CROSSOVEREQ_H +#define CROSSOVEREQ_H + +#include "Effect.h" +#include "CrossoverEQControls.h" +#include "ValueBuffer.h" +#include "lmms_math.h" +#include "BasicFilters.h" + +class CrossoverEQEffect : public Effect +{ +public: + CrossoverEQEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ); + virtual ~CrossoverEQEffect(); + virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ); + + virtual EffectControls* controls() + { + return &m_controls; + } + +private: + CrossoverEQControls m_controls; + + void sampleRateChanged(); + + float m_sampleRate; + + float m_gain1; + float m_gain2; + float m_gain3; + float m_gain4; + + StereoLinkwitzRiley m_lp1; + StereoLinkwitzRiley m_lp2; + StereoLinkwitzRiley m_lp3; + + StereoLinkwitzRiley m_hp2; + StereoLinkwitzRiley m_hp3; + StereoLinkwitzRiley m_hp4; + + sampleFrame * m_tmp1; + sampleFrame * m_tmp2; + sampleFrame * m_work; + + bool m_needsUpdate; + + friend class CrossoverEQControls; +}; + +#endif diff --git a/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp b/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp new file mode 100644 index 000000000..8a9eecf4d --- /dev/null +++ b/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp @@ -0,0 +1,115 @@ +/* + * CrossoverEQControlDialog.cpp - A native 4-band Crossover Equalizer + * good for simulating tonestacks or simple peakless (flat-band) equalization + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 + +#include "CrossoverEQControlDialog.h" +#include "CrossoverEQControls.h" +#include "embed.h" +#include "ToolTip.h" +#include "LedCheckbox.h" +#include "Knob.h" +#include "Fader.h" + +CrossoverEQControlDialog::CrossoverEQControlDialog( CrossoverEQControls * controls ) : + EffectControlDialog( controls ) +{ + setAutoFillBackground( true ); + QPalette pal; + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); + setPalette( pal ); + setFixedSize( 167, 188 ); + + // knobs + Knob * xover12 = new Knob( knobBright_26, this ); + xover12->move( 29, 15 ); + xover12->setModel( & controls->m_xover12 ); + xover12->setLabel( "1/2" ); + xover12->setHintText( tr( "Band 1/2 Crossover:" ), " Hz" ); + + Knob * xover23 = new Knob( knobBright_26, this ); + xover23->move( 69, 15 ); + xover23->setModel( & controls->m_xover23 ); + xover23->setLabel( "2/3" ); + xover23->setHintText( tr( "Band 2/3 Crossover:" ), " Hz" ); + + Knob * xover34 = new Knob( knobBright_26, this ); + xover34->move( 109, 15 ); + xover34->setModel( & controls->m_xover34 ); + xover34->setLabel( "3/4" ); + xover34->setHintText( tr( "Band 3/4 Crossover:" ), " Hz" ); + + m_fader_bg = QPixmap( PLUGIN_NAME::getIconPixmap( "fader_bg" ) ); + m_fader_empty = QPixmap( PLUGIN_NAME::getIconPixmap( "fader_empty" ) ); + m_fader_knob = QPixmap( PLUGIN_NAME::getIconPixmap( "fader_knob2" ) ); + + // faders + Fader * gain1 = new Fader( &controls->m_gain1, "Band 1 Gain", this, + &m_fader_bg, &m_fader_empty, &m_fader_knob ); + gain1->move( 7, 56 ); + gain1->setDisplayConversion( false ); + gain1->setHintText( tr( "Band 1 Gain:" ), " dBV" ); + + Fader * gain2 = new Fader( &controls->m_gain2, "Band 2 Gain", this, + &m_fader_bg, &m_fader_empty, &m_fader_knob ); + gain2->move( 47, 56 ); + gain2->setDisplayConversion( false ); + gain2->setHintText( tr( "Band 2 Gain:" ), " dBV" ); + + Fader * gain3 = new Fader( &controls->m_gain3, "Band 3 Gain", this, + &m_fader_bg, &m_fader_empty, &m_fader_knob ); + gain3->move( 87, 56 ); + gain3->setDisplayConversion( false ); + gain3->setHintText( tr( "Band 3 Gain:" ), " dBV" ); + + Fader * gain4 = new Fader( &controls->m_gain4, "Band 4 Gain", this, + &m_fader_bg, &m_fader_empty, &m_fader_knob ); + gain4->move( 127, 56 ); + gain4->setDisplayConversion( false ); + gain4->setHintText( tr( "Band 4 Gain:" ), " dBV" ); + + // leds + LedCheckBox * mute1 = new LedCheckBox( "M", this, tr( "Band 1 Mute" ), LedCheckBox::Red ); + mute1->move( 11, 158 ); + mute1->setModel( & controls->m_mute1 ); + ToolTip::add( mute1, tr( "Mute Band 1" ) ); + + LedCheckBox * mute2 = new LedCheckBox( "M", this, tr( "Band 2 Mute" ), LedCheckBox::Red ); + mute2->move( 51, 158 ); + mute2->setModel( & controls->m_mute2 ); + ToolTip::add( mute2, tr( "Mute Band 2" ) ); + + LedCheckBox * mute3 = new LedCheckBox( "M", this, tr( "Band 3 Mute" ), LedCheckBox::Red ); + mute3->move( 91, 158 ); + mute3->setModel( & controls->m_mute3 ); + ToolTip::add( mute3, tr( "Mute Band 3" ) ); + + LedCheckBox * mute4 = new LedCheckBox( "M", this, tr( "Band 4 Mute" ), LedCheckBox::Red ); + mute4->move( 131, 158 ); + mute4->setModel( & controls->m_mute4 ); + ToolTip::add( mute4, tr( "Mute Band 4" ) ); +} diff --git a/plugins/CrossoverEQ/CrossoverEQControlDialog.h b/plugins/CrossoverEQ/CrossoverEQControlDialog.h new file mode 100644 index 000000000..08c678886 --- /dev/null +++ b/plugins/CrossoverEQ/CrossoverEQControlDialog.h @@ -0,0 +1,50 @@ +/* + * CrossoverEQControlDialog.h - A native 4-band Crossover Equalizer + * good for simulating tonestacks or simple peakless (flat-band) equalization + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 CROSSOVEREQ_CONTROL_DIALOG_H +#define CROSSOVEREQ_CONTROL_DIALOG_H + +#include +#include "EffectControlDialog.h" + +class CrossoverEQControls; + +class CrossoverEQControlDialog : public EffectControlDialog +{ + Q_OBJECT +public: + CrossoverEQControlDialog( CrossoverEQControls * controls ); + virtual ~CrossoverEQControlDialog() + { + } + +private: + QPixmap m_fader_bg; + QPixmap m_fader_empty; + QPixmap m_fader_knob; +}; + +#endif diff --git a/plugins/CrossoverEQ/CrossoverEQControls.cpp b/plugins/CrossoverEQ/CrossoverEQControls.cpp new file mode 100644 index 000000000..9c58eabff --- /dev/null +++ b/plugins/CrossoverEQ/CrossoverEQControls.cpp @@ -0,0 +1,116 @@ +/* + * CrossoverEQControls.cpp - A native 4-band Crossover Equalizer + * good for simulating tonestacks or simple peakless (flat-band) equalization + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 "CrossoverEQControls.h" +#include "CrossoverEQ.h" + +CrossoverEQControls::CrossoverEQControls( CrossoverEQEffect * eff ) : + EffectControls( eff ), + m_effect( eff ), + m_xover12( 125.f, 50.f, 10000.f, 1.0f, this, "Band 1/2 Crossover" ), + m_xover23( 1250.f, 50.f, 20000.f, 1.0f, this, "Band 2/3 Crossover" ), + m_xover34( 5000.f, 50.f, 20000.f, 1.0f, this, "Band 3/4 Crossover" ), + m_gain1( 0.f, -60.f, 30.f, 0.1f, this, "Band 1 Gain" ), + m_gain2( 0.f, -60.f, 30.f, 0.1f, this, "Band 2 Gain" ), + m_gain3( 0.f, -60.f, 30.f, 0.1f, this, "Band 3 Gain" ), + m_gain4( 0.f, -60.f, 30.f, 0.1f, this, "Band 4 Gain" ), + m_mute1( false, this, "Mute Band 1" ), + m_mute2( false, this, "Mute Band 2" ), + m_mute3( false, this, "Mute Band 3" ), + m_mute4( false, this, "Mute Band 4" ) +{ + connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) ); + connect( &m_xover12, SIGNAL( dataChanged() ), this, SLOT( xover12Changed() ) ); + connect( &m_xover23, SIGNAL( dataChanged() ), this, SLOT( xover23Changed() ) ); + connect( &m_xover34, SIGNAL( dataChanged() ), this, SLOT( xover34Changed() ) ); + + m_xover12.setScaleLogarithmic( true ); + m_xover23.setScaleLogarithmic( true ); + m_xover34.setScaleLogarithmic( true ); +} + +void CrossoverEQControls::saveSettings( QDomDocument & doc, QDomElement & elem ) +{ + m_xover12.saveSettings( doc, elem, "xover12" ); + m_xover23.saveSettings( doc, elem, "xover23" ); + m_xover34.saveSettings( doc, elem, "xover34" ); + + m_gain1.saveSettings( doc, elem, "gain1" ); + m_gain2.saveSettings( doc, elem, "gain2" ); + m_gain3.saveSettings( doc, elem, "gain3" ); + m_gain4.saveSettings( doc, elem, "gain4" ); + + m_mute1.saveSettings( doc, elem, "mute1" ); + m_mute2.saveSettings( doc, elem, "mute2" ); + m_mute3.saveSettings( doc, elem, "mute3" ); + m_mute4.saveSettings( doc, elem, "mute4" ); +} + +void CrossoverEQControls::loadSettings( const QDomElement & elem ) +{ + m_xover12.loadSettings( elem, "xover12" ); + m_xover23.loadSettings( elem, "xover23" ); + m_xover34.loadSettings( elem, "xover34" ); + + m_gain1.loadSettings( elem, "gain1" ); + m_gain2.loadSettings( elem, "gain2" ); + m_gain3.loadSettings( elem, "gain3" ); + m_gain4.loadSettings( elem, "gain4" ); + + m_mute1.loadSettings( elem, "mute1" ); + m_mute2.loadSettings( elem, "mute2" ); + m_mute3.loadSettings( elem, "mute3" ); + m_mute4.loadSettings( elem, "mute4" ); + + m_effect->m_needsUpdate = true; +} + +void CrossoverEQControls::xover12Changed() +{ + float v = m_xover12.value(); + if( m_xover23.value() < v ) { m_xover23.setValue( v ); } + if( m_xover34.value() < v ) { m_xover34.setValue( v ); } +} + +void CrossoverEQControls::xover23Changed() +{ + float v = m_xover23.value(); + if( m_xover12.value() > v ) { m_xover12.setValue( v ); } + if( m_xover34.value() < v ) { m_xover34.setValue( v ); } +} + +void CrossoverEQControls::xover34Changed() +{ + float v = m_xover34.value(); + if( m_xover12.value() > v ) { m_xover12.setValue( v ); } + if( m_xover23.value() > v ) { m_xover23.setValue( v ); } +} + + +void CrossoverEQControls::sampleRateChanged() +{ + m_effect->sampleRateChanged(); +} diff --git a/plugins/CrossoverEQ/CrossoverEQControls.h b/plugins/CrossoverEQ/CrossoverEQControls.h new file mode 100644 index 000000000..18e87baee --- /dev/null +++ b/plugins/CrossoverEQ/CrossoverEQControls.h @@ -0,0 +1,86 @@ +/* + * CrossoverEQControls.h - A native 4-band Crossover Equalizer + * good for simulating tonestacks or simple peakless (flat-band) equalization + * + * Copyright (c) 2014 Vesa Kivimäki + * Copyright (c) 2006-2014 Tobias Doerffel + * + * 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 CROSSOVEREQ_CONTROLS_H +#define CROSSOVEREQ_CONTROLS_H + +#include "EffectControls.h" +#include "CrossoverEQControlDialog.h" + +class CrossoverEQEffect; + +class CrossoverEQControls : public EffectControls +{ + Q_OBJECT +public: + CrossoverEQControls( CrossoverEQEffect * eff ); + virtual ~CrossoverEQControls() {} + + virtual void saveSettings( QDomDocument & doc, QDomElement & elem ); + virtual void loadSettings( const QDomElement & elem ); + inline virtual QString nodeName() const + { + return( "crossoevereqcontrols" ); + } + + virtual int controlCount() + { + return( 11 ); + } + + virtual EffectControlDialog * createView() + { + return( new CrossoverEQControlDialog( this ) ); + } + +private slots: + void xover12Changed(); + void xover23Changed(); + void xover34Changed(); + void sampleRateChanged(); + +private: + CrossoverEQEffect * m_effect; + + FloatModel m_xover12; + FloatModel m_xover23; + FloatModel m_xover34; + + FloatModel m_gain1; + FloatModel m_gain2; + FloatModel m_gain3; + FloatModel m_gain4; + + BoolModel m_mute1; + BoolModel m_mute2; + BoolModel m_mute3; + BoolModel m_mute4; + + friend class CrossoverEQControlDialog; + friend class CrossoverEQEffect; +}; + +#endif diff --git a/plugins/CrossoverEQ/artwork.png b/plugins/CrossoverEQ/artwork.png new file mode 100644 index 0000000000000000000000000000000000000000..5510d2b3c3edc757483f2b21a7c3eb957ab2e448 GIT binary patch literal 52627 zcmV(~K+nI4P)g_yty{sF@t zATdCQG5mBS)S^+-VsLL&pOdkdyO}YtwIg=q$x~Igkx1#B%-El6xtp8W``T+3^56gK z|Ec)Rp919io9o}a{QTo%!hh@^`N_Bawb$@Fulw2i|JG;!weS4dYku$Zeti7z`M$sQ zp1*ZnKd!^?eU|){9sPUO;P>wHU%Iz{YYl$yj|(u5gLxcO{hb^3e33#W$n$Udv7cUL z{&v;g|5<-!=YIC*_n!N7maY%^&1-+>4u5Yq|Ju*|jdNK)F4({HUSICv^}Bvt&%gCK z^;dk!zvMoCyoUN4pYgM${yX;dd^|WG4;)pF`;Bkk{(z`Ly{z7IQA<9os08G>>GJV< z`MKYam!Iq9vF9W5a;5c?y^)ta{h14WUc&pge7gDmrux0l`{@FHyhpB|i|Us>Z~fDI z^5aBSAJo^+`;F~LALLIPbS>}uef%^~3G#da{H`PU>)t!B&)2@zYX?5|^W#mQuD5pHT}?MtX@rRCK} zT%RUwb}B-?hNo+B>pEhFk`yA>*Vn7}x{SQ)hZB9>*t_ShKB3oZ-#4s2Hub~Ne?$Pe zuAx5d(e?cT`ttlIPm_HUT9;9lyc_tZ$Z&bQ9}VXt+P}ITdH?zOTwN~p`Lp~Gg$$vt z`_Xs*B>g?_Yf>-4PN>U)JfBDEBkJ%u2!5>N$G!e0vdQOoqxm%2`V@V*)(NQ}y!7YL zq1q19<@$%}i!TxTbmZ&BgXAZ#V?T9iuOU(1H${Hq1?9yB>5HouY4`HU^SrE>yc|&x z`Lt3}(w6`F-q+Bhmrr>bhJN&HQOe@>nUKt2rp(|11uLwj<4HNckxqRP90v?te(@8i1O>ss`BzrHT6$hF5ET~xUq zlaH6YMi+f~?EOH<`|>?MOOY4bd0o%X>+sw4me1?_viADpp8T+j&vm?R;gf^Wmwi@w z{`_G_`osQw*h7Er%a$O|{dnHv^&PI)h3jh``8Sc?51Dhmda{pj{k|aif<&&ApkCap z$_wE6!Mv-UMpB;*^uv|CKZeNV(CU3*KXOp{oQSE(q~K6|3~KzMoZPeGa8R1_pSoFnNzby8I>EMdDma*vR?34 z;CQ9uS9yT0Y=QS?bXU9evH4}bYH zwKsl@zpp0n$q3~Iy}g8=`a8-c|4|hu`Ttb8`v3Ef=-&z<{C0t=e!}zAZ&R<5ADEPS z;i+Ev>fb5F{YW%F50(5j8a`k6%GbUGDBLGLya9G8CIZ;YRvQAC395nvs0m{70n4AM zVisz~zyEjtmdE$MFz4h?-|kES5&O8G>d)vya6LNuuvh@Y$V^;~OejrUm7R%QzQRaC z^a`tadB{F_RrOA%RCV|Z0TYD`Qv18BK2E2i6hS@X^OF*KrV1&D>HA}nMX5G5Ly?h~ z=|zDFCiJySBBE^@k(~qvV0|Y^VIt%^Q~z90r7DrE_ADZRBef~Dmower-Vx$?n5D?n z7k77|bcNd2HC(BIiV`~!O~8rV*F7a!uYg=33sIxkSM0j-bbC6d)eEgkWg=!oBtwOa zx{{B4&z=lk9wkC%udubmwHs}O#sy6IIbfXHv zS1f-ab)uQ1_W4N>zLfA*FeE93I$`@ji8kK_=1}KG6do$v5Wa{VQ;YNf!08+kWz{be)*m-$dfgcBLpo4Hxh*b zx&qu#r8jN`GK{T>hI80vZD;eHV|*i6?C*gNfektoGFh4ob27j)*(_2IRNDjEBS_nQ zFZB(tzp(U%XAsgJsLZ)1e9vUKVw%LM?4fuhL0_XQu!HjA0o+6>Q6AqH$j1E6-Va2Q z+(NN2H6jI3!y?GTfrV^Hb)=LbMGb*mL^vkGCUAAm$L3~ADv-rSsS1$1*oLAqC|B$O z^#$tJwu>DwQZN_x5!4BP{!8*tZ;6^wSud$g@#la3Gk^Z`Kfj=L(I$thP*?u)=YQg6 z#eel*{3EG}#(|AM88DSfxE)aG$bDn`hW-im311IGMOg)RgGVUC7K1OGym8Ynglz5_ zoO)*@FgCUvaWI?gy-{&|K-EI`pj;Uk?31`391Fr1M;#YcYGiE~vk&4PpeOs7eBFk6 zQRWnijy6O)?wBRDAuF)^!D+>eJHr=|H^hJC%lHS91-}Z%-CzrH?~?DP_-aA~Ooe3+ zhJGb4l;EbhLyibP6OVkq5^RHpR^j9&ejJ z9mWzzs@STG+Jq^x6q(ZLl^L1|Uyc1H*pXx@cLhC^Iud<@Lk;_5@qK^ij6~I5>PUJ4 zbV2^d|K)$HKm6fO{NYc3?9{9hMEIxw=il*P|EquC7!%}<&3>B?B}KWJQsLA*@qM6Q zAl{VQ-KY&gF-%!0h;O{^ton{==buB9HwF#}o4o_asB}sf70*0<5h190=V7rqM`2sZ zT20+(VdaD@)SQSw$`BS?V3uE8^ObxLg~!6?Kuo9=M1q^LH6bR4ZgvR~-lyA61}q2nM(EFcUL<5o&pk{NIT zl~uv8!P^SH8LToYgHVH9lz}YJ0a+IUzjE+cm)A$pOvX@h1aZPh<3WU*L6iPSTbw_pCkJpK{#z;1!1;fF&BcT-@%?PRPw`VIC&`0~}s zEu;ohjS|EBWaL-gY_74{C|FvcoU0>f#N z!6@CR9n@Z!%=Q4H+|oM-a%&JVpdK5)9jGaJZYX06Arv$w$Jp$e5WjG{|A~-A{UX>+ z&=lktlq?eE5ZEOg38$Y-`N9TN6js1-r5bX>ncxfGxAvH)bH5EL zgp%aYPOwW)M&5bIgF`zccm*dnTtGFNPc6S{ED6yDL~cl}bKpG}0B#!EFSYlgu~f?T?fO`BvCXa2(Z% zcu-=@VWhO@*}fTmCsj~0JQ5oVQ$hSIqaMU)rXz*UeO36P#v`1&6$~LCu;;+E51^jc zL5-rMI92#Mgsj2di;5HT8eHUnWFNlpu9r1UU;Hir=6jNmqP>xRA@RBSx}+msul z4bldpj+mmWurW~|$Qhm498Q^{+ujW`>W$m+4RjF?!4Ji7R2`0>N*E?oHA-H-8FnX8 z#1uOVd?Px5J0rdm<6u;Es1qYqxx4XL%6)=(Q76RBnGR`%F2#pnm8dFv!j~!R@CGA! zGLA1$fwDPw%kIpY>Kex+&j({nO2K!sZxgohbtn;mjzUXtJy;q{|H2u;*O^ouXf4Vb z#m59Y4ZkZD2~)8R>P{}>xEEQIQN=h0rR{9)I@ub8B}X1?35I}}@}K5RQ1q*iTlsP~)`qCyP*`b=7~|lS6QlV(6mi@@tL%nK;0z#snjN5r(z`lUh9rxxg`I_W2#b#^7A z&^e)!Ax6qXJyIQ7IY{AIB?>xNc<2C7!LyBCi4>W8sdg%B0KP**c@;Ml|~N3%+M_y z9vvq0Zq_Nx*?>dT`ukDLn}fTF@uv;UCpuBEV&^WoxjCpuyrZFvq()O7NCR`V;5(xYXODwd{M?&pEB?I zKYL)FY!!yi_xg$rZ_7UuGe>U|d0Qw#jEg*7#hgXeAaZf|4P>z&%He=o6W6*?(auvZ zUh$EMyEdV3g`Oa@$>>$aQ77jZ%z`Biq^hi`rtREpffPHG7=n>(3V(o1>9AeOIg-Pg z778{MCo(2gaj_hiK6DBd%5gu)ctd?QP)ewqvA6PVD(AUS1NMpgWJ}<7C(gxj1QJf} z=3JE|4}piFUyFDYX)sed3Y^ZoNgu=wIt5{oA>8f8)=g-j;mti?wOS)7acXz^CZe5U ziNDv?RrN!nCr<!~#|u zlxc_a+)CPRfdJkfbHkF23`LiBI4MCTuYy)})r2CJGGwu;a2&D;W4(EkD4Bi8E*d3D zS+1yihw|Aq-g7?~eo$kxmoWyEDw+^iDO7MIiaW}85*tE>B15pH=!~YZWN@#O(Vn7S#2$gb)bkd};xP^MHiMYe2nn6l16YLKyE99{Gv*l|e$UD+Xw`=s^* zm3hhPgqqG;!k1w@Vq>Nd8`m4*;C8Ur;y47!K}r#Jl~JudrrrxqAsuE3+XUIhxCwdn zF>rKgH_~vMU4-yLc5~1sEro-md{S#8qct1vsyJ<6CHA6a75z|5i##>l+H{9Jx^{dh zJB2TYaE7s>E>HlOn?nb0Y{n%j&^QUXp|wb>M)H+?kw9!fH=0enhA1AzDI0N+hZ1vl zslJjd19rC*RIwk%u;76(b)s3gPMAhTz;5o%?gJjX!T-4Kb;Gpg;m)<0*G&Rv3Tf361PlDl zDHkLclFF&U&4he(B`3}Y(x(Z@leJn8klxpF90$bX@<5HgbvQePZ-;T7o&U2pCO2{l zT1M?)^hL1AE8Q~iBHskL7xE~=l3B1tkY$W1t-Z)Vwc6;maI=B32nW_gSr~@cKqSH1 zFwLyX!UpfHLLb`cOZctUR{P!#aEXCcQQfcez6;1I}7 z?W9!k>Db$%N{Hd04!gK{5*UxigEMXTktAE9iu2|jZVG^H{U#}aPubhbs)3Qom3X4%Dg$cPFBJm4f1pcw;?Q? z^E^4mfyib(l<5stbip>zE$_MAFnCKE^d+bn@(@xs=7SUCsLh+g4P^roiRi&0$y$?P zol~E5RmDok8H_hW95NS*u_U?OAif(R32P&BydV0#F0u0gk=EcRg6k}_zSD&$qEWY;xT1Rr(|`=zW^%b z&C%|59<|yqhYI_OIxc!4bh*-}k8Toe^1YGLtB6<<!CJg@jYNaG#V5Mw9cy5?60oUIt}`%uW2_$d^D* zAx-d$$^yl$*x_h`SiN_3nj4vmB_MIbc>o7?u_@|G za~CPA)znML17yQQDDMKCKF1iqAQg+&krT80_y^vgDitShhe0ksJih=KB; zn20MxV&1YxbHnKBSFDpMPT0#>4UrDz7s)B6XoI1PXOfQwv_$!G2$8&(xNhQ{d*f=H z6zXl57D3fP<%61_yGRpEw8gMul&#i@$|WIPN$NsOsU_4+$PJ@}9DeobBw0c&<*<`C zHJlb69Of;;2thJYb;dAQo25eeN6-1RBE-m*%;8|k+QM+{Fn2;&qF7f~b}@&rqVvnl z7R7c7{uHz*vrbMG4leQV2{IIuVDAH$6GVAnxK-0SM{=A_nlxXDa2m|1#CIpWkhh|q zWxexcH?)VLWGUltIG=*(YWimiv4tr@vXDI>9}GJ>XA~z1)Djb8U$T(WtA_nu$a~>i z$x)2#=S&X7gUq%H@ve|5G!LGO?Lx)GQ|J3$m{{|6SL?P#P}`~8t@hbPsN#|k*%CWFseNey z74$690#PS7a8qg(vx>O*)w<+Ubt=P>H&t95C73?BN+}cpqPQ!p?CinYV^YObA=HR- zGaR_Uk7*mGJ|M@2a!jKYQzLooXU|M4+bxtu;=|Y_xST9)FTbm+C3+~Ln~DRIUqOWL z2*a~w10LviB@r?nZI~3ph5FS<-|&{yaW(0!#YP|s@gxxZ7|3odr8~%lyffi2?NFYB zsyBuoY!h4tLSh0ggVekX^Wuxoj#?v|F0u_9!Nd_?AQMusqj_nqLhJ^+4O4RBJdm2G zJIJ~!M`z;#intAGpWNKR3qqSEcx8%c&Qq^Qu43|Oh`@VmRd$<(2;9_oJ9jHq)KD#4 zL8D84E$+RHMFp3nqEKo1$VDBO!eVoRYY-0O7Df z4M9>6NmK@78nTlm0&ZA#l08+~YQ!TLYLvrXhPk(D{{hUTWYC)7&OhI_HC<#2m4RkU z>84F8!P*2k#K|lyl$ss0CBC3?f;vmA$@~nMiEY24(xxy@5r!M}ro`CP1M0XsJy*-| zqyrCu;d3CXy4c~0Fez_pYDg#ER!7&|$I-e=^KK&3!o>-R2C3Tp|MiPdx5QKW9(NEF zQw=PyK8vpX=h=0583XbprXYFXoWSVEYm=hHV=;8LDcvUV*xVSDR#Pti6d>v47dxcu zdpGdYb7JpPHhAyC0rTR(S&zhAIB9yxRj3_A4Tzvdt7iHGJCv(9Th7ZcA#rT)_EydK zz!c;%%ovVVww@A49?2NRgTmxMSq$;6kMC*(RE`g!R&oO3be^U8o&)B&d!a{CTXF0B z%HO0tl}?5hQNkR>xvF)e8h9RP7G0IIu69UrN-O;{6A2n^wqiXt>EO#D zt6L}#_62@8g`A1LC3z%*qbu2By@{5j8a5pbsBErS(kV-J38RXBa#Hbzsj`6 z24X7eN#%j^AQ6@*L!nlX14i^_*G0;o65NIpzbb2h{u<;>PzJV7wiKG#N+lWS;rJGa zz`XCXMi3}7wJSMcupixyF^(=fSAi!}jIGW8a%<^hy(w}lG?W@}1f&}3MoC95-P&Cb zXBQqA*Ph=L!f|_$X~@tvOjB|Pht3}IFb5IE*DJS|9B`!+A~%L!fbKa3>@>D7RBov4tE?ED@ifd6701e0(%j|(oMMYG&03|CMNPxKAiE}CA|0x) z${8~__8{fG?~5fc#vmSz+WmWww-#IIJ~^wJNYqx+*Hq?e0k{oA)5u%0u&>bola$~fyA^vip`r7%X-A$>=#!!u` z0W6W#WUEf4-av;nubI2a-D>qtYLaPK1tHOVWwdA03_ObP7Jt;$`l=5Yx2~X=+%b=) zjogvgSD9=u=O8jbjMTunp;w;0t$~mN%uVfyAA)Kz!ill48mOHVli|VI6URwAfg4uR zVrA1-6B+LsPOYYLWEk#A?t^YKQ{I4^bxmIUWaL3wljf>I2+TvsH^>9{p46Albv+l` zXoDHr=zk7wTgb~}5<(umR`+VEPPSZzsqAqu>Gi~0XHXRN*e!&i;JdJo#I}M5Ca_Xa z*RBk4Aghf_&W?0CoQe$tios15ds*vTb5m~APKF&l=wT}BY|ZGd#syN*yr|t9ESHeF z+JU^3E|CxEroK)ZQ~ek)*QeZYU6?|xLRZVHbSSw69ri97_UhJ!QXwqKn(s;*tD?$~ z(I|9;aJr${ea=z?--X_*$?&?NdiLVFV$mvZ(z|ghyR~9TB6XmbP&uq?;#!G}p!RXK zaTLCcZEr{#;t4Srwpe>~Nl_nE9hXQ$aJvw#Bo>9Zpponi=7NoceWQ4wC@00CT~^HT z#)#XM(zJFpGV#NSH-oz%za-qdlsj^@%IEF+9us6bb4%x#LmQYJjo6QBRL$<*a#bh% z#_bwgktVI9l}(({g6irbM;?i#gKvg(`BS}96ZD4cq#GT&ve)@ZN6>Zyi*q@CD6%)( zm3=06n>|uz7;7nCX19x*bhWS))Vf8b=x*AZ-n#VsK2o!tq+DQ4pFhYCBU6?t(-ufm zY?4OlLR}yg(Qd)b3XDOqC^1TesL5b)R$Zs0t2malPSYLBmhejr^jz5O8g)_!YMrwwu*z4H$>o3FtqcgoC~izp}^jdO40|q9^Hk>FF}3j=CiSz zz}5%d2d{t)#w9Hj7qSc;#V+q0bAoI`WMSgem>kld7o#qv53IAWqq`JzJ9{RCf-S6^ z6%Am`gDn$Zi4MWv1WeH5>XI->aqc8*_dXCUQ;a2i_1PNDsjTpBBgsO=C>AM&+ZRS8 zK@qYz?4atrlx822O}U1kbv;P0R?N#npOZ}Nnq`v#UOf~*T&Nh=2W<*rGOx|;h23FH zb^`|uq?|NGvI*DI1`>d8ye4{X^Td6+N1h%=9ii zBYdYdno5y=;(L-}SE1WL0>4dU2{8ouHOPDOk`}=piarXN4NP?oj_g@Vc1aoS-hgzZ zz!X^RF-<3R+?ds+;jm;>&mY=n(vC^7Ft(pqIzEaclwE~e-&54V+(k~KPV4A7{F?D9 zgih|7tWf+gWH$qm8@~AfQYz{f7IEgy0snXRbUEpbt zV9&5FFQa<&U7?gw4RGSbOvo5Ltyq%;CPr{})20?@Du?D(gD%KHXouNBaL!JuIW{9F zwKsCpYcQ2#x=}eW7wXZ5S*N1Y$sJ@WF#=r^(ZEuh+swpkqf%tuP;Et%Z(-XTmIv4- zw{z&`u}3TL^+bDi2vV(-iF!~&8F7v8i`D|jl&da2Kptcj3+48d#d-Htr5nVfrxI77 zV~~#`ywG1jzi3x#qJ=T?R>9(qvTg zgmDHs3)zl^vh752Fpt2ZcnFwjcbu+ntwGi3+Zc z$%VMGqbKfQU01!86S^q1&NI_ED9*|Y!8)nkWjM50V;~FUfDw~eCmcPlMr2^RFgY5z zy=~;y;LDGrsVjBzNHhmF!M3urr>;r0qAB&>{Yg<+3dq zWC|<05!(VzxnyEUgP&2~C0!qRT5F#5pw9eA1eCk&%@&(1nk_yfTs1epWbCpreT;1BaoRANVQhVjL^_g~dWgks@y zwh(z2C5xLMJ%XYJB7v=V8AvNvqw9UmZ;zzD3TrQXCzuo813Q$&QEybfJCV9bed~b@snkvJ zvvrp04#y3@DsameL$t*skMk--I1@Dq)3O<%i2%~_}^Y~d8J zozzX)u{%XDr`|R;q&IRHN5Zy3Da-}M2&B{Po8YHWzEN%PO4bIM2YLqFl=Z#%ItP#1j3GQW z+zA4^Xr8O9aynKGA{Qrz+^Fb$zo^CnQY^ENUqtbo{(aTg->D>d@5_9SW0aSX?$T4o zYIDSmEf3O~%-zv-^h{-VQfoA?*BwEGcgZeha@0Yd-^nlYs*7u@SjL^37_k$(Z)6X2 z8ll+&1`Wu8&YqC5v}X&cR#zAF=qYEro94nESPeoK)WmhMN?TMr9!QRNib5^f1Ub5= zz2_0p{Hr~A%nA0L&1i2C-hJo3kQj}oGf1q_{l!NB6qw{31ZjZ3# zou6B)o_fxc^EHFD61g4d-pJkBFmKLDavX!lhHpkI-4(zl}N#-E6 z=VH4i=a^V#cZBmYcKk#4j_P~=#^%|ha5M&WI}w?vdC$%@*mX^;2x;(f(#(Pge&wlZZ)7PUg@rRPVw|nO(I&{V zjFRek?a{*}MizDSTuM1xKBkY=WVjYJoa1bdX;f<&t%y=QKyHp)l_E)pW8mjT^NZrn`-F^MhX~;I`Rwru-bu^Pwhq1p0 zU+2MD#hl7o@O5-mtF#cCK(#O>L3glpF}XLzn1izJY;a(?Gox7gY+U4pPP&|>zQCl{ zUx{)7d17j}%*OryCF^Z=HA|K>t;c@c*S8~2t7i<5P&0$d^V8?FiU|@82(F6@;10N! zq6a-=0O~qjr__iR0tQS#2@CWM(l)r7|;=v14!l%-zi1_jyTqNOcTY zyP;B9#(ebwiZc^5NkSb7WzUDnMZNF-)AWl5_l?L47eN--t2vlM1|DSOB@aSL{6TYFzOgtx#YkHRJw>2@q4g+0l3JH(8nq7P;y z>^k%fHP&bK)g&`X4C=g}qM=q^4GY_Gcf~YE-urMb18gwQhRl!UL5$=57V6`OMCwQw zUyk2>FrT`+A_hFGsM!Z|iI@} zxmu_i1DhL>u9!q&uQ*)vN$Bo_Dcxb(t8E;3UlYP=Rg3p#Mjpde2x)j%$wThhPRHF% zMcNJNXxUM27qu7L4G#!O#;W7ZPtw@gn3@xfTM=C#uv(3j9dJKzUzSLHs#{^^W6F@15@&6t8jJ3&%{Oy^4H zIkV>16u6V+#Z{B?WT$k+*OvF06_MHt3u!LFmwL!;aV+D2&I0y8v==4%^GF31P(#)1dsx*^O+s^d zuRRIdP_6!cQgHgT`{>SVOMBealHh9T+?Du#!Tk+BM$5_4(XoLSvjh#WQ70E_^z2VY z15IOKS5c{i9;T9XN#5ep8M(*cqY? zfmW<#?Z}^w?ruWIaB#z)K*f1@cwN?SwiXtK zk0kTBRK=<3T(x;N#B}UQqQysiFi3~jaNbYyk|N5E0?iKO*V?WeL3%Lq0_mqt$H*ia z!6SyVSgJin%1Ml4lsoYytw_?-k9=l0eMW9+Z)%c6Lka7t{84Na;H9}g1#9T*@K zDXm75m!NS`>l^X9u1SC4JcDrm{Qj(7Oq*uB~8-EJj&>YRKsf$x|+TD zSuu4|+++=gHAUBTQsbe@dt}t`4l))ooSAJKv0Gb5nt@nBUZ^j2w5MIdQ8Q9@HyB!E zN;?rr+>NL@tGXnove#w;HX*+)%)KWG=ICy`_LP0#V#R~-Ql+jlM^2jX;b5yUzqn;H zUPi5A;iN7~oD1ijZ$t;zCFq?j7cM5t8r*7WEP}BNAGuegBk`A^&mf<#$ZH;jjAPcy6i1P* zh;J$tu~&Dp;sgtq(Lo2%mf|u&^CqzafqKv|Oj?v-GWsnn7sHEH!q7qZLotrusC_mS zi>*Co2@mXTIL>?cYhdNsCVEx zfK7dl(?);o&{~6?%7+hPba(*OS9y5PMpd1!c{7@jMwAlL#|8XgGVM(8$Ggb}v6F4T(U!-*Y1uwUhO_m}`?R zR9FM@hG8b$EBJ6&p=_i%_;EA?2pYS;rsW+>fgXW0=qk2dXx&tA2AI*T{aV$N7qq)| z`DNsdo-I-5GyNn>`Uyja@;r$d{a&;i*~-nvt)*O?GB`sN1KCm;!ltkKFdK#4;if54GO3}m@8IG?G$Xc zTumxSz3}L6TWhz7#Dx7QAF~~hQu1ARBi?XVE#=|ix+e7wwiv>ueF2l3g`$kn74>m# zF4H)_*2XhJ<-5}Oz4Z*WE*XXr$O7Hk9`YKmx@S1>|Zpm83ut8L?OL<9g9|br1kTM%HEs2?t`)0fGDkD76cd(~7-FIw!Pikydv^5|f zJzJJS7-w_VYg6^?-@BcEeHoeb_uw#uyeG;OLHG-=qNZRG-F*TP!gWnT>iZ8u)nQb_ zZN+$ausM-$o0Nfk{~%7DdfE-DAS>C!cvbO?o>!W*L%^0|-i@0C$Vf^jE{hCUugTm; z*`B@D<#L8JFyk6RZRrpKZ%(L7ql+q<7-->a=}KwRz*~#mqr_^Bf$B!rB<4PE%ocP= zM5~vOUu2?w_CB2&Y=1u{x#yi`EzOeIyrf&QuT&C|57yeuADs9qCdiBtMTl>JDY_Po~h4510rpHC9n~;eXm=vl? ztmia8&LgWU=CGrmJd1%-G24b~*!R)ZRrEw&LIj9TQDKA62lL83>5IpXys7cqub9#0I*d9CCsIA8c zTS#rTOe!CeGmL#7QsC+(jTuw~JF4^AtbUQ{DWB1h`Z?$PoGtx4Gkq&Q1AC0y65|9d ziL>@%{>oTi1(T;S*3p@A=1P^JWoYG5F+JG$ATrQWRz2WXgP=}+dZ{#QwG^pI)atdR zZ*mpx1EjNfE`caHq47m}V{1k=5ia&7r!r{4h(}AmMq~p9aMD@`EYff)9r``6!Bkqk zy$qX8g4@-zO|?cCSAL=!t-)UcLJ)T0*-#0uAjSB!Ur!syBHj8+LnyBn#n7rKy$16U zg4T>?3SWlv?P;{330-yM2sbWkd$L_*uJ&lz24(}X{PXu}WMaHt%)QY$+7*DJqi?3Y ziZQh}Uaq)mn;kjx-WA{*eVmkTx{xAkW5xF?JejENUcHWPZO*!aJl12g{!nK9EFV>V z@~|BQVyoJJk%U@cBVZf1Mn?cjTXZ9m*ALG7tKj-z=CBh}!>6#fVD#QJwUBt2*AK8C zq`Juv(A5GStz|fR$tWWnI)P$Sxo8ISDi?`9EybY0Na#Yi<*Yz=-+D< z>4w%OPb5rQko6O*iJ^y;WVrO~G!Lg!6BZCVPCA@XL>t_+0jM3Toup1iwxwYbO=aum zm0^=@*{}z3T$CD#KGHnsSn!&RV+$_1A&u7<+-ot$Ko4X#PsOa^#Omip)3XwJv-8km}n6dL>S|xpWlW)h+b$l zlCYvspEO8FQ3+Cx2m4gaFh{CIyXLbic(wFv;>2u|nQ8LWhL4U$37KTQ$uy=L_ui-- z((hWV>iEQb^$js}5opnsLB?ne1D^+zzL`!!M=2bx-{BT1 zwu7=jSHIm$m6Aq=H{Q^Qc-Ym87P*yu=A~326nl5!Q){wGlAWURvmn_|H-;WYs(u$5 z|Gj|Bt!>pn0_8>Q#rR@;yJ6aM0IU6Q#oEn!iT9h-VCREhFY-yGW?O$%$qK~0x$p)r z7T?4m8_)`djzzttwTo7)3_ir!a>7Fo*@G0kI<+GAB8H-2$Oz;%YAPdx{Yg{yu9&E| z^;HeE-bAT%5NxDy&Ay02^^Cm=Pp4|ZK3~_4CQ3<=y!wDk&-TjgJB``K#geD@{}{st zdv5G*Vcea8d>PCqNgY((R2r8W&+1q}RY!8MOc)}_$>q6w(+R>fp#ToZ>#wE&;BpMdomCIvB+ooKZXeG&N(-ai=APN|JcnFa4i+~tg_ z&I~Q86OV^OoJ8swoxXAh)ADy!XO>xbSa5S(Aw?8a#GKF{N{uEWfcu@$J-yvG-=!q~s=V!L?8sjs2OM znXP5DaQ16*?N4ENJ4bp@J508cdFU9e5AQ2*>ajB4g3D^qz^^{gcXVv`USu^q>&|Qu zh&i5b76T8Zz6k5ts7_KBxmu&?VrVIHbwF)oo7vXojQ#YX5^Yqt_q&>v=*wHqR*mdw z#!;a*I>fqmTT^_ue=ARbL3YYA&mzh(f3R;Y0HQv5s&X8d9sfuzwwxz`MJN1Ku%r<` zzj#lcpaN~Y(RY6APlNcw`If2N54=ujL6$IG2yc4F2%7C~&a=Pa*VWv|Y+WPXxkMe5 z)fL*=ylI=jmgW#OELAZdh!=ZpF7E)?%5?zxMg~YcxXdPgXnWmFH{43RgctD6CcfzYQOtp*+f&E;L3kr00`niBzIKJIEA}F^S_R zEd-az8k_MLT8k$)e0gDCS7We`PwSFCn4^qxN8@43Xj$K-?9~Jh^F{4WQ+AnX4f6Hi z`QnK;F7s>vP(ZK0z;-vEv`}T3p0{ISuR$?d(WTZ%pQjk35tC7yScBB3;~P&yD4b^K ze%Lt}<3avBxM#J9=bWy!PctS7jj_dLw4Cl3D3@gC7X4gLEI*ko&nxvxwKf0%AOJ~3 zK~z+K!fpR7h#l>N`Jo$5hR&thL9VkG{5sQ4Fef17O{HmLG41z1VERyj3@n)MLa@u9e&sTv|NRSQs@So5bcq*v92&_ho)H&4LO(QjIm%;F&!OPdd>^3w?O(@XRnML@L?_5kc55S(BFi4 zby`}7@Afy|tv&HRK4o1uK3?n!Uee7^XLK}u*m3sQ$TB3}Z0%GM{qqCYBv%kpOoVsz z2C7W4_4HCGmC#cGv;EchdTJbNi zb#pyE|Bd12T9==B*3WKT6*sl-#0B}8P17wp+j}(1Ic8yXWN7uE`r;j5nI9J!w2_U% zeUkCU%=lma*Z-|Y0u?96+>Rbpa1Y|EGDkC%)?R%ud%)7(b{GEYpZyi~-01aUuZ4JX ze@x*&`=|dU;=+~ttTJ1j<4Z6d-23U~M}cUhURWSoP-{)Wu7n+I59FI+6LblWM607n zhF4>>y@6ivM(qo0Km2$9{GYQ;$;jRwg|+|bO8(RT_`m272W=s-f7{6A80J-H*9 zWrQnsDyD3Kt5{E`{|-x@TM+AaoIlFr?{hHUO!>k+gI5-@3z^pX1~2~GzxrqRljskV zwdlrDA;tL5|C4`;+3fXiJnW^UKByQGM$Luo*7x3PQ!#O0$RjL@fAsJFqwcSZe%6db z{v%ivFZ*pKB$*4^}?mE+UXbf^TuC>RL|U^0@sVGZ>Tkwv2%y|;Y$d`IC+uhIqWy$AMJTQ8Hu7vJ`NME2$r7poNK44F?ixey|40G3f7KAi{smO zB`T2>tP$upYsUT7epBxjH@FFL2qU6S=DREAPKG91Tf8fgoiC5~cx?gu8(X{j+dHUh z!u_x;8Nhp==p@z72Nh#%A-@#sTZ>nG!t(~z#K%D1$~|sg)snhdFCNX-&hCO?q&U;E zuhK2(Yp_?euHiHFbe(+l8SDsRC1uUvr;PGoEZ7pJ!OxaK!nx-<{?lMntkJP`!xkaZ#rMTgMBwlb1?o3=m858w_hf>m9*#18o4Q zZbycYl~~-^_<-t)Dd(e=tAEW$M1yCgS@O2~a75gQbs#}S`*y;E5n!sAD^Z>Dwmp%% ztGR@*oioepZC1qWtK0`AH}myDtm5*`whmU%h!$0g!EB6@a8s&q8Tu_cfZ%!9R$L<7 zTX<>57+P+^KFw{#zLPNr^Md^b)9PmNcGh@vrE$w*)QhFXC5P!b2dFd8_iyZeN@V7_ zna}zqL3LnLy7}4FlNDNpmKKZ+TaxzmC{7wATPaP3`MX-cyDf0LW&SiLtjlN z72mMFFWP%ko99%&%)ywTp6ovt*D%DDXDu$Xg9_YeIJmMik$r=IA#)+(=M!HIS#{w> zam#4%><}!yanreo0oSCjZ#@-rajxNQgXc4C&1M^vPM`$L0tp?mgt9}E1MJ|#kVb7Dx^3Xi%`Xuz?Y!+34<}RE2b6h z-g8TTbJgI{VAdeCw}%AitMlbsxUtdIS*5x55lPeWIgvPq&S*=;rd^cM!CH7RH-r~Y zY&<5|!pm7SFGoi|Uy74HoCaBJgb#VKc+hB=l#?A9`k}I$2iu2AiL2 zxgd6(f%ss~BHxV_)M`Prim}6)+Fqrq)BM~p<|ee^lU|#&(P07JW2dYeB#~>N-}>)7 z#j@f>@($%gixg?Ymvt}$A4x35-SJu6-`dA+WAvs+-dq^BWSiGi8D3a{PN&o{hgb`{ z4SgB8gTk;A-s;JLGb9;BL=u*rVT2>n%B~!6KO4!3j0aC=Wm}=~>PQ=+w`J8I#tnS< z#gaEnq zl`EfHo;GRieV=R64gwms9wBK?h83boe1&T?(c+2V!;NK%)JAuA&3o^TrSp##28i=F zfBP?*ju9PRHQ78zeEj3@e}_K<9Ab5#>lhsyQ#uJ-_yhKGSWw!qsT_qq1HT|w$MLnL zes`Yd7Or#0WIfF5Vn4!lEmqA|`d6^k_#gk~Pn~(R2U+j-n_rH;lVAVgckl%Jys_S8 z%!V;Bq?AQW_F731JFx77xp%+W z{`99mfoUJ&ZRBe=T#Vo^{_&5DFt!>h(F_YK?kDh?h&48GRkpHzbe)Q0=Ow}DsK<}- z!LDzxthxUhTu;aDgcr6psV{;zxthg=cC+wKmd@O_1pyb=8sJKkKc ziO68>Y_BnciuVb=Z&(~(`s2g_#U)%_5d#c2MVI5sa<7ucsvS}f| z`RyOh8dveEj!@Ply*dZng}pav!Z4aFY%kD0n0hr-HrZX-$Hvyct|Z@bu-Hd=RmINc zzH1q)zHz-icoxigvzh0O*+2$M=Qn@&eZR45b-Ko7@UF(ntW%jPxyyO!W^H5I?q9MM zJ~sJumDUN**F+sm2O7q@-i&Nb?FWM$9ZvRnFvYtvRRmUsyRvGZ1%>k4-~S%3Zb-R0 zt|g>ZL6(r}z|&DLR@_fAaL|opkMVXzv$CEB>2^j{^H$%He7t^Ot*_K>wr5!}ZzX0& zN7^nzUY)vB97k-is`>l!_Z*h0pTuS9umSlF@%q#-1uCx|3k?IA>?c8Xch!5HO{X6D zQ}Y*B7M91X=EZt%K3@IL&)$5fvPU1N+6}?FBRgbid{C9ATkM?ks${q^q|ImQeK2hg z#`l8>(;G=s((6yQps(4Ua_N}7vO=HPIKy`b8z@RydvdazY2Jcrxw)&!$3}40i)kDeK33E5GB~|5G}J}-J8n>f;MNzg*7@G zNYgPlZrRLwx3?&wRnr!YDkK>;yHZxm=div)O=#+d_X@OS+2_}6usNsjVyH`Cr; z3ELW$dMaiMh&!Xmah`hf8n31_kHz|A?dEOh9V3F z2}52Gwl#WJ`PK3>1#SznQIP@^n( zJqq60?PJ5H*{iu4Mq3Cs50k;lY?awB_LraOE{1;^uf7A~KhZSVyIIVM=g=_hLY|wn zX2ffDwoZD#93-p-Fy4%v%N-Nt$>hUmz2fQ^I%rk=+;3!lbR(n=8W_hTEt7xsr@w9x zlt!au)`iz*XYm(*_%&B24D^TTjIDHh?&OnafltV{;~zoY-on{{w2kIrQX*ZYc=MV+ zuy*0|;mMQzy}S7l3Yo2FQWpR6Z~m5;g0JcvpIja0O7b86<_}Cu;yD#FyZhCThgcKS z&TW70cC@zVM|u2aVB92Ec_SsID`cAC=DpR5#H$H>`8@rD?o9zxn=$n-|MkD@5HT%O zo(4&{unGS1$KSJTcidw1G)1t(hw7V=TS)6*uE}b`=30>6f^6Hc zWa4%c@6Y|u`QXdN&1R?^s^KqJmn}FJyperBWv<)Fz!d3&S$9wu?K6L#=F68JKaYTP z-lQ(YY$NXMcgOje2=D5Hxowd9jppn*rY5!?A@LN+F7>AcCREckT*>pL0VQusE*rCd3Y@$e2}`aC2XCTeQTxIaoFy-xp;B2 z7~iv1^MGUd4ln+MEHon3dYvZ+B-?faC0BH~m2|3FS&ML~O(u;+IoKX05$l8L>ZsAV zJW_pytQ+?DzB1Hxqt|GeR(*zbS`TB*84^TxdYfIq>Mc-~QkKkl=xoxVOr4->?A(~a z{hW$s-wU#r-DFLtS%|XJleSTS1>K1d*3uJ9`0;!d*ds zUW`jyVgIt=&ulC%~=bY-O~tL3~i6p5IgxpKm=;qVj4{<5Vs9uLh4`MyMH>Y6`1LAh(O!nP#)~xep3kBJ@O=flU-o%@{HgA&A zm1#SkN zFFHi2mH2RECydeDQi*T3~ zoy~`;)e8BiQ#K?T_&Ty!Qe5`pe*O)e=-wN{D+b}t*43jbF&GbHDZ3h`nLJE+v9u=< zJnhwT8$De9v}?#GNUj&{`u$((=V`T5Py?|G*+CwR3bBZos6Cu#DOSDD{r28Wh00B+ z@FG}akk7jfNh)j&EN|qxdLEd~4C>IHuDn-|cTtf(nCs+X1~BSuZ2Dlfd$Vxs=oI&2 zt&O{oYjDkAuO?~ack6(H9P%&DQ=1`uFvS~QK(*RiymOV*+u^AMT0&h-0xmHqVM`*J z)EG^8-i1^AnT_m;%r~ANPz^EI&u&YEHi%){V&Xg)FX=^uU+rcT8>qE7HzSWuvS-3o zg3b$8GJQ}_9pvF>d`dBP6Hch&DtIi|sb~uBN4>OnS7{aEmJWm{YjjT*j}%|V2P^(9 zDp%vRTmz1<^D4<(?-_Rg-Y?`kH5iGSeXpZ<~o^@&tT5Y4yC+3ETW5g zCgnGSfiZa3;$_Z8k$D`V*;l!ZW~7@PL^d57TQkwMN$J}0$3Omc@2+JqJ;@yi@HLa) z|N0Ne^$p!0ZPT5dBI4?#c12sZxI}oDaEUY!&D(OUHhMpqMP;^cos*MPpmP!duWPho zYieKd((h`I;;;XwKT%tFMe)rxd-a0Fb@97@{2x)VJ8#p9d>o(6ox*|{#ht~+{KEbG zzs=q+IS2D1C#>8!%1&!z-N`tjl=96LgGc(QRZq2A-n_M;+UOd0rT7_CL7Mg9`q{dh zf!f&;b+~=VX6mGJvHZoQZR%QCcqr=5w_Lochw$mnD~fw6tQ$SJ<;~_Ikn2MBnO6=u zp#{}q1)(+bCD>fV)A{QE!H>U2XY?4N3azVWvC(~5|1gth7h@>vHm;9gZ|g(fA0_rP zU@T^h)(F(YhYwZ>YVC>10FB+0xGd}hdP$w%%nP3WwIZzo`t7fO^L=%g&%#vrS{siG z<{ODGi1i0so;Rj_RazM74-GQ zvg%218R1lZ^B2G4%5HultZxKq2WhQfRic{2qn)TB){~lqyNcKR75DnTo4ua`++6u0 zMjQvI5xZ02MkFhWOe06|+Jl>onUdeu83p#u9G+Y&JNEh)tIHPPV1?bC# zq}ON3B5)>8o6a_jNO0#{EUq|A&!N0BSl-=;M(@O<0+)@9N$n>6scFBBXyNeSY<@zp zxrya%qsYRpPMoa@ysjp)MGv?$!7TcH=fZOv*Ow+&L}kw(tN(v;^^Ukftc#Zqc4*s> z)giQPu&z`}tALWT`!#UsU9~p+kVM}wW#TO^UQ zuWx>)P_U(Asl}*FhBO1}%j+NT?00GiwVeK9#lntI(%h23GTc4-=T=K4VAI5r@PBV@-k&tAJ|g=UNQ42(h&K&+M=uRxwGI{OAb17QNYZZ?rJ3EHkG+Q?t!9Jp32|wJ>_U)?*YZb4L zf55)~4d`{odyBC@h_R_N=Z;d!PW6u@%ZM3##EXYcdCt2In0Iy)r-koqK~8iM-Dd_7 z(%T_U)S!PKc%JZeJqMI(-uTA|%8X~hMN-3gGMIW5gLnc;wLm(SwSIp0- zJ;_1_B*qk>=`4u4a>R8oxlC#zvuw011jCL>fAi|@yFkGO34~r*TZv^JbD_s zy{d`I%P=1-Hg2%@M6OPqh$Z+A;*$OW&e2_YHHszJXeBAV4I@t0kYCu?{LO#=N5tXl z(?0XChZ!$Q7Qgw&f1sjyo{z=Z_&f}XM+~b@B4&6eA=^OPR*z*MHhbsY&MR^Z>Q1iL zU_B2q^zhXeRHJ6@>pYEi@{Hhr_~YN=PXQaB%@(*LNgn?2>%SyN9r|?JdG?dc>kIMx z+or@-fjnq^z*uM5aux#(5aNkOh?fT+@xhZDIiU$=$ z$3}0*=47*b@Ea3eJzd^Q@!Z4|G(QnDUEx*6(RBA4qGM(n!e#S9byH9B+kf&q-aAkR z*c)5(yT7%vpGLbjlR@gDQCFP>R8`0v)LvktgQFz+356Gvhd@V>@4_8c_L`NE*qyCViUj|_qxx%*I*8a4_2TW$J($Tp zl#LTq&|=J9$L-zAdu*`QW|X#1WOn6yE7(2`O%Zk^Ljzs|Rw5^|qz#GDR*fnsZ-4Sg z_Tzn3sv%>YHQw%+X_XE+rMC&cz_SNq&r^5`y*#wu(pHxpM z_IX>VBe}sGt8*~35Ous@vvCn(DD_U}7iZr+#11jg8}efAhc&ICvAd;%E1QAYD*7{d zsXF=ZJuR@$Xi4d5z%_ng=iiaXCTFrS`yg4zhA~b`+rz}!(fW!|_z-7B^g(>X7{xAa zi11a^orGl5=YEvg7V#NCWI^Fo7KdKca%nR)g12N*_?iD-VC@_}xtpE+wHlYGyBI zTz9`IL2(_ zczQJQHL~Hjb|Wz{Rnk5c-PS2nSGO31$hqQQkqaFj%RiD5wNdbwOv09 z*4^vlE!y=rFGk#~%dwQEEqjL`NJi5@ro*mwe-gmxV5`p^Hic9%{0qDOOz}EUjWWZg!;l9{+;6wPfg;_ng*L@--PhOxFFh&o}k;8uaSNSAj+57A6NS4XX~t|sL|z%`hu zY!ybniEwlpdp!(q@hiK!9MNhXqp8DJ$pO9=Vh5^~4-9XyfDXKZ9o}4_>@M$*fBh%S zgB8UD?%Nq3Z(=Dw{_giJd#hk=VT_{g*>(j4r&#Iemk0J_S0iFVyA!M-ht;%E?Khza zaMbbjG(V@t2SXO?38o8QpZ*Nu!N2XB%S_IUW9-_?JQ45Ayi~*ZBXadbgfix9mFW>3tmDIoB>bzJLHuV#ju+ ze5iw~Vuc$}4zhtnLgM%F2lxX~q(~q|h?9^EM#hIKVw$R7to(O$9e6TP3tW}8a>awqp4tLjM-EODXg@_sJqu=F!JMr-8K8} zjcv{xkWH(rQ6N&8qZXz~amK@8^rE{tjUJ0^lM19H1*k{FlWjL})Qaj>dfw7PoqdX;MjvpSI5<6~jQd0-cQJ=!Kh zx%wpci|kjuBapB0Upa-jgrbe8`SGdND6LaY7Q0AfCNcm3AOJ~3K~y6+^5{p>sC>2U zay=LEEb&&U!_eyL8NH#{5ttiTHJ$l+`D$7v4|$U^X*h1mD9Z=ZmF>wG75Nz1uv^gi zK3$5PmIXZ6QPfAjkkTFPMcFOVwvw9o`dFA3kM6AH z%-MLYGv3ueDQ$KSXV6ft>UbZ6>;ZR@y>@18r`KHq8=YoRj~^`x@i;ZzLz0{geb>%Y z=Ig|@(RC9snDJ(JJwFqp&uSSqtBj9k^}QR3Ce?$kQk<)=_d94ZaCsy8EY2t!`Zo}Z zKKdblXklx{C~IFU3d)trK36Vw(jQXOCxrf~}CvL&NCuF$N6YD^e?AnLqja3O>r5=TVM z>!T>d%1yM3Mtw^rla!h|n8Q2^vs0j1eVlQqHZ%g#%M^4L!04UqP77g0qE|(OcL*Z| z9bR|KuHYS(7f4IILU?iRn0N8rwO?G_x%Z~`&g-t%d2(bUOT0NfmBzqX^wz)Xdo;yU zD=iUu7FnmC=tFN_Eyke-3Y)}epk>E(k@7g3(1QL%d>>3@P5i<(qfgB0XJ8~(Gz@_bxq^NPwo8o} zpGIL3^`Nxd1)j*LlHAb;*o*8BER4=|CU74N_%bekIO3K3Hwp{1>~kN$x%QanWjU%> zJ?pWwiRuZ`Q4b}#OS2s1!(6n=3I%jMVEZx99aS04O^k^~wP>`QwYX`lsQ9fJ^lS&O zvPvdtjTS+MeU*#SD*RT=%v#v}S-fn^WMn(?Q|*{%n?c3^F-8w!X+6+Zk$ZHRV0$z<`eyz#1}0htjG=`JBJ(WFjdRf@k$9hlX=T)w zR&II=<`{%8R0o!ILO4gJThM1K>mov%12-$|Za`}Tc0#YBgx)I<{yia#R`Os~@Dbs!nNIyhcrd)~mb5st9#^Fq-4pOBZZle$hw8U0-xQNs-F zD=Ks39>}MfU@UWHDtZNOQg@?JSPt_d)fh9ecTv>#UZd+r5kycu`M0 zh+fIVCQttB|K=ap2QfGCImoV96sYWX{{C+tK4~lKSsJRFWYSYuQeR%zMBar7S2mdP zmgG4C+ZTfuTl6&QE%ac{iwhg|!S7>jtjHd2RqgoS{j-0{PO1097OV%6gQ?E%{QbX6 z_D|$qv@Wbe1N3{-N9W#Oip`mZZY^U;1MZ+r`1!x~i?w+@8nLXZZ$j%SYDtcQHuTxa z`%R9sFum#|^>o{FQW(YSsu(zc{FndLKgq{)^3C%}xbb@3{Mn!Wg#G#d? z#;T(A+HQ;O1#ha(@o@~Ruv_DS5|)L65nx_b64e{Xrj3hMIuczUv>wnVp2D1`Avnr> zfu2{YRC((5eG>PHn9#IlzGNc<@|iTN7vxMuW)+?0`6lKvbUw;3Jg96`57xHw4{|YP z97yZnwquOYI?CgG85QGD>)Ux zNN=oko+ELah`fvP*BZ8?reX-T6FLlv4DESp3X?LuFzD^r-?Umgyl*TnraECa(!U}1 zqBmvdL5*7-?c3joG&~L2HNVde{tm_vww2SPeHyHLmEsX{ieMAf%`)iYBJB%E0WOA> z=eL5B&d>gpe~iMUGlX5+%H6-&H@zK+Nh0;G;U_ z!yN5oRwW6a6195#%8Dz+ zGYi7-cyF_1y!msPkzNDqcqq?9>NW*I^@V@zbrX<(S> z;mcbpedKAyEz4ENyO7w@!1vj83cKCB7K`>EPPV#zQkpj`D3N=VYlueCKLXnGQ9i{P z+{f*0?(}Gkn6z%#u5Qc7f+AESZp8}FL^G==iMw8*-O26M{V0ttg4}_$V9TshE`=_2 zlxqauCL?!ol~%7-GYP_Ax8R!wYgae9x5jLZo*^%cc4P;i8p|p;O|FlG_D`7CM8YTPfj879cL!z)nBGu(Y zPqsOIUJ!4jPfV5W)xSv#wA_4bDcxC*T7>E`?HrI-DqrK7b$QnlNP^i~)k%*ad{hI* zsC-YKjZUy=TwZcPZ?ME^*W)y4oc6XkOW5|(29aGHBdMr>THq(QR0~ttbo$!3M$MfS z+OC@C)*Z2;FrXy+K#q zvpN+!$SkNtwoU9hNkXbgLsk^eoM3_6d%0(}1 zR8K!VqiPqYAePKl=5RCP@iQ0Z263)@6s1@z$-}rV)ZdU3L+MF<=Iu0_sA3|_XkUYs z9JT0!Ae)+W@ho-zBfoKs$6XtqFh=c|^p6Qmqqn4KvQTCgH>r1FDYX7X_6fg<)5il@ zRLexa5ca`SE29N1q!uYc>KkFQQTlzeNAlx8{6mb6?p6HHb|ZeVee;9=@P`#Hb72sa z?Wpd4HTiM$Dx5a6$wF6Nwx*;Ibq+B1sm&!rJo#=d6ofWxYC}j3_D+` zGx9YioG$b_7D{%I+7uCG3IquZX|-< zA7~nKUDYlwK}$JebR+Vn=~b6#TkKx**zf$t4`^mJ#gR9XSIzn#CGOwe80j^i_oB|J zmHAfYRb^Ha?st|%wH=MBIGJNtffF^s*iy6*2s8wGQ70uUs={bwH{u;+184BP?|!%H zX{Hy)!ZzNd#XfjzIbl>b2C&u28wJK@ZRxOgW;$6Cwu$zvyYJ6}_)DFXO4AKmp!TW|bjM!fB z)ocviY_n5?66~y;=P0+0wUe(uv-D`4ei%~X zjjeZ$iWgW4*Nnp`D$~Yj!uDeE(~|XuXuEPXRIRu6P7`OXTBIpKZlR7gLz>_=nBB=Y zME{1SFUDDz(u9wMqQs`P$&PoWV55r9B!x>mDZ-A$_36_w&6Go_fNAyO-XZkysJnPf zTx+OMEG?sH@i|k@V|F&COxh^^QrE)geEfx+vgwSk7tV4feYA8%VP!4_vq2le=#5AU zJSE9&%4&^vJ&_tZ6KTwAl1q@&W{VhYTqO`wbtw@+msU9IHn=0{R_yrda~rTWy*)r) zr1fIWTv`T#NJdl)!p~GhcUFXUG;$kl1h2QyyOsAa6w4X~uBZq|o!(I)e@YIK=C$Ky z12NEQFZOqhE-g-u{+;MBZra%~mCnK=>%Z4J4P$3PYFFOO-ms`+@|uBd=u+(;U4mu% z+?kX63&b=e4&rc?16R^myFd%ssxv1$^}xND0G_>Sy63DbhzosQHK53g6e)s<)Q;IlCypE>F0|R1G7wEx zuT74wKdrZv1gX}IPM(*o6o5(!AWSyp*^=eLoXY5pZARCIWM!P+4MuyyYo9*Gsv*oJ zWttsNGBU=l_FFiq%@{V!8*%3*Hp%+sD?^uiyF$i2}3Wq7czu5 zo9E-g?-Mf^&$`Q8gUoW8ltA3*ql95n*q*egg*j0cidYq4rM~&Kzx6|sOI?S$)GYM1xanELNK+)s{i)F zO#ChA40Z@V_*>s$OTEfn8WK{pV-4Qv^ffTO8NIWu4BU?ad;b&$Au708T}MP&D?qDN zI0<|~%rZypdm(MsNw*7xo2yO%H(@>#`wJtU6UoK*fBgq+^8%xJkfSVyeU7s*^>j@} zwew{aVeR*uF)!Sl-kp8767}04*G(c-@sn?4m*uh|%u<@{Rd;HUB(^dy`KnW+$q3<2 zm|CXrGJJfUyVe*qBgpWtHPHvXUSrWFj8UZoP3xlGMc6|b`asQSU0D)*x-McRLj!3~ z;`{)rq_eIGog4RGLG%I3c|0azyQ%=~M1^M{ zcl9}ben%k~ISVreqwhLiKSp#`ABKLsBt^3|{WHe{7(f44>T{$AFjQs>wBu$d2PCk5ZGRqyd_d%YgB61ey$m)T5-(@q@>aMf_ zaqoI`xiBW!Ul{h7W$-Y?{kZKZZYVg{<09O@{`yF;T@FkZUhA&Kn}$d|w5BFHN7V~T zqdz7>mA|UaGrSQZc0m$$nb;#5kDNVDL~DwuhEDsi2(Vi73rtD{bbI4^G-ju|I?qAMk8bO}N5HqXq`9z+Qoj>NoQHCfh(IYM3!0-&PV%H0E^nmyKNm$)K5F=@>`NIBgew z%mVIK!+4Q*LQg~l?)7H2j+r4+{QQ=|9wqvBgf<@)`Hqh2bw<#~%Q-t9M>g`tV;+{N z)=;F!0Y7(mv{~Is9}f7#@e1-hhz{>N$gfo@)qM%evm7tYt4(1jL!Py}wQ5JWW-C*O z3d$taYqw1~0jeStw^1@dr(>Srn|F9Y_(PD`NOZD&A?<;4SCgB2WoGuG4Y>E46;zNb zsu6=Nv?+Z4k_>gW?5YNI%@w>QdkzETKw4S-cHQ=Ed0wG zYom6#vt#bJAq2N8eJ1;h6GLffbQ3&xb!TRgIUJ`A#eK1EFE@Uk1~;$A@Y*-36T?Xf zY*lfpH6`~ZEs*&{bs;uTooFl2gl5o3(UV)Ne$mI(PU=F)p7c=G8S!2^$!W!O{Wq|O za*Dz;lOFZ8EqLn@;;T2PF5;R__lxxu1{d*Os0vGKhV3r(&CEuqF-D>Ix)fJDQ)$lv z2XujTw(C1Lm&}?BvdeMbz99P>qE)6G+x+oQ{tVVle{}ZVY&vR=xbVHd^F3q>{gHfr z1=lEkxw^1T_%y2vvoS!Ups1FN4za1QKUs_X9IH)}y$gmKtugsPwK%u8Dx*q4^~K(u zAOFdZE5xUp5JT_5md$95U;T~mK?+lXcVv~&ZXxy1kFzq{o#%gns!2+9?H&&h)nJ1 z<;49!p2AOCu;frgg2?k)cR%$m$1*Rf)t;cmZMUBZT09O?MNb1+!%S;VEcNp4y%uKc zv!I=4Va85|QtbB#UXeW8U=V&$$X;gKHu=?G`X&0KbGs3TT+u_xrI^9H9PNB4y#L(Magcq%bcNU7`KO>TU{lFBlh* zUJr;~GSJ5z^Li@w#mMIb->6R_US&AR0($+*uYSAQL?W?!(|XrY5C=tf=_UP=)El>w(NO zK;ZNX9O_6=87EDLNGJ1vRpsQv(+gerDG48F1lk(AS5bZDU}Q~KM4i?rlF&~sND=y@ zU{hU^FBWJ7uLvG0tSn=K?vAuC5VbHfJ9)nOa_=e=b+4Se*Ox-R$=YcZ?j1BKFQWw5 z?p(7n+Mey`Vz4Zk4g8Km8+y5l+^I(3*6@{;*J+KO8{btJdxzG-bWnZcyV9wdjW)_f z*?eH?Jg>nrVQB5LTZ68x7N!>8)3d&~I~8|BD9~&kGj@}}UiJ9Nw2IR9#Jx~B5ilRh z`clns8H?^6%g=1N=ut#pqYN4fHHMs3LKfM%WK;|zZ?q=efYXr?wDAC{NIrE}kbWv*bzy&7Fe13ad8A?$Zb73H z`We|zkcA(LnbVQI(M!4ajk%E9YOM7L{H<`NIyDpv(gk12xV&V_sJU|r+$+jV;en3Y z9+k4!WrMEus--8{Iy0SZ<)FWwNjW9 zas~uxkgY;LgrN_C-S_QvhF-~E6<(<%4*3Z z30FoYDT=oGMKY|M>sl{jor!sQ47UX%;T_IHI=dHDw?!lM3u+I%Z`>>P>N!!{=ry?4 z;>SP!Q_?p*6#XXap`!3wn;-n(yJgeL23zQ}CMyw&_5vZScX0J6CQ=)O-!y5gk`zny zKYwO=W0Z2aw-QfKVdc6_-rl1;a{L~V69zz~ZL_N?u4whMRM#RCs zR5!VrgF35Cu80b`ebCzobksLfwVX8)Uj5}(FU~5y626%6l#AVsu*$K7en#yR{sGO$ zYR9yN%*K0{L+RVU^fzgA^cncw&?e`;=EuEKbm2anRIuG>!^=^=f@g=@grObJs%u_Z zui%zKNS2lF(P_JK^YqQVTP@7p>2hOtX@F!$yR$t|@BGbQ{RPHo>|Ms>rvBBStrn%{ zY1Hv3y)rmvr^oX`VpXn6g8kmeyzp3zfHk8ey1WVR=tGDvtL~U_)9#CGFP2?ArxLcv zmb5XEbncaW?>pZ)DOF{rk^^EdvU4KWuwGFqT8eZRzR>G|`lg*6SO2CHRuAXvQtq{A ztzf%j6ha4uY)}r&4!T)c0({zFu(5gsms`BU_Mm$w+T!t;cr>oonH`W$(^2frsQdPgg@>{u3K0o- z46qyPRixmrjf@8wPLE{wGE(baq$@I&cpLe+AUEwEAa86nuA#WSaV--J;jA6SqH03O z;G&_IRz%{eKK3rf&!4SK9N`XjqvNU&U?_Vh?V%8X#byj)?J~@S8GoSfoJd- z16837(Dj6QGy9`h1FbVJczw2#h4Mq@%v0o>m4@<+I^(16oZ^r#g4nyJ*lq1UW|6HAGk$9p)z*8e!WZvDiES&^q93UBL>LgmPSj1T{gFs zd0vloow$87wzA}Aw9dVv=Edx<#R)2PMQRdQZX^emNi(Z4b99<7tW~gKy%*U#;S1Rn z2X;T^;FM~?xL2Wp{6(&Y>tb2y$6^3=+_3xd0fWWDbw5}Z^% zDPxi20uNdi)S^F>h|2Ew)>u~F*R;CsNjmgdyRpM^W6nuyopA|me-ttbe%j!= z;Pv_Jj2{~3vF1f&J&Gz5RY!Vc3CsDhSXE$`7~6x|btEdjv8=K?1Y)nVFrCa*I${QQ z23H7vo%n7lt~Zj`5qN`kIc5W~jjD3n0vS~Sk_~+X_PH8hJPpDLs%^{-nik60Ovq6S z=>2vssRtfe<22D^ZOZF;5^pIB?H$Z8o1lwDiP(5!=qj;43kxm^8{@i_)s1V^!W^lj zR3w+CXgb@H2s^Lx&LUB(5wWGvab{HN0+DMYp70Z-*m8mDs?0+hrfm_gzfG<=W zM^6J@j7Hi`c;mKxAhgiCqw5oL-8`OaDd?`>{EmtG z`noVxCKk?&2G3x>;3t3flX6l=3D(t}qolm~!H>RIpx05d&VC1vF6_+8pJeUE<`r?) zth-K#p{*lk>>PA?vwa{G?CK$#dx5t?eyb!m!Fa*yo2i|9C0A?w;gA2YW`LPh61$6F zciW5K{K0Rrfnk;1j}+QYtP8C<_gz;ZB9K#+7$J2J4J}&V%iz(FxRDqrH@7wBXt1kI zueZYGRavURDRH=5`N^OC3CrHl8o8idjr}qho9})1M|cF`i~hKZFp|Q)lkqe4PzwwC zsH}X`R;Se{tv2Ta*>x=6vP#SKWVVgH9%TE%=%0vvL+i}p+<#dl5SPGru{@6hx5W4J zHjVTulnt-lvlvYE8wv^X5aCQdL}aTE*AvY$;7ZmJZwZ$KZ(#1m9;@QJ0F^*$zbL^A z@*=Zd>iQK0{YJF2qWa2qS`~&q0)HjN%1y5T03ZNKL_t)kjbHwiUoKopP*T%j>TA!E zSEeHj_UquZ-A_f{u2<-;3K>mDrDGpCnPu!447qu?&Pc1OX`J;DC#HxUJA?iXc8AC8 z*eZEsoAE2({&rP6D{NDm7$Jr*d1o+9aH-gBx4;@StyYT|o#u%~c^fN*yvmS$7G_@M zIlwFN`3_}v1z%@jwknY@p}Uc-y3vOV-jiSa#dao8g5v|CHIEWMN z05w8+ZKvyTHK}3m3zrvdbo}*&9ZF;KQr0l z$3OJ4m7Tb7SP92F67@1tHxNV_1{r~cYt_}7qc0DX8~VRvA1)na);6600mk>2efM~%&o*YaDorrF*nw= z$Risj&O6FzYy!OtcLegq%iz+5wT0dk+ndmGZ#Ah>s+v;m3g~4p&ci0Nj1|Q`+xT*< z3u+Ztxj)=E?_Dz0Z14*Fs_vt-g)9 z$zW*m`cfsie%$=F6BB1IFG($ndKbrJobIQMI`iL>k}}T2ND`GKx1rit88jBDh37W6 zL!j8@)Nvu_Cae}_#6ofqy1rslmYwR7EbTL7;Ib-I)`}3(GRbDduF`~}i)t_5~= z&caOYz3ZiaF8}WZ#Lco7wmY9=qqk!mQ}12DIXxjTYtU{;sSr*#zF4@iG!Q#V!@UVz?1bBHSPNGvO*6A3s;Ouu zYg>(S?_D9jV+L28O{;H%CGQYMPgXW&EPP#rzN>}hwF-Ty#{K0+#Mv77a+ZTP!`|ht z*DU$Sj`;qudqyVx!?Km`gcd;}GmuPtJL5TcoAXe|#^91h*m?XkV|k-_!s+zZ){etz z^5_5R|HR%xAIb8gyCvM7q)tR`u+Hc=Z|{txK>H4tD$AVT`=5Rn9T0kx?*>l?dGPwz zU-(ac`?pzXRTo2zCf%dFgdz-U__csRTY;bGaQ22q9eWQ6zId^ZR_i=F1>Jvhj`GI; zV=$ZW_ElIKHjg%VJNz&I^Z$tP27j^O9~1Z{O*7MKagUeja!}T z4)SWeUvK{2-~9)$oOm>*G~QO-rDPx)WELJ>8!#WJmw(}wqLKXkFZ?nODZ~x!jkZa? zZ=y|RbMC*aCOjA5eHM2!_U*`k9(BblpF$ny{&B2_)9d-32La+$Jm3YkuRpl+RKa^= zYRL%|S1{g7XbE!QTdISMMT<%3;;;VPzfX)~m^iqbWk$BEUhg*OW3jxlC8=3XB3jWa z68?k#;vbe+zqIgz(ur-1-jLR4*^m|mN8P7*;Pj_QKcT%Hm{t~>1N6$+T)-X5&tuY;)zTN0V><(|`2aNK96T{sp+s{V^P!k23VSpA2_NSvx7c z@qME*ktyVD#5|Ka>kQqPE4`Nn?5*G|y-Pt_eU~)k$xNvoS<3xSHW~%S{fGbge+JUo zIAa@JrBOmM+r*}FiSpjTztej)U1;D^2ykfu{X)aR6VpM{V2g5P;7n5Q@>Q%Gm(Fa? z`kahLeNpbfvcWL+3Z#_|Zo4z|bW3@hX1=4h=SgP!c?7kPgEy(j?t43*reIBYQkflR zFl4iK<&7Ej@@%a^ZZxlAKi;6v`a!e-)GX|XIV}7nOBm3<oHAdm?)ipBfrY`bE2L!Y{5?JE6}(uY%$FS&Jc$i+d-}R>+?VVYiL?1<~mkc|p6r z#m0CnAs!EiM5b0n`K5e9xC0)emq^|P^uZ$%=}z`1nup>yFQ!!a%(vtO4Y^C3z6()4 zX0Sget=B_O?_kM*;n?j}77O?q$hD7Bly$v1<4cd@O8R)A=XuI=VgoB+NF6_2I&L?c zL661l3NB}cT>`Lsxs;4Ic~^!yteR_EL}kRs1M-DZV-u^R zGf^FdOdK7zx(8Q~74~+d<;hM}JD4;<)@EzrYI11hgQ5`G?(Xc>qoMdV_c}xbw7k73fDzCk*L`U;Ymrlf+yc;=6 zXs6Ysd`CbVNWLM8R8eh%RZ3u4jl34ga4*3a$L=x;C)J9pqLm~>*s&2&w#lil0}WyI zqU6c)Y6IRu3?a8vrXJxPfqGS@XsWkpJ?)sDW`P2)O9?p?p%*rZQdzstzdC~RWWqNB7Z({n6jd@M}G zS_S2-(torVv~;Xh+fnGIuk)7psAe&%du?Rtw^H_AmqVT=5v^8dvhqx!y|VI}Tz;x# zbRjaxRnsvYf_>TOtcbH(vQkNswd%8L8SK?zmJKrU=;|L5Cdc@3CUd=1f%+S0O=41$ z@MLJmY{7VN#b#-P$fH#zO^Z(3W#ak9Rzb1Sh*oH)LaIa#L`q){D+7`GGF9 z8rMn13A87F`p^F*wv3@ttXh?#bBOWnZ-2MQ5$M4_`+J%-O1QBVrzr#Q5b5zu3S4#S~M1$9>Qu; zDcKOxtQKZ(tnDSRQ>5igXHp5&q_|MoJ9i|HSHL%ozwz^bqr~MXEifaAE{JrtlV7lNv%AxzBfQw}L4Q=fg)XoU)}$TsFjelpL}|;AS>r{#ai{RejkkfcU9bLwV@`7( zj|c9?)N0C@eGmrUJWjsb6`xcM-!?)7u_!aHSMFqnvT{{qpjAbRN7V0Em1k4-X$7|2 zG&+&aMP1Kaj25*6E(_*LcyxRx^P#0)Sj~jFN(Lc2rgCg)H(e*v8nHJ1$gg+IHa6yU z-_G!wgT}dTEI}}&PhQ)2w1#`qn{kt5OeA{Y7RRdeYI;FDTS-FmdSJIPzSS7fxkqn}x`bvltR*1ORz$mK*k z9?Ph2k;H#+n(?x~74PCHump*uxOWV>=Z^YxE zWz6uD8pU0m+~tZN4vU+L#;JuxP zo@SC}>;~ck&4Gp!vwGH(Aa_lRGAo$AZzE^YR^w%h9`%;6UEbP=GK<74R3u&z6pJ#b z^bOvnLT*u4jmo79@-pNh<=om8;m*jiHl9Jn-t}4HHx?5uNT=iKfRJyo%L=#@y(Pp0(&t}1qG%w2p5 z;BBzBI^#PU|LNcTd!qCNZYBxC?gr1|Pk-~z#9A^z{$p%$s`icD3R=5KAHzwNyPsEl zsV4iZ;BJt(Ko8BxZMa>u+WIxK;~vCR@I$;Jm@D~@fAb$`yCHvu3psQSz<>6ezrbx% z<4uIX6A#P`YBa{yeAZl}#Y*u@y*2oGQnxagHiH<0T1dBJjoedS(-EvvBygPlB@CkC zegLp zuG&IOHtX287xpG_8#`H-4AHa@b$LHTcG}oXR2gZeh38yEF1D+#Luip^soKM5wm5X) z6O%Dh!P8?#)1PG$+3Ec&K`^RQ`N7%^MsY8QtKny1VuQ4a(a3`jZdGiP?k>V8%d;?b zV~|s7=S@k{WQ~dO_7wXr?)#?F@RAan`~iE{K`0I(%_^w3n_3!8wQW2suI0>OT!QCZ^h#Z6YAGz`p+6}B1` zdh*fXN@MlHrm7p|BKBG}DmT?!LMs}Un@DF%10ihT>qcbGZg z3(HI2PD29G6ztXeO)bEKwqdfk_9t*mJ|o?3U0g?s5IYFlsxjv=0SI*|1WSi_jQc6_ zOJ~Ic8KTl9gr{O>8SEC?=grVSxw^34Pm*^^R2vt)YY#0zYJv5$Fr|2@Qs#2Sq$9|J zvsexMg%&2kZu9#TBwk8k1v=2Z9%y~h^WwEP<2;$misq)dX>RB@kqbXB{3MBH+zHc8 z0npAQI_5CZPB@FcP>fe=~R5McO%@m7t9v)rGgmdCoX1s)VtAAv%?^WZS35P2%@>< zNh_hmR4TMEW*PSk);Qtk0M6m3;-XO6XzoQ!v4&c|iJeprqyq~2HdgN{@mr9&+0nR5 z5wM+`Y!accwa4`=W|c-jUH$I9llt0;`Os1vO_u5!8Vhe$Z6cg}9wPFH4}$zQnO()Z zT7%Y%*Ph>D{FRN0MX{(D*vD!uaa{M<)%Vt+7q z!+kSPoU&z-@!(vnTB`kqG%;1hIsjizcj%nPzlT8jMj_)m2$1}|PeS0UI~rBr*!4#B z;A_BZz?e>05KSE7h7!}(8lGZVLXb;)l`D#Dj<-pzh9_(jAINb937%pN`F}E%e*f$L z`q$VRSWmolc5Yb3iibb{i@y}py%&8suX=b3XI+;LP6c}}q6Tjc=`IVzLBSY}JpJ*< zlt^C&@o27>Kk91ENM;&s*O?81hdk+j{h$5@+gp`toXZWK;AJoV>|gvjwVXbTxwqz; zF5xW|R1-GV(g-(R>xBaGm+BZMlwkJ@GI@Amsq*_II3wAj~ja};$03Qt7KZkmSKIeeM+4GyDO7AJ>vG*zqFkuqJW(Yq_qkQVnn>CCV*Bq<=%z>q z@^h75iRVcoSDXv@2+@aXlQEbqzLfK7#kCsSB#GJ;=XDYIaC$9vUDVS4F|34nZs#d` ze3?{;Ls>`1HjYifhEA|wo0q=`lKoL4 zK5wDMvnRH$?;V^9!>h4faIW6;v}#S(jVkETwD@YV#-N9;jkBq_n69Sg@I{N8$>yq{ zY!JSOTDRAENnkS4OqeaOpE2DHz~TS8reR`dc$6mbwilbD|x(Ot0aP@pM?qI z`_`_wPWh)wZ@JIIC8;r@n4~%cwe=!eI}br6?p1F4WJ+n)e)daZwAUFefinqymy2(n zysxI$mG^Viq{E7zJ?8ZOeWaA8%pTpSp2RfTsV!)QI^~_~Bbm2EP>W*JqF)lxw;`0` zzyIt11$IgW*x!kxcG(}BKmD^m(d)PyZb945Y)Mw*-HnY?`J7U;Ah5BM?#?S0y&9`2 zs@0cKUz@n|9`eFJojhWyL$Hx!=yU6n@PGd2zaeI_uB}4gt8u>#zP(=j<~RQgM&RoW ze33|ORVh$ytf039yXm%=DHZpisY;xSxCU?aVn?HtRK#(toPJ)tui6X)vq7@y!-&=K zR{WR$__sXFLpOdGETaK)@+ZIfr(D+%wmgmO8|s}lCu<1$YZ*M=X-iH^<6_4P%EcXR z$Ltq*1i1P=gc&XNk^0JFr@bb$`N4i0`orWWa|S-CNuPhyvrcd5fD^tK+uis=^bbYZXg3)}Ht=XvzG#s|>lBK1O^qt8u?|W^CPh^u*>3KJ}nAgVfAW zUy{O1Z1q=36PfyTTVzyA+@PbqfZ z&xow(=cGJF(`R)!sSy`#PiE7$%_>+f(X9Cvxg1%&sy|s`T!0iH<_tctcxT4sa&W&-PakSGT0aMl+r#%l^|dDb_$fMT47tD$p*jWoxY3Sh!A*-0UrHcOjs#!x{GL{S?kH%?h8I{4lOz_$h zz}Ayn*v88zl{dRItL=94Sm@xlhqgnd=T*zV^J0hEm>!FdnRL_eJa%Yrn0k7L9X?gS z(+i#wf7J#vU$WzQfj3qJ{XEQa2fGy+I(w9LvR)X2tR!$fG5a{`#wN>$7h|2VIE{%^jJL6r~w`&h?Oap&k7}NT%F6zPJfcP zi_0aS@3xMb%jstH(N4S{HjCbL@B5$s_rHZG#qUhUkE|d*fz?o?4gFFt`m(IqL73sdDDi_ z+)sI?`H~VzRyT9@H<|f&7(_IUH)mEK1E->Ri{2%{?7F#*gt~U+^J6``2~5DJQuLMiS}VwRkOu8*Hn#V5Nw@ zO^#WS4#B%&S$v5M$2oTVooMs&ls6Am?#(e;$v zLoLIa&@Siqe(w)hwfTE@qdkTV#sAu+@zE=$h6N;z3#*5xhA49V;#trM)<7;GOvaJp zH=kC#=N8f@7p;os?}D>diTBjv=wkG1*}ed0clhH!_&pKhh5{T}h5I5xW-*umRdmk*vskhyTubVjdATwHS1LZYkR%|CY9aMtODr0=$RpjIoXH*u4s8`aMEq^e6r03^h z=nUg^y>up@mDDtvFLvq|d`+;fS2tZnq%d`fvsC_x+$`&iS2BBW*~O|jVt9#}jLzuJ zHZ4rmZLh=A6kMtZ4WCTCp0S;1`U8wm+BOk3 zHiKNM)_RsM29AuHQ~)?vQzB{?>q@Iu1Ues2wGkWCR2C`*ZA_nK4dR0b6)n)PyZ=g3ddHbB|D8Z^z+t*N-81duDvXV z@5$-|;-O4?=VWv3#*CuP9g zr@{~_u;$hu+@-YMc5{Cu>naAFr!Rpu?>xI`2|xGZYbN21 z*!vtN8;=$5vB|tCn^?i{&dWEK8+!_84RJi0z`h02#Tc!4ewK=HSHL_YvA8gw?9`iP zw9d;M{|Hr=aJDb5nXG2tKa192*FKW2!XE*1tGR9jUE{7I85L|F)S4JwR6^Ul?WTMG za-J64WlXovWk=O7T=>uR*ng1==BG%51FfOkX4lP^Tzsp+b%|2UuyY7%#9ZKY?t6o( zcka1axAFh{U;j7DHiJ)TCv>{lN&b1SyJ_Qs_wkq!VYGJyb`NqdMmZl=TxVjFU7hyyz_#|%VTbYLlFo*uY6XUB9;aH8?I3b8 zW&W+wK6W&GIe+!P{g32Fqg@N~jXj@}lz;fkfBSER>)|Fp{+52f^AZ1zJDlfE-mUnF zrp40qXMY;pwfSvIG$ub!W4SEDwS^$>bzm4>_v-4=Hu??g=fxN|Y01C)tN&SnmlDoq zhb|)6li&QCe?xmV-E}#VBk@Nf*j-Lb6Q9&JeZm?B(`jBzf`9M_f1ph2PRc{0xi&;F z@usd8!M!C&8)ZCw@s^F*Bm`4TQ$+3W2O`Y@bba~xFL3CxMPddE<4XkJVsO7HwCh9E z!fSrx87yWi@IrU@kFaGo|u|9#Dc$Abc6D;g^fBYS>M?Zez`uc~w%J@+# z9{yfel4(|8E{@c0@VolW1#qE|KU z+o>r0Ha%7P(TbQ!Vp>4!^q0m(Z*lRo;K%F6dt+sARZ|$D!Fy?sdG}j{i>@()u@8Mt zHQ&1~u0Q&sVf|T{IkYDpYhael?7V$3h@dx}V!zhVpK=twoqXT$G@=JK-n0jO3vDw> zU8HWDnul&P^5FTbI_=$vRQ2TR*LUo3?1#;s@BG2vzp=Uw!*r>jH-?^gHK^yej353E zA7%Uy#kU*&ZbPTngScttOotyyEN{$`tieDxSzq1t#=2yd+y2h*P0btsQiMBqE9OV= zJ3qdWrhQ$$7k~8jhXSPSz*}+A`EcXMNByL9HDCK2?62xl^>VC1SaPk-`kK5ir@tH9 zz+*Fps@GA;MX|eFrMR-CG<{~TfXh^QxmIJ{N@Q6MdVi?0?~J7HSLPX#{Q*?a2x(wcs8 zAJ}V?J-KTzYjL3udd9-`pbeQgS~Ye&cyDsbr>0?6OZb%1D57tn_Nt1p_4 zZsj0{?xaUH9@kyGnO?;`bRW)CbtHY@5nALvPB*&iDK*cZ9XZPDEY^NGD_mcu;rJtW z<5~lEy?*1_SUprzvd5ca+ll#G`ndVF;3oLV;j1|r#>}blSQWeJ4dv&49V;ATx|Dxw zsjJlXRN%ymw&fd*hRDIsS(ve@B_OPMC!Is%Gv0xZ1~wn*UDBz(=~Hw%i%u&CQ_tTP z%%0dc69ULJE(&YpGu5CqAv3JhoOt%8H6eCp6eE*;DZIU|5(TE5+m>+LmI@FZW(d?iNg1op8Pi#)eJQ-*&dQCWeVY0o4W3O5xVd=M=5pN>tz38x`VG%H+(bO; zrteRycE@6$BHhrva};|hc4b?0wY-#N^3_B-tD?FhS*<$D;?!yNMe6Cy9{6MGHd$9Z z$_wk4Jm=+jOTEfngpp;^!c-JvC`dvCtwW0j*CO^M|9tE086;E9Q#x%J?9Q6MrC&E6 z+j-04)rv3TC9u(9p#d?D>pV5cPD9)%*P`3g#Iz^a?xYt!hwLK5=>^X$-ufjNS*T!0 zZ{Wq+$|1bb_-GBDN$-Od23OLiv)h(q>h#mMP5O3rOYAv&?QZ0L^lLwhXmFhokxX>z zNBMAk70-l0@fy&l@eFz5vl=&(m7RfL!`6>Zr+!(7oCCVT##P^AN_DbLi2}VjB`jDW zcMMI38@wIMZE-Pp<>YF*;@lxENxMo#tLns>Sa&K^amXB4JS=3@jn@Ywi|CqP+B8;7 z>I#JbVnA(XIC(YfSk(3zH#teQr0-5#2_HqoBulR#BlI-c`^>*W3-e?(r~NXm=&hJr zwGMBM7LDqYJ#UPKmGk|RhTE1!q!qpfc!rl7jR6b#3T+Qn;6T66jgo+TpBs|nllTsoKq&Q(fG zG?pGv!`X+=75uUeBR?fs`3npFGYz7me^E=0?8#{ay4sRv9h>pJ5-O6|f!#B)x@kiT zbNEHZJPaTqxve_JBevw#S?i${%yB^kwTsQ7UDAj2&=YexJd2WylvtqeQYjFnsj_4os^Tc!k53Gv$1n<`+ zZ|QnrIjE-CV(d*DjkjogYYy|p=#3{5uA)t2pS$sHstyM)S~O-4YC2alJ_;(&qJN24 zGR_nwt;ll`;k~Q*x{ce5S4-|Cn1#Jk!E)Pd>-5@?jk-(@01G~at6GDnEu^=%%mts3 zIpOC{WT_RqrigQ{E3#&SvX&cz!H&sjcKBV=y2w!;3)=b=Ti z`voQJO_mNKK`~YXQ{{HwVgt!-zI2u7@?rYw#HEFaX^)v95QFM50r;C7wnr`_WOA~eacbyH2ZZ`tGKNA@Z<{P zqbF?@X`P-z619T_&!L0;)nsLpT1UmUBvjKNWZU~5v(5uZJ5bLR`aq*}Dzwx|I$Tc4 zr+%rDKKVe2>-favLZW+`;Zx*eFS*V)gW!YGZHM$r| zv$31TSXIgjdNg88Jux{w@|3Yc>Fr5{X;2?QhLYv8AWyjpHrQaz#XY)u`47@$wGy(Oy4Kfp8VkCXtQ43R)30X}j^* zBEN|o{X{~_c2Xa~8jFj@UaDcoDxP?RwTaEMiZ|ec&9&h+fn{ln<~X)C)uapDHEE_4%)`X$!fl@$p-XnKp+;iX zgd<4ZK)+00@omI7Pt2Jt-&8lEiZ&hkX6|CYDGd9*8mn)On@T6YRz{3TeiT`Y%tn}L zZ`f2+_Jd<-RqSwzRQakFUJ_Bk#a^4?ok~+kV`|R_oo8<>mi9vq%^S8GbNBld@YT2bul80dTvyD>tyK(i*c;PDL~Fa{Ehc@Spg$7c7*9Yazu zp^b?3(0jw8SWAJB-}>SXV>YF@;vmp>K|f5--65AT+9Y@9gC!}!A%6UN9cI;$Wc~WI z{&~-ds}^BG#@IZ2r5ps4?u}v6qI7#xdCZfR;@$WKxusJn)I3~ev^V2*UluOVJ=R4nYf{4 z3pb_MyNNAnZL(IQwXMV8+O*gQh6~=CUW3oijITG}z9nxMKl|d1x8n>|KGe7Ji#avB zY_ZQ(V+t~{wfBun`%lBbxAu@OV`($v70H)&v2#&1VGY_PoJC(7?;YFD@^2NVQfZLLf)ZB<&?EO%qLppQn(DY*SWjjwZ zn9A|`(NbTwu{DTKT6UAx?y=2Vy3VHjTCDzgm42+jd>-Y`th3Is-cQNWc9NITva@{B za2(w^n_b|^CR9B0QZHm7fs^ZmJ9jePjQQFp@uHE=o~{myH@u)N!#$a?*yF->Fru-2 z{}S!1q?J*=*pE8ZmBuo|Ph@N7#~*V~}#p_Nm<@w!sxZW@p$l77iGHcj6-UR^Y&={I4loTEJnwd5>R;^+efA{ z1=W=a_N3u_?BGl5Lx2iqnsblO$uYG7VOPT}laeHRO(BEWB~ zCM%5V-I=e49!dBGEOHs{lW2ZmE*dh=*yMfD_U2wn%ACQ10t~4q=6dNMwo})lS8npt z?6F~cY3opmW+|5TXdi8p7L8R?PfXiNqpwcn(FE?oVxEPm*P74H+CSs(Z+!c<=qM1} zYUmbiZH;>NVh;VV-8*d`S5g+)oxb!ck8b#31<(p=V6IcQA=BNvJ5h^RqBDCBp6#?) zw7U^gf#9{j(Ml$exQg+V8m86tBpbz^VoFUD@VB|@Eso-D^-;t%^@dauTCeiZe%7`O zd6(-z)V6y3wU=nhTMw#!d^@WJdpYA;5cjx+}~tix(Gm zFg&?U3YWI~8Ja?~OP-ySLp?cGqje5K+?WXjFm7i(p}kkTFk6xu*wSc(I(-pcjpo(y zwKXmpivNoop)pF1Ni1hHX`FXcCnyhTxGhF ztU>QZssGDsCtsSrlsiJVNTZ2#7fSl?E!57+Z(Jo#|GtasF}5Y{O^C)J^-eEz%AZR~ zF+0}Y*0HCE_syt5YR)5aODu9YwT(TKyBROjja;1Yhqb0Hj2FE-o+emDcJ8r=DVy<| zw=-ENl85J+{P6xp{b~(aGaITjMm#$|XZ@PeO$SXaQtGI_=3-Hi-Hi47G~-`EAm`Lmy%myMtuv`ty{gl=Ml07gYfKATG&(})MAH*4U z$EKG}7?^QsPii=?OuqIZVJS->hap1+d(&=l>^q%R52FTa7kO>2*;pnn>WE+u^}$9d zLmMGxW|-XRVTFAd`(E@Ku;frL3s`zYJF2 zY@5+s6O7VBr@I0*ckh_ld0qdq4nNO4{OTY7;=8WX>50y`V3Q0RWZy(c7EqONCp8;Z z6Y2sxD(ZJ*e+VB~bzXZbB>Xf40H~sKo|yMVTk40G1<~~s^zc*4n!Fy}Kt!E|xiwBw z<5Q<_3;i=rXJ)TQNJTF(TvKp@Jf*6r!gs+iC9KwhCQ6=r(W3E+$=mO|^ZMA_&3LRB z*=ZIuS4f35iLT(Y6o+w!{K|@I<5p}duFrRvcdQz{H`Of4_=wGW8{}Go_HKhqGv-*@ zW4=Nc5tT1x3nGXyxu-h+b%@eAU`KMDy71no9(}-E+Y7!q`&xKiuoi_9NqLMMwTu;Y z0>(*uHjA6agL%__xw&S(X{R#M=;I-0Ct7irW}Z|Bo4WoCfqj+J*e7uG{~L4SN+XAE zg(ALZ>&g>*HTtdOc(;q)f)$HaZ-OX{f>#G7m0gbXH2fXn6?#&t3CCL6lWqzhMJ|Ol zUVCa>G_?=Q3ihZI4iOl&wZ)vyn*}>WRPH;z!}r;c&C~=fuv46>{a~*BP3gT#OQZaF z)iIU&$ALPpDZYCJE{HO(y|}*I{QT46ZbIaat;OvaPYD7WUE`A$riEz-w0c4(dYOp4 z89=#)U!p3?)AVHU)&{i}lcL3dThM}BFWOteI_rLfU0h2eI!kP8ycQudN>^b<72~`a{s0ojZtDWBZ4}5Ur?&-9 zXEzx|mPx=+IdN0UzPor(9eAGgi^c8OIF#pvUq$7986&Zc>y0y;x|BeVh1WaD!W-mj zluxq8cUYFaLpQJ9MaNXJWP<=sJm7p8Ch6pXbQ-G`po=3tH9Tys~G{PnE~bGQyOy)NXP z--~e%p1tXIlkq`EH#spD*B-1oP1ta}YdC&kyx7DHZgawn&Y|XgG}b-ocH?sbMi4qP zv_Tz_MR(4aa5Cd&j7gLLU(p-A7al1#l{Na%sXUr$#Azm$Jb^o`>_T{Z;k9VJvyaK+ zb4U^JibMaLa-k<;>Pn<(z6w72}l{)gqaSoF9EN^miJ4&=oLyg6*O0N zvRmUd7ps}1rCYz5)#aeH5<}^3!D}JG0Zmrim!f51eE;UM^}|g+WZXTeu26@k7QUVP zTS{3~-=$&lF7jEL-{q#7(G#9s^!JNzAFs3D7N?^u84eR2x_1Ahu?f_bRm>0>!(!6t z>?TKgg+k6WV>B1ZE@9^8?Ucf1h5AmHuzieQFw=Wm~8H$FP>V zdw0Dq*A6c4+E*t6*nTwT74#b9)WL6)LdmqwUK%Tn#^LoZcD&QaqhL5mwnoSBOjb6` z2K`zvMV*sU$y9obbxg{G?&HMlwwjs--(K@OFX`9U>0X>FW}S=oI9HdMr^XP3z3_Nb zHnJt_3V^9pbM#Fe^?*AEksU#5{V|i|UQGA@?DRT}dt7*@p#J+x)b3 z+p|rDe19c0!5i8X7t;2*f^>*lx|?sNaZCiYk1d$MO)%4TeqWizUJH7ou}OoL#m6f8 zJ(%Anw-uWc#Enfi;{p28b*sB7$=!l7aV4#F*e}T#Oysya_1|)%H&hjkj%yniUnBi0z-d@yf=OC)=ff?k|nSR@#ThltI zrF2*|p1H|`L6W)c7fG;xzS8-W7EoN*8$OOCkQvn zI^^bAL0*tcWZPUxv(B6kv>T5kwhk@XH}NQtyliuM^07*?d2==!Tl!*bgSJx|=-0%L zD<~@I`>=fMJQ;TrnXR_;hFSCtb)CiXOj;kbQ1{&<*-?!5&g-@4P2;Z?hQ&i0((|Kjc$_N$JYJJd55H883ezEd4cXEdo7{* zyzy+A=6ZIF4Xv>sD0iN@xLaefSW|JmZ3jo#5NI({^iJ_K3tx5DoZS9A97sn~> zgP33N>!q|9n?#ixGT2K`#x@o;<#p;VJbA;3y=W$ee8&|%jL+nmkxTu|)_$p{S1H@0 z4vd%p01U-RL_t(pg`f)j>cZVHuKSB_M_5?AW2j}hKb&?KY`&Wb`+#~f=T3otrwE-WoxEWM@17K}q z*NYKDz5ZsJ8TTaC;=MH%ll2@`wP}vL8}PV*umkMpmoz#YTglb1?dQuh+2N$Wi20R% zO|k1q$~t2>wS&F8zSw=i?y8a)gbT{HcPK6Ioj21(N2Iir;1H@qzrVd76g%IgWgIrV zb3WY9M3NRLd|L_oi;7z<$(PgKp~Ct9+B=tB$&n%qf03DXoj%NTPcxvA;00J9@eFL) z^U`csAP`7{G@_-^h>@VLr^?RE2o{lcrCqKbU^R=j)asItop(n>Mn?R9m4pD}VARQ@ zbW9Rr>Jie>NYx{Ql!C+)Q@J#9d8KBDJIuq3<$%P%q?uDtp0Y6p&t0yf&?2EK!cb=N z;5kdNrJrhWgIp6#h@TXxL!}rqAt_UF_TTahm>f|!M0b!^sVzuBnvFRzMn9+4*(Zw- zDN%^IFb{s}A{9bvDFtiySN>>e-r7BX$Z-^r}W2 zgs18!HKm>*3Z)1|CK9Rni33&wDur77e1Dcgxu|ozlNy|&5iWr_R$?;bL#Bp?pQ?p2 zw2(%_kCHW@VS@RQVVs(j%bxr;2DD~sjl>uUgEOOmBb8`yPlXmI!k$Co0Z*gJ)z!OV zXsHcOGc!IusT!vMb8Ji(HIst#q8Ih#tgHb!4Lp6AI7M?NiwvV=L{8-3 zP=z`91~I5_Jdldzh(z_X=it&uf_pD=v%f=#h|ahoRf76SnkOFyYz)+klByC1 zo(*ZkjOAy<;j%`RiHr;npn0Zd&ru2?qjT~IH1RPDrcjJ1MhS^$1ZJ}1dNzNx7HuG9 z%IU=mzW@FWm$M@XE(>#sk_(HTU$*bG)f;HG zra)9rsi>wzd&XQYNO}OxP?RK|uB$VIl$grQGck{(4t_#YC?rqoBb#xm%A7`+o5Xa~ zJ)$|i%w&~;#>pU4g$IF4^4)aF%78n(RSVJ7dD2g*sd7A(qQF3fG*V(A)=U|U zC{9x&(J?@EPFQlYCBy;Lvr!`s)DS`<#)R0+EY6h~EfVWYO^yw3DN<);6eA77dlkmo zh#eGa3GT|lL3<@a%?`6zi}5Uq6Ln?n=n7jpM@>x8vFgLw?RA33wdSBi9UQ|pxGHCu zvGXG-xhnSr^TAo6^GvOga2iO-1GW)&4_Qnez9mit#5Bg*g}^PD5zH ziCf9OFij^yNItMJ`uVX`m#|^L>V?@_ih_Dta~(XyO=5ys8JoHO)*6g8hH7cJNf~L* zYKu^^xV9?BLkgTJjVrQ+H&zF*HH}=XAfqAYidN@l3aaj|s)L^d%H)fEDCqf-_~4tL zYMH?398ft^>OdTlC)`z9um|m^udGbXMMmeTZ@Bj~#FtWP^JUHG!^p3H^&9^B_kVCc zPge%P1>Lv>yC-Wbt&V``5>(cnI)>(-U%lq>^qyb->?gbkk4^mttj>h0&SS2IXeF0I zNDpLtLVdfARClA0jB=@jlsK#Mi1MV$GjR;~(sta{3UvsKr80#9xy&sJ+k-e#V;w7& zo#4rgQAW;}C(>Z#5_kyC^bqHnQhjnY2v$5YzFI&|f$8bODM7J_O_0J2VRYzki(I6V z2uQ}WI<-1BN6A4QIXafXLCr=;ADqkF21rGjqPl;RiZD~> zgp3(GpWxww&H-b_urWV$)#~_6OP8L%_>4Di z-to<=?@&BU(PKXP1tz?G`-XRK-!4=K+sW-4&@a?wVa#*pn^)iR>H2j2PuDAM){^Z7 z%gRW!@U8!lg!wO|(2wb|y)^uE{b;TqTua?LO$(*92Yg(0%65XA*p+2h?;rpUD%Ad4 z+)%wbG`RwT_W#q~mF^ElhtJslg#VBQ{Z7Q`>cl;Wvb9vMtPGn%WYckL^~+kXbZXQ# zri87fNmHLKUbO4Vig&u)5!aK~Nx0VGLna&ZKn~3fYf7(gx*=;@``WMVmQ^7yDqikY zKnI7}OgHIg?ppiW{Jyo);x6~?+5NK6h%dS_mw7QiVqTkPa=pKjWN}6M*e~6iU)?hs zactZb(Pq2C`g-=y+d{&+D-v&SO2YP zwA{B{ACK(yzD~QjZ?_zL-QVn}r27?Yn_{+~xr1U3CiA1~rsbjU%e38??AAlKIB&ao zPbmruTo8Bz5^yv9)i% zakCSWqcQ%-(DYiV?-O_0%F!6^`*&x|H|@7h^0lZi*>5xLW|MhSNk2RbX4Mh_V&**J z*0|QU{gF=9DAp~nRhg(DE$zae-+hhZ5P@Lb`(1}No8(^AUq5l_JzREs-&K=cJq%41 z+RfLYor-P07pFwSCO4CApy|}4OM|Nt^+t-Q_pc?Vb&Xoh6EDp5si<~yvMg+EWx2*# z+t_$Xt+O2LYGtkCCXJCp8tK7SFti!$EUML%lj{c~rZ>CirNUJ>+0xd{WO&!tE-qSA zwvt{t$=P`uHgn$a<B zGx6Tqx-knD*5GA9TNCM<6)y*)5w4PS{kCMk;karI>xG6L8w=N}nxyKC<3+OeM#c3z zv(;O9qxD4A!Q59Z(#&(~EL1sGp<=SJXKj@fTsM2jRjV(&?7hEqIdN-)ux_dje8{(b zu+A%MJFV5px294yTP?9}?4^@doz#`BhLAgZ)s4u$X(!hW&ZfR)L)#0>ew%r1??yqj z)tT1NcwGoGyFH+>Ri}$9pRF3+_>Omi>PUddfz;66?AsW}cef@t5^QVVZ>`UMCe@aO z*7fn8tuM9{es&-<>{g;3biCi#Ef&CjT(sYHn{7S}W&g3sb_C3}`+ei~Z@YHN!X3ZU zxZ01&u8(qXqO+ODPVqm9{2i38v$N&HU literal 0 HcmV?d00001 diff --git a/plugins/CrossoverEQ/fader_bg.png b/plugins/CrossoverEQ/fader_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..abe28110594016ba54bfbedbbbf0e4083256641b GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^3P7B~!3HFsZ#L=!Qk(@Ik;M!Q+`=Ht$S`Y;1W=H@ z#M9T6{T>gWn53Y_73rryA;}Wgh!W@g+}zZ>5(ej@)Wnk16ovB4k_-iRPv3y>Mm}+% zq7+XT$B>MBZ*Lj$GAQu49&B6iD1XOc(=dUHjT7z&Ux=~Z?)7V@iuK8NXJ+^wex+v^ m7cU6ZMI>18JG{p0*Iw>mJ7(n&=9lw8+B{wTT-G@yGywn+8#>?s literal 0 HcmV?d00001 diff --git a/plugins/CrossoverEQ/fader_empty.png b/plugins/CrossoverEQ/fader_empty.png new file mode 100644 index 0000000000000000000000000000000000000000..4a95f05aa4ccd260e734b6b792da3853129b606a GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^3P7B~!2~2TE-t+Zq&N#aB8wRqxP?KOkzv*x37{Z* ziKnkC`#l~$UM+)$rAksjA;}Wgh!W@g+}zZ>5(ej@)Wnk16ovB4k_-iRPv3y>Mm}+% zA_q?w$B>MBZ_gSEGB9wkD40I{?w`yh&d+th^VOv*hK&vi0vs$%xTqh}I+ceQcii4m R@Cj%ZgQu&X%Q~loCID9JGCcqQ literal 0 HcmV?d00001 diff --git a/plugins/CrossoverEQ/fader_knob2.png b/plugins/CrossoverEQ/fader_knob2.png new file mode 100644 index 0000000000000000000000000000000000000000..252b485ee8784472c5629cb49f36e94b43e31a04 GIT binary patch literal 783 zcmV+q1MvKbP)E=Z010qNS#tmY3ljhU3ljkVnw%H_000McNliru-V6>6DjHiJ>&yTE02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00MVOL_t(Y$HkR9P8>lHhQI2W zft7Z6tPtT!BwT?rZ~;r)0cWIKfE*uyjV#$InGaxDTmXrP4bTQASh0(jp{pG9bkAeg zscEUzkC~~zs{X%f;Dd+6&15pU9t;L&d7dAL2qJ*6xm@DCQWQl34XXgnIgVh|pci#qRRf@!_MR(? z#e$ukozwAne3ApW%pH_v*?@{5&TY&>d-S6>Rn%-9*lXupmK9G=PbF}aM`NSW2Op6v|uXN(*(ylSlrUCWU7p6PT7u$==`RmH=@1Ev}PGlz)7)sZ)Jg!{hH z2FOtLNxYjWFjlJ--Uo5#bvWdC&hzs#W`;ONCLs%DStebCSGAReT9HAO^*-Er?-6m# z=kvsUaM0M=Dw2&nny9LZ;c(cCw&A|5@^}WrEV+;>!_3IC3{_=!cQ=({(1%i0Ro4Lo z?(Xi^fThKKBSJ}$`kL>K5Ia>6MA@OhD~fS^eB7o0_V@Se`VT_f$N^nS3p%&%x1Hnz$%4wd3pJ5G#Z^2MNx`Ktztn{dlU#rqda4C zOSY(y*1h*0Rb@7t{kXloodEY8V#nk032+2#|A!yp{d7A0_0fN0{sIMGiQ&E)@hSiS N002ovPDHLkV1oZ)VzdAN literal 0 HcmV?d00001 diff --git a/src/gui/widgets/Fader.cpp b/src/gui/widgets/Fader.cpp index 1af7bb040..0f0bef69d 100644 --- a/src/gui/widgets/Fader.cpp +++ b/src/gui/widgets/Fader.cpp @@ -170,7 +170,7 @@ void Fader::mouseMoveEvent( QMouseEvent *mouseEvent ) { int dy = m_moveStartPoint - mouseEvent->globalY(); - float delta = dy * ( m_model->maxValue() - m_model->minValue() ) / (float) ( height() - ( *s_knob ).height() ); + float delta = dy * ( m_model->maxValue() - m_model->minValue() ) / (float) ( height() - ( *m_knob ).height() ); model()->setValue( m_startValue + delta ); @@ -186,7 +186,7 @@ void Fader::mousePressEvent( QMouseEvent* mouseEvent ) if( mouseEvent->button() == Qt::LeftButton && ! ( mouseEvent->modifiers() & Qt::ControlModifier ) ) { - if( mouseEvent->y() >= knobPosY() - ( *s_knob ).height() && mouseEvent->y() < knobPosY() ) + if( mouseEvent->y() >= knobPosY() - ( *m_knob ).height() && mouseEvent->y() < knobPosY() ) { updateTextFloat(); s_textFloat->show(); @@ -346,13 +346,16 @@ void Fader::paintEvent( QPaintEvent * ev) // background painter.drawPixmap( ev->rect(), *m_back, ev->rect() ); - // peak leds //float fRange = abs( m_fMaxPeak ) + abs( m_fMinPeak ); + int height = m_back->height(); + int width = m_back->width() / 2; + int center = m_back->width() - width; + int peak_L = calculateDisplayPeak( m_fPeakValue_L - m_fMinPeak ); int persistentPeak_L = qMax( 3, calculateDisplayPeak( m_persistentPeak_L - m_fMinPeak ) ); - painter.drawPixmap( QRect( 0, peak_L, 11, 116 - peak_L ), *m_leds, QRect( 0, peak_L, 11, 116 - peak_L ) ); + painter.drawPixmap( QRect( 0, peak_L, width, height - peak_L ), *m_leds, QRect( 0, peak_L, width, height - peak_L ) ); if( m_persistentPeak_L > 0.05 ) { @@ -363,7 +366,7 @@ void Fader::paintEvent( QPaintEvent * ev) int peak_R = calculateDisplayPeak( m_fPeakValue_R - m_fMinPeak ); int persistentPeak_R = qMax( 3, calculateDisplayPeak( m_persistentPeak_R - m_fMinPeak ) ); - painter.drawPixmap( QRect( 11, peak_R, 11, 116 - peak_R ), *m_leds, QRect( 11, peak_R, 11, 116 - peak_R ) ); + painter.drawPixmap( QRect( center, peak_R, width, height - peak_R ), *m_leds, QRect( center, peak_R, width, height - peak_R ) ); if( m_persistentPeak_R > 0.05 ) { @@ -373,7 +376,7 @@ void Fader::paintEvent( QPaintEvent * ev) } // knob - painter.drawPixmap( 0, knobPosY() - ( *m_knob ).height(), *s_knob ); + painter.drawPixmap( 0, knobPosY() - m_knob->height(), *m_knob ); } From f357bc7291a3e5e40dcb35a947d9c78b0b84de07 Mon Sep 17 00:00:00 2001 From: Dave French Date: Mon, 15 Dec 2014 15:54:05 +0000 Subject: [PATCH 40/51] Proposed fix for #1411 Crash on LB302 preset preview . --- plugins/lb302/lb302.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 2f02dffc3..dfc54e005 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -780,10 +780,12 @@ void lb302Synth::processNote( NotePlayHandle * _n ) void lb302Synth::play( sampleFrame * _working_buffer ) { + m_notesMutex.lock(); while( ! m_notes.isEmpty() ) { processNote( m_notes.takeFirst() ); }; + m_notesMutex.unlock(); const fpp_t frames = engine::mixer()->framesPerPeriod(); From f27ea7bc2b97b58b0165e03df7c28c10ab2296c9 Mon Sep 17 00:00:00 2001 From: Dave French Date: Mon, 15 Dec 2014 21:40:58 +0000 Subject: [PATCH 41/51] Proposed fix for #1432 LB302 preset preview audio cut-off --- plugins/lb302/lb302.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 2f02dffc3..e3e2628c6 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -789,7 +789,7 @@ void lb302Synth::play( sampleFrame * _working_buffer ) process( _working_buffer, frames ); instrumentTrack()->processAudioBuffer( _working_buffer, frames, NULL ); - release_frame = 0; +// release_frame = 0; //removed for issue # 1432 } From 8d3637e754f734235c2163860d6a482da6c5f96f Mon Sep 17 00:00:00 2001 From: Dave French Date: Mon, 15 Dec 2014 15:54:05 +0000 Subject: [PATCH 42/51] Proposed fix for #1411 Crash on LB302 preset preview . --- plugins/lb302/lb302.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 2f02dffc3..dfc54e005 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -780,10 +780,12 @@ void lb302Synth::processNote( NotePlayHandle * _n ) void lb302Synth::play( sampleFrame * _working_buffer ) { + m_notesMutex.lock(); while( ! m_notes.isEmpty() ) { processNote( m_notes.takeFirst() ); }; + m_notesMutex.unlock(); const fpp_t frames = engine::mixer()->framesPerPeriod(); From 8b2ce06da8c255b0ef8075717182f3aab3cee9a7 Mon Sep 17 00:00:00 2001 From: Dave French Date: Tue, 16 Dec 2014 16:41:08 +0000 Subject: [PATCH 43/51] Proposed fix for 1450 Mem leak in sample-track --- src/core/SampleBuffer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 2db7e26fa..6941c6da9 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -942,6 +942,7 @@ void SampleBuffer::visualize( QPainter & _p, const QRect & _dr, _p.drawPolyline( l, nb_frames / fpp ); _p.drawPolyline( r, nb_frames / fpp ); delete[] l; + delete[] r; } From 91063ab7d2eeaee29545fafdc989f666ab23642d Mon Sep 17 00:00:00 2001 From: falkTX Date: Tue, 16 Dec 2014 19:40:02 +0000 Subject: [PATCH 44/51] Update Carla plugin to latest API --- plugins/carlabase/carla.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp index ad3d92019..db14178a2 100644 --- a/plugins/carlabase/carla.cpp +++ b/plugins/carlabase/carla.cpp @@ -251,16 +251,16 @@ intptr_t CarlaInstrument::handleDispatcher(const NativeHostDispatcherOpcode opco switch (opcode) { - case HOST_OPCODE_NULL: + case NATIVE_HOST_OPCODE_NULL: break; - case HOST_OPCODE_UPDATE_PARAMETER: - case HOST_OPCODE_UPDATE_MIDI_PROGRAM: - case HOST_OPCODE_RELOAD_PARAMETERS: - case HOST_OPCODE_RELOAD_MIDI_PROGRAMS: - case HOST_OPCODE_RELOAD_ALL: + case NATIVE_HOST_OPCODE_UPDATE_PARAMETER: + case NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM: + case NATIVE_HOST_OPCODE_RELOAD_PARAMETERS: + case NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS: + case NATIVE_HOST_OPCODE_RELOAD_ALL: // nothing break; - case HOST_OPCODE_UI_UNAVAILABLE: + case NATIVE_HOST_OPCODE_UI_UNAVAILABLE: handleUiClosed(); break; } @@ -459,7 +459,7 @@ PluginView* CarlaInstrument::instantiateView(QWidget* parent) void CarlaInstrument::sampleRateChanged() { - fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, handleGetSampleRate()); + fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, handleGetSampleRate()); } // ------------------------------------------------------------------- From f2ab783db9443f3cba62867db29aa9fdcacf2a09 Mon Sep 17 00:00:00 2001 From: falkTX Date: Tue, 16 Dec 2014 19:40:31 +0000 Subject: [PATCH 45/51] Fix build when using old linux systems --- src/gui/PianoRoll.cpp | 5 +++++ src/gui/plugin_browser.cpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/gui/PianoRoll.cpp b/src/gui/PianoRoll.cpp index 2b454b381..266a1415a 100644 --- a/src/gui/PianoRoll.cpp +++ b/src/gui/PianoRoll.cpp @@ -70,6 +70,11 @@ #include "text_float.h" +#if QT_VERSION < 0x040800 +#define MiddleButton MidButton +#endif + + typedef AutomationPattern::timeMap timeMap; diff --git a/src/gui/plugin_browser.cpp b/src/gui/plugin_browser.cpp index 9827ce2e7..95ec8b42a 100644 --- a/src/gui/plugin_browser.cpp +++ b/src/gui/plugin_browser.cpp @@ -28,6 +28,8 @@ #include #include +#include // for std::sort + #include "plugin_browser.h" #include "embed.h" #include "debug.h" From f65ec076034f8ce6b96e39832655242e96f9404b Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Tue, 16 Dec 2014 15:32:20 -0500 Subject: [PATCH 46/51] Bump version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fbbd979a..e30f417b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ INCLUDE(FindPkgConfig) SET(VERSION_MAJOR "1") SET(VERSION_MINOR "0") -SET(VERSION_PATCH "99") +SET(VERSION_PATCH "100") #SET(VERSION_SUFFIX "") SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") IF(VERSION_SUFFIX) From da6fd6ef5cd72d98a29cd83cac9d0b2dcb69433a Mon Sep 17 00:00:00 2001 From: Vesa V Date: Tue, 16 Dec 2014 23:00:14 +0200 Subject: [PATCH 47/51] Update opl2instrument.cpp --- plugins/opl2/opl2instrument.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/opl2/opl2instrument.cpp b/plugins/opl2/opl2instrument.cpp index bb64c901b..88166ab39 100644 --- a/plugins/opl2/opl2instrument.cpp +++ b/plugins/opl2/opl2instrument.cpp @@ -497,7 +497,7 @@ void opl2instrument::loadPatch(unsigned char inst[14]) { void opl2instrument::tuneEqual(int center, float Hz) { float tmp; for(int n=0; n<128; ++n) { - tmp = Hz*pow( 2, ( n - center ) / 12.0 + pitchbend / 1200.0 ); + tmp = Hz*pow( 2.0, ( n - center ) * ( 1.0 / 12.0 ) + pitchbend * ( 1.0 / 1200.0 ) ); fnums[n] = Hz2fnum( tmp ); } } @@ -505,7 +505,7 @@ void opl2instrument::tuneEqual(int center, float Hz) { // Find suitable F number in lowest possible block int opl2instrument::Hz2fnum(float Hz) { for(int block=0; block<8; ++block) { - unsigned int fnum = Hz * pow(2, 20-block) / 49716; + unsigned int fnum = Hz * pow( 2.0, 20.0 - (double)block ) * ( 1.0 / 49716.0 ); if(fnum<1023) { return fnum + (block << 10); } From 347b5a121dc369757a32dbdd46e0bc6ea48985f8 Mon Sep 17 00:00:00 2001 From: Vesa V Date: Tue, 16 Dec 2014 23:02:00 +0200 Subject: [PATCH 48/51] Update papu_instrument.cpp --- plugins/papu/papu_instrument.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/papu/papu_instrument.cpp b/plugins/papu/papu_instrument.cpp index 0b45eacad..8a3d387c9 100644 --- a/plugins/papu/papu_instrument.cpp +++ b/plugins/papu/papu_instrument.cpp @@ -360,11 +360,11 @@ void papuInstrument::playNote( NotePlayHandle * _n, //PRNG Frequency = (1048576 Hz / (ratio + 1)) / 2 ^ (shiftclockfreq + 1) char sopt=0; char ropt=1; - float fopt = 524288.0 / ( ropt * pow( 2, sopt+1 ) ); + float fopt = 524288.0 / ( ropt * pow( 2.0, sopt + 1.0 ) ); float f; for ( char s=0; s<16; s++ ) for ( char r=0; r<8; r++ ) { - f = 524288.0 / ( r * pow( 2, s+1 ) ); + f = 524288.0 / ( r * pow( 2.0, s + 1.0 ) ); if( fabs( freq-fopt ) > fabs( freq-f ) ) { fopt = f; ropt = r; From d21f0a7114b8afccf2acb2f726b2e1df790b8ee5 Mon Sep 17 00:00:00 2001 From: Daniel Winzen Date: Mon, 15 Dec 2014 21:08:16 +0100 Subject: [PATCH 49/51] Remove RackView widget before deleting the ChannelView Fixes the following two errors I spotted using valgrind: When deleting a channel; ==936== Invalid read of size 8 ==936== at 0x56FA1D: FxMixerView::deleteChannel(int) (FxMixerView.cpp:374) ==936== by 0x60E9A79: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.6) ==936== by 0x5216BF1: QAction::triggered(bool) (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.6) ==936== by 0x52185C2: QAction::activate(QAction::ActionEvent) (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.6) ==936== Address 0x14d51b90 is 32 bytes inside a block of size 40 free'd ==936== at 0x4C2C2E0: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==936== by 0x56F9ED: FxMixerView::deleteChannel(int) (FxMixerView.cpp:370) ==936== by 0x60E9A79: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.6) ==936== by 0x5216BF1: QAction::triggered(bool) (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.6) When loading a new project after adding some channels: ==936== Invalid read of size 8 ==936== at 0x570785: FxMixerView::refreshDisplay() (FxMixerView.cpp:202) ==936== by 0x4B590E: Song::clearProject() (Song.cpp:740) ==936== by 0x4B7885: Song::createNewProject() (Song.cpp:817) ==936== by 0x60E9A79: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.6) ==936== Address 0x56a12ab0 is 32 bytes inside a block of size 40 free'd ==936== at 0x4C2C2E0: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==936== by 0x57075B: FxMixerView::refreshDisplay() (FxMixerView.cpp:201) ==936== by 0x4B590E: Song::clearProject() (Song.cpp:740) ==936== by 0x4B7885: Song::createNewProject() (Song.cpp:817) --- src/gui/FxMixerView.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 8948e8474..f750bbc76 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -194,11 +194,12 @@ void FxMixerView::refreshDisplay() for( int i = 1; iremoveWidget(m_fxChannelViews[i]->m_fxLine); + m_racksLayout->removeWidget( m_fxChannelViews[i]->m_rackView ); delete m_fxChannelViews[i]->m_fader; delete m_fxChannelViews[i]->m_muteBtn; delete m_fxChannelViews[i]->m_fxLine; + delete m_fxChannelViews[i]->m_rackView; delete m_fxChannelViews[i]; - m_racksLayout->removeWidget( m_fxChannelViews[i]->m_rackView ); } m_channelAreaWidget->adjustSize(); @@ -343,15 +344,14 @@ void FxMixerView::deleteChannel(int index) // delete the view chLayout->removeWidget(m_fxChannelViews[index]->m_fxLine); + m_racksLayout->removeWidget( m_fxChannelViews[index]->m_rackView ); delete m_fxChannelViews[index]->m_fader; delete m_fxChannelViews[index]->m_muteBtn; delete m_fxChannelViews[index]->m_fxLine; + delete m_fxChannelViews[index]->m_rackView; delete m_fxChannelViews[index]; m_channelAreaWidget->adjustSize(); - // delete the fx rack - m_racksLayout->removeWidget( m_fxChannelViews[index]->m_rackView ); - // make sure every channel knows what index it is for(int i=0; i Date: Tue, 16 Dec 2014 23:49:39 +0200 Subject: [PATCH 50/51] LR filter -> direct form 2 --- include/BasicFilters.h | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/include/BasicFilters.h b/include/BasicFilters.h index eda8d7b14..e6dfbcbe3 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -64,7 +64,6 @@ public: for( int i = 0; i < CHANNELS; ++i ) { m_z1[i] = m_z2[i] = m_z3[i] = m_z4[i] = 0.0f; - m_y1[i] = m_y2[i] = m_y3[i] = m_y4[i] = 0.0f; } } @@ -119,34 +118,16 @@ public: inline float update( float in, ch_cnt_t ch ) { - const double y = m_a0 * in + ( m_z1[ch] * m_a1 ) + ( m_z2[ch] * m_a2 ) + - ( m_z3[ch] * m_a1 ) + ( m_z4[ch] * m_a0 ) - - ( m_y1[ch] * m_b1 ) - ( m_y2[ch] * m_b2 ) - - ( m_y3[ch] * m_b3 ) - ( m_y4[ch] * m_b4 ); - - m_z4[ch] = m_z3[ch]; - m_z3[ch] = m_z2[ch]; - m_z2[ch] = m_z1[ch]; - m_z1[ch] = in; - - m_y4[ch] = m_y3[ch]; - m_y3[ch] = m_y2[ch]; - m_y2[ch] = m_y1[ch]; - m_y1[ch] = y; - - return y; - -// for some reason converting to direct form 2 doesn't seem to work for this filter -/* const double x = in - ( m_z1[ch] * m_b1 ) - ( m_z2[ch] * m_b2 ) - + const double x = in - ( m_z1[ch] * m_b1 ) - ( m_z2[ch] * m_b2 ) - ( m_z3[ch] * m_b3 ) - ( m_z4[ch] * m_b4 ); - + const double y = ( m_a0 * x ) + ( m_z1[ch] * m_a1 ) + ( m_z2[ch] * m_a2 ) + + ( m_z3[ch] * m_a1 ) + ( m_z4[ch] * m_a0 ); m_z4[ch] = m_z3[ch]; m_z3[ch] = m_z2[ch]; m_z2[ch] = m_z1[ch]; m_z1[ch] = x; - return ( m_a0 * x ) + ( m_z1[ch] * m_a1 ) + ( m_z2[ch] * m_a2 ) + - ( m_z3[ch] * m_a1 ) + ( m_z4[ch] * m_a0 );*/ + return y; } private: @@ -158,7 +139,6 @@ private: typedef double frame[CHANNELS]; frame m_z1, m_z2, m_z3, m_z4; - frame m_y1, m_y2, m_y3, m_y4; }; typedef LinkwitzRiley<2> StereoLinkwitzRiley; From 43ad2d52bd69044c512563ccdcee9a8fe766c313 Mon Sep 17 00:00:00 2001 From: Dave French Date: Wed, 17 Dec 2014 01:32:10 +0000 Subject: [PATCH 51/51] added EXPORT to Fader to allow use in plugins in windows builds --- include/Fader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Fader.h b/include/Fader.h index 9e8f034ea..3e808802a 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -57,7 +57,7 @@ class TextFloat; -class Fader : public QWidget, public FloatModelView +class EXPORT Fader : public QWidget, public FloatModelView { Q_OBJECT public: