Merge branch 'master' into ed_refac

Conflicts:
	include/AutomationEditor.h
	include/SongEditor.h
	plugins/delay/delaycontrols.cpp
	plugins/delay/delaycontrolsdialog.cpp
	src/gui/editors/AutomationEditor.cpp
	src/gui/editors/BBEditor.cpp
	src/gui/editors/PianoRoll.cpp
This commit is contained in:
Lukas W
2015-01-06 23:05:13 +01:00
124 changed files with 3809 additions and 694 deletions

1
.gitignore vendored
View File

@@ -7,3 +7,4 @@
/plugins/zynaddsubfx/zynaddsubfx/ExternalPrograms/Spliter/Makefile
/plugins/zynaddsubfx/zynaddsubfx/doc/Makefile
/plugins/zynaddsubfx/zynaddsubfx/doc/gen/Makefile
/data/locale/*.qm

View File

@@ -14,8 +14,8 @@ INCLUDE(CheckIncludeFiles)
INCLUDE(FindPkgConfig)
SET(VERSION_MAJOR "1")
SET(VERSION_MINOR "0")
SET(VERSION_PATCH "100")
SET(VERSION_MINOR "1")
SET(VERSION_PATCH "0")
#SET(VERSION_SUFFIX "")
SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
IF(VERSION_SUFFIX)
@@ -563,7 +563,7 @@ FOREACH(_item ${ts_targets})
ADD_DEPENDENCIES(update-locales "${_item}")
ENDFOREACH(_item ${ts_targets})
ADD_CUSTOM_TARGET(finalize-locales)
ADD_CUSTOM_TARGET(finalize-locales ALL)
FOREACH(_item ${qm_targets})
ADD_DEPENDENCIES(finalize-locales "${_item}")
ENDFOREACH(_item ${qm_targets})

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1 +0,0 @@
<<3C>d<18><EFBFBD>!<1C>`<60><><EFBFBD>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -382,7 +382,7 @@ Jeff Bai邮箱jeffbaichina@gmail.com</translation>
</message>
<message>
<source>Click here and the values from the clipboard will be pasted at the first visible measure.</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Automation Editor - no pattern</source>
@@ -682,19 +682,19 @@ Jeff Bai邮箱jeffbaichina@gmail.com</translation>
<name>DualFilterControls</name>
<message>
<source>Filter 1 enabled</source>
<translation> 1 </translation>
<translation> 1 </translation>
</message>
<message>
<source>Filter 1 type</source>
<translation> 1 </translation>
<translation> 1 </translation>
</message>
<message>
<source>Cutoff 1 frequency</source>
<translation> 1 </translation>
<translation> 1 </translation>
</message>
<message>
<source>Q/Resonance 1</source>
<translation type="unfinished"></translation>
<translation> 1 Q值</translation>
</message>
<message>
<source>Gain 1</source>
@@ -702,23 +702,23 @@ Jeff Bai邮箱jeffbaichina@gmail.com</translation>
</message>
<message>
<source>Mix</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Filter 2 enabled</source>
<translation> 2</translation>
<translation> 2 </translation>
</message>
<message>
<source>Filter 2 type</source>
<translation> 2 </translation>
<translation> 2 </translation>
</message>
<message>
<source>Cutoff 2 frequency</source>
<translation> 2 </translation>
<translation> 2 </translation>
</message>
<message>
<source>Q/Resonance 2</source>
<translation type="unfinished"></translation>
<translation> 2 Q值</translation>
</message>
<message>
<source>Gain 2</source>
@@ -754,31 +754,31 @@ Jeff Bai邮箱jeffbaichina@gmail.com</translation>
</message>
<message>
<source>2x LowPass</source>
<translation type="unfinished"></translation>
<translation>2 </translation>
</message>
<message>
<source>RC LowPass 12dB</source>
<translation type="unfinished"></translation>
<translation>RC (12dB)</translation>
</message>
<message>
<source>RC BandPass 12dB</source>
<translation type="unfinished"></translation>
<translation>RC (12dB)</translation>
</message>
<message>
<source>RC HighPass 12dB</source>
<translation type="unfinished"></translation>
<translation>RC (12dB)</translation>
</message>
<message>
<source>RC LowPass 24dB</source>
<translation type="unfinished"></translation>
<translation>RC (24dB)</translation>
</message>
<message>
<source>RC BandPass 24dB</source>
<translation type="unfinished"></translation>
<translation>RC (24dB)</translation>
</message>
<message>
<source>RC HighPass 24dB</source>
<translation type="unfinished"></translation>
<translation>RC (24dB)</translation>
</message>
<message>
<source>Vocal Formant Filter</source>
@@ -849,7 +849,7 @@ Jeff Bai邮箱jeffbaichina@gmail.com</translation>
</message>
<message>
<source>Wet Level:</source>
<translation type="unfinished">湿</translation>
<translation></translation>
</message>
<message>
<source>The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output.</source>
@@ -865,7 +865,7 @@ Jeff Bai邮箱jeffbaichina@gmail.com</translation>
</message>
<message>
<source>The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects.</source>
<translation type="unfinished"></translation>
<translation>CPU占用率但是可能导致延迟或混响产生撕裂</translation>
</message>
<message>
<source>GATE</source>
@@ -877,11 +877,11 @@ Jeff Bai邮箱jeffbaichina@gmail.com</translation>
</message>
<message>
<source>The Gate knob controls the signal level that is considered to be &apos;silence&apos; while deciding when to stop processing signals.</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Controls</source>
<translation></translation>
<translation></translation>
</message>
<message>
<source>Effect plugins function as a chained series of effects where the signal will be processed from top to bottom.
@@ -924,7 +924,7 @@ Right clicking will bring up a context menu where you can change the order in wh
</message>
<message>
<source>Attack</source>
<translation></translation>
<translation></translation>
</message>
<message>
<source>Hold</source>
@@ -940,7 +940,7 @@ Right clicking will bring up a context menu where you can change the order in wh
</message>
<message>
<source>Release</source>
<translation></translation>
<translation></translation>
</message>
<message>
<source>Modulation</source>
@@ -952,7 +952,7 @@ Right clicking will bring up a context menu where you can change the order in wh
</message>
<message>
<source>LFO Attack</source>
<translation>LFO attack</translation>
<translation>LFO </translation>
</message>
<message>
<source>LFO speed</source>
@@ -968,11 +968,11 @@ Right clicking will bring up a context menu where you can change the order in wh
</message>
<message>
<source>Freq x 100</source>
<translation type="unfinished"></translation>
<translation> x 100</translation>
</message>
<message>
<source>Modulate Env-Amount</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
</context>
<context>
@@ -983,11 +983,11 @@ Right clicking will bring up a context menu where you can change the order in wh
</message>
<message>
<source>Predelay:</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope.</source>
<translation type="unfinished"></translation>
<translation>使</translation>
</message>
<message>
<source>ATT</source>
@@ -995,15 +995,15 @@ Right clicking will bring up a context menu where you can change the order in wh
</message>
<message>
<source>Attack:</source>
<translation type="unfinished"></translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings.</source>
<translation type="unfinished">(ADSR Attack)</translation>
<translation>使</translation>
</message>
<message>
<source>HOLD</source>
<translation>HOLD</translation>
<translation></translation>
</message>
<message>
<source>Hold:</source>
@@ -1011,43 +1011,43 @@ Right clicking will bring up a context menu where you can change the order in wh
</message>
<message>
<source>Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level.</source>
<translation type="unfinished"></translation>
<translation>使</translation>
</message>
<message>
<source>DEC</source>
<translation>DEC</translation>
<translation></translation>
</message>
<message>
<source>Decay:</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos.</source>
<translation type="unfinished">(ADSR Decay)</translation>
<translation>使</translation>
</message>
<message>
<source>SUST</source>
<translation>SUST</translation>
<translation></translation>
</message>
<message>
<source>Sustain:</source>
<translation type="unfinished"></translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero.</source>
<translation type="unfinished">(ADSR Sustain)</translation>
<translation>使</translation>
</message>
<message>
<source>REL</source>
<translation type="unfinished">REL</translation>
<translation></translation>
</message>
<message>
<source>Release:</source>
<translation type="unfinished">退</translation>
<translation></translation>
</message>
<message>
<source>Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings.</source>
<translation type="unfinished">(ADSR Release)</translation>
<translation>使</translation>
</message>
<message>
<source>AMT</source>
@@ -1055,15 +1055,15 @@ Right clicking will bring up a context menu where you can change the order in wh
</message>
<message>
<source>Modulation amount:</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope.</source>
<translation type="unfinished"></translation>
<translation>使LFO对此包络的调制量</translation>
</message>
<message>
<source>LFO predelay:</source>
<translation type="unfinished"></translation>
<translation>LFO </translation>
</message>
<message>
<source>Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate.</source>

View File

@@ -35,13 +35,15 @@
class EffectChain;
class FloatModel;
class BoolModel;
class AudioPort : public ThreadableJob
{
MM_OPERATORS
public:
AudioPort( const QString & _name, bool _has_effect_chain = true,
FloatModel * volumeModel = NULL, FloatModel * panningModel = NULL );
AudioPort( const QString & _name, bool _has_effect_chain = true,
FloatModel * volumeModel = NULL, FloatModel * panningModel = NULL,
BoolModel * mutedModel = NULL );
virtual ~AudioPort();
inline sampleFrame * buffer()
@@ -117,14 +119,15 @@ private:
fx_ch_t m_nextFxChannel;
QString m_name;
EffectChain * m_effects;
PlayHandleList m_playHandles;
QMutex m_playHandleLock;
FloatModel * m_volumeModel;
FloatModel * m_panningModel;
BoolModel * m_mutedModel;
friend class Mixer;
friend class MixerWorkerThread;

View File

@@ -131,6 +131,9 @@ protected slots:
void setEditMode(AutomationEditor::EditModes mode);
void setEditMode(int mode);
void flipYButtonPressed();
void flipXButtonPressed();
void setProgressionType(AutomationPattern::ProgressionTypes type);
void setProgressionType(int type);
void setTension();
@@ -176,6 +179,8 @@ private:
static QPixmap * s_toolErase;
static QPixmap * s_toolSelect;
static QPixmap * s_toolMove;
static QPixmap * s_toolYFlip;
static QPixmap * s_toolXFlip;
ComboBoxModel m_zoomingXModel;
ComboBoxModel m_zoomingYModel;
@@ -281,6 +286,9 @@ private:
QAction* m_linearAction;
QAction* m_cubicHermiteAction;
ToolButton * m_flipYButton;
ToolButton * m_flipXButton;
Knob * m_tensionKnob;
ComboBox * m_zoomingXComboBox;

View File

@@ -158,6 +158,8 @@ public:
public slots:
void clear();
void objectDestroyed( jo_id_t );
void flipY( int min, int max );
void flipX( int length = -1 );
private:
void cleanObjects();

View File

@@ -51,6 +51,8 @@ protected slots:
void changeName();
void disconnectObject( QAction * _a );
void toggleRecording();
void flipY();
void flipX();
protected:
virtual void constructContextMenu( QMenu * );

View File

@@ -57,6 +57,9 @@ public slots:
void play();
void stop();
protected:
virtual void closeEvent( QCloseEvent * _ce );
private:
BBTrackContainerView* m_trackContainerView;
ComboBox * m_bbComboBox;

View File

@@ -26,6 +26,7 @@
#define CONTROLLER_RACK_VIEW_H
#include <QWidget>
#include <QCloseEvent>
#include "SerializingObject.h"
#include "lmms_basics.h"
@@ -56,6 +57,8 @@ public:
public slots:
void deleteController( ControllerView * _view );
protected:
virtual void closeEvent( QCloseEvent * _ce );
private slots:
virtual void update();

363
include/Delay.h Normal file
View File

@@ -0,0 +1,363 @@
/*
* Delay.h - Delay effect objects to use as building blocks in DSP
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* 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 DELAY_H
#define DELAY_H
#include "lmms_basics.h"
#include "lmms_math.h"
#include "interpolation.h"
#include "MemoryManager.h"
// brief usage
// Classes:
// CombFeedback: a feedback comb filter - basically a simple delay line, makes a comb shape in the freq response
// CombFeedfwd: a feed-forward comb filter - an "inverted" comb filter, can be combined with CombFeedback to create a net allpass if negative gain is used
// CombFeedbackDualtap: same as CombFeedback but takes two delay values
// AllpassDelay: an allpass delay - combines feedback and feed-forward - has flat frequency response
// all classes are templated with channel count, any arbitrary channel count can be used for each fx
// Methods (for all classes):
// setDelay sets delay amount in frames. It's up to you to make this samplerate-agnostic.
// Fractions are allowed - linear interpolation is used to deal with them
// CombFeedbackDualTap is a special case: it requires 2 delay times
// setMaxDelay (re)sets the maximum allowed delay, in frames
// NOTE: for performance reasons, there's no bounds checking at setDelay, so make sure you set maxDelay >= delay!
// clearHistory clears the delay buffer
// setGain sets the feedback/feed-forward gain, in linear amplitude, negative values are allowed
// 1.0 is full feedback/feed-forward, -1.0 is full negative feedback/feed-forward
// update runs the fx for one frame - takes as arguments input and number of channel to run, returns output
template<ch_cnt_t CHANNELS>
class CombFeedback
{
public:
typedef double frame[CHANNELS];
CombFeedback( int maxDelay ) :
m_size( maxDelay ),
m_position( 0 ),
m_feedBack( 0.0 ),
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC( frame, maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~CombFeedback()
{
MM_FREE( m_buffer );
}
inline void setMaxDelay( int maxDelay )
{
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC( frame, maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
m_position %= m_size;
}
inline void clearHistory()
{
memset( m_buffer, 0, sizeof( frame ) * m_size );
}
inline void setDelay( double delay )
{
m_delay = static_cast<int>( ceil( delay ) );
m_fraction = 1.0 - ( delay - floor( delay ) );
}
inline void setGain( double gain )
{
m_gain = gain;
}
inline double update( double in, ch_cnt_t ch )
{
int readPos = m_position - m_delay;
if( readPos < 0 ) { readPos += m_size; }
const double y = linearInterpolate( m_buffer[readPos][ch], m_buffer[( readPos + 1 ) % m_size][ch], m_fraction );
++m_position %= m_size;
m_buffer[m_position][ch] = in + m_gain * y;
return y;
}
private:
frame * m_buffer;
int m_size;
int m_position;
double m_gain;
int m_delay;
double m_fraction;
};
template<ch_cnt_t CHANNELS>
class CombFeedfwd
{
typedef double frame[CHANNELS];
CombFeedfwd( int maxDelay ) :
m_size( maxDelay ),
m_position( 0 ),
m_feedBack( 0.0 ),
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC( frame, maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~CombFeedfwd()
{
MM_FREE( m_buffer );
}
inline void setMaxDelay( int maxDelay )
{
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC( frame, maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
m_position %= m_size;
}
inline void clearHistory()
{
memset( m_buffer, 0, sizeof( frame ) * m_size );
}
inline void setDelay( double delay )
{
m_delay = static_cast<int>( ceil( delay ) );
m_fraction = 1.0 - ( delay - floor( delay ) );
}
inline void setGain( double gain )
{
m_gain = gain;
}
inline double update( double in, ch_cnt_t ch )
{
int readPos = m_position - m_delay;
if( readPos < 0 ) { readPos += m_size; }
const double y = linearInterpolate( m_buffer[readPos][ch], m_buffer[( readPos + 1 ) % m_size][ch], m_fraction ) + in * m_gain;
++m_position %= m_size;
m_buffer[m_position][ch] = in;
return y;
}
private:
frame * m_buffer;
int m_size;
int m_position;
double m_gain;
int m_delay;
double m_fraction;
};
template<ch_cnt_t CHANNELS>
class CombFeedbackDualtap
{
typedef double frame[CHANNELS];
CombFeedbackDualtap( int maxDelay ) :
m_size( maxDelay ),
m_position( 0 ),
m_feedBack( 0.0 ),
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC( frame, maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~CombFeedbackDualtap()
{
MM_FREE( m_buffer );
}
inline void setMaxDelay( int maxDelay )
{
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC( frame, maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
m_position %= m_size;
}
inline void clearHistory()
{
memset( m_buffer, 0, sizeof( frame ) * m_size );
}
inline void setDelays( double delay1, double delay2 )
{
m_delay1 = static_cast<int>( ceil( delay1 ) );
m_fraction1 = 1.0 - ( delay1 - floor( delay1 ) );
m_delay2 = static_cast<int>( ceil( delay2 ) );
m_fraction2 = 1.0 - ( delay2 - floor( delay2 ) );
}
inline void setGain( double gain )
{
m_gain = gain;
}
inline double update( double in, ch_cnt_t ch )
{
int readPos1 = m_position - m_delay1;
if( readPos1 < 0 ) { readPos1 += m_size; }
int readPos2 = m_position - m_delay2;
if( readPos2 < 0 ) { readPos2 += m_size; }
const double y = linearInterpolate( m_buffer[readPos1][ch], m_buffer[( readPos1 + 1 ) % m_size][ch], m_fraction1 ) +
linearInterpolate( m_buffer[readPos2][ch], m_buffer[( readPos2 + 1 ) % m_size][ch], m_fraction2 );
++m_position %= m_size;
m_buffer[m_position][ch] = in + m_gain * y;
return y;
}
private:
frame * m_buffer;
int m_size;
int m_position;
double m_gain;
int m_delay1;
int m_delay2;
double m_fraction1;
double m_fraction2;
};
template<ch_cnt_t CHANNELS>
class AllpassDelay
{
public:
typedef double frame[CHANNELS];
AllpassDelay( int maxDelay ) :
m_size( maxDelay ),
m_position( 0 ),
m_feedBack( 0.0 ),
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC( frame, maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~AllpassDelay()
{
MM_FREE( m_buffer );
}
inline void setMaxDelay( int maxDelay )
{
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC( frame, maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
m_position %= m_size;
}
inline void clearHistory()
{
memset( m_buffer, 0, sizeof( frame ) * m_size );
}
inline void setDelay( double delay )
{
m_delay = static_cast<int>( ceil( delay ) );
m_fraction = 1.0 - ( delay - floor( delay ) );
}
inline void setGain( double gain )
{
m_gain = gain;
}
inline double update( double in, ch_cnt_t ch )
{
int readPos = m_position - m_delay;
if( readPos < 0 ) { readPos += m_size; }
const double y = linearInterpolate( m_buffer[readPos][ch], m_buffer[( readPos + 1 ) % m_size][ch], m_fraction ) + in * -m_gain;
const double x = in + m_gain * y;
++m_position %= m_size;
m_buffer[m_position][ch] = x;
return y;
}
private:
frame * m_buffer;
int m_size;
int m_position;
double m_gain;
int m_delay;
double m_fraction;
};
// convenience typedefs for stereo effects
typedef CombFeedback<2> StereoCombFeedback;
typedef CombFeedfwd<2> StereoCombFeedfwd;
typedef CombFeedbackDualtap<2> StereoCombFeedbackDualtap;
typedef AllpassDelay<2> StereoAllpassDelay;
#endif

View File

@@ -73,6 +73,7 @@ private:
private slots:
void renameChannel();
void removeChannel();
void removeUnusedChannels();
void moveChannelLeft();
void moveChannelRight();
void displayHelp();

View File

@@ -92,6 +92,9 @@ public:
// notify the view that an fx channel was deleted
void deleteChannel(int index);
// delete all unused channels
void deleteUnusedChannels();
// move the channel to the left or right
void moveChannelLeft(int index);
void moveChannelRight(int index);
@@ -99,6 +102,9 @@ public:
// make sure the display syncs up with the fx mixer.
// useful for loading projects
void refreshDisplay();
protected:
virtual void closeEvent( QCloseEvent * _ce );
private slots:
void updateFaders();

View File

@@ -38,6 +38,7 @@
#include "Track.h"
class QLineEdit;
template<class T> class QQueue;
class InstrumentFunctionArpeggioView;
@@ -202,10 +203,10 @@ public:
return &m_effectChannelModel;
}
void setIndicator( FadeButton *fb );
signals:
void instrumentChanged();
void newNote();
void midiNoteOn( const Note& );
void midiNoteOff( const Note& );
void nameChanged();
@@ -250,6 +251,8 @@ private:
IntModel m_pitchRangeModel;
IntModel m_effectChannelModel;
FadeButton *m_fb;
Instrument * m_instrument;
InstrumentSoundShaping m_soundShaping;

View File

@@ -27,6 +27,7 @@
#define PROJECT_NOTES_H
#include <QMainWindow>
#include <QCloseEvent>
#include "JournallingObject.h"
@@ -56,6 +57,7 @@ public:
protected:
virtual void closeEvent( QCloseEvent * _ce );
void setupActions();

View File

@@ -38,7 +38,7 @@ public:
}
virtual ~RmsHelper()
{
if( m_buffer ) delete m_buffer;
if( m_buffer ) delete[] m_buffer;
}
inline void setSize( int size )

View File

@@ -148,9 +148,11 @@ public:
private:
FloatModel m_volumeModel;
FloatModel m_panningModel;
AudioPort m_audioPort;
friend class SampleTrackView;
} ;
@@ -181,6 +183,7 @@ private:
EffectRackView * m_effectRack;
QWidget * m_effWindow;
Knob * m_volumeKnob;
Knob * m_panningKnob;
} ;

View File

@@ -34,6 +34,7 @@
#include "MeterModel.h"
#include "VstSyncController.h"
class AutomationTrack;
class Pattern;
class TimeLineWidget;
@@ -169,18 +170,11 @@ public:
return m_recording;
}
inline bool isExportDone() const
bool isExportDone() const;
inline void setRenderBetweenMarkers( bool renderBetweenMarkers )
{
if ( m_exportLoop )
{
return m_exporting == true &&
m_playPos[Mode_PlaySong].getTicks() >= length() * ticksPerTact();
}
else
{
return m_exporting == true &&
m_playPos[Mode_PlaySong].getTicks() >= ( length() + 1 ) * ticksPerTact();
}
m_renderBetweenMarkers = renderBetweenMarkers;
}
inline PlayModes playMode() const
@@ -344,6 +338,7 @@ private:
volatile bool m_recording;
volatile bool m_exporting;
volatile bool m_exportLoop;
volatile bool m_renderBetweenMarkers;
volatile bool m_playing;
volatile bool m_paused;

View File

@@ -73,6 +73,8 @@ public slots:
void setEditModeDraw();
void setEditModeSelect();
protected:
virtual void closeEvent( QCloseEvent * _ce );
private slots:
void setHighQuality( bool );

View File

@@ -67,7 +67,7 @@ const int TRACK_OP_WIDTH_COMPACT = 60;
* Tracks can be resized by shift-dragging anywhere inside the track
* display. This sets the minimum size in pixels for a track.
*/
const int MINIMAL_TRACK_HEIGHT = 8;
const int MINIMAL_TRACK_HEIGHT = 32;
const int DEFAULT_TRACK_HEIGHT = 32;
const int TCO_BORDER_WIDTH = 2;
@@ -120,7 +120,7 @@ public:
{
return m_length;
}
virtual void movePosition( const MidiTime & _pos );
virtual void changeLength( const MidiTime & _length );
@@ -539,7 +539,9 @@ private:
QString m_name;
int m_height;
protected:
BoolModel m_mutedModel;
private:
BoolModel m_soloModel;
bool m_mutedBeforeSolo;

View File

@@ -51,7 +51,7 @@ public:
virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
virtual void loadSettings( const QDomElement & _this );
QWidget * contentWidget()
QScrollArea * contentWidget()
{
return( m_scrollArea );
}

View File

@@ -71,9 +71,9 @@ inline float cubicInterpolate( float v0, float v1, float v2, float v3, float x )
float frcu = frsq*v0;
float t1 = v3 + 3*v1;
return( v1 + 0.5f * frcu + x * ( v2 - frcu * ( 1.0f/6.0f ) -
t1 * ( 1.0f/6.0f ) - v0 / 3.0f ) + frsq * x * ( t1 *
( 1.0f/6.0f ) - 0.5f * v2 ) + frsq * ( 0.5f * v2 - v1 ) );
return( v1 + fastFmaf( 0.5f, frcu, x ) * ( v2 - frcu * ( 1.0f/6.0f ) -
fastFmaf( t1, ( 1.0f/6.0f ), -v0 ) * ( 1.0f/3.0f ) ) + frsq * x * ( t1 *
( 1.0f/6.0f ) - 0.5f * v2 ) + frsq * fastFmaf( 0.5f, v2, -v1 ) );
}
@@ -102,7 +102,7 @@ inline float optimalInterpolate( float v0, float v1, float x )
const float c2 = even * -0.004541102062639801;
const float c3 = odd * -1.57015627178718420;
return ( ( c3*z + c2 ) * z + c1 ) * z + c0;
return fastFmaf( fastFmaf( fastFmaf( c3, z, c2 ), z, c1 ), z, c0 );
}
@@ -119,7 +119,7 @@ inline float optimal4pInterpolate( float v0, float v1, float v2, float v3, float
const float c2 = even1 * -0.246185007019907091 + even2 * 0.24614027139700284;
const float c3 = odd1 * -0.36030925263849456 + odd2 * 0.10174985775982505;
return ( ( c3*z + c2 ) * z + c1 ) * z + c0;
return fastFmaf( fastFmaf( fastFmaf( c3, z, c2 ), z, c1 ), z, c0 );
}
@@ -130,7 +130,7 @@ inline float lagrangeInterpolate( float v0, float v1, float v2, float v3, float
const float c1 = v2 - v0 * ( 1.0f / 3.0f ) - v1 * 0.5f - v3 * ( 1.0f / 6.0f );
const float c2 = 0.5f * (v0 + v2) - v1;
const float c3 = ( 1.0f/6.0f ) * ( v3 - v0 ) + 0.5f * ( v1 - v2 );
return ( ( c3*x + c2 ) * x + c1 ) * x + c0;
return fastFmaf( fastFmaf( fastFmaf( c3, x, c2 ), x, c1 ), x, c0 );
}

View File

@@ -48,10 +48,10 @@ using namespace std;
#define _isinff(x) isinf(x)
#endif
#ifndef exp10
#define exp10(x) pow( 10, x )
#define exp10(x) pow( 10.0, x )
#endif
#ifndef exp10f
#define exp10f(x) powf( 10, x )
#define exp10f(x) powf( 10.0f, x )
#endif
#endif
@@ -239,10 +239,10 @@ static inline float linearToLogScale( float min, float max, float value )
//! @brief Converts linear amplitude (0-1.0) to dBV scale.
//! @brief Converts linear amplitude (0-1.0) to dBV scale. Handles zeroes as -inf.
//! @param amp Linear amplitude, where 1.0 = 0dBV.
//! @return Amplitude in dBV. -inf for 0 amplitude.
static inline float ampToDbv( float amp )
static inline float safeAmpToDbv( float amp )
{
return amp == 0.0f
? -INFINITY
@@ -250,10 +250,10 @@ static inline float ampToDbv( float amp )
}
//! @brief Converts dBV-scale to linear amplitude with 0dBV = 1.0
//! @brief Converts dBV-scale to linear amplitude with 0dBV = 1.0. Handles infinity as zero.
//! @param dbv The dBV value to convert: all infinites are treated as -inf and result in 0
//! @return Linear amplitude
static inline float dbvToAmp( float dbv )
static inline float safeDbvToAmp( float dbv )
{
return isinff( dbv )
? 0.0f
@@ -261,6 +261,24 @@ static inline float dbvToAmp( float dbv )
}
//! @brief Converts linear amplitude (>0-1.0) to dBV scale.
//! @param amp Linear amplitude, where 1.0 = 0dBV. ** Must be larger than zero! **
//! @return Amplitude in dBV.
static inline float ampToDbv( float amp )
{
return log10f( amp ) * 20.0f;
}
//! @brief Converts dBV-scale to linear amplitude with 0dBV = 1.0
//! @param dbv The dBV value to convert. ** Must be a real number - not inf/nan! **
//! @return Linear amplitude
static inline float dbvToAmp( float dbv )
{
return exp10f( dbv * 0.05f );
}
//! returns 1.0f if val >= 0.0f, -1.0 else
static inline float sign( float val )

View File

@@ -83,7 +83,8 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
for( fpp_t f = 0; f < frames; ++f )
{
// qDebug( "offset %d, value %f", f, m_ampControls.m_volumeModel.value( f ) );
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
sample_t s[2] = { buf[f][0], buf[f][1] };
// vol knob
@@ -122,7 +123,6 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
checkGate( outSum / frames );

View File

@@ -88,13 +88,13 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
const float w = wetLevel();
for( fpp_t f = 0; f < frames; ++f )
{
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
sample_t s[2] = { buf[f][0], buf[f][1] };
m_bbFX.nextSample( s[0], s[1] );
buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
checkGate( outSum / frames );

View File

@@ -10,7 +10,8 @@ ADD_SUBDIRECTORY(CrossoverEQ)
ADD_SUBDIRECTORY(delay)
ADD_SUBDIRECTORY(DualFilter)
ADD_SUBDIRECTORY(dynamics_processor)
ADD_SUBDIRECTORY(flanger)
ADD_SUBDIRECTORY(Eq)
ADD_SUBDIRECTORY(Flanger)
ADD_SUBDIRECTORY(flp_import)
ADD_SUBDIRECTORY(HydrogenImport)
ADD_SUBDIRECTORY(kicker)

View File

@@ -196,9 +196,9 @@ bool CrossoverEQEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
double outSum = 0.0;
for( int f = 0; f < frames; ++f )
{
outSum = buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1];
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 );

View File

@@ -155,11 +155,11 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
s[0] += ( s2[0] * mix2 );
s[1] += ( s2[1] * mix2 );
}
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
// do another mix with dry signal
buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
checkGate( outSum / frames );

View File

@@ -0,0 +1,6 @@
INCLUDE(BuildPlugin)
INCLUDE_DIRECTORIES(${FFTW3F_INCLUDE_DIRS})
LINK_DIRECTORIES(${FFTW3F_LIBRARY_DIRS})
LINK_LIBRARIES(${FFTW3F_LIBRARIES})
BUILD_PLUGIN(eq EqEffect.cpp EqControls.cpp EqControlsDialog.cpp EqFilter.h EqParameterWidget.cpp EqFader.h EqSpectrumView.h DBvModel.cpp DBvModel.h
MOCFILES EqControls.h EqParameterWidget.h EqFader.h DBvModel.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")

14
plugins/Eq/DBvModel.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include "DBvModel.h"
DBvModel::DBvModel(float val, float min, float max, float step,
Model *parent, const QString &displayName,
bool defaultConstructed) :
FloatModel( val, min, max, step, parent, displayName, defaultConstructed )
{
connect(this, SIGNAL( dataChanged() ), this,SLOT( calcAmp() ) );
}
void DBvModel::calcAmp()
{
m_amp = dbvToAmp( value() );
}

31
plugins/Eq/DBvModel.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef DBVMODEL
#define DBVMODEL
#include "AutomatableModel.h"
class DBvModel : public FloatModel
{
Q_OBJECT
public:
DBvModel( float val = 0, float min = 0, float max = 0, float step = 0,
Model * parent = NULL,
const QString& displayName = QString(),
bool defaultConstructed = false );
inline float getAmp() const
{
return m_amp;
}
private slots:
void calcAmp();
private:
float m_amp;
};
#endif // DBVMODEL

196
plugins/Eq/EqControls.cpp Normal file
View File

@@ -0,0 +1,196 @@
/*
* eqcontrols.cpp - defination of EqControls class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 <QtXml/QDomElement>
#include "EqControls.h"
#include "EqEffect.h"
EqControls::EqControls( EqEffect *effect ) :
EffectControls( effect ),
m_effect( effect ),
m_inGainModel( 0.0, -60.0, 20.0, 0.01, this, tr( "Input gain") ),
m_outGainModel( -.0, -60.0, 20.0, 0.01, this, tr( "Output gain" ) ),
m_lowShelfGainModel( 0.0 , -40, 40, 0.001, this, tr( "Low shelf gain" ) ),
m_para1GainModel( 0.0 , -40, 40, 0.001, this, tr( "Peak 1 gain" ) ),
m_para2GainModel( 0.0 , -40, 40, 0.001, this, tr( "Peak 2 gain" ) ),
m_para3GainModel( 0.0 , -40, 40, 0.001, this, tr( "Peak 3 gain" ) ),
m_para4GainModel( 0.0 , -40, 40, 0.001, this, tr( "Peak 4 gain" ) ),
m_highShelfGainModel( 0.0 , -40, 40, 0.001, this, tr( "High Shelf gain" ) ),
m_hpResModel( 0.707,0.003, 10.0 , 0.001, this, tr( "HP res" ) ),
m_lowShelfResModel( 1.4,0.55, 10.0 , 0.001, this , tr( "Low Shelf res" ) ),
m_para1BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 1 BW" ) ),
m_para2BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 2 BW" ) ),
m_para3BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 3 BW" ) ),
m_para4BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 4 BW" ) ),
m_highShelfResModel( 1.4, 0.55, 10.0 , 0.001, this , tr( "High Shelf res" ) ),
m_lpResModel( 0.707,0.003, 10.0 , 0.001, this , tr( "LP res" ) ),
m_hpFeqModel( 31.0, 30.0, 20000, 0.001, this , tr( "HP freq" ) ),
m_lowShelfFreqModel( 80.0, 25.0, 20000, 0.001, this , tr( "Low Shelf freq" ) ),
m_para1FreqModel( 120.0, 27.0, 20000, 0.001, this , tr( "Peak 1 freq" ) ),
m_para2FreqModel( 250.0, 27.0, 20000, 0.001, this, tr( "Peak 2 freq" ) ),
m_para3FreqModel( 2000.0, 27.0, 20000, 0.001, this , tr( "Peak 3 freq" ) ),
m_para4FreqModel( 4000.0, 27.0, 20000, 0.001, this , tr( "Peak 4 freq" ) ),
m_highShelfFreqModel( 12000.0, 27.0, 20000, 0.001, this , tr( "High shelf freq" ) ),
m_lpFreqModel( 18000.0, 27.0, 20000, 0.001, this , tr( "LP freq" ) ),
m_hpActiveModel( false, this , tr( "HP active" ) ),
m_lowShelfActiveModel( false, this , tr( "Low shelf active" ) ),
m_para1ActiveModel(false, this , tr( "Peak 1 active" ) ),
m_para2ActiveModel( false, this , tr( "Peak 2 active" ) ),
m_para3ActiveModel( false, this , tr( "Peak 3 active" ) ),
m_para4ActiveModel( false, this , tr( "Peak 4 active" ) ),
m_highShelfActiveModel( false, this , tr( "High shelf active" ) ),
m_lpActiveModel( false, this , tr( "LP active" ) ),
m_lp12Model( false, this , tr( "LP 12" ) ),
m_lp24Model( false, this , tr( "LP 24" ) ),
m_lp48Model( false, this , tr( "LP 48" ) ),
m_hp12Model( false, this , tr( "HP 12" ) ),
m_hp24Model( false, this , tr( "HP 24" ) ),
m_hp48Model( false, this , tr( "HP 48" ) ),
m_lpTypeModel( 0,0,2,this, tr( "low pass type") ) ,
m_hpTypeModel( 0,0,2,this, tr( "high pass type") )
{
m_hpFeqModel.setScaleLogarithmic( true );
m_lowShelfFreqModel.setScaleLogarithmic( true );
m_para1FreqModel.setScaleLogarithmic( true );
m_para2FreqModel.setScaleLogarithmic( true );
m_para3FreqModel.setScaleLogarithmic( true );
m_para4FreqModel.setScaleLogarithmic( true );
m_highShelfFreqModel.setScaleLogarithmic( true );
m_lpFreqModel.setScaleLogarithmic( true );
m_para1GainModel.setScaleLogarithmic( true );
m_inPeakL = 0;
m_inPeakR = 0;
m_outPeakL = 0;
m_outPeakR = 0;
m_lowShelfPeakL = 0; m_lowShelfPeakR = 0;
m_para1PeakL = 0; m_para1PeakR = 0;
m_para2PeakL = 0; m_para2PeakR = 0;
m_para3PeakL = 0; m_para3PeakR = 0;
m_para4PeakL = 0; m_para4PeakR = 0;
m_highShelfPeakL = 0; m_highShelfPeakR = 0;
m_inProgress = false;
m_analyseIn = true;
m_analyseOut = true;
m_inGainModel.setScaleLogarithmic( true );
}
void EqControls::loadSettings( const QDomElement &_this )
{
m_inGainModel.loadSettings( _this, "Inputgain" );
m_outGainModel.loadSettings( _this, "Outputgain");
m_lowShelfGainModel.loadSettings( _this , "Lowshelfgain" );
m_para1GainModel.loadSettings( _this, "Peak1gain" );
m_para2GainModel.loadSettings( _this, "Peak2gain" );
m_para3GainModel.loadSettings( _this, "Peak3gain" );
m_para4GainModel.loadSettings( _this, "Peak4gain" );
m_highShelfGainModel.loadSettings( _this , "HighShelfgain");
m_hpResModel.loadSettings( _this ,"HPres");
m_lowShelfResModel.loadSettings( _this, "LowShelfres" );
m_para1BwModel.loadSettings( _this ,"Peak1bw" );
m_para2BwModel.loadSettings( _this ,"Peak2bw" );
m_para3BwModel.loadSettings( _this ,"Peak3bw" );
m_para4BwModel.loadSettings( _this ,"Peak4bw" );
m_highShelfResModel.loadSettings( _this, "HighShelfres" );
m_lpResModel.loadSettings( _this, "LPres");
m_hpFeqModel.loadSettings( _this, "HPfreq" );
m_lowShelfFreqModel.loadSettings( _this, "LowShelffreq" );
m_para1FreqModel.loadSettings( _this, "Peak1freq" );
m_para2FreqModel.loadSettings( _this, "Peak2freq" );
m_para3FreqModel.loadSettings( _this, "Peak3freq" );
m_para4FreqModel.loadSettings( _this, "Peak4freq" );
m_highShelfFreqModel.loadSettings( _this, "Highshelffreq" );
m_lpFreqModel.loadSettings( _this, "LPfreq" );
m_hpActiveModel.loadSettings( _this, "HPactive" );
m_lowShelfActiveModel.loadSettings( _this, "Lowshelfactive" );
m_para1ActiveModel.loadSettings( _this, "Peak1active");
m_para2ActiveModel.loadSettings( _this, "Peak2active");
m_para3ActiveModel.loadSettings( _this, "Peak3active");
m_para4ActiveModel.loadSettings( _this, "Peak4active");
m_highShelfActiveModel.loadSettings( _this, "Highshelfactive" );
m_lpActiveModel.loadSettings( _this, "LPactive" );
m_lp12Model.loadSettings( _this , "LP12" );
m_lp24Model.loadSettings( _this , "LP24" );
m_lp48Model.loadSettings( _this , "LP48" );
m_hp12Model.loadSettings( _this , "HP12" );
m_hp24Model.loadSettings( _this , "HP24" );
m_hp48Model.loadSettings( _this , "HP48" );
m_lpTypeModel.loadSettings( _this, "LP" );
m_hpTypeModel.loadSettings( _this, "HP" );
}
void EqControls::saveSettings( QDomDocument &doc, QDomElement &parent )
{
m_inGainModel.saveSettings( doc, parent, "Inputgain" );
m_outGainModel.saveSettings( doc, parent, "Outputgain");
m_lowShelfGainModel.saveSettings( doc, parent , "Lowshelfgain" );
m_para1GainModel.saveSettings( doc, parent, "Peak1gain" );
m_para2GainModel.saveSettings( doc, parent, "Peak2gain" );
m_para3GainModel.saveSettings( doc, parent, "Peak3gain" );
m_para4GainModel.saveSettings( doc, parent, "Peak4gain" );
m_highShelfGainModel.saveSettings( doc, parent, "HighShelfgain");
m_hpResModel.saveSettings( doc, parent ,"HPres");
m_lowShelfResModel.saveSettings( doc, parent, "LowShelfres" );
m_para1BwModel.saveSettings( doc, parent,"Peak1bw" );
m_para2BwModel.saveSettings( doc, parent,"Peak2bw" );
m_para3BwModel.saveSettings( doc, parent,"Peak3bw" );
m_para4BwModel.saveSettings( doc, parent,"Peak4bw" );
m_highShelfResModel.saveSettings( doc, parent, "HighShelfres" );
m_lpResModel.saveSettings( doc, parent, "LPres");
m_hpFeqModel.saveSettings( doc, parent, "HPfreq" );
m_lowShelfFreqModel.saveSettings( doc, parent, "LowShelffreq" );
m_para1FreqModel.saveSettings( doc, parent, "Peak1freq" );
m_para2FreqModel.saveSettings( doc, parent, "Peak2freq" );
m_para3FreqModel.saveSettings( doc, parent, "Peak3freq" );
m_para4FreqModel.saveSettings( doc, parent, "Peak4freq" );
m_highShelfFreqModel.saveSettings( doc, parent, "Highshelffreq" );
m_lpFreqModel.saveSettings( doc, parent, "LPfreq" );
m_hpActiveModel.saveSettings( doc, parent, "HPactive" );
m_lowShelfActiveModel.saveSettings( doc, parent, "Lowshelfactive" );
m_para1ActiveModel.saveSettings( doc, parent, "Peak1active" );
m_para2ActiveModel.saveSettings( doc, parent, "Peak2active" );
m_para3ActiveModel.saveSettings( doc, parent, "Peak3active" );
m_para4ActiveModel.saveSettings( doc, parent, "Peak4active" );
m_highShelfActiveModel.saveSettings( doc, parent, "Highshelfactive" );
m_lpActiveModel.saveSettings( doc, parent, "LPactive" );
m_lp12Model.saveSettings( doc, parent, "LP12" );
m_lp24Model.saveSettings( doc, parent, "LP24" );
m_lp48Model.saveSettings( doc, parent, "LP48" );
m_hp12Model.saveSettings( doc, parent, "HP12" );
m_hp24Model.saveSettings( doc, parent, "HP24" );
m_hp48Model.saveSettings( doc, parent, "HP48" );
m_lpTypeModel.saveSettings( doc, parent, "LP" );
m_hpTypeModel.saveSettings( doc, parent, "HP" );
}

138
plugins/Eq/EqControls.h Normal file
View File

@@ -0,0 +1,138 @@
/*
* eqcontrols.h - defination of EqControls class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 EQCONTROLS_H
#define EQCONTROLS_H
#include "EffectControls.h"
#include "EqControlsDialog.h"
#include "Knob.h"
#include "DBvModel.h"
class EqEffect;
class EqControls : public EffectControls
{
Q_OBJECT
public:
explicit EqControls( EqEffect* effect );
virtual ~EqControls()
{
}
virtual void saveSettings ( QDomDocument& doc, QDomElement& parent );
virtual void loadSettings ( const QDomElement &_this );
inline virtual QString nodeName() const
{
return "Eq";
}
virtual int controlCount()
{
return 39;
}
virtual EffectControlDialog* createView()
{
return new EqControlsDialog( this );
}
float m_inPeakL;
float m_inPeakR;
float m_outPeakL;
float m_outPeakR;
float m_lowShelfPeakL, m_lowShelfPeakR;
float m_para1PeakL, m_para1PeakR;
float m_para2PeakL, m_para2PeakR;
float m_para3PeakL, m_para3PeakR;
float m_para4PeakL, m_para4PeakR;
float m_highShelfPeakL, m_highShelfPeakR;
bool m_analyseIn;
bool m_analyseOut;
EqAnalyser m_inFftBands;
EqAnalyser m_outFftBands;
bool m_inProgress;
bool visable();
private:
EqEffect* m_effect;
DBvModel m_inGainModel;
DBvModel m_outGainModel;
FloatModel m_lowShelfGainModel;
FloatModel m_para1GainModel;
FloatModel m_para2GainModel;
FloatModel m_para3GainModel;
FloatModel m_para4GainModel;
FloatModel m_highShelfGainModel;
FloatModel m_hpResModel;
FloatModel m_lowShelfResModel;
FloatModel m_para1BwModel;
FloatModel m_para2BwModel;
FloatModel m_para3BwModel;
FloatModel m_para4BwModel;
FloatModel m_highShelfResModel;
FloatModel m_lpResModel;
FloatModel m_hpFeqModel;
FloatModel m_lowShelfFreqModel;
FloatModel m_para1FreqModel;
FloatModel m_para2FreqModel;
FloatModel m_para3FreqModel;
FloatModel m_para4FreqModel;
FloatModel m_highShelfFreqModel;
FloatModel m_lpFreqModel;
BoolModel m_hpActiveModel;
BoolModel m_lowShelfActiveModel;
BoolModel m_para1ActiveModel;
BoolModel m_para2ActiveModel;
BoolModel m_para3ActiveModel;
BoolModel m_para4ActiveModel;
BoolModel m_highShelfActiveModel;
BoolModel m_lpActiveModel;
BoolModel m_lp12Model;
BoolModel m_lp24Model;
BoolModel m_lp48Model;
BoolModel m_hp12Model;
BoolModel m_hp24Model;
BoolModel m_hp48Model;
IntModel m_lpTypeModel;
IntModel m_hpTypeModel;
friend class EqControlsDialog;
friend class EqEffect;
};
#endif // EQCONTROLS_H

View File

@@ -0,0 +1,172 @@
/*
* eqcontrolsdialog.cpp - defination of EqControlsDialog class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 "EqControlsDialog.h"
#include "EqControls.h"
#include "embed.h"
#include "Fader.h"
#include "EqFader.h"
#include "Engine.h"
#include "AutomatableButton.h"
#include "QWidget"
#include "MainWindow.h"
#include "LedCheckbox.h"
EqControlsDialog::EqControlsDialog( EqControls *controls ) :
EffectControlDialog( controls )
{
m_controls = controls;
setAutoFillBackground( true );
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
setPalette( pal );
setFixedSize( 350, 275 );
m_inSpec = new EqSpectrumView( &controls->m_inFftBands, this);
m_inSpec->move( 51, 2 );
m_inSpec->color = QColor( 238, 154, 120, 80 );
m_outSpec = new EqSpectrumView( &controls->m_outFftBands, this);
m_outSpec->move( 51, 2 );
m_outSpec->color = QColor(145, 205, 22, 80);
m_parameterWidget = new EqParameterWidget( this , controls );
m_parameterWidget->move( 51, 2 );
setBand( 0, &controls->m_hpActiveModel, &controls->m_hpFeqModel, &controls->m_hpResModel, 0, QColor(255 ,255, 255), tr( "HP" ) ,0,0);
setBand( 1, &controls->m_lowShelfActiveModel, &controls->m_lowShelfFreqModel, &controls->m_lowShelfResModel, &controls->m_lowShelfGainModel, QColor(255 ,255, 255), tr( "Low Shelf" ), &controls->m_lowShelfPeakL , &controls->m_lowShelfPeakR );
setBand( 2, &controls->m_para1ActiveModel, &controls->m_para1FreqModel, &controls->m_para1BwModel, &controls->m_para1GainModel, QColor(255 ,255, 255), tr( "Peak 1" ), &controls->m_para1PeakL, &controls->m_para1PeakR );
setBand( 3, &controls->m_para2ActiveModel, &controls->m_para2FreqModel, &controls->m_para2BwModel, &controls->m_para2GainModel, QColor(255 ,255, 255), tr( "Peak 2" ), &controls->m_para2PeakL, &controls->m_para2PeakR );
setBand( 4, &controls->m_para3ActiveModel, &controls->m_para3FreqModel, &controls->m_para3BwModel, &controls->m_para3GainModel, QColor(255 ,255, 255), tr( "Peak 3" ), &controls->m_para3PeakL, &controls->m_para3PeakR );
setBand( 5, &controls->m_para4ActiveModel, &controls->m_para4FreqModel, &controls->m_para4BwModel, &controls->m_para4GainModel, QColor(255 ,255, 255), tr( "Peak 4" ), &controls->m_para4PeakL, &controls->m_para4PeakR );
setBand( 6, &controls->m_highShelfActiveModel, &controls->m_highShelfFreqModel, &controls->m_highShelfResModel, &controls->m_highShelfGainModel, QColor(255 ,255, 255), tr( "High Shelf" ), &controls->m_highShelfPeakL, &controls->m_highShelfPeakR );
setBand( 7, &controls->m_lpActiveModel, &controls->m_lpFreqModel, &controls->m_lpResModel, 0, QColor(255 ,255, 255), tr( "LP" ) ,0,0);
int cw = width()/8; //the chanel width in pixels
int ko = ( cw * 0.5 ) - ((new Knob( knobBright_26, 0 ))->width() * 0.5 );
m_inGainFader = new EqFader( &controls->m_inGainModel, tr( "In Gain" ), this, &controls->m_inPeakL, &controls->m_inPeakR);
m_inGainFader->move( 10, 5 );
m_inGainFader->setDisplayConversion( false );
m_inGainFader->setHintText( tr( "Gain" ), "dBv");
m_outGainFader = new EqFader( &controls->m_outGainModel, tr( "Out Gain" ), this, &controls->m_outPeakL, &controls->m_outPeakR );
m_outGainFader->move( 315, 5 );
m_outGainFader->setDisplayConversion( false );
m_outGainFader->setHintText( tr( "Gain" ), "dBv");
//gain faders
int fo = (cw * 0.5) - (m_outGainFader->width() * 0.5 );
for( int i = 1; i < m_parameterWidget->bandCount() - 1; i++)
{
m_gainFader = new EqFader( m_parameterWidget->getBandModels(i)->gain, tr( "" ), this ,m_parameterWidget->getBandModels( i )->peakL, m_parameterWidget->getBandModels( i )->peakR );
m_gainFader->move( cw * i + fo , 123 );
m_gainFader->setMinimumHeight(80);
m_gainFader->resize(m_gainFader->width() , 80);
m_gainFader->setDisplayConversion( false );
m_gainFader->setHintText( tr( "Gain") , "dB");
}
for( int i = 0; i < m_parameterWidget->bandCount() ; i++)
{
m_resKnob = new Knob( knobBright_26, this );
if(i ==0 || i == 7)
{
m_resKnob->move( cw * i + ko , 190 );
} else
{
m_resKnob->move( cw * i + ko , 205 );
}
m_resKnob->setVolumeKnob(false);
m_resKnob->setModel( m_parameterWidget->getBandModels( i )->res );
if(i > 1 && i < 6) { m_resKnob->setHintText( tr( "Bandwidth: " ) , " Octave" ); }
else { m_resKnob->setHintText( tr( "Resonance : " ) , "" ); }
m_freqKnob = new Knob( knobBright_26, this );
if( i == 0 || i == 7 )
{
m_freqKnob->move( cw * i + ko, 222 );
} else
{
m_freqKnob->move(cw * i + ko, 235 );
}
m_freqKnob->setVolumeKnob( false );
m_freqKnob->setModel( m_parameterWidget->getBandModels( i )->freq );
m_freqKnob->setHintText( tr( "Frequency:" ), "Hz" );
m_activeBox = new LedCheckBox( m_parameterWidget->getBandModels( i )->name , this , "" , LedCheckBox::Green );
m_activeBox->move( cw * i + fo + 3, 260 );
m_activeBox->setModel( m_parameterWidget->getBandModels( i )->active );
}
//hp filter type
m_hp12Box = new LedCheckBox( tr( "12dB" ), this , "" , LedCheckBox::Green );
m_hp12Box->move( cw*0 + ko, 170 );
m_hp12Box->setModel( &controls->m_hp12Model );
m_hp24Box = new LedCheckBox( tr( "24dB" ), this , "" , LedCheckBox::Green );
m_hp24Box->move( cw*0 + ko, 150 );
m_hp24Box->setModel( &controls->m_hp24Model );
m_hp48Box = new LedCheckBox( tr( "48dB" ), this , "" , LedCheckBox::Green );
m_hp48Box->move( cw*0 + ko, 130 );
m_hp48Box->setModel( &controls->m_hp48Model );
//LP filter type
m_lp12Box = new LedCheckBox( tr( "12dB"), this , "" , LedCheckBox::Green );
m_lp12Box->move( cw*7 + ko -5 , 170 );
m_lp12Box->setModel( &controls->m_lp12Model );
m_lp24Box = new LedCheckBox( tr( "24dB"), this , "" , LedCheckBox::Green );
m_lp24Box->move( cw*7 + ko - 5, 150 );
m_lp24Box->setModel( &controls->m_lp24Model );
m_lp48Box = new LedCheckBox( tr( "48dB"), this , "" , LedCheckBox::Green );
m_lp48Box->move( cw*7 + ko - 5, 130 );
m_lp48Box->setModel( &controls->m_lp48Model );
automatableButtonGroup *lpBtnGrp = new automatableButtonGroup(this,tr ( "lp grp" ) );
lpBtnGrp->addButton( m_lp12Box);
lpBtnGrp->addButton( m_lp24Box );
lpBtnGrp->addButton( m_lp48Box );
lpBtnGrp->setModel( &m_controls->m_lpTypeModel, false);
automatableButtonGroup *hpBtnGrp = new automatableButtonGroup( this, tr( "hp grp" ) );
hpBtnGrp->addButton( m_hp12Box );
hpBtnGrp->addButton( m_hp24Box );
hpBtnGrp->addButton( m_hp48Box );
hpBtnGrp->setModel( &m_controls->m_hpTypeModel,false);
}
void EqControlsDialog::mouseDoubleClickEvent(QMouseEvent *event)
{
m_originalHeight = parentWidget()->height() == 150 ? m_originalHeight : parentWidget()->height() ;
parentWidget()->setFixedHeight( parentWidget()->height() == m_originalHeight ? 150 : m_originalHeight );
update();
}

View File

@@ -0,0 +1,94 @@
/*
* eqcontrolsdialog.h - defination of EqControlsDialog class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 EQCONTROLSDIALOG_H
#define EQCONTROLSDIALOG_H
#include "EffectControlDialog.h"
#include "Fader.h"
#include "Knob.h"
#include "LedCheckbox.h"
#include "EqParameterWidget.h"
#include "MainWindow.h"
#include "qpushbutton.h"
#include "EqSpectrumView.h"
class EqControls;
class EqControlsDialog : public EffectControlDialog
{
public:
EqControlsDialog( EqControls* controls );
virtual ~EqControlsDialog()
{
}
EqBand * setBand(EqControls *controls);
private slots:
void updateVuMeters();
private:
EqControls * m_controls;
Fader* m_inGainFader;
Fader* m_outGainFader;
Fader* m_gainFader;
Knob* m_resKnob;
Knob* m_freqKnob;
LedCheckBox* m_activeBox;
LedCheckBox* m_lp12Box;
LedCheckBox* m_lp24Box;
LedCheckBox* m_lp48Box;
LedCheckBox* m_hp12Box;
LedCheckBox* m_hp24Box;
LedCheckBox* m_hp48Box;
LedCheckBox* m_analyzeBox;
EqParameterWidget* m_parameterWidget;
EqSpectrumView* m_inSpec;
EqSpectrumView* m_outSpec;
virtual void mouseDoubleClickEvent(QMouseEvent *event);
EqBand* setBand( int index, BoolModel* active, FloatModel* freq, FloatModel* res, FloatModel* gain, QColor color, QString name, float* peakL, float* peakR)
{
EqBand* filterModels = m_parameterWidget->getBandModels( index );
filterModels->active = active;
filterModels->freq = freq;
filterModels->res = res;
filterModels->color = color;
filterModels->gain = gain;
filterModels->peakL = peakL;
filterModels->peakR = peakR;
return filterModels;
}
int m_originalHeight;
};
#endif // EQCONTROLSDIALOG_H

265
plugins/Eq/EqEffect.cpp Normal file
View File

@@ -0,0 +1,265 @@
/*
* eqeffect.cpp - defination of EqEffect class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 "EqEffect.h"
#include "embed.cpp"
#include "lmms_math.h"
#include "BasicFilters.h"
#include "interpolation.h"
#include "Engine.h"
#include "MainWindow.h"
#include "EqFader.h"
extern "C"
{
Plugin::Descriptor PLUGIN_EXPORT eq_plugin_descriptor =
{
STRINGIFY( PLUGIN_NAME ),
"Equalizer",
QT_TRANSLATE_NOOP( "pluginBrowser", "A native eq plugin" ),
"Dave French <contact/dot/dave/dot/french3/at/googlemail/dot/com>",
0x0100,
Plugin::Effect,
new PluginPixmapLoader( "logo" ),
NULL,
NULL
} ;
}
EqEffect::EqEffect(Model *parent, const Plugin::Descriptor::SubPluginFeatures::Key *key) :
Effect( &eq_plugin_descriptor, parent, key ),
m_eqControls( this )
{
}
EqEffect::~EqEffect()
{
}
bool EqEffect::processAudioBuffer(sampleFrame *buf, const fpp_t frames)
{
if( !isEnabled() || !isRunning () )
{
return( false );
}
m_eqControls.m_inProgress = true;
double outSum = 0.0;
for( fpp_t f = 0; f < frames; ++f )
{
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
const float outGain = m_eqControls.m_outGainModel.getAmp();
const int sampleRate = Engine::mixer()->processingSampleRate();
sampleFrame m_inPeak = { 0, 0 };
if(m_eqControls.m_analyseIn )
{
m_eqControls.m_inFftBands.analyze( buf, frames );
}
else
{
m_eqControls.m_inFftBands.clear();
}
gain(buf , frames, m_eqControls.m_inGainModel.getAmp() , &m_inPeak );
m_eqControls.m_inPeakL = m_eqControls.m_inPeakL < m_inPeak[0] ? m_inPeak[0] : m_eqControls.m_inPeakL;
m_eqControls.m_inPeakR = m_eqControls.m_inPeakR < m_inPeak[1] ? m_inPeak[1] : m_eqControls.m_inPeakR;
if(m_eqControls.m_hpActiveModel.value() ){
m_hp12.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 );
m_hp12.processBuffer( buf, frames );
if( m_eqControls.m_hp24Model.value() || m_eqControls.m_hp48Model.value() )
{
m_hp24.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 );
m_hp24.processBuffer( buf, frames );
}
if( m_eqControls.m_hp48Model.value() )
{
m_hp480.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 );
m_hp480.processBuffer( buf, frames );
m_hp481.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 );
m_hp481.processBuffer( buf, frames );
}
}
if( m_eqControls.m_lowShelfActiveModel.value() )
{
m_lowShelf.setParameters( sampleRate, m_eqControls.m_lowShelfFreqModel.value(), m_eqControls.m_lowShelfResModel .value(), m_eqControls.m_lowShelfGainModel.value() );
m_lowShelf.processBuffer( buf, frames );
}
if( m_eqControls.m_para1ActiveModel.value() )
{
m_para1.setParameters( sampleRate, m_eqControls.m_para1FreqModel.value(), m_eqControls.m_para1BwModel.value(), m_eqControls.m_para1GainModel.value() );
m_para1.processBuffer( buf, frames );
}
if( m_eqControls.m_para2ActiveModel.value() )
{
m_para2.setParameters( sampleRate, m_eqControls.m_para2FreqModel.value(), m_eqControls.m_para2BwModel.value(), m_eqControls.m_para2GainModel.value() );
m_para2.processBuffer( buf, frames );
}
if( m_eqControls.m_para3ActiveModel.value() )
{
m_para3.setParameters( sampleRate, m_eqControls.m_para3FreqModel.value(), m_eqControls.m_para3BwModel.value(), m_eqControls.m_para3GainModel.value() );
m_para3.processBuffer( buf, frames );
}
if( m_eqControls.m_para4ActiveModel.value() )
{
m_para4.setParameters( sampleRate, m_eqControls.m_para4FreqModel.value(), m_eqControls.m_para4BwModel.value(), m_eqControls.m_para4GainModel.value() );
m_para4.processBuffer( buf, frames );
}
if( m_eqControls.m_highShelfActiveModel.value() )
{
m_highShelf.setParameters( sampleRate, m_eqControls.m_highShelfFreqModel.value(), m_eqControls.m_highShelfResModel.value(), m_eqControls.m_highShelfGainModel.value());
m_highShelf.processBuffer( buf, frames );
}
if(m_eqControls.m_lpActiveModel.value() ){
m_lp12.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 );
m_lp12.processBuffer( buf, frames );
if( m_eqControls.m_lp24Model.value() || m_eqControls.m_lp48Model.value() )
{
m_lp24.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 );
m_lp24.processBuffer( buf, frames );
}
if( m_eqControls.m_lp48Model.value() )
{
m_lp480.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 );
m_lp480.processBuffer( buf, frames );
m_lp481.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 );
m_lp481.processBuffer( buf, frames );
}
}
sampleFrame outPeak = { 0, 0 };
gain( buf, frames, outGain, &outPeak );
m_eqControls.m_outPeakL = m_eqControls.m_outPeakL < outPeak[0] ? outPeak[0] : m_eqControls.m_outPeakL;
m_eqControls.m_outPeakR = m_eqControls.m_outPeakR < outPeak[1] ? outPeak[1] : m_eqControls.m_outPeakR;
checkGate( outSum / frames );
if(m_eqControls.m_analyseOut )
{
m_eqControls.m_outFftBands.analyze( buf, frames );
setBandPeaks( &m_eqControls.m_outFftBands , ( int )( sampleRate * 0.5 ) );
}
else
{
m_eqControls.m_outFftBands.clear();
}
m_eqControls.m_inProgress = false;
return isRunning();
}
float EqEffect::peakBand( float minF, float maxF, EqAnalyser *fft, int sr )
{
float peak = -60;
float * b = fft->m_bands;
float h = 0;
for(int x = 0; x < MAX_BANDS; x++, b++)
{
if( bandToFreq( x ,sr) >= minF && bandToFreq( x,sr ) <= maxF )
{
h = 20*( log10( *b / fft->m_energy ) );
peak = h > peak ? h : peak;
}
}
return (peak+100)/100;
}
void EqEffect::setBandPeaks(EqAnalyser *fft, int samplerate )
{
m_eqControls.m_lowShelfPeakR = m_eqControls.m_lowShelfPeakL =
peakBand( 0,
m_eqControls.m_lowShelfFreqModel.value(), fft , samplerate );
m_eqControls.m_para1PeakL = m_eqControls.m_para1PeakR =
peakBand( m_eqControls.m_para1FreqModel.value()
- (m_eqControls.m_para1FreqModel.value() * m_eqControls.m_para1BwModel.value() * 0.5),
m_eqControls.m_para1FreqModel.value()
+ (m_eqControls.m_para1FreqModel.value() * m_eqControls.m_para1BwModel.value() * 0.5),
fft , samplerate );
m_eqControls.m_para2PeakL = m_eqControls.m_para2PeakR =
peakBand( m_eqControls.m_para2FreqModel.value()
- (m_eqControls.m_para2FreqModel.value() * m_eqControls.m_para2BwModel.value() * 0.5),
m_eqControls.m_para2FreqModel.value()
+ (m_eqControls.m_para2FreqModel.value() * m_eqControls.m_para2BwModel.value() * 0.5),
fft , samplerate );
m_eqControls.m_para3PeakL = m_eqControls.m_para3PeakR =
peakBand( m_eqControls.m_para3FreqModel.value()
- (m_eqControls.m_para3FreqModel.value() * m_eqControls.m_para3BwModel.value() * 0.5),
m_eqControls.m_para3FreqModel.value()
+ (m_eqControls.m_para3FreqModel.value() * m_eqControls.m_para3BwModel.value() * 0.5),
fft , samplerate );
m_eqControls.m_para4PeakL = m_eqControls.m_para4PeakR =
peakBand( m_eqControls.m_para4FreqModel.value()
- (m_eqControls.m_para4FreqModel.value() * m_eqControls.m_para4BwModel.value() * 0.5),
m_eqControls.m_para4FreqModel.value()
+ (m_eqControls.m_para4FreqModel.value() * m_eqControls.m_para4BwModel.value() * 0.5),
fft , samplerate );
m_eqControls.m_highShelfPeakL = m_eqControls.m_highShelfPeakR =
peakBand( m_eqControls.m_highShelfFreqModel.value(),
samplerate * 0.5 , fft, samplerate );
}
extern "C"
{
//needed for getting plugin out of shared lib
Plugin * PLUGIN_EXPORT lmms_plugin_main( Model* parent, void* data )
{
return new EqEffect( parent , static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>( data ) );
}
}

104
plugins/Eq/EqEffect.h Normal file
View File

@@ -0,0 +1,104 @@
/* eqeffect.h - defination of EqEffect class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 EQEFFECT_H
#define EQEFFECT_H
#include "Effect.h"
#include "EqControls.h"
#include "lmms_math.h"
#include "BasicFilters.h"
#include "EqFilter.h"
class EqEffect : public Effect
{
public:
EqEffect( Model* parent , const Descriptor::SubPluginFeatures::Key* key );
virtual ~EqEffect();
virtual bool processAudioBuffer( sampleFrame *buf, const fpp_t frames );
virtual EffectControls* controls()
{
return &m_eqControls;
}
inline void gain( sampleFrame *buf, const fpp_t frames, float scale, sampleFrame* peak )
{
peak[0][0] = 0.0f; peak[0][1] = 0.0f;
for( fpp_t f = 0; f < frames; ++f )
{
buf[f][0] *= scale;
buf[f][1] *= scale;
if( fabs( buf[f][0] ) > peak[0][0] )
{
peak[0][0] = fabs( buf[f][0] );
}
if( fabs( buf[f][1] ) > peak[0][1] )
{
peak[0][1] = fabs( buf[f][0] );
}
}
}
private:
EqControls m_eqControls;
EqHp12Filter m_hp12;
EqHp12Filter m_hp24;
EqHp12Filter m_hp480;
EqHp12Filter m_hp481;
EqLowShelfFilter m_lowShelf;
EqPeakFilter m_para1;
EqPeakFilter m_para2;
EqPeakFilter m_para3;
EqPeakFilter m_para4;
EqHighShelfFilter m_highShelf;
EqLp12Filter m_lp12;
EqLp12Filter m_lp24;
EqLp12Filter m_lp480;
EqLp12Filter m_lp481;
void analyze( sampleFrame *buf, const fpp_t frames, EqAnalyser* fft );
float peakBand(float minF, float maxF,EqAnalyser*, int);
inline float bandToFreq ( int index , int sampleRate )
{
return index * sampleRate / (MAX_BANDS * 2);
}
void setBandPeaks( EqAnalyser *fft , int);
};
#endif // EQEFFECT_H

101
plugins/Eq/EqFader.h Normal file
View File

@@ -0,0 +1,101 @@
/* eqfader.h - defination of EqFader class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 EQFADER_H
#define EQFADER_H
#include "Fader.h"
#include "EffectControls.h"
#include "MainWindow.h"
#include "qwidget.h"
#include "TextFloat.h"
#include "qlist.h"
class EqFader : public Fader
{
public:
Q_OBJECT
public:
EqFader( FloatModel * model, const QString & name, QWidget * parent, float* lPeak, float* rPeak ) :
Fader( model, name, parent)
{
setMinimumSize( 23, 116 );
setMaximumSize( 23, 116 );
resize( 23, 116 );
m_lPeak = lPeak;
m_rPeak = rPeak;
connect( Engine::mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( updateVuMeters() ) );
m_model = model;
setPeak_L( 0 );
setPeak_R( 0 );
}
~EqFader()
{
}
private slots:
void updateVuMeters()
{
const float opl = getPeak_L();
const float opr = getPeak_R();
const float fall_off = 1.2;
if( *m_lPeak > opl )
{
setPeak_L( *m_lPeak );
*m_lPeak = 0;
}
else
{
setPeak_L( opl/fall_off );
}
if( *m_rPeak > opr )
{
setPeak_R( *m_rPeak );
*m_rPeak = 0;
}
else
{
setPeak_R( opr/fall_off );
}
update();
}
private:
float* m_lPeak;
float* m_rPeak;
FloatModel* m_model;
};
#endif // EQFADER_H

445
plugins/Eq/EqFilter.h Normal file
View File

@@ -0,0 +1,445 @@
/*
* eqfilter.cpp - defination of EqFilterclass.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 EQFILTER_H
#define EQFILTER_H
#include "BasicFilters.h"
#include "lmms_math.h"
///
/// \brief The EqFilter class.
/// A wrapper for the StereoBiQuad class, giving it freq, res, and gain controls.
/// It is designed to process periods in one pass, with recalculation of coefficents
/// upon parameter changes. The intention is to use this as a bass class, children override
/// the calcCoefficents() function, providing the coefficents a1, a2, b0, b1, b2.
///
class EqFilter : public StereoBiQuad
{
public:
EqFilter()
{
}
virtual inline void setSampleRate( int sampleRate )
{
if( sampleRate != m_sampleRate )
{
m_sampleRate = sampleRate;
calcCoefficents();
}
}
virtual inline void setFrequency( float freq ){
if ( freq != m_freq )
{
m_freq = freq;
calcCoefficents();
}
}
virtual inline void setQ( float res )
{
if ( res != m_res )
{
m_res = res;
calcCoefficents();
}
}
virtual inline void setGain( float gain )
{
if ( gain != m_gain )
{
m_gain = gain;
calcCoefficents();
}
}
virtual inline void setParameters( float sampleRate, float freq, float res, float gain )
{
bool hasChanged = false;
if( sampleRate != m_sampleRate )
{
m_sampleRate = sampleRate;
hasChanged = true;
}
if ( freq != m_freq )
{
m_freq = freq;
hasChanged = true;
}
if ( res != m_res )
{
m_res = res;
hasChanged = true;
}
if ( gain != m_gain )
{
m_gain = gain;
hasChanged = true;
}
if ( hasChanged ) { calcCoefficents(); }
}
///
/// \brief processBuffer
/// \param buf Audio Buffer
/// \param frames Count of sampleFrames in Audio Buffer
///
virtual void processBuffer( sampleFrame* buf, const fpp_t frames )
{
for ( fpp_t f = 0 ; f < frames ; ++f)
{
buf[f][0] = update( buf[f][0] , 0);
buf[f][1] = update( buf[f][1] , 1);
}
}
protected:
///
/// \brief calcCoefficents
/// Override this in child classes to provide the coefficents, based on
/// Freq, Res and Gain
virtual void calcCoefficents(){
setCoeffs( 0, 0, 0, 0, 0 );
}
float m_sampleRate;
float m_freq;
float m_res;
float m_gain;
float m_bw;
};
///
/// \brief The EqHp12Filter class
/// A 2 pole High Pass Filter
/// Coefficent calculations from http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
class EqHp12Filter : public EqFilter
{
public :
virtual void calcCoefficents()
{
// calc intermediate
float w0 = F_2PI * m_freq / m_sampleRate;
float c = cosf( w0 );
float s = sinf( w0 );
float alpha = s / ( 2 * m_res );
float a0, a1, a2, b0, b1, b2; // coeffs to calculate
//calc coefficents
b0 = ( 1 + c ) * 0.5;
b1 = ( -( 1 + c ) );
b2 = ( 1 + c ) * 0.5;
a0 = 1 + alpha;
a1 = ( -2 * c );
a2 = 1 - alpha;
//normalise
b0 /= a0;
b1 /= a0;
b2 /= a0;
a1 /= a0;
a2 /= a0;
a0 = 1;
setCoeffs( a1, a2, b0, b1, b2 );
}
};
///
/// \brief The EqLp12Filter class.
/// A 2 pole low pass filter
/// Coefficent calculations from http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
///
class EqLp12Filter : public EqFilter
{
public :
virtual void calcCoefficents()
{
// calc intermediate
float w0 = F_2PI * m_freq / m_sampleRate;
float c = cosf( w0 );
float s = sinf( w0 );
float alpha = s / ( 2 * m_res );
float a0, a1, a2, b0, b1, b2; // coeffs to calculate
//calc coefficents
b0 = ( 1 - c ) * 0.5;
b1 = 1 - c;
b2 = ( 1 - c ) * 0.5;
a0 = 1 + alpha;
a1 = -2 * c;
a2 = 1 - alpha;
//normalise
b0 /= a0;
b1 /= a0;
b2 /= a0;
a1 /= a0;
a2 /= a0;
a0 = 1;
setCoeffs( a1, a2, b0, b1, b2 );
}
};
///
/// \brief The EqPeakFilter class
/// A Peak Filter
/// Coefficent calculations from http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
///
class EqPeakFilter : public EqFilter
{
public:
virtual void calcCoefficents()
{
// calc intermediate
float w0 = F_2PI * m_freq / m_sampleRate;
float c = cosf( w0 );
float s = sinf( w0 );
float A = pow( 10, m_gain * 0.025);
float alpha = s * sinh( log( 2 ) / 2 * m_bw * w0 / sinf(w0) );
float a0, a1, a2, b0, b1, b2; // coeffs to calculate
//calc coefficents
b0 = 1 + alpha*A;
b1 = -2*c;
b2 = 1 - alpha*A;
a0 = 1 + alpha/A;
a1 = -2*c;
a2 = 1 - alpha/A;
//normalise
b0 /= a0;
b1 /= a0;
b2 /= a0;
a1 /= a0;
a2 /= a0;
a0 = 1;
setCoeffs( a1, a2, b0, b1, b2 );
}
virtual inline void setParameters( float sampleRate, float freq, float bw, float gain )
{
bool hasChanged = false;
if( sampleRate != m_sampleRate )
{
m_sampleRate = sampleRate;
hasChanged = true;
}
if ( freq != m_freq )
{
m_freq = freq;
hasChanged = true;
}
if ( bw != m_bw )
{
m_bw = bw;
hasChanged = true;
}
if ( gain != m_gain )
{
m_gain = gain;
hasChanged = true;
}
if ( hasChanged ) { calcCoefficents(); }
}
};
class EqLowShelfFilter : public EqFilter
{
public :
virtual void calcCoefficents()
{
// calc intermediate
float w0 = F_2PI * m_freq / m_sampleRate;
float c = cosf( w0 );
float s = sinf( w0 );
float A = pow( 10, m_gain * 0.025);
// float alpha = s / ( 2 * m_res );
float beta = sqrt( A ) / m_res;
float a0, a1, a2, b0, b1, b2; // coeffs to calculate
//calc coefficents
b0 = A * ( ( A+1 ) - ( A-1 ) * c + beta * s );
b1 = 2 * A * ( ( A - 1 ) - ( A + 1 ) * c) ;
b2 = A * ( ( A + 1 ) - ( A - 1 ) * c - beta * s);
a0 = ( A + 1 ) + ( A - 1 ) * c + beta * s;
a1 = -2 * ( ( A - 1 ) + ( A + 1 ) * c );
a2 = ( A + 1 ) + ( A - 1) * c - beta * s;
//normalise
b0 /= a0;
b1 /= a0;
b2 /= a0;
a1 /= a0;
a2 /= a0;
a0 = 1;
setCoeffs( a1, a2, b0, b1, b2 );
}
};
class EqHighShelfFilter : public EqFilter
{
public :
virtual void calcCoefficents()
{
// calc intermediate
float w0 = F_2PI * m_freq / m_sampleRate;
float c = cosf( w0 );
float s = sinf( w0 );
float A = pow( 10, m_gain * 0.025 );
float beta = sqrt( A ) / m_res;
float a0, a1, a2, b0, b1, b2; // coeffs to calculate
//calc coefficents
b0 = A *( ( A +1 ) + ( A - 1 ) * c + beta * s);
b1 = -2 * A * ( ( A - 1 ) + ( A + 1 ) * c );
b2 = A * ( ( A + 1 ) + ( A - 1 ) * c - beta * s);
a0 = ( A + 1 ) - ( A - 1 ) * c + beta * s;
a1 = 2 * ( ( A - 1 ) - ( A + 1 ) * c );
a2 = ( A + 1) - ( A - 1 ) * c - beta * s;
//normalise
b0 /= a0;
b1 /= a0;
b2 /= a0;
a1 /= a0;
a2 /= a0;
a0 = 1;
setCoeffs( a1, a2, b0, b1, b2 );
}
};
class EqLinkwitzRiley : public StereoLinkwitzRiley
{
public:
EqLinkwitzRiley() :
StereoLinkwitzRiley( 44100),
m_freq(0 ),
m_sr( 1 )
{
}
virtual inline void setSR( int sampleRate )
{
if( sampleRate != m_sr )
{
m_sr = sampleRate;
setSampleRate( sampleRate );
setLowpass(m_freq);
}
}
virtual inline void setFrequency( float freq ){
if ( freq != m_freq )
{
m_freq = freq;
setLowpass(m_freq);
}
}
virtual void processBuffer( sampleFrame* buf, const fpp_t frames )
{
for ( fpp_t f = 0 ; f < frames ; ++f)
{
buf[f][0] = update( buf[f][0] , 0);
buf[f][1] = update( buf[f][1] , 1);
}
}
protected:
float m_freq;
int m_sr;
};
#endif // EQFILTER_H

View File

@@ -0,0 +1,255 @@
/*
* eqparameterwidget.cpp - defination of EqParameterWidget class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 "EqParameterWidget.h"
#include "QPainter"
#include "qwidget.h"
#include "lmms_math.h"
#include "MainWindow.h"
#include "QMouseEvent"
#include "EqControls.h"
EqParameterWidget::EqParameterWidget( QWidget *parent, EqControls * controls ) :
QWidget( parent ),
m_bands ( 0 ),
m_selectedBand ( 0 )
{
m_bands = new EqBand[8];
resize( 250, 116 );
// connect( Engine::mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( update() ) );
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(100);
float totalLength = log10( 21000 );
m_pixelsPerUnitWidth = width( ) / totalLength ;
float totalHeight = 80;
m_pixelsPerUnitHeight = (height() - 4) / ( totalHeight );
m_scale = 1.5;
m_pixelsPerOctave = freqToXPixel( 10000 ) - freqToXPixel( 5000 );
m_controls = controls;
tf = new TextFloat();
tf->hide();
}
EqParameterWidget::~EqParameterWidget()
{
if(m_bands)
{
delete[] m_bands;
m_bands = 0;
}
}
void EqParameterWidget::paintEvent( QPaintEvent *event )
{
QPainter painter( this );
//Draw Frequecy maker lines
painter.setPen( QPen( QColor( 100, 100, 100, 200 ), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) );
for( int x = 20 ; x < 100; x += 10)
{
painter.drawLine( freqToXPixel( x ) , 0, freqToXPixel( x ) , height() );
}
for( int x = 100 ; x < 1000; x += 100)
{
painter.drawLine( freqToXPixel( x ) , 0, freqToXPixel( x ) , height() );
}
for( int x = 1000 ; x < 11000; x += 1000)
{
painter.drawLine( freqToXPixel( x ) , 0, freqToXPixel( x ) , height() );
}
//draw 0dB line
painter.drawLine(0, gainToYPixel( 0 ) , width(), gainToYPixel( 0 ) );
for( int i = 0 ; i < bandCount() ; i++ )
{
m_bands[i].color.setAlpha( m_bands[i].active->value() ? activeAplha() : inactiveAlpha() );
painter.setPen( QPen( m_bands[i].color, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) );
float x = freqToXPixel( m_bands[i].freq->value() );
float y = height() * 0.5;
float gain = 1;
if( m_bands[i].gain )
{
gain = m_bands[i].gain->value();
}
y = gainToYPixel( gain );
float bw = m_bands[i].freq->value() * m_bands[i].res->value();
m_bands[i].x = x; m_bands[i].y = y;
const int radius = 7;
painter.drawEllipse( x - radius , y - radius, radius * 2 ,radius * 2 );
QString msg = QString ( "%1" ).arg ( QString::number (i + 1) );
painter.drawText(x - ( radius * 0.5 ), y + ( radius * 0.85 ), msg );
painter.setPen( QPen( m_bands[i].color, 1, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin ) );
if( i == 0 || i == bandCount() - 1 )
{
painter.drawLine(x , y, x, y - (m_bands[i].res->value() * 4 ) );
}
else
{
painter.drawLine(freqToXPixel(m_bands[i].freq->value()-(bw * 0.5)),y,freqToXPixel(m_bands[i].freq->value()+(bw * 0.5)),y);
}
}
}
void EqParameterWidget::mousePressEvent( QMouseEvent *event )
{
m_oldX = event->x(); m_oldY = event->y();
m_selectedBand = selectNearestHandle( event->x(), event->y() );
m_mouseAction = none;
if ( event->button() == Qt::LeftButton ) m_mouseAction = drag;
if ( event->button() == Qt::RightButton ) m_mouseAction = res;
}
void EqParameterWidget::mouseReleaseEvent( QMouseEvent *event )
{
m_selectedBand = 0;
m_mouseAction = none;
const int inXmin = 228;
const int inXmax = 250;
const int inYmin = 20;
const int inYmax = 30;
const int outXmin = 228;
const int outXmax = 250;
const int outYmin = 30;
const int outYmax = 40;
if(event->x() > inXmin && event->x() < inXmax && event->y() > inYmin && event->y() < inYmax )
{
m_controls->m_analyseIn = !m_controls->m_analyseIn;
}
if(event->x() > outXmin && event->x() < outXmax && event->y() > outYmin && event->y() < outYmax )
{
m_controls->m_analyseOut = !m_controls->m_analyseOut;
}
tf->hide();
}
void EqParameterWidget::mouseMoveEvent( QMouseEvent *event )
{
int deltaX = event->x() - m_oldX;
int deltaR = event->y() - m_oldY;
m_oldX = event->x(); m_oldY = event->y();
if(m_selectedBand && m_selectedBand->active->value() )
{
switch ( m_mouseAction ) {
case none :
break;
case drag:
if( m_selectedBand->freq ) m_selectedBand->freq->setValue( xPixelToFreq( m_oldX ) );
if( m_selectedBand->gain )m_selectedBand->gain->setValue( yPixelToGain( m_oldY ) );
break;
case res:
if( m_selectedBand->res )m_selectedBand->res->incValue( ( deltaX) * resPixelMultiplyer() );
if( m_selectedBand->res )m_selectedBand->res->incValue( (-deltaR) * resPixelMultiplyer() );
break;
default:
break;
}
}
if( m_oldX > 0 && m_oldX < width() && m_oldY > 0 && m_oldY < height() )
{
tf->setText( QString::number(xPixelToFreq( m_oldX )) + tr( "Hz ") );
tf->show();
const int x = event->x() > width() * 0.5 ?
m_oldX - tf->width() :
m_oldX;
tf->moveGlobal(this, QPoint( x, m_oldY - tf->height() ) );
}
}
void EqParameterWidget::mouseDoubleClickEvent( QMouseEvent *event )
{
EqBand* selected = selectNearestHandle( event->x() , event->y() );
if( selected )
{
selected->active->setValue( selected->active->value() ? 0 : 1 );
}
}
EqBand* EqParameterWidget::selectNearestHandle( const int x, const int y )
{
EqBand* selectedModel = 0;
float* distanceToHandles = new float[bandCount()];
//calc distance to each handle
for( int i = 0 ; i < bandCount() ; i++ )
{
int xOffset = m_bands[i].x - x;
int yOffset = m_bands[i].y - y;
distanceToHandles[i] = fabs( sqrt( ( xOffset * xOffset ) + ( yOffset * yOffset ) ) );
}
//select band
int shortestBand = 0;
for ( int i = 1 ; i < bandCount() ; i++ )
{
if ( distanceToHandles [i] < distanceToHandles[shortestBand] ){
shortestBand = i;
}
}
if(distanceToHandles[shortestBand] < maxDistanceFromHandle() )
{
selectedModel = &m_bands[shortestBand];
}
delete distanceToHandles;
return selectedModel;
}
EqBand::EqBand() :
gain ( 0 ),
res ( 0 ),
freq ( 0 ),
color ( QColor( 255, 255, 255 ) ),
x( 0 ),
y( 0 ),
name ( QString( "" ) ),
peakL( 0 ),
peakR( 0 )
{
}

View File

@@ -0,0 +1,166 @@
/*
* eqparameterwidget.cpp - defination of EqParameterWidget class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 EQPARAMETERWIDGET_H
#define EQPARAMETERWIDGET_H
#include <QWidget>
#include "EffectControls.h"
#include "TextFloat.h"
class EqControls;
class EqBand
{
public :
EqBand();
FloatModel* gain;
FloatModel* res;
FloatModel* freq;
BoolModel* active;
QColor color;
int x;
int y;
QString name;
float* peakL;
float* peakR;
};
class EqParameterWidget : public QWidget
{
Q_OBJECT
public:
explicit EqParameterWidget( QWidget *parent = 0, EqControls * controls = 0);
~EqParameterWidget();
const int bandCount()
{
return 8;
}
const int maxDistanceFromHandle()
{
return 20;
}
EqBand* getBandModels( int i )
{
return &m_bands[i];
}
const int activeAplha()
{
return 200;
}
const int inactiveAlpha()
{
return 100;
}
const float resPixelMultiplyer()
{
return 100;
}
signals:
public slots:
protected:
virtual void paintEvent ( QPaintEvent * event );
virtual void mousePressEvent(QMouseEvent * event );
virtual void mouseReleaseEvent(QMouseEvent * event);
virtual void mouseMoveEvent(QMouseEvent * event);
virtual void mouseDoubleClickEvent(QMouseEvent * event);
private:
EqBand *m_bands;
EqControls *m_controls;
float m_pixelsPerUnitWidth;
float m_pixelsPerUnitHeight;
float m_pixelsPerOctave;
float m_scale;
EqBand* m_selectedBand;
TextFloat *tf;
EqBand* selectNearestHandle( const int x, const int y );
enum MouseAction { none, drag, res } m_mouseAction;
int m_oldX, m_oldY;
int *m_xGridBands;
inline int freqToXPixel( float freq )
{
return ( log10( freq ) * m_pixelsPerUnitWidth * m_scale ) - ( width() * 0.5 );
}
inline float xPixelToFreq( int x )
{
return pow( 10, ( x + ( width() * 0.5 ) ) / ( m_pixelsPerUnitWidth * m_scale ) );
}
inline int gainToYPixel( float gain )
{
return ( height() - 3) - ( gain * m_pixelsPerUnitHeight ) - ( (height() -3 ) * 0.5);
}
inline float yPixelToGain( int y )
{
return ( ( 0.5 * height() ) - y) / m_pixelsPerUnitHeight;
}
};
#endif // EQPARAMETERWIDGET_H

225
plugins/Eq/EqSpectrumView.h Normal file
View File

@@ -0,0 +1,225 @@
/* eqspectrumview.h - defination of EqSpectrumView class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 EQSPECTRUMVIEW_H
#define EQSPECTRUMVIEW_H
#include "qpainter.h"
//#include "eqeffect.h"
#include "qwidget.h"
#include "fft_helpers.h"
#include "Engine.h"
const int MAX_BANDS = 2048;
class EqAnalyser
{
public:
fftwf_plan m_fftPlan;
fftwf_complex * m_specBuf;
float m_absSpecBuf[FFT_BUFFER_SIZE+1];
float m_buffer[FFT_BUFFER_SIZE*2];
int m_framesFilledUp;
float m_bands[MAX_BANDS];
float m_energy;
int m_sr;
bool m_active;
EqAnalyser() :
m_framesFilledUp ( 0 ),
m_energy ( 0 ),
m_sr ( 1 ),
m_active ( true )
{
m_inProgress=false;
m_specBuf = (fftwf_complex *) fftwf_malloc( ( FFT_BUFFER_SIZE + 1 ) * sizeof( fftwf_complex ) );
m_fftPlan = fftwf_plan_dft_r2c_1d( FFT_BUFFER_SIZE*2, m_buffer, m_specBuf, FFTW_MEASURE );
clear();
}
virtual ~EqAnalyser()
{
fftwf_destroy_plan( m_fftPlan );
fftwf_free( m_specBuf );
}
bool getInProgress()
{
return m_inProgress;
}
void clear()
{
m_framesFilledUp = 0;
m_energy = 0;
memset( m_buffer, 0, sizeof( m_buffer ) );
memset( m_bands, 0, sizeof( m_bands ) );
}
void analyze( sampleFrame *buf, const fpp_t frames )
{
if ( m_active )
{
m_inProgress=true;
const int FFT_BUFFER_SIZE = 2048;
fpp_t f = 0;
if( frames > FFT_BUFFER_SIZE )
{
m_framesFilledUp = 0;
f = frames - FFT_BUFFER_SIZE;
}
// meger channels
for( ; f < frames; ++f )
{
m_buffer[m_framesFilledUp] =
( buf[f][0] + buf[f][1] ) * 0.5;
++m_framesFilledUp;
}
if( m_framesFilledUp < FFT_BUFFER_SIZE )
{
m_inProgress = false;
return;
}
m_sr = Engine::mixer()->processingSampleRate();
const int LOWEST_FREQ = 0;
const int HIGHEST_FREQ = m_sr / 2;
fftwf_execute( m_fftPlan );
absspec( m_specBuf, m_absSpecBuf, FFT_BUFFER_SIZE+1 );
compressbands( m_absSpecBuf, m_bands, FFT_BUFFER_SIZE+1,
MAX_BANDS,
( int )( LOWEST_FREQ * ( FFT_BUFFER_SIZE + 1 ) / ( float )( m_sr / 2 ) ),
( int )( HIGHEST_FREQ * ( FFT_BUFFER_SIZE + 1) / ( float )( m_sr / 2 ) ) );
m_energy = maximum( m_bands, MAX_BANDS ) / maximum( m_buffer, FFT_BUFFER_SIZE );
m_framesFilledUp = 0;
m_inProgress = false;
m_active = false;
}
}
private:
bool m_inProgress;
};
class EqSpectrumView : public QWidget
{
public:
explicit EqSpectrumView( EqAnalyser * b, QWidget * _parent = 0 ):
QWidget( _parent ),
m_sa( b )
{
setFixedSize( 250, 116 );
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(2000);
setAttribute( Qt::WA_TranslucentBackground, true );
m_skipBands = MAX_BANDS * 0.5;
float totalLength = log10( 21000);
m_pixelsPerUnitWidth = width( ) / totalLength ;
m_scale = 1.5;
color = QColor( 255, 255, 255, 255 );
}
virtual ~EqSpectrumView()
{
}
QColor color;
EqAnalyser *m_sa;
QPainterPath pp;
virtual void paintEvent( QPaintEvent* event )
{
m_sa->m_active = isVisible();
const int fh = height();
const int LOWER_Y = -60; // dB
QPainter p( this );
p.setPen( QPen( color, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) );
const float e = m_sa->m_energy;
if( e <= 0 )
{
//dont draw anything
return;
}
if(m_sa->getInProgress() ){
p.fillPath( pp ,QBrush( color ) );
return;
}
pp = QPainterPath();
float * b = m_sa->m_bands;
int h;
pp.moveTo( 0,height() );
for( int x = 0; x < MAX_BANDS; ++x, ++b )
{
h = (int)( fh * 2.0 / 3.0 * ( 20 * ( log10 ( *b / e ) ) - LOWER_Y ) / (-LOWER_Y ) );
if( h < 0 ) h = 0; else if( h >= fh ) continue;
pp.lineTo( freqToXPixel(bandToFreq( x ) ), fh-h );
}
pp.lineTo( width(), height() );
pp.closeSubpath();
p.fillPath( pp, QBrush( color ) );
p.drawPath( pp );
}
inline int bandToXPixel( float band )
{
return ( log10( band - m_skipBands ) * m_pixelsPerUnitWidth * m_scale );
}
inline float bandToFreq ( int index )
{
return index * m_sa->m_sr / (MAX_BANDS * 2 );
}
inline int freqToXPixel( float freq )
{
return ( log10( freq ) * m_pixelsPerUnitWidth * m_scale ) - ( width() * 0.5 );
}
private:
float m_pixelsPerUnitWidth;
float m_scale;
int m_skipBands;
} ;
#endif // EQSPECTRUMVIEW_H

BIN
plugins/Eq/artwork.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,3 @@
INCLUDE(BuildPlugin)
BUILD_PLUGIN(flanger FlangerEffect.cpp FlangerControls.cpp FlangerControlsDialog.cpp Noise.cpp QuadratureLfo.cpp MonoDelay.cpp MOCFILES FlangerControls.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")

View File

@@ -0,0 +1,83 @@
/*
* flangercontrols.cpp - defination of FlangerControls class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 <QtXml/QDomElement>
#include "FlangerControls.h"
#include "FlangerEffect.h"
#include "Engine.h"
#include "Song.h"
FlangerControls::FlangerControls( FlangerEffect *effect ) :
EffectControls ( effect ),
m_effect ( effect ),
m_delayTimeModel(0.001, 0.0001, 0.050, 0.0001, this, tr( "Delay Samples" ) ) ,
m_lfoFrequencyModel( 0.25, 0.01, 5, 0.0001, 20000.0 ,this, tr( "Lfo Frequency" ) ),
m_lfoAmountModel( 0.0, 0.0, 0.0025 , 0.0001 , this , tr( "Seconds" ) ),
m_feedbackModel( 0.0 , 0.0 , 1.0 , 0.0001, this, tr( "Regen" ) ),
m_whiteNoiseAmountModel( 0.0 , 0.0 , 0.05 , 0.0001, this, tr( "Noise" ) ),
m_invertFeedbackModel ( false , this, tr( "Invert" ) )
{
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( changedSampleRate() ) );
}
void FlangerControls::loadSettings( const QDomElement &_this )
{
m_delayTimeModel.loadSettings( _this, "DelayTimeSamples" );
m_lfoFrequencyModel.loadSettings( _this, "LfoFrequency" );
m_lfoAmountModel.loadSettings( _this, "LfoAmount" );
m_feedbackModel.loadSettings( _this, "Feedback" );
m_whiteNoiseAmountModel.loadSettings( _this, "WhiteNoise" );
m_invertFeedbackModel.loadSettings( _this, "Invert" );
}
void FlangerControls::saveSettings( QDomDocument &doc, QDomElement &parent )
{
m_delayTimeModel.saveSettings( doc , parent, "DelayTimeSamples" );
m_lfoFrequencyModel.saveSettings( doc, parent , "LfoFrequency" );
m_lfoAmountModel.saveSettings( doc, parent , "LfoAmount" );
m_feedbackModel.saveSettings( doc, parent, "Feedback" ) ;
m_whiteNoiseAmountModel.saveSettings( doc, parent , "WhiteNoise" ) ;
m_invertFeedbackModel.saveSettings( doc, parent, "Invert" );
}
void FlangerControls::changedSampleRate()
{
m_effect->changeSampleRate();
}

View File

@@ -27,48 +27,48 @@
#include "EffectControls.h"
#include "Knob.h"
#include "flangercontrolsdialog.h"
#include "FlangerControlsDialog.h"
class FlangerEffect;
class FlangerControls : public EffectControls
{
Q_OBJECT
Q_OBJECT
public:
FlangerControls( FlangerEffect* effect );
virtual ~FlangerControls()
{
}
virtual void saveSettings ( QDomDocument& doc, QDomElement& parent );
virtual void loadSettings ( const QDomElement &_this );
inline virtual QString nodeName() const
{
return "Flanger";
}
virtual int controlCount()
{
return 5;
}
virtual EffectControlDialog* createView()
{
return new FlangerControlsDialog( this );
}
FlangerControls( FlangerEffect* effect );
virtual ~FlangerControls()
{
}
virtual void saveSettings ( QDomDocument& doc, QDomElement& parent );
virtual void loadSettings ( const QDomElement &_this );
inline virtual QString nodeName() const
{
return "Flanger";
}
virtual int controlCount()
{
return 5;
}
virtual EffectControlDialog* createView()
{
return new FlangerControlsDialog( this );
}
private slots:
void changedSampleRate();
void changedSampleRate();
private:
FlangerEffect* m_effect;
FloatModel m_delayTimeModel;
TempoSyncKnobModel m_lfoFrequencyModel;
FloatModel m_lfoAmountModel;
FloatModel m_feedbackModel;
FloatModel m_whiteNoiseAmountModel;
BoolModel m_invertFeedbackModel;
FlangerEffect* m_effect;
FloatModel m_delayTimeModel;
TempoSyncKnobModel m_lfoFrequencyModel;
FloatModel m_lfoAmountModel;
FloatModel m_feedbackModel;
FloatModel m_whiteNoiseAmountModel;
BoolModel m_invertFeedbackModel;
friend class FlangerControlsDialog;
friend class FlangerEffect;
friend class FlangerControlsDialog;
friend class FlangerEffect;
};

View File

@@ -22,8 +22,8 @@
*
*/
#include "flangercontrolsdialog.h"
#include "flangercontrols.h"
#include "FlangerControlsDialog.h"
#include "FlangerControls.h"
#include "embed.h"
#include "LedCheckbox.h"
#include "TempoSyncKnob.h"

View File

@@ -32,10 +32,10 @@ class FlangerControls;
class FlangerControlsDialog : public EffectControlDialog
{
public:
FlangerControlsDialog( FlangerControls* controls );
virtual ~FlangerControlsDialog()
{
}
FlangerControlsDialog( FlangerControls* controls );
virtual ~FlangerControlsDialog()
{
}
};
#endif // FLANGERCONTROLSDIALOG_H

View File

@@ -0,0 +1,151 @@
/*
* flangereffect.cpp - defination of FlangerEffect class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 "FlangerEffect.h"
#include "Engine.h"
#include "embed.cpp"
extern "C"
{
Plugin::Descriptor PLUGIN_EXPORT flanger_plugin_descriptor =
{
STRINGIFY( PLUGIN_NAME ),
"Flanger",
QT_TRANSLATE_NOOP( "pluginBrowser", "A native flanger plugin" ),
"Dave French <contact/dot/dave/dot/french3/at/googlemail/dot/com>",
0x0100,
Plugin::Effect,
new PluginPixmapLoader( "logo" ),
NULL,
NULL
} ;
FlangerEffect::FlangerEffect( Model *parent, const Plugin::Descriptor::SubPluginFeatures::Key *key ) :
Effect( &flanger_plugin_descriptor, parent, key ),
m_flangerControls( this )
{
m_lfo = new QuadratureLfo( Engine::mixer()->processingSampleRate() );
m_lDelay = new MonoDelay( 1, Engine::mixer()->processingSampleRate() );
m_rDelay = new MonoDelay( 1, Engine::mixer()->processingSampleRate() );
m_noise = new Noise;
}
FlangerEffect::~FlangerEffect()
{
if(m_lDelay )
{
delete m_lDelay;
}
if( m_rDelay )
{
delete m_rDelay;
}
if(m_lfo )
{
delete m_lfo;
}
if(m_noise)
{
delete m_noise;
}
}
bool FlangerEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{
return( false );
}
double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float length = m_flangerControls.m_delayTimeModel.value() * Engine::mixer()->processingSampleRate();
const float noise = m_flangerControls.m_whiteNoiseAmountModel.value();
float amplitude = m_flangerControls.m_lfoAmountModel.value() * Engine::mixer()->processingSampleRate();
bool invertFeedback = m_flangerControls.m_invertFeedbackModel.value();
m_lfo->setFrequency( m_flangerControls.m_lfoFrequencyModel.value() );
m_lDelay->setFeedback( m_flangerControls.m_feedbackModel.value() );
m_rDelay->setFeedback( m_flangerControls.m_feedbackModel.value() );
sample_t dryS[2];
float leftLfo;
float rightLfo;
for( fpp_t f = 0; f < frames; ++f )
{
buf[f][0] += m_noise->tick() * noise;
buf[f][1] += m_noise->tick() * noise;
dryS[0] = buf[f][0];
dryS[1] = buf[f][1];
m_lfo->tick(&leftLfo, &rightLfo);
m_lDelay->setLength( ( float )length + ( amplitude * leftLfo ) );
m_rDelay->setLength( ( float )length+ ( amplitude * rightLfo ) );
if(invertFeedback)
{
m_lDelay->tick( &buf[f][1] );
m_rDelay->tick(&buf[f][0] );
} else
{
m_lDelay->tick( &buf[f][0] );
m_rDelay->tick( &buf[f][1] );
}
buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] );
buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] );
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
checkGate( outSum / frames );
return isRunning();
}
void FlangerEffect::changeSampleRate()
{
m_lfo->setSampleRate( Engine::mixer()->processingSampleRate() );
m_lDelay->setSampleRate( Engine::mixer()->processingSampleRate() );
m_rDelay->setSampleRate( Engine::mixer()->processingSampleRate() );
}
extern "C"
{
//needed for getting plugin out of shared lib
Plugin * PLUGIN_EXPORT lmms_plugin_main( Model* parent, void* data )
{
return new FlangerEffect( parent , static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>( data ) );
}
}}

View File

@@ -27,30 +27,30 @@
#define FLANGEREFFECT_H
#include "Effect.h"
#include "flangercontrols.h"
#include "quadraturelfo.h"
#include "monodelay.h"
#include "noise.h"
#include "FlangerControls.h"
#include "QuadratureLfo.h"
#include "MonoDelay.h"
#include "Noise.h"
class FlangerEffect : public Effect
{
public:
FlangerEffect( Model* parent , const Descriptor::SubPluginFeatures::Key* key );
virtual ~FlangerEffect();
virtual bool processAudioBuffer( sampleFrame *buf, const fpp_t frames );
virtual EffectControls* controls()
{
return &m_flangerControls;
}
void changeSampleRate();
FlangerEffect( Model* parent , const Descriptor::SubPluginFeatures::Key* key );
virtual ~FlangerEffect();
virtual bool processAudioBuffer( sampleFrame *buf, const fpp_t frames );
virtual EffectControls* controls()
{
return &m_flangerControls;
}
void changeSampleRate();
private:
FlangerControls m_flangerControls;
MonoDelay* m_lDelay;
MonoDelay* m_rDelay;
QuadratureLfo* m_lfo;
Noise* m_noise;
FlangerControls m_flangerControls;
MonoDelay* m_lDelay;
MonoDelay* m_rDelay;
QuadratureLfo* m_lfo;
Noise* m_noise;
};

View File

@@ -22,20 +22,20 @@
*
*/
#include "monodelay.h"
#include "MonoDelay.h"
#include "interpolation.h"
#include "lmms_math.h"
MonoDelay::MonoDelay( int maxTime , int sampleRate )
{
m_buffer = 0;
m_maxTime = maxTime;
m_maxLength = maxTime * sampleRate;
m_length = m_maxLength;
m_buffer = 0;
m_maxTime = maxTime;
m_maxLength = maxTime * sampleRate;
m_length = m_maxLength;
m_index = 0;
m_feedback = 0.0f;
setSampleRate( sampleRate );
m_index = 0;
m_feedback = 0.0f;
setSampleRate( sampleRate );
}
@@ -43,10 +43,10 @@ MonoDelay::MonoDelay( int maxTime , int sampleRate )
MonoDelay::~MonoDelay()
{
if( m_buffer )
{
delete m_buffer;
}
if( m_buffer )
{
delete m_buffer;
}
}
@@ -54,24 +54,24 @@ MonoDelay::~MonoDelay()
void MonoDelay::tick( sample_t* sample )
{
m_buffer[m_index] = *sample;
int readIndex = m_index - ( int )m_length;
if(readIndex < 0)
{
readIndex += m_maxLength;
}
float fract = fraction( m_length );
if(readIndex != m_maxLength-1 )
{
*sample = linearInterpolate(m_buffer[readIndex] ,
m_buffer[readIndex+1], fract );
} else
{
*sample = linearInterpolate(m_buffer[readIndex] ,
m_buffer[0], fract );
}
m_buffer[m_index] += *sample * m_feedback;
m_index = ( m_index +1 ) % m_maxLength;
m_buffer[m_index] = *sample;
int readIndex = m_index - ( int )m_length - 1;
if(readIndex < 0)
{
readIndex += m_maxLength;
}
float fract = 1.0f - fraction( m_length );
if(readIndex != m_maxLength-1 )
{
*sample = linearInterpolate(m_buffer[readIndex] ,
m_buffer[readIndex+1], fract );
} else
{
*sample = linearInterpolate(m_buffer[readIndex] ,
m_buffer[0], fract );
}
m_buffer[m_index] += *sample * m_feedback;
m_index = ( m_index +1 ) % m_maxLength;
}
@@ -79,11 +79,11 @@ void MonoDelay::tick( sample_t* sample )
void MonoDelay::setSampleRate( int sampleRate )
{
if( m_buffer )
{
delete m_buffer;
}
if( m_buffer )
{
delete m_buffer;
}
m_buffer = new sample_t[( int )( sampleRate * m_maxTime )];
m_buffer = new sample_t[( int )( sampleRate * m_maxTime )];
}

View File

@@ -30,31 +30,31 @@
class MonoDelay
{
public:
MonoDelay( int maxTime , int sampleRate );
~MonoDelay();
inline void setLength( float length )
{
if( length <= m_maxLength && length >= 0 )
{
m_length = length;
}
}
MonoDelay( int maxTime , int sampleRate );
~MonoDelay();
inline void setLength( float length )
{
if( length <= m_maxLength && length >= 0 )
{
m_length = length;
}
}
inline void setFeedback( float feedback )
{
m_feedback = feedback;
}
inline void setFeedback( float feedback )
{
m_feedback = feedback;
}
void tick( sample_t* sample );
void setSampleRate( int sampleRate );
void tick( sample_t* sample );
void setSampleRate( int sampleRate );
private:
sample_t* m_buffer;
int m_maxLength;
float m_length;
int m_index;
float m_feedback;
float m_maxTime;
sample_t* m_buffer;
int m_maxLength;
float m_length;
int m_index;
float m_feedback;
float m_maxTime;
};
#endif // MONODELAY_H

View File

@@ -22,12 +22,12 @@
*
*/
#include "noise.h"
#include "Noise.h"
#include "lmms_math.h"
Noise::Noise()
{
inv_randmax = 1.0/FAST_RAND_MAX; /* for range of 0 - 1.0 */
inv_randmax = 1.0/FAST_RAND_MAX; /* for range of 0 - 1.0 */
}
@@ -35,5 +35,5 @@ Noise::Noise()
float Noise::tick()
{
return (float) ((2.0 * fast_rand() * inv_randmax) - 1.0);
return (float) ((2.0 * fast_rand() * inv_randmax) - 1.0);
}

View File

@@ -28,10 +28,10 @@
class Noise
{
public:
Noise();
float tick();
Noise();
float tick();
private:
double inv_randmax;
double inv_randmax;
};
#endif // NOISE_H

View File

@@ -22,17 +22,17 @@
*
*/
#include "quadraturelfo.h"
#include "QuadratureLfo.h"
QuadratureLfo::QuadratureLfo( int sampleRate )
{
setSampleRate(sampleRate);
setSampleRate(sampleRate);
}
void QuadratureLfo::tick( float *s, float *c )
{
*s = sinf( m_phase );
*c = cosf( m_phase );
m_phase += m_increment;
*s = sinf( m_phase );
*c = cosf( m_phase );
m_phase += m_increment;
}

View File

@@ -30,44 +30,44 @@
class QuadratureLfo
{
public:
QuadratureLfo( int sampleRate );
~QuadratureLfo()
{
}
QuadratureLfo( int sampleRate );
~QuadratureLfo()
{
}
inline void setFrequency( double frequency )
{
if( frequency < 0 || frequency > ( m_samplerate / 2.0 ) || frequency == m_frequency )
{
return;
}
m_frequency = frequency;
m_increment = m_frequency * m_twoPiOverSr;
inline void setFrequency( double frequency )
{
if( frequency < 0 || frequency > ( m_samplerate / 2.0 ) || frequency == m_frequency )
{
return;
}
m_frequency = frequency;
m_increment = m_frequency * m_twoPiOverSr;
if( m_phase >= F_2PI )
{
m_phase -= F_2PI;
}
}
if( m_phase >= F_2PI )
{
m_phase -= F_2PI;
}
}
inline void setSampleRate ( int samplerate )
{
m_samplerate = samplerate;
m_twoPiOverSr = F_2PI / samplerate;
m_increment = m_frequency * m_twoPiOverSr;
}
inline void setSampleRate ( int samplerate )
{
m_samplerate = samplerate;
m_twoPiOverSr = F_2PI / samplerate;
m_increment = m_frequency * m_twoPiOverSr;
}
void tick( float *s, float *c );
void tick( float *s, float *c );
private:
double m_frequency;
double m_phase;
double m_increment;
double m_twoPiOverSr;
int m_samplerate;
double m_frequency;
double m_phase;
double m_increment;
double m_twoPiOverSr;
int m_samplerate;
};

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
plugins/Flanger/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -567,6 +567,22 @@ lookahead_limiter::lookahead_limiter() {
asc_coeff = 1.f;
}
lookahead_limiter::~lookahead_limiter()
{
if( buffer != NULL)
{
free(buffer);
}
if( nextpos != NULL)
{
free(nextpos);
}
if( nextdelta != NULL)
{
free(nextdelta);
}
}
void lookahead_limiter::activate()
{
is_active = true;

View File

@@ -608,6 +608,7 @@ public:
void reset_asc();
bool get_asc();
lookahead_limiter();
~lookahead_limiter();
void set_multi(bool set);
void process(float &left, float &right, float *multi_buffer);
void set_sample_rate(uint32_t sr);

View File

@@ -47,6 +47,7 @@ struct ladspa_instance: public plugin_ctl_iface
#endif
ladspa_instance(audio_module_iface *_module, ladspa_plugin_metadata_set *_ladspa, int sample_rate);
virtual ~ladspa_instance();
virtual const line_graph_iface *get_line_graph_iface() const { return module->get_line_graph_iface(); }
virtual float get_param_value(int param_no);
virtual void set_param_value(int param_no, float value);

View File

@@ -263,6 +263,7 @@ class mono_audio_module:
}
public:
mono_audio_module();
~mono_audio_module();
void params_changed();
void activate();
void set_sample_rate(uint32_t sr);
@@ -291,6 +292,7 @@ class stereo_audio_module:
}
public:
stereo_audio_module();
~stereo_audio_module();
void params_changed();
void activate();
void set_sample_rate(uint32_t sr);

View File

@@ -84,6 +84,7 @@ public:
uint32_t srate;
bool is_active;
multibandlimiter_audio_module();
~multibandlimiter_audio_module();
void activate();
void deactivate();
void params_changed();

View File

@@ -460,6 +460,14 @@ stereo_audio_module::stereo_audio_module() {
meter_outR = 0.f;
}
stereo_audio_module::~stereo_audio_module()
{
if( buffer != NULL )
{
free(buffer);
}
}
void stereo_audio_module::activate() {
active = true;
}
@@ -686,6 +694,14 @@ mono_audio_module::mono_audio_module() {
meter_outR = 0.f;
}
mono_audio_module::~mono_audio_module()
{
if( buffer != NULL )
{
free(buffer);
}
}
void mono_audio_module::activate() {
active = true;
}

View File

@@ -252,6 +252,14 @@ multibandlimiter_audio_module::multibandlimiter_audio_module()
asc_old = true;
}
multibandlimiter_audio_module::~multibandlimiter_audio_module()
{
if( buffer != NULL)
{
free(buffer);
}
}
void multibandlimiter_audio_module::activate()
{
is_active = true;

View File

@@ -54,6 +54,11 @@ ladspa_instance::ladspa_instance(audio_module_iface *_module, ladspa_plugin_meta
module->post_instantiate();
}
ladspa_instance::~ladspa_instance()
{
delete module;
}
float ladspa_instance::get_param_value(int param_no)
{
// XXXKF hack

View File

@@ -116,6 +116,8 @@ static void activateDj_eq_mono(LADSPA_Handle instance) {
}
static void cleanupDj_eq_mono(LADSPA_Handle instance) {
Dj_eq_mono *plugin_data = (Dj_eq_mono *)instance;
free(plugin_data->filters);
free(instance);
}
@@ -283,6 +285,8 @@ static void activateDj_eq(LADSPA_Handle instance) {
}
static void cleanupDj_eq(LADSPA_Handle instance) {
Dj_eq *plugin_data = (Dj_eq *)instance;
free(plugin_data->filters);
free(instance);
}

View File

@@ -137,6 +137,7 @@ static void cleanupFastLookaheadLimiter(LADSPA_Handle instance) {
#line 188 "fast_lookahead_limiter_1913.xml"
FastLookaheadLimiter *plugin_data = (FastLookaheadLimiter *)instance;
free(plugin_data->buffer);
free(plugin_data->chunks);
free(instance);
}

View File

@@ -202,6 +202,11 @@ static void cleanupImp(LADSPA_Handle instance) {
local_free(plugin_data->op);
local_free(plugin_data->overlap);
local_free(plugin_data->opc);
unsigned int i;
for (i=0; i<IMPULSES; i++) {
local_free(plugin_data->impulse_freq[i]);
}
local_free(plugin_data->impulse_freq);
free(instance);
}

View File

@@ -163,6 +163,7 @@ static void cleanupVynil(LADSPA_Handle instance) {
free(plugin_data->buffer_m);
free(plugin_data->buffer_s);
free(plugin_data->click_buffer);
free(plugin_data->highp);
free(plugin_data->lowp_m);
free(plugin_data->lowp_s);
free(plugin_data->noise_filt);

View File

@@ -145,7 +145,8 @@ activate_eq(LADSPA_Handle instance) {
static
void
cleanup_eq(LADSPA_Handle instance) {
eq *plugin_data = (eq *)instance;
free(plugin_data->filters);
free(instance);
}

View File

@@ -167,7 +167,8 @@ activate_eq(LADSPA_Handle instance) {
static
void
cleanup_eq(LADSPA_Handle instance) {
eq *plugin_data = (eq *)instance;
free(plugin_data->filters);
free(instance);
}

View File

@@ -150,7 +150,7 @@ bool SpectrumAnalyzer::processAudioBuffer( sampleFrame* _buf, const fpp_t _frame
m_framesFilledUp = 0;
checkGate( 0 );
checkGate( 1 );
return isRunning();
}

View File

@@ -31,6 +31,7 @@
#include "ConfigManager.h"
VstSubPluginFeatures::VstSubPluginFeatures( Plugin::PluginTypes _type ) :
SubPluginFeatures( _type )
{
@@ -52,16 +53,40 @@ void VstSubPluginFeatures::fillDescriptionWidget( QWidget * _parent,
void VstSubPluginFeatures::listSubPluginKeys( const Plugin::Descriptor * _desc,
KeyList & _kl ) const
{
QStringList dlls = QDir( ConfigManager::inst()->vstDir() ).
entryList( QStringList() << "*.dll",
QDir::Files, QDir::Name );
QStringList *dlls = new QStringList();
const QString path = QString("");
addPluginsFromDir(dlls, path );
// TODO: eval m_type
for( QStringList::ConstIterator it = dlls.begin();
it != dlls.end(); ++it )
for( QStringList::ConstIterator it = dlls->begin();
it != dlls->end(); ++it )
{
EffectKey::AttributeMap am;
am["file"] = *it;
_kl.push_back( Key( _desc, QFileInfo( *it ).baseName(), am ) );
}
delete dlls;
}
void VstSubPluginFeatures::addPluginsFromDir( QStringList* filenames, QString path ) const
{
QStringList dirs = QDir ( ConfigManager::inst()->vstDir() + path ).
entryList( QStringList() << "*" ,
QDir::Dirs, QDir::Name );
for( int i = 0; i < dirs.size(); i++ )
{
if( dirs.at( i )[0] != '.' )
{
addPluginsFromDir( filenames, path+QDir::separator() + dirs.at( i ) );
}
}
QStringList dlls = QDir( ConfigManager::inst()->vstDir() + path ).
entryList( QStringList() << "*.dll",
QDir::Files, QDir::Name );
for( int i = 0; i < dlls.size(); i++ )
{
QString fName = path + QDir::separator() + dlls.at( i );
fName.remove( 0, 1 );
filenames->append( fName );
}
}

View File

@@ -40,8 +40,13 @@ public:
virtual void listSubPluginKeys( const Plugin::Descriptor * _desc,
KeyList & _kl ) const;
private:
void addPluginsFromDir(QStringList* filenames, QString path) const;
} ;
#endif

View File

@@ -71,4 +71,3 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) :
}
#include "moc_delaycontrols.cxx"

View File

@@ -214,11 +214,10 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
s[0] *= outputGain;
s[1] *= outputGain;
out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];
// mix wet/dry signals
_buf[f][0] = d * _buf[f][0] + w * s[0];
_buf[f][1] = d * _buf[f][1] + w * s[1];
out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];
}
checkGate( out_sum / _frames );

View File

@@ -1,3 +0,0 @@
INCLUDE(BuildPlugin)
BUILD_PLUGIN(flanger flangereffect.cpp flangercontrols.cpp flangercontrolsdialog.cpp noise.cpp quadraturelfo.cpp monodelay.cpp MOCFILES flangercontrols.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")

View File

@@ -1,83 +0,0 @@
/*
* flangercontrols.cpp - defination of FlangerControls class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 <QtXml/QDomElement>
#include "flangercontrols.h"
#include "flangereffect.h"
#include "Engine.h"
#include "Song.h"
FlangerControls::FlangerControls( FlangerEffect *effect ) :
EffectControls ( effect ),
m_effect ( effect ),
m_delayTimeModel(0.001, 0.0001, 0.050, 0.0001, this, tr( "Delay Samples" ) ) ,
m_lfoFrequencyModel( 0.25, 0.01, 5, 0.0001, 20000.0 ,this, tr( "Lfo Frequency" ) ),
m_lfoAmountModel( 0.0, 0.0, 0.0025 , 0.0001 , this , tr( "Seconds" ) ),
m_feedbackModel( 0.0 , 0.0 , 1.0 , 0.0001, this, tr( "Regen" ) ),
m_whiteNoiseAmountModel( 0.0 , 0.0 , 0.05 , 0.0001, this, tr( "Noise" ) ),
m_invertFeedbackModel ( false , this, tr( "Invert" ) )
{
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( changedSampleRate() ) );
}
void FlangerControls::loadSettings( const QDomElement &_this )
{
m_delayTimeModel.loadSettings( _this, "DelayTimeSamples" );
m_lfoFrequencyModel.loadSettings( _this, "LfoFrequency" );
m_lfoAmountModel.loadSettings( _this, "LfoAmount" );
m_feedbackModel.loadSettings( _this, "Feedback" );
m_whiteNoiseAmountModel.loadSettings( _this, "WhiteNoise" );
m_invertFeedbackModel.loadSettings( _this, "Invert" );
}
void FlangerControls::saveSettings( QDomDocument &doc, QDomElement &parent )
{
m_delayTimeModel.saveSettings( doc , parent, "DelayTimeSamples" );
m_lfoFrequencyModel.saveSettings( doc, parent , "LfoFrequency" );
m_lfoAmountModel.saveSettings( doc, parent , "LfoAmount" );
m_feedbackModel.saveSettings( doc, parent, "Feedback" ) ;
m_whiteNoiseAmountModel.saveSettings( doc, parent , "WhiteNoise" ) ;
m_invertFeedbackModel.saveSettings( doc, parent, "Invert" );
}
void FlangerControls::changedSampleRate()
{
m_effect->changeSampleRate();
}

View File

@@ -1,151 +0,0 @@
/*
* flangereffect.cpp - defination of FlangerEffect class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 "flangereffect.h"
#include "Engine.h"
#include "embed.cpp"
extern "C"
{
Plugin::Descriptor PLUGIN_EXPORT flanger_plugin_descriptor =
{
STRINGIFY( PLUGIN_NAME ),
"Flanger",
QT_TRANSLATE_NOOP( "pluginBrowser", "A native flanger plugin" ),
"Dave French <contact/dot/dave/dot/french3/at/googlemail/dot/com>",
0x0100,
Plugin::Effect,
new PluginPixmapLoader( "logo" ),
NULL,
NULL
} ;
FlangerEffect::FlangerEffect( Model *parent, const Plugin::Descriptor::SubPluginFeatures::Key *key ) :
Effect( &flanger_plugin_descriptor, parent, key ),
m_flangerControls( this )
{
m_lfo = new QuadratureLfo( Engine::mixer()->processingSampleRate() );
m_lDelay = new MonoDelay( 1, Engine::mixer()->processingSampleRate() );
m_rDelay = new MonoDelay( 1, Engine::mixer()->processingSampleRate() );
m_noise = new Noise;
}
FlangerEffect::~FlangerEffect()
{
if(m_lDelay )
{
delete m_lDelay;
}
if( m_rDelay )
{
delete m_rDelay;
}
if(m_lfo )
{
delete m_lfo;
}
if(m_noise)
{
delete m_noise;
}
}
bool FlangerEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{
return( false );
}
double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float length = m_flangerControls.m_delayTimeModel.value() * Engine::mixer()->processingSampleRate();
const float noise = m_flangerControls.m_whiteNoiseAmountModel.value();
float amplitude = m_flangerControls.m_lfoAmountModel.value() * Engine::mixer()->processingSampleRate();
bool invertFeedback = m_flangerControls.m_invertFeedbackModel.value();
m_lfo->setFrequency( m_flangerControls.m_lfoFrequencyModel.value() );
m_lDelay->setFeedback( m_flangerControls.m_feedbackModel.value() );
m_rDelay->setFeedback( m_flangerControls.m_feedbackModel.value() );
sample_t dryS[2];
float leftLfo;
float rightLfo;
for( fpp_t f = 0; f < frames; ++f )
{
buf[f][0] += m_noise->tick() * noise;
buf[f][1] += m_noise->tick() * noise;
dryS[0] = buf[f][0];
dryS[1] = buf[f][1];
m_lfo->tick(&leftLfo, &rightLfo);
m_lDelay->setLength( ( float )length + ( amplitude * leftLfo ) );
m_rDelay->setLength( ( float )length+ ( amplitude * rightLfo ) );
if(invertFeedback)
{
m_lDelay->tick( &buf[f][1] );
m_rDelay->tick(&buf[f][0] );
} else
{
m_lDelay->tick( &buf[f][0] );
m_rDelay->tick( &buf[f][1] );
}
buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] );
buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] );
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
checkGate( outSum / frames );
return isRunning();
}
void FlangerEffect::changeSampleRate()
{
m_lfo->setSampleRate( Engine::mixer()->processingSampleRate() );
m_lDelay->setSampleRate( Engine::mixer()->processingSampleRate() );
m_rDelay->setSampleRate( Engine::mixer()->processingSampleRate() );
}
extern "C"
{
//needed for getting plugin out of shared lib
Plugin * PLUGIN_EXPORT lmms_plugin_main( Model* parent, void* data )
{
return new FlangerEffect( parent , static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>( data ) );
}
}}

View File

@@ -172,10 +172,11 @@ void VstPlugin::tryLoad( const QString &remoteVstPluginExecutable )
QString p = m_plugin;
if( QFileInfo( p ).dir().isRelative() )
{
p = ConfigManager::inst()->vstDir() + QDir::separator() + p;
}
if( QFileInfo( p ).dir().isRelative() )
{
p = ConfigManager::inst()->vstDir() + p;
}
sendMessage( message( IdVstLoadPlugin ).addString( QSTR_TO_STDSTR( p ) ) );

View File

@@ -130,11 +130,10 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf,
s[0] *= output;
s[1] *= output;
out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];
// mix wet/dry signals
_buf[f][0] = d * _buf[f][0] + w * s[0];
_buf[f][1] = d * _buf[f][1] + w * s[1];
out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];
}
checkGate( out_sum / _frames );

View File

@@ -373,6 +373,119 @@ float *AutomationPattern::valuesAfter( const MidiTime & _time ) const
void AutomationPattern::flipY( int min, int max )
{
timeMap tempMap = m_timeMap;
timeMap::ConstIterator iterate = m_timeMap.lowerBound(0);
float tempValue = 0;
int numPoints = 0;
for( int i = 0; ( iterate + i + 1 ) != m_timeMap.end() && ( iterate + i ) != m_timeMap.end() ; i++)
{
numPoints++;
}
for( int i = 0; i <= numPoints; i++ )
{
if ( min < 0 )
{
tempValue = valueAt( ( iterate + i ).key() ) * -1;
putValue( MidiTime( (iterate + i).key() ) , tempValue, false);
}
else
{
tempValue = max - valueAt( ( iterate + i ).key() );
putValue( MidiTime( (iterate + i).key() ) , tempValue, false);
}
}
generateTangents();
emit dataChanged();
}
void AutomationPattern::flipX( int length )
{
timeMap tempMap;
timeMap::ConstIterator iterate = m_timeMap.lowerBound(0);
float tempValue = 0;
int numPoints = 0;
for( int i = 0; ( iterate + i + 1 ) != m_timeMap.end() && ( iterate + i ) != m_timeMap.end() ; i++)
{
numPoints++;
}
float realLength = ( iterate + numPoints ).key();
if ( length != -1 && length != realLength)
{
if ( realLength < length )
{
tempValue = valueAt( ( iterate + numPoints ).key() );
putValue( MidiTime( length ) , tempValue, false);
numPoints++;
for( int i = 0; i <= numPoints; i++ )
{
tempValue = valueAt( ( iterate + i ).key() );
cleanObjects();
MidiTime newTime = MidiTime( length - ( iterate + i ).key() );
tempMap[newTime] = tempValue;
}
}
else
{
//for ( int i = 0; ( iterate + i ).key() < length ; i++ )
//{
// tempValue = valueAt( ( iterate + i ).key() );
//}
//putValue( MidiTime( length ) , tempValue, false);
//numPoints++;
for( int i = 0; i <= numPoints; i++ )
{
tempValue = valueAt( ( iterate + i ).key() );
cleanObjects();
MidiTime newTime;
if ( ( iterate + i ).key() <= length )
{
newTime = MidiTime( length - ( iterate + i ).key() );
}
else
{
newTime = MidiTime( ( iterate + i ).key() );
}
tempMap[newTime] = tempValue;
}
}
}
else
{
for( int i = 0; i <= numPoints; i++ )
{
tempValue = valueAt( ( iterate + i ).key() );
cleanObjects();
MidiTime newTime = MidiTime( realLength - ( iterate + i ).key() );
tempMap[newTime] = tempValue;
}
}
m_timeMap.clear();
m_timeMap = tempMap;
generateTangents();
emit dataChanged();
}
void AutomationPattern::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
_this.setAttribute( "pos", startPosition() );
@@ -724,7 +837,7 @@ void AutomationPattern::generateTangents()
void AutomationPattern::generateTangents( timeMap::const_iterator it,
int numToGenerate )
{
if( m_timeMap.size() < 2 )
if( m_timeMap.size() < 2 && numToGenerate > 0 )
{
m_tangents[it.key()] = 0;
return;

Some files were not shown because too many files have changed in this diff Show More