code:
/*
 * BBEditor.h - view-component of BB-Editor
 *
 * Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef BB_EDITOR_H
#define BB_EDITOR_H

#include "Editor.h"
#include "TrackContainerView.h"

class BBTrackContainer;
class ComboBox;

class BBTrackContainerView;

class BBEditor : public Editor
{
	Q_OBJECT
public:
	BBEditor( BBTrackContainer * _tc );
	~BBEditor();

	QSize sizeHint() const override;

	const BBTrackContainerView* trackContainerView() const {
		return m_trackContainerView;
	}
	BBTrackContainerView* trackContainerView() {
		return m_trackContainerView;
	}

	void removeBBView( int bb );

public slots:
	void play() override;
	void stop() override;

private:
	BBTrackContainerView* m_trackContainerView;
	ComboBox * m_bbComboBox;
} ;

class BBTrackContainerView : public TrackContainerView
{
	Q_OBJECT
public:
	BBTrackContainerView(BBTrackContainer* tc);

	bool fixedTCOs() const override
	{
		return true;
	}

	void removeBBView(int bb);

	void saveSettings(QDomDocument& doc, QDomElement& element) override;
	void loadSettings(const QDomElement& element) override;

public slots:
	void addSteps();
	void cloneSteps();
	void removeSteps();
	void addSampleTrack();
	void addAutomationTrack();
	void clonePattern();

protected slots:
	void dropEvent(QDropEvent * de ) override;
	void updatePosition();

private:
	BBTrackContainer * m_bbtc;
	void makeSteps( bool clone );
};

#endif


code:
/*
 * BBTrack.h - class BBTrack, a wrapper for using bbEditor
 *              (which is a singleton-class) as track
 *
 * Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef BB_TRACK_H
#define BB_TRACK_H

#include <QtCore/QObject>
#include <QtCore/QMap>
#include <QStaticText>

#include "TrackContentObjectView.h"
#include "Track.h"
#include "TrackView.h"

class TrackLabelButton;
class TrackContainer;

class BBTCO : public TrackContentObject
{
public:
	BBTCO( Track * _track );
	virtual ~BBTCO() = default;

	void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
	void loadSettings( const QDomElement & _this ) override;
	inline QString nodeName() const override
	{
		return( "bbtco" );
	}

	int bbTrackIndex();

	TrackContentObjectView * createView( TrackView * _tv ) override;

private:

	friend class BBTCOView;

} ;

class BBTCOView : public TrackContentObjectView
{
	Q_OBJECT
public:
	BBTCOView( TrackContentObject * _tco, TrackView * _tv );
	virtual ~BBTCOView() = default;

public slots:
	void update() override;

protected slots:
	void openInBBEditor();
	void resetName();
	void changeName();

protected:
	void paintEvent( QPaintEvent * pe ) override;
	void mouseDoubleClickEvent( QMouseEvent * _me ) override;
	void constructContextMenu( QMenu * ) override;

private:
	BBTCO * m_bbTCO;
	QPixmap m_paintPixmap;

	QStaticText m_staticTextName;
} ;

class LMMS_EXPORT BBTrack : public Track
{
	Q_OBJECT
public:
	BBTrack( TrackContainer* tc );
	virtual ~BBTrack();

	virtual bool play( const TimePos & _start, const fpp_t _frames,
						const f_cnt_t _frame_base, int _tco_num = -1 ) override;
	TrackView * createView( TrackContainerView* tcv ) override;
	TrackContentObject* createTCO(const TimePos & pos) override;

	virtual void saveTrackSpecificSettings( QDomDocument & _doc,
							QDomElement & _parent ) override;
	void loadTrackSpecificSettings( const QDomElement & _this ) override;

	static BBTrack * findBBTrack( int _bb_num );
	static void swapBBTracks( Track * _track1, Track * _track2 );

	int index()
	{
		return s_infoMap[this];
	}

	bool automationDisabled( Track * _track )
	{
		return( m_disabledTracks.contains( _track ) );
	}
	void disableAutomation( Track * _track )
	{
		m_disabledTracks.append( _track );
	}
	void enableAutomation( Track * _track )
	{
		m_disabledTracks.removeAll( _track );
	}

protected:
	inline QString nodeName() const override
	{
		return( "bbtrack" );
	}

private:
	QList<Track *> m_disabledTracks;

	typedef QMap<BBTrack *, int> infoMap;
	static infoMap s_infoMap;

	friend class BBTrackView;

} ;

class BBTrackView : public TrackView
{
	Q_OBJECT
public:
	BBTrackView( BBTrack* bbt, TrackContainerView* tcv );
	virtual ~BBTrackView();

	bool close() override;

	const BBTrack * getBBTrack() const
	{
		return( m_bbTrack );
	}

public slots:
	void clickedTrackLabel();

private:
	BBTrack * m_bbTrack;
	TrackLabelButton * m_trackLabel;

} ;

#endif

repo_name: CYBERDEViL/LMMS

license: mit


code:
/*
 * BBTrackContainer.h - model-component of BB-Editor
 *
 * Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef BB_TRACK_CONTAINER_H
#define BB_TRACK_CONTAINER_H

#include "TrackContainer.h"
#include "ComboBoxModel.h"

class LMMS_EXPORT BBTrackContainer : public TrackContainer
{
	Q_OBJECT
	mapPropertyFromModel(int,currentBB,setCurrentBB,m_bbComboBoxModel);
public:
	BBTrackContainer();
	virtual ~BBTrackContainer();

	virtual bool play(TimePos start, const fpp_t frames, const f_cnt_t frameBase, int tcoNum = -1);

	void updateAfterTrackAdd() override;

	inline QString nodeName() const override
	{
		return "bbtrackcontainer";
	}

	bar_t lengthOfBB(int bb) const;
	inline bar_t lengthOfCurrentBB()
	{
		return lengthOfBB(currentBB());
	}
	int numOfBBs() const;
	void removeBB(int bb);

	void swapBB(int bb1, int bb2);

	void updateBBTrack(TrackContentObject * tco);
	void fixIncorrectPositions();
	void createTCOsForBB(int bb);

	AutomatedValueMap automatedValuesAt(TimePos time, int tcoNum) const override;

public slots:
	void play();
	void stop();
	void updateComboBox();
	void currentBBChanged();

private:
	ComboBoxModel m_bbComboBoxModel;

	friend class BBEditor;

} ;

#endif


code:
/*
 * BandLimitedWave.h - helper functions for band-limited
 *                    	waveform generation
 *
 * Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef BANDLIMITEDWAVE_H
#define BANDLIMITEDWAVE_H

class QDataStream;
class QString;

#include "lmms_export.h"
#include "interpolation.h"
#include "lmms_basics.h"
#include "lmms_math.h"
#include "Engine.h"
#include "Mixer.h"

#define MAXLEN 11
#define MIPMAPSIZE 2 << ( MAXLEN + 1 )
#define MIPMAPSIZE3 3 << ( MAXLEN + 1 )
#define MAXTBL 23
#define MINTLEN 2 << 0
#define MAXTLEN 3 << MAXLEN

// table for table sizes
const int TLENS[MAXTBL+1] = { 2 << 0, 3 << 0, 2 << 1, 3 << 1,
					2 << 2, 3 << 2, 2 << 3, 3 << 3,
					2 << 4, 3 << 4, 2 << 5, 3 << 5,
					2 << 6, 3 << 6, 2 << 7, 3 << 7,
					2 << 8, 3 << 8, 2 << 9, 3 << 9,
					2 << 10, 3 << 10, 2 << 11, 3 << 11 };

typedef struct
{
public:
	inline sample_t sampleAt( int table, int ph )
	{
		if( table % 2 == 0 )
		{	return m_data[ TLENS[ table ] + ph ]; }
		else
		{	return m_data3[ TLENS[ table ] + ph ]; }
	}
	inline void setSampleAt( int table, int ph, sample_t sample )
	{
		if( table % 2 == 0 )
		{	m_data[ TLENS[ table ] + ph ] = sample; }
		else
		{ 	m_data3[ TLENS[ table ] + ph ] = sample; }
	}
private:
	sample_t m_data [ MIPMAPSIZE ];
	sample_t m_data3 [ MIPMAPSIZE3 ];

} WaveMipMap;

QDataStream& operator<< ( QDataStream &out, WaveMipMap &waveMipMap );

QDataStream& operator>> ( QDataStream &in, WaveMipMap &waveMipMap );

class LMMS_EXPORT BandLimitedWave
{
public:
	enum Waveforms
	{
		BLSaw,
		BLSquare,
		BLTriangle,
		BLMoog,
		NumBLWaveforms
	};

	BandLimitedWave() {};
	virtual ~BandLimitedWave() {};

	/*! \brief This method converts frequency to wavelength. The oscillate function takes wavelength as argument so
	 * use this to convert your note frequency to wavelength before using it.
	 */
	static inline float freqToLen( float f )
	{
		return freqToLen( f, Engine::mixer()->processingSampleRate() );
	}

	/*! \brief This method converts frequency to wavelength, but you can use any custom sample rate with it.
	 */
	static inline float freqToLen( float f, sample_rate_t sr )
	{
		return static_cast<float>( sr ) / f;
	}

	/*! \brief This method converts phase delta to wavelength. It assumes a phase scale of 0 to 1. */
	static inline float pdToLen( float pd )
	{
		return 1.0f / pd;
	}

	/*! \brief This method provides interpolated samples of bandlimited waveforms.
	 *  \param _ph The phase of the sample.
	 *  \param _wavelen The wavelength (length of one cycle, ie. the inverse of frequency) of the wanted oscillation, measured in sample frames
	 *  \param _wave The wanted waveform. Options currently are saw, triangle, square and moog saw.
	 */
	static inline sample_t oscillate( float _ph, float _wavelen, Waveforms _wave )
	{
		// get the next higher tlen
		int t = 0;
		while( t < MAXTBL && _wavelen >= TLENS[t+1] ) { t++; }

		int tlen = TLENS[t];
		const float ph = fraction( _ph );
		const float lookupf = ph * static_cast<float>( tlen );
		int lookup = static_cast<int>( lookupf );
		const float ip = fraction( lookupf );

		const sample_t s1 = s_waveforms[ _wave ].sampleAt( t, lookup );
		const sample_t s2 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen );

		const int lm = lookup == 0 ? tlen - 1 : lookup - 1;
		const sample_t s0 = s_waveforms[ _wave ].sampleAt( t, lm );
		const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 2 ) % tlen );
		const sample_t sr = optimal4pInterpolate( s0, s1, s2, s3, ip );

		return sr;

/*		lookup = lookup << 1;
		tlen = tlen << 1;
		t += 1;
		const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, lookup );
		const sample_t s4 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen );
		const sample_t s34 = linearInterpolate( s3, s4, ip );

		const float ip2 = ( ( tlen - _wavelen ) / tlen - 0.5 ) * 2.0;

		return linearInterpolate( s12, s34, ip2 );
	*/
	};

	static void generateWaves();

	static bool s_wavesGenerated;

	static WaveMipMap s_waveforms [NumBLWaveforms];

	static QString s_wavetableDir;
};

#endif


code:
/*
 * BasicFilters.h - simple but powerful filter-class with most used filters
 *
 * original file by ???
 * modified and enhanced by Tobias Doerffel
 *
 * Lowpass_SV code originally from Nekobee, Copyright (C) 2004 Sean Bolton and others
 * adapted & modified for use in LMMS
 *
 * Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef BASIC_FILTERS_H
#define BASIC_FILTERS_H

#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif

#include <math.h>

#include "lmms_basics.h"
#include "lmms_constants.h"
#include "interpolation.h"
#include "MemoryManager.h"

template<ch_cnt_t CHANNELS=DEFAULT_CHANNELS> class BasicFilters;

template<ch_cnt_t CHANNELS>
class LinkwitzRiley
{
	MM_OPERATORS
public:
	LinkwitzRiley( float sampleRate )
	{
		m_sampleRate = sampleRate;
		clearHistory();
	}
	virtual ~LinkwitzRiley() {}

	inline void clearHistory()
	{
		for( int i = 0; i < CHANNELS; ++i )
		{
			m_z1[i] = m_z2[i] = m_z3[i] = m_z4[i] = 0.0f;
		}
	}

	inline void setSampleRate( float sampleRate )
	{
		m_sampleRate = sampleRate;
	}

	inline void setCoeffs( float freq )
	{
		// wc
		const double wc = D_2PI * freq;
		const double wc2 = wc * wc;
		const double wc3 = wc2 * wc;
		m_wc4 = wc2 * wc2;

		// k
		const double k = wc / tan( D_PI * freq / m_sampleRate );
		const double k2 = k * k;
		const double k3 = k2 * k;
		m_k4 = k2 * k2;

		// a
		static const double sqrt2 = sqrt( 2.0 );
		const double sq_tmp1 = sqrt2 * wc3 * k;
		const double sq_tmp2 = sqrt2 * wc * k3;

		m_a = 1.0 / ( 4.0 * wc2 * k2 + 2.0 * sq_tmp1 + m_k4 + 2.0 * sq_tmp2 + m_wc4 );

		// b
		m_b1 = ( 4.0 * ( m_wc4 + sq_tmp1 - m_k4 - sq_tmp2 ) ) * m_a;
		m_b2 = ( 6.0 * m_wc4 - 8.0 * wc2 * k2 + 6.0 * m_k4 ) * m_a;
		m_b3 = ( 4.0 * ( m_wc4 - sq_tmp1 + sq_tmp2 - m_k4 ) ) * m_a;
		m_b4 = ( m_k4 - 2.0 * sq_tmp1 + m_wc4 - 2.0 * sq_tmp2 + 4.0 * wc2 * k2 ) * m_a;
	}

	inline void setLowpass( float freq )
	{
		setCoeffs( freq );
		m_a0 = m_wc4 * m_a;
		m_a1 = 4.0 * m_a0;
		m_a2 = 6.0 * m_a0;
	}

	inline void setHighpass( float freq )
	{
		setCoeffs( freq );
		m_a0 = m_k4 * m_a;
		m_a1 = -4.0 * m_a0;
		m_a2 = 6.0 * m_a0;
	}

	inline float update( float in, ch_cnt_t ch )
	{
		const double x = in - ( m_z1[ch] * m_b1 ) - ( m_z2[ch] * m_b2 ) -
			( m_z3[ch] * m_b3 ) - ( m_z4[ch] * m_b4 );
		const double y = ( m_a0 * x ) + ( m_z1[ch] * m_a1 ) + ( m_z2[ch] * m_a2 ) +
			( m_z3[ch] * m_a1 ) + ( m_z4[ch] * m_a0 );
		m_z4[ch] = m_z3[ch];
		m_z3[ch] = m_z2[ch];
		m_z2[ch] = m_z1[ch];
		m_z1[ch] = x;

		return y;
	}

private:
	float m_sampleRate;
	double m_wc4;
	double m_k4;
	double m_a, m_a0, m_a1, m_a2;
	double m_b1, m_b2, m_b3, m_b4;

	typedef double frame[CHANNELS];
	frame m_z1, m_z2, m_z3, m_z4;
};
typedef LinkwitzRiley<2> StereoLinkwitzRiley;

template<ch_cnt_t CHANNELS>
class BiQuad
{
	MM_OPERATORS
public:
	BiQuad()
	{
		clearHistory();
	}
	virtual ~BiQuad() {}

	inline void setCoeffs( float a1, float a2, float b0, float b1, float b2 )
	{
		m_a1 = a1;
		m_a2 = a2;
		m_b0 = b0;
		m_b1 = b1;
		m_b2 = b2;
	}
	inline void clearHistory()
	{
		for( int i = 0; i < CHANNELS; ++i )
		{
			m_z1[i] = 0.0f;
			m_z2[i] = 0.0f;
		}
	}
	inline float update( float in, ch_cnt_t ch )
	{
		// biquad filter in transposed form
		const float out = m_z1[ch] + m_b0 * in;
		m_z1[ch] = m_b1 * in + m_z2[ch] - m_a1 * out;
		m_z2[ch] = m_b2 * in - m_a2 * out;
		return out;
	}
private:
	float m_a1, m_a2, m_b0, m_b1, m_b2;
	float m_z1 [CHANNELS], m_z2 [CHANNELS];

	friend class BasicFilters<CHANNELS>; // needed for subfilter stuff in BasicFilters
};
typedef BiQuad<2> StereoBiQuad;

template<ch_cnt_t CHANNELS>
class OnePole
{
	MM_OPERATORS
public:
	OnePole()
	{
		m_a0 = 1.0;
		m_b1 = 0.0;
		for( int i = 0; i < CHANNELS; ++i )
		{
			m_z1[i] = 0.0;
		}
	}
	virtual ~OnePole() {}

	inline void setCoeffs( float a0, float b1 )
	{
		m_a0 = a0;
		m_b1 = b1;
	}

	inline float update( float s, ch_cnt_t ch )
	{
		if( qAbs( s ) < 1.0e-10f && qAbs( m_z1[ch] ) < 1.0e-10f ) return 0.0f;
		return m_z1[ch] = s * m_a0 + m_z1[ch] * m_b1;
	}

private:
	float m_a0, m_b1;
	float m_z1 [CHANNELS];
};
typedef OnePole<2> StereoOnePole;

template<ch_cnt_t CHANNELS>
class BasicFilters
{
	MM_OPERATORS
public:
	enum FilterTypes
	{
		LowPass,
		HiPass,
		BandPass_CSG,
		BandPass_CZPG,
		Notch,
		AllPass,
		Moog,
		DoubleLowPass,
		Lowpass_RC12,
		Bandpass_RC12,
		Highpass_RC12,
		Lowpass_RC24,
		Bandpass_RC24,
		Highpass_RC24,
		Formantfilter,
		DoubleMoog,
		Lowpass_SV,
		Bandpass_SV,
		Highpass_SV,
		Notch_SV,
		FastFormant,
		Tripole,
		NumFilters
	};

	static inline float minFreq()
	{
		return( 5.0f );
	}

	static inline float minQ()
	{
		return( 0.01f );
	}

	inline void setFilterType( const int _idx )
	{
		m_doubleFilter = _idx == DoubleLowPass || _idx == DoubleMoog;
		if( !m_doubleFilter )
		{
			m_type = static_cast<FilterTypes>( _idx );
			return;
		}

		// Double lowpass mode, backwards-compat for the goofy
		// Add-NumFilters to signify doubleFilter stuff
		m_type = _idx == DoubleLowPass
			? LowPass
			: Moog;
		if( m_subFilter == NULL )
		{
			m_subFilter = new BasicFilters<CHANNELS>(
						static_cast<sample_rate_t>(
							m_sampleRate ) );
		}
		m_subFilter->m_type = m_type;
	}

	inline BasicFilters( const sample_rate_t _sample_rate ) :
		m_doubleFilter( false ),
		m_sampleRate( (float) _sample_rate ),
		m_sampleRatio( 1.0f / m_sampleRate ),
		m_subFilter( NULL )
	{
		clearHistory();
	}

	inline ~BasicFilters()
	{
		delete m_subFilter;
	}

	inline void clearHistory()
	{
		// reset in/out history for biquads
		m_biQuad.clearHistory();

		// reset in/out history
		for( ch_cnt_t _chnl = 0; _chnl < CHANNELS; ++_chnl )
		{
			// reset in/out history for moog-filter
			m_y1[_chnl] = m_y2[_chnl] = m_y3[_chnl] = m_y4[_chnl] =
					m_oldx[_chnl] = m_oldy1[_chnl] =
					m_oldy2[_chnl] = m_oldy3[_chnl] = 0.0f;

			// tripole
			m_last[_chnl] = 0.0f;

			// reset in/out history for RC-filters
			m_rclp0[_chnl] = m_rcbp0[_chnl] = m_rchp0[_chnl] = m_rclast0[_chnl] = 0.0f;
			m_rclp1[_chnl] = m_rcbp1[_chnl] = m_rchp1[_chnl] = m_rclast1[_chnl] = 0.0f;

			for(int i=0; i<6; i++)
			   m_vfbp[i][_chnl] = m_vfhp[i][_chnl] = m_vflast[i][_chnl] = 0.0f;

			// reset in/out history for SV-filters
			m_delay1[_chnl] = 0.0f;
			m_delay2[_chnl] = 0.0f;
			m_delay3[_chnl] = 0.0f;
			m_delay4[_chnl] = 0.0f;
		}
	}

	inline sample_t update( sample_t _in0, ch_cnt_t _chnl )
	{
		sample_t out;
		switch( m_type )
		{
			case Moog:
			{
				sample_t x = _in0 - m_r*m_y4[_chnl];

				// four cascaded onepole filters
				// (bilinear transform)
				m_y1[_chnl] = qBound( -10.0f,
						( x + m_oldx[_chnl] ) * m_p
							- m_k * m_y1[_chnl],
								10.0f );
				m_y2[_chnl] = qBound( -10.0f,
					( m_y1[_chnl] + m_oldy1[_chnl] ) * m_p
							- m_k * m_y2[_chnl],
								10.0f );
				m_y3[_chnl] = qBound( -10.0f,
					( m_y2[_chnl] + m_oldy2[_chnl] ) * m_p
							- m_k * m_y3[_chnl],
								10.0f );
				m_y4[_chnl] = qBound( -10.0f,
					( m_y3[_chnl] + m_oldy3[_chnl] ) * m_p
							- m_k * m_y4[_chnl],
								10.0f );

				m_oldx[_chnl] = x;
				m_oldy1[_chnl] = m_y1[_chnl];
				m_oldy2[_chnl] = m_y2[_chnl];
				m_oldy3[_chnl] = m_y3[_chnl];
				out = m_y4[_chnl] - m_y4[_chnl] * m_y4[_chnl] *
						m_y4[_chnl] * ( 1.0f / 6.0f );
				break;
			}

			// 3x onepole filters with 4x oversampling and interpolation of oversampled signal:
			// input signal is linear-interpolated after oversampling, output signal is averaged from oversampled outputs
			case Tripole:
			{
				out = 0.0f;
				float ip = 0.0f;
				for( int i = 0; i < 4; ++i )
				{
					ip += 0.25f;
					sample_t x = linearInterpolate( m_last[_chnl], _in0, ip ) - m_r * m_y3[_chnl];

					m_y1[_chnl] = qBound( -10.0f,
						( x + m_oldx[_chnl] ) * m_p
							- m_k * m_y1[_chnl],
								10.0f );
					m_y2[_chnl] = qBound( -10.0f,
						( m_y1[_chnl] + m_oldy1[_chnl] ) * m_p
								- m_k * m_y2[_chnl],
									10.0f );
					m_y3[_chnl] = qBound( -10.0f,
						( m_y2[_chnl] + m_oldy2[_chnl] ) * m_p
								- m_k * m_y3[_chnl],
									10.0f );
					m_oldx[_chnl] = x;
					m_oldy1[_chnl] = m_y1[_chnl];
					m_oldy2[_chnl] = m_y2[_chnl];

					out += ( m_y3[_chnl] - m_y3[_chnl] * m_y3[_chnl] * m_y3[_chnl] * ( 1.0f / 6.0f ) );
				}
				out *= 0.25f;
				m_last[_chnl] = _in0;
				return out;
			}

			// 4-pole state-variant lowpass filter, adapted from Nekobee source code
			// and extended to other SV filter types
			// /* Hal Chamberlin's state variable filter */

			case Lowpass_SV:
			case Bandpass_SV:
			{
				float highpass;

				for( int i = 0; i < 2; ++i ) // 2x oversample
				{
					m_delay2[_chnl] = m_delay2[_chnl] + m_svf1 * m_delay1[_chnl];				/* delay2/4 = lowpass output */
					highpass = _in0 - m_delay2[_chnl] - m_svq * m_delay1[_chnl];
					m_delay1[_chnl] = m_svf1 * highpass + m_delay1[_chnl];           			/* delay1/3 = bandpass output */

					m_delay4[_chnl] = m_delay4[_chnl] + m_svf2 * m_delay3[_chnl];
					highpass = m_delay2[_chnl] - m_delay4[_chnl] - m_svq * m_delay3[_chnl];
					m_delay3[_chnl] = m_svf2 * highpass + m_delay3[_chnl];
				}

				/* mix filter output into output buffer */
				return m_type == Lowpass_SV
					? m_delay4[_chnl]
					: m_delay3[_chnl];
			}

			case Highpass_SV:
			{
				float hp;

				for( int i = 0; i < 2; ++i ) // 2x oversample
				{
					m_delay2[_chnl] = m_delay2[_chnl] + m_svf1 * m_delay1[_chnl];
					hp = _in0 - m_delay2[_chnl] - m_svq * m_delay1[_chnl];
					m_delay1[_chnl] = m_svf1 * hp + m_delay1[_chnl];
				}

				return hp;
			}

			case Notch_SV:
			{
				float hp1, hp2;

				for( int i = 0; i < 2; ++i ) // 2x oversample
				{
					m_delay2[_chnl] = m_delay2[_chnl] + m_svf1 * m_delay1[_chnl];				/* delay2/4 = lowpass output */
					hp1 = _in0 - m_delay2[_chnl] - m_svq * m_delay1[_chnl];
					m_delay1[_chnl] = m_svf1 * hp1 + m_delay1[_chnl];           			/* delay1/3 = bandpass output */

					m_delay4[_chnl] = m_delay4[_chnl] + m_svf2 * m_delay3[_chnl];
					hp2 = m_delay2[_chnl] - m_delay4[_chnl] - m_svq * m_delay3[_chnl];
					m_delay3[_chnl] = m_svf2 * hp2 + m_delay3[_chnl];
				}

				/* mix filter output into output buffer */
				return m_delay4[_chnl] + hp1;
			}

			// 4-times oversampled simulation of an active RC-Bandpass,-Lowpass,-Highpass-
			// Filter-Network as it was used in nearly all modern analog synthesizers. This
			// can be driven up to self-oscillation (BTW: do not remove the limits!!!).
			// (C) 1998 ... 2009 S.Fendt. Released under the GPL v2.0  or any later version.

			case Lowpass_RC12:
			{
				sample_t lp, bp, hp, in;
				for( int n = 4; n != 0; --n )
				{
					in = _in0 + m_rcbp0[_chnl] * m_rcq;
					in = qBound( -1.0f, in, 1.0f );

					lp = in * m_rcb + m_rclp0[_chnl] * m_rca;
					lp = qBound( -1.0f, lp, 1.0f );

					hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
					bp = qBound( -1.0f, bp, 1.0f );

					m_rclast0[_chnl] = in;
					m_rclp0[_chnl] = lp;
					m_rchp0[_chnl] = hp;
					m_rcbp0[_chnl] = bp;
				}
				return lp;
			}
			case Highpass_RC12:
			case Bandpass_RC12:
			{
				sample_t hp, bp, in;
				for( int n = 4; n != 0; --n )
				{
					in = _in0 + m_rcbp0[_chnl] * m_rcq;
					in = qBound( -1.0f, in, 1.0f );

					hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
					bp = qBound( -1.0f, bp, 1.0f );

					m_rclast0[_chnl] = in;
					m_rchp0[_chnl] = hp;
					m_rcbp0[_chnl] = bp;
				}
				return m_type == Highpass_RC12 ? hp : bp;
			}

			case Lowpass_RC24:
			{
				sample_t lp, bp, hp, in;
				for( int n = 4; n != 0; --n )
				{
					// first stage is as for the 12dB case...
					in = _in0 + m_rcbp0[_chnl] * m_rcq;
					in = qBound( -1.0f, in, 1.0f );

					lp = in * m_rcb + m_rclp0[_chnl] * m_rca;
					lp = qBound( -1.0f, lp, 1.0f );

					hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
					bp = qBound( -1.0f, bp, 1.0f );

					m_rclast0[_chnl] = in;
					m_rclp0[_chnl] = lp;
					m_rcbp0[_chnl] = bp;
					m_rchp0[_chnl] = hp;

					// second stage gets the output of the first stage as input...
					in = lp + m_rcbp1[_chnl] * m_rcq;
					in = qBound( -1.0f, in, 1.0f );

					lp = in * m_rcb + m_rclp1[_chnl] * m_rca;
					lp = qBound( -1.0f, lp, 1.0f );

					hp = m_rcc * ( m_rchp1[_chnl] + in - m_rclast1[_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_rcb + m_rcbp1[_chnl] * m_rca;
					bp = qBound( -1.0f, bp, 1.0f );

					m_rclast1[_chnl] = in;
					m_rclp1[_chnl] = lp;
					m_rcbp1[_chnl] = bp;
					m_rchp1[_chnl] = hp;
				}
				return lp;
			}
			case Highpass_RC24:
			case Bandpass_RC24:
			{
				sample_t hp, bp, in;
				for( int n = 4; n != 0; --n )
				{
					// first stage is as for the 12dB case...
					in = _in0 + m_rcbp0[_chnl] * m_rcq;
					in = qBound( -1.0f, in, 1.0f );

					hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
					bp = qBound( -1.0f, bp, 1.0f );

					m_rclast0[_chnl] = in;
					m_rchp0[_chnl] = hp;
					m_rcbp0[_chnl] = bp;

					// second stage gets the output of the first stage as input...
					in = m_type == Highpass_RC24
						? hp + m_rcbp1[_chnl] * m_rcq
						: bp + m_rcbp1[_chnl] * m_rcq;

					in = qBound( -1.0f, in, 1.0f );

					hp = m_rcc * ( m_rchp1[_chnl] + in - m_rclast1[_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_rcb + m_rcbp1[_chnl] * m_rca;
					bp = qBound( -1.0f, bp, 1.0f );

					m_rclast1[_chnl] = in;
					m_rchp1[_chnl] = hp;
					m_rcbp1[_chnl] = bp;
				}
				return m_type == Highpass_RC24 ? hp : bp;
			}

			case Formantfilter:
			case FastFormant:
			{
				if( qAbs( _in0 ) < 1.0e-10f && qAbs( m_vflast[0][_chnl] ) < 1.0e-10f ) { return 0.0f; } // performance hack - skip processing when the numbers get too small
				sample_t hp, bp, in;

				out = 0;
				const int os = m_type == FastFormant ? 1 : 4; // no oversampling for fast formant
				for( int o = 0; o < os; ++o )
				{
					// first formant
					in = _in0 + m_vfbp[0][_chnl] * m_vfq;
					in = qBound( -1.0f, in, 1.0f );

					hp = m_vfc[0] * ( m_vfhp[0][_chnl] + in - m_vflast[0][_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_vfb[0] + m_vfbp[0][_chnl] * m_vfa[0];
					bp = qBound( -1.0f, bp, 1.0f );

					m_vflast[0][_chnl] = in;
					m_vfhp[0][_chnl] = hp;
					m_vfbp[0][_chnl] = bp;

					in = bp + m_vfbp[2][_chnl] * m_vfq;
					in = qBound( -1.0f, in, 1.0f );

					hp = m_vfc[0] * ( m_vfhp[2][_chnl] + in - m_vflast[2][_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_vfb[0] + m_vfbp[2][_chnl] * m_vfa[0];
					bp = qBound( -1.0f, bp, 1.0f );

					m_vflast[2][_chnl] = in;
					m_vfhp[2][_chnl] = hp;
					m_vfbp[2][_chnl] = bp;

					in = bp + m_vfbp[4][_chnl] * m_vfq;
					in = qBound( -1.0f, in, 1.0f );

					hp = m_vfc[0] * ( m_vfhp[4][_chnl] + in - m_vflast[4][_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_vfb[0] + m_vfbp[4][_chnl] * m_vfa[0];
					bp = qBound( -1.0f, bp, 1.0f );

					m_vflast[4][_chnl] = in;
					m_vfhp[4][_chnl] = hp;
					m_vfbp[4][_chnl] = bp;

					out += bp;

					// second formant
					in = _in0 + m_vfbp[0][_chnl] * m_vfq;
					in = qBound( -1.0f, in, 1.0f );

					hp = m_vfc[1] * ( m_vfhp[1][_chnl] + in - m_vflast[1][_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_vfb[1] + m_vfbp[1][_chnl] * m_vfa[1];
					bp = qBound( -1.0f, bp, 1.0f );

					m_vflast[1][_chnl] = in;
					m_vfhp[1][_chnl] = hp;
					m_vfbp[1][_chnl] = bp;

					in = bp + m_vfbp[3][_chnl] * m_vfq;
					in = qBound( -1.0f, in, 1.0f );

					hp = m_vfc[1] * ( m_vfhp[3][_chnl] + in - m_vflast[3][_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_vfb[1] + m_vfbp[3][_chnl] * m_vfa[1];
					bp = qBound( -1.0f, bp, 1.0f );

					m_vflast[3][_chnl] = in;
					m_vfhp[3][_chnl] = hp;
					m_vfbp[3][_chnl] = bp;

					in = bp + m_vfbp[5][_chnl] * m_vfq;
					in = qBound( -1.0f, in, 1.0f );

					hp = m_vfc[1] * ( m_vfhp[5][_chnl] + in - m_vflast[5][_chnl] );
					hp = qBound( -1.0f, hp, 1.0f );

					bp = hp * m_vfb[1] + m_vfbp[5][_chnl] * m_vfa[1];
					bp = qBound( -1.0f, bp, 1.0f );

					m_vflast[5][_chnl] = in;
					m_vfhp[5][_chnl] = hp;
					m_vfbp[5][_chnl] = bp;

					out += bp;
				}
            	return m_type == FastFormant ? out * 2.0f : out * 0.5f;
			}

			default:
				out = m_biQuad.update( _in0, _chnl );
				break;
		}

		if( m_doubleFilter )
		{
			return m_subFilter->update( out, _chnl );
		}

		// Clipper band limited sigmoid
		return out;
	}

	inline void calcFilterCoeffs( float _freq, float _q )
	{
		// temp coef vars
		_q = qMax( _q, minQ() );

		if( m_type == Lowpass_RC12  ||
			m_type == Bandpass_RC12 ||
			m_type == Highpass_RC12 ||
			m_type == Lowpass_RC24 ||
			m_type == Bandpass_RC24 ||
			m_type == Highpass_RC24 )
		{
			_freq = qBound( 50.0f, _freq, 20000.0f );
			const float sr = m_sampleRatio * 0.25f;
			const float f = 1.0f / ( _freq * F_2PI );

			m_rca = 1.0f - sr / ( f + sr );
			m_rcb = 1.0f - m_rca;
			m_rcc = f / ( f + sr );

			// Stretch Q/resonance, as self-oscillation reliably starts at a q of ~2.5 - ~2.6
			m_rcq = _q * 0.25f;
			return;
		}

		if( m_type == Formantfilter ||
			m_type == FastFormant )
		{
			_freq = qBound( minFreq(), _freq, 20000.0f ); // limit freq and q for not getting bad noise out of the filter...

			// formats for a, e, i, o, u, a
			static const float _f[6][2] = { { 1000, 1400 }, { 500, 2300 },
							{ 320, 3200 },
							{ 500, 1000 },
							{ 320, 800 },
							{ 1000, 1400 } };
			static const float freqRatio = 4.0f / 14000.0f;

			// Stretch Q/resonance
			m_vfq = _q * 0.25f;

			// frequency in lmms ranges from 1Hz to 14000Hz
			const float vowelf = _freq * freqRatio;
			const int vowel = static_cast<int>( vowelf );
			const float fract = vowelf - vowel;

			// interpolate between formant frequencies
			const float f0 = 1.0f / ( linearInterpolate( _f[vowel+0][0], _f[vowel+1][0], fract ) * F_2PI );
			const float f1 = 1.0f / ( linearInterpolate( _f[vowel+0][1], _f[vowel+1][1], fract ) * F_2PI );

			// samplerate coeff: depends on oversampling
			const float sr = m_type == FastFormant ? m_sampleRatio : m_sampleRatio * 0.25f;

			m_vfa[0] = 1.0f - sr / ( f0 + sr );
			m_vfb[0] = 1.0f - m_vfa[0];
			m_vfc[0] = f0 /	( f0 + sr );
			m_vfa[1] = 1.0f - sr / ( f1 + sr );
			m_vfb[1] = 1.0f - m_vfa[1];
			m_vfc[1] = f1 /	( f1 + sr );
			return;
		}

		if( m_type == Moog ||
			m_type == DoubleMoog )
		{
			// [ 0 - 0.5 ]
			const float f = qBound( minFreq(), _freq, 20000.0f ) * m_sampleRatio;
			// (Empirical tunning)
			m_p = ( 3.6f - 3.2f * f ) * f;
			m_k = 2.0f * m_p - 1;
			m_r = _q * powf( F_E, ( 1 - m_p ) * 1.386249f );

			if( m_doubleFilter )
			{
				m_subFilter->m_r = m_r;
				m_subFilter->m_p = m_p;
				m_subFilter->m_k = m_k;
			}
			return;
		}

		if( m_type == Tripole )
		{
			const float f = qBound( 20.0f, _freq, 20000.0f ) * m_sampleRatio * 0.25f;

			m_p = ( 3.6f - 3.2f * f ) * f;
			m_k = 2.0f * m_p - 1.0f;
			m_r = _q * 0.1f * powf( F_E, ( 1 - m_p ) * 1.386249f );

			return;
		}

		if( m_type == Lowpass_SV ||
			m_type == Bandpass_SV ||
			m_type == Highpass_SV ||
			m_type == Notch_SV )
		{
			const float f = sinf( qMax( minFreq(), _freq ) * m_sampleRatio * F_PI );
			m_svf1 = qMin( f, 0.825f );
			m_svf2 = qMin( f * 2.0f, 0.825f );
			m_svq = qMax( 0.0001f, 2.0f - ( _q * 0.1995f ) );
			return;
		}

		// other filters
		_freq = qBound( minFreq(), _freq, 20000.0f );
		const float omega = F_2PI * _freq * m_sampleRatio;
		const float tsin = sinf( omega ) * 0.5f;
		const float tcos = cosf( omega );

		const float alpha = tsin / _q;

		const float a0 = 1.0f / ( 1.0f + alpha );

		const float a1 = -2.0f * tcos * a0;
		const float a2 = ( 1.0f - alpha ) * a0;

		switch( m_type )
		{
			case LowPass:
			{
				const float b1 = ( 1.0f - tcos ) * a0;
				const float b0 = b1 * 0.5f;
				m_biQuad.setCoeffs( a1, a2, b0, b1, b0 );
				break;
			}
			case HiPass:
			{
				const float b1 = ( -1.0f - tcos ) * a0;
				const float b0 = b1 * -0.5f;
				m_biQuad.setCoeffs( a1, a2, b0, b1, b0 );
				break;
			}
			case BandPass_CSG:
			{
				const float b0 = tsin * a0;
				m_biQuad.setCoeffs( a1, a2, b0, 0.0f, -b0 );
				break;
			}
			case BandPass_CZPG:
			{
				const float b0 = alpha * a0;
				m_biQuad.setCoeffs( a1, a2, b0, 0.0f, -b0 );
				break;
			}
			case Notch:
			{
				m_biQuad.setCoeffs( a1, a2, a0, a1, a0 );
				break;
			}
			case AllPass:
			{
				m_biQuad.setCoeffs( a1, a2, a2, a1, 1.0f );
				break;
			}
			default:
				break;
		}

		if( m_doubleFilter )
		{
			m_subFilter->m_biQuad.setCoeffs( m_biQuad.m_a1, m_biQuad.m_a2, m_biQuad.m_b0, m_biQuad.m_b1, m_biQuad.m_b2 );
		}
	}

private:
	// biquad filter
	BiQuad<CHANNELS> m_biQuad;

	// coeffs for moog-filter
	float m_r, m_p, m_k;

	// coeffs for RC-type-filters
	float m_rca, m_rcb, m_rcc, m_rcq;

	// coeffs for formant-filters
	float m_vfa[4], m_vfb[4], m_vfc[4], m_vfq;

	// coeffs for Lowpass_SV (state-variant lowpass)
	float m_svf1, m_svf2, m_svq;

	typedef sample_t frame[CHANNELS];

	// in/out history for moog-filter
	frame m_y1, m_y2, m_y3, m_y4, m_oldx, m_oldy1, m_oldy2, m_oldy3;
	// additional one for Tripole filter
	frame m_last;

	// in/out history for RC-type-filters
	frame m_rcbp0, m_rclp0, m_rchp0, m_rclast0;
	frame m_rcbp1, m_rclp1, m_rchp1, m_rclast1;

	// in/out history for Formant-filters
	frame m_vfbp[6], m_vfhp[6], m_vflast[6];

	// in/out history for Lowpass_SV (state-variant lowpass)
	frame m_delay1, m_delay2, m_delay3, m_delay4;

	FilterTypes m_type;
	bool m_doubleFilter;

	float m_sampleRate;
	float m_sampleRatio;
	BasicFilters<CHANNELS> * m_subFilter;

} ;

#endif


code:
/*
 * BufferManager.h - A buffer caching/memory management system
 *
 * 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 - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef BUFFER_MANAGER_H
#define BUFFER_MANAGER_H

#include "lmms_export.h"
#include "lmms_basics.h"

class LMMS_EXPORT BufferManager
{
public:
	static void init( fpp_t framesPerPeriod );
	static sampleFrame * acquire();
	// audio-buffer-mgm
	static void clear( sampleFrame * ab, const f_cnt_t frames,
						const f_cnt_t offset = 0 );
#ifndef LMMS_DISABLE_SURROUND
	static void clear( surroundSampleFrame * ab, const f_cnt_t frames,
						const f_cnt_t offset = 0 );
#endif
	static void release( sampleFrame * buf );
};

#endif


code:
/*
 * CPULoadWidget.h - widget for displaying CPU-load (partly based on
 *                    Hydrogen's CPU-load-widget)
 *
 * Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CPULOAD_WIDGET_H
#define CPULOAD_WIDGET_H

#include <QtCore/QTimer>
#include <QPixmap>
#include <QWidget>

#include "lmms_basics.h"

class CPULoadWidget : public QWidget
{
	Q_OBJECT
public:
	CPULoadWidget( QWidget * _parent );
	virtual ~CPULoadWidget();

protected:
	void paintEvent( QPaintEvent * _ev ) override;

protected slots:
	void updateCpuLoad();

private:
	int m_currentLoad;

	QPixmap m_temp;
	QPixmap m_background;
	QPixmap m_leds;

	bool m_changed;

	QTimer m_updateTimer;

} ;

#endif


code:
/*
 * CaptionMenu.h - context menu with a caption
 *
 * Copyright (c) 2007-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CAPTION_MENU_H
#define CAPTION_MENU_H

#include <QMenu>

#include "lmms_export.h"

///
/// \brief A context menu with a caption
///
class LMMS_EXPORT CaptionMenu : public QMenu
{
	Q_OBJECT
public:
	CaptionMenu( const QString & _title, QWidget * _parent = 0 );
	virtual ~CaptionMenu();
} ;

#endif


code:
/*
 * Clipboard.h - the clipboard for patterns, notes etc.
 *
 * Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CLIPBOARD_H
#define CLIPBOARD_H

#include <QtCore/QMap>
#include <QDomElement>

namespace Clipboard
{
	enum class MimeType
	{
		StringPair,
		Default
	};

	// Convenience Methods
	const QMimeData * getMimeData();
	bool hasFormat( MimeType mT );

	// Helper methods for String data
	void copyString( const QString & str, MimeType mT );
	QString getString( MimeType mT );

	// Helper methods for String Pair data
	void copyStringPair( const QString & key, const QString & value );
	QString decodeKey( const QMimeData * mimeData );
	QString decodeValue( const QMimeData * mimeData );

	inline const char * mimeType( MimeType type )
	{
		switch( type )
		{
			case MimeType::StringPair:
				return "application/x-lmms-stringpair";
			break;
			case MimeType::Default:
			default:
				return "application/x-lmms-clipboard";
				break;
		}
	}
} ;

#endif


code:
/* ColorChooser.h - declaration and definition of ColorChooser class.
 *
 * Copyright (c) 2019 CYBERDEViLNL <cyberdevilnl/at/protonmail/dot/ch>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#include <QApplication>
#include <QColor>
#include <QColorDialog>
#include <QKeyEvent>
#include <QVector>

class ColorChooser: public QColorDialog
{
public:
	ColorChooser(const QColor &initial, QWidget *parent): QColorDialog(initial, parent) {};
	ColorChooser(QWidget *parent): QColorDialog(parent) {};
	//! For getting a color without having to initialise a color dialog
	ColorChooser() {};
	enum class Palette {Default, Track, Mixer};
	//! Set global palette via array, checking bounds
	void setPalette (QVector<QColor>);
	//! Set global paletter via enum
	void setPalette (Palette);
	//! Set palette via enum, return self pointer for chaining
	ColorChooser* withPalette (Palette);
	//! Return a certain palette
	static QVector<QColor> getPalette (Palette);

protected:
	//! Forward key events to the parent to prevent stuck notes when the dialog gets focus
	void keyReleaseEvent(QKeyEvent *event) override
	{
		QKeyEvent ke(*event);
		QApplication::sendEvent(parentWidget(), &ke);
	}
private:
	//! Copy the current QColorDialog palette into an array
	static QVector<QColor> defaultPalette();
	//! Generate a nice palette, with adjustable value
	static QVector<QColor> nicePalette (int);
};


code:
/*
 * ComboBox.h - class ComboBox, a combo box view for models
 *
 * Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef COMBOBOX_H
#define COMBOBOX_H

#include <QMenu>
#include <QWidget>

#include "ComboBoxModel.h"
#include "AutomatableModelView.h"

class LMMS_EXPORT ComboBox : public QWidget, public IntModelView
{
	Q_OBJECT
public:
	ComboBox( QWidget* parent = NULL, const QString& name = QString() );
	virtual ~ComboBox();

	ComboBoxModel* model()
	{
		return castModel<ComboBoxModel>();
	}

	const ComboBoxModel* model() const
	{
		return castModel<ComboBoxModel>();
	}

	static constexpr int DEFAULT_HEIGHT = 22;

public slots:
	void selectNext();
	void selectPrevious();

protected:
	void contextMenuEvent( QContextMenuEvent* event ) override;
	void mousePressEvent( QMouseEvent* event ) override;
	void paintEvent( QPaintEvent* event ) override;
	void wheelEvent( QWheelEvent* event ) override;

private:
	static QPixmap* s_background;
	static QPixmap* s_arrow;
	static QPixmap* s_arrowSelected;

	QMenu m_menu;

	bool m_pressed;

private slots:
	void setItem( QAction* item );

} ;

#endif


code:
/*
 * ComboBoxModel.h - declaration of class ComboBoxModel
 *
 * Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef COMBOBOX_MODEL_H
#define COMBOBOX_MODEL_H

#include <memory>
#include <utility>
#include <vector>

#include "AutomatableModel.h"
#include "embed.h"

class LMMS_EXPORT ComboBoxModel : public IntModel
{
	Q_OBJECT
	MODEL_IS_VISITABLE
public:
	ComboBoxModel( Model* parent = NULL,
					const QString& displayName = QString(),
					bool isDefaultConstructed = false ) :
		IntModel( 0, 0, 0, parent, displayName, isDefaultConstructed )
	{
	}

	virtual ~ComboBoxModel()
	{
		clear();
	}

	void addItem( QString item, std::unique_ptr<PixmapLoader> loader = nullptr );

	void clear();

	int findText( const QString& txt ) const;

	QString currentText() const
	{
		return ( size() > 0 && value() < size() ) ? m_items[value()].first : QString();
	}

	const PixmapLoader* currentData() const
	{
		return m_items[value()].second.get();
	}

	const QString & itemText( int i ) const
	{
		return m_items[qBound<int>( minValue(), i,  maxValue() )].first;
	}

	const PixmapLoader* itemPixmap( int i ) const
	{
		return m_items[qBound<int>( minValue(), i, maxValue() )].second.get();
	}

	int size() const
	{
		return m_items.size();
	}

private:
	typedef std::pair<QString, std::unique_ptr<PixmapLoader> > Item;

	std::vector<Item> m_items;

} ;

#endif


code:
/*
 * ConfigManager.h - class ConfigManager, a class for managing LMMS-configuration
 *
 * Copyright (c) 2005-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CONFIG_MGR_H
#define CONFIG_MGR_H

#include "lmmsconfig.h"

#include <QtCore/QMap>
#include <QtCore/QPair>
#include <QtCore/QStringList>
#include <QtCore/QVector>
#include <QtCore/QObject>

#include "lmms_export.h"

class LmmsCore;

const QString PROJECTS_PATH = "projects/";
const QString TEMPLATE_PATH = "templates/";
const QString PRESETS_PATH = "presets/";
const QString SAMPLES_PATH = "samples/";
const QString GIG_PATH = "samples/gig/";
const QString SF2_PATH = "samples/soundfonts/";
const QString LADSPA_PATH ="plugins/ladspa/";
const QString DEFAULT_THEME_PATH = "themes/default/";
const QString TRACK_ICON_PATH = "track_icons/";
const QString LOCALE_PATH = "locale/";
const QString PORTABLE_MODE_FILE = "/portable_mode.txt";

class LMMS_EXPORT ConfigManager : public QObject
{
	Q_OBJECT

	using UpgradeMethod = void(ConfigManager::*)();

public:
	static inline ConfigManager * inst()
	{
		if(s_instanceOfMe == NULL )
		{
			s_instanceOfMe = new ConfigManager();
		}
		return s_instanceOfMe;
	}

	const QString & workingDir() const
	{
		return m_workingDir;
	}

	void initPortableWorkingDir();

	void initInstalledWorkingDir();

	void initDevelopmentWorkingDir();

	const QString & dataDir() const
	{
		return m_dataDir;
	}

	QString factoryProjectsDir() const
	{
		return dataDir() + PROJECTS_PATH;
	}

	QString factoryTemplatesDir() const
	{
		return factoryProjectsDir() + TEMPLATE_PATH;
	}

	QString factoryPresetsDir() const
	{
		return dataDir() + PRESETS_PATH;
	}

	QString factorySamplesDir() const
	{
		return dataDir() + SAMPLES_PATH;
	}

	QString userProjectsDir() const
	{
		return workingDir() + PROJECTS_PATH;
	}

	QString userTemplateDir() const
	{
		return workingDir() + TEMPLATE_PATH;
	}

	QString userPresetsDir() const
	{
		return workingDir() + PRESETS_PATH;
	}

	QString userSamplesDir() const
	{
		return workingDir() + SAMPLES_PATH;
	}

	const QString & vstDir() const
	{
		return m_vstDir;
	}

	const QString & ladspaDir() const
	{
		return m_ladspaDir;
	}

	const QString & sf2Dir() const
	{
		return m_sf2Dir;
	}

#ifdef LMMS_HAVE_FLUIDSYNTH
	const QString & sf2File() const
	{
		return m_sf2File;
	}
#endif

#ifdef LMMS_HAVE_STK
	const QString & stkDir() const
	{
		return m_stkDir;
	}
#endif

	const QString & gigDir() const
	{
		return m_gigDir;
	}

	QString userVstDir() const
	{
		return m_vstDir;
	}

	QString userLadspaDir() const
	{
		return workingDir() + LADSPA_PATH;
	}

	QString userSf2Dir() const
	{
		return workingDir() + SF2_PATH;
	}

	QString userGigDir() const
	{
		return workingDir() + GIG_PATH;
	}

	QString defaultThemeDir() const
	{
		return m_dataDir + DEFAULT_THEME_PATH;
	}

	QString themeDir() const
	{
		return m_themeDir;
	}

	const QString & backgroundPicFile() const
	{
		return m_backgroundPicFile;
	}

	QString trackIconsDir() const
	{
		return m_dataDir + TRACK_ICON_PATH;
	}

	const QString recoveryFile() const
	{
		return m_workingDir + "recover.mmp";
	}

	inline const QStringList & recentlyOpenedProjects() const
	{
		return m_recentlyOpenedProjects;
	}

	QString localeDir() const
	{
		return m_dataDir + LOCALE_PATH;
	}

	const QString & version() const
	{
		return m_version;
	}

	// Used when the configversion attribute is not present in a configuration file.
	// Returns the appropriate config file version based on the LMMS version.
	unsigned int legacyConfigVersion();

	QString defaultVersion() const;

	static QStringList availableVstEmbedMethods();
	QString vstEmbedMethod() const;

	// Returns true if the working dir (e.g. ~/lmms) exists on disk.
	bool hasWorkingDir() const;

	void addRecentlyOpenedProject(const QString & _file);

	const QString & value(const QString & cls,
					const QString & attribute) const;
	const QString & value(const QString & cls,
					const QString & attribute,
					const QString & defaultVal) const;
	void setValue(const QString & cls, const QString & attribute,
						const QString & value);
	void deleteValue(const QString & cls, const QString & attribute);

	void loadConfigFile(const QString & configFile = "");
	void saveConfigFile();

	void setWorkingDir(const QString & workingDir);
	void setVSTDir(const QString & vstDir);
	void setLADSPADir(const QString & ladspaDir);
	void setSF2Dir(const QString & sf2Dir);
	void setSF2File(const QString & sf2File);
	void setSTKDir(const QString & stkDir);
	void setGIGDir(const QString & gigDir);
	void setThemeDir(const QString & themeDir);
	void setBackgroundPicFile(const QString & backgroundPicFile);

	// Creates the working directory & subdirectories on disk.
	void createWorkingDir();

signals:
	void valueChanged( QString cls, QString attribute, QString value );

private:
	static ConfigManager * s_instanceOfMe;

	ConfigManager();
	ConfigManager(const ConfigManager & _c);
	~ConfigManager();

	void upgrade_1_1_90();
	void upgrade_1_1_91();
	void upgrade();

	// List of all upgrade methods
	static const std::vector<UpgradeMethod> UPGRADE_METHODS;

	QString m_workingDir;
	QString m_dataDir;
	QString m_vstDir;
	QString m_ladspaDir;
	QString m_sf2Dir;
#ifdef LMMS_HAVE_FLUIDSYNTH
	QString m_sf2File;
#endif
#ifdef LMMS_HAVE_STK
	QString m_stkDir;
#endif
	QString m_gigDir;
	QString m_themeDir;
	QString m_backgroundPicFile;
	QString m_lmmsRcFile;
	QString m_version;
	unsigned int m_configVersion;
	QStringList m_recentlyOpenedProjects;

	typedef QVector<QPair<QString, QString> > stringPairVector;
	typedef QMap<QString, stringPairVector> settingsMap;
	settingsMap m_settings;

	friend class LmmsCore;
};
#endif


code:
/*
 * ControlLayout.h - layout for controls
 *
 * Copyright (c) 2019-2019 Johannes Lorenz <j.git$$$lorenz-ho.me, $$$=@>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef CONTROLLAYOUT_H
#define CONTROLLAYOUT_H

#include <QLayout>
#include <QMultiMap>
#include <QStyle>
class QLayoutItem;
class QRect;
class QString;

/**
	Layout for controls (models)

	Originally token from Qt's FlowLayout example. Modified.

	Features a search bar, as well as looking up widgets with string keys
	Keys have to be provided in the widgets' objectNames
*/
class ControlLayout : public QLayout
{
	Q_OBJECT

public:
	explicit ControlLayout(QWidget *parent,
		int margin = -1, int hSpacing = -1, int vSpacing = -1);
	~ControlLayout() override;

	void addItem(QLayoutItem *item) override;
	int horizontalSpacing() const;
	int verticalSpacing() const;
	Qt::Orientations expandingDirections() const override;
	bool hasHeightForWidth() const override;
	int heightForWidth(int) const override;
	int count() const override;
	QLayoutItem *itemAt(int index) const override;
	QLayoutItem *itemByString(const QString& key) const;
	QSize minimumSize() const override;
	void setGeometry(const QRect &rect) override;
	QSize sizeHint() const override;
	QLayoutItem *takeAt(int index) override;
	//! remove focus from QLineEdit search bar
	//! this may be useful if the mouse is outside the layout
	void removeFocusFromSearchBar();

private slots:
	void onTextChanged(const QString&);

private:
	int doLayout(const QRect &rect, bool testOnly) const;
	int smartSpacing(QStyle::PixelMetric pm) const;
	QMap<QString, QLayoutItem *>::const_iterator pairAt(int index) const;

	QMultiMap<QString, QLayoutItem *> m_itemMap;
	int m_hSpace;
	int m_vSpace;
	// relevant dimension is width, as later, heightForWidth() will be called
	// 400 looks good and is ~4 knobs in a row
	constexpr const static int m_minWidth = 400;
	class QLineEdit* m_searchBar;
	//! name of search bar, must be ASCII sorted before any alpha numerics
	static constexpr const char* s_searchBarName = "!!searchBar!!";
};

#endif // CONTROLLAYOUT_H


code:
/*
 * Controller.h - declaration of class controller, which provides a
 *                standard for all controllers and controller plugins
 *
 * Copyright (c) 2008-2009 Paul Giblock <pgllama/at/gmail.com>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CONTROLLER_H
#define CONTROLLER_H

#include "lmms_export.h"
#include "Engine.h"
#include "Model.h"
#include "JournallingObject.h"
#include "ValueBuffer.h"

class ControllerDialog;
class Controller;
class ControllerConnection;

typedef QVector<Controller *> ControllerVector;

class LMMS_EXPORT Controller : public Model, public JournallingObject
{
	Q_OBJECT
public:
	enum ControllerTypes
	{
		DummyController,
		LfoController,
		MidiController,
		PeakController,
		/*
		XYController,
		EquationController
		*/
		NumControllerTypes
	} ;

	Controller( ControllerTypes _type, Model * _parent,
						const QString & _display_name );

	virtual ~Controller();

	virtual float currentValue( int _offset );
	// The per-controller get-value-in-buffers function
	virtual ValueBuffer * valueBuffer();

	inline bool isSampleExact() const
	{
		return m_sampleExact;
	}

	void setSampleExact( bool _exact )
	{
		m_sampleExact = _exact;
	}

	inline ControllerTypes type() const
	{
		return( m_type );
	}

	// return whether this controller updates models frequently - used for
	// determining when to update GUI
	inline bool frequentUpdates() const
	{
		switch( m_type )
		{
			case LfoController: return( true );
			case PeakController: return( true );
			default:
				break;
		}
		return( false );
	}

	virtual const QString & name() const
	{
		return( m_name );
	}

	void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
	void loadSettings( const QDomElement & _this ) override;
	QString nodeName() const override;

	static Controller * create( ControllerTypes _tt, Model * _parent );
	static Controller * create( const QDomElement & _this,
							Model * _parent );

	inline static float fittedValue( float _val )
	{
		return qBound<float>( 0.0f, _val, 1.0f );
	}

	static long runningPeriods()
	{
		return s_periods;
	}
	static unsigned int runningFrames();
	static float runningTime();

	static void triggerFrameCounter();
	static void resetFrameCounter();

	//Accepts a ControllerConnection * as it may be used in the future.
	void addConnection( ControllerConnection * );
	void removeConnection( ControllerConnection * );
	int connectionCount() const;

	bool hasModel( const Model * m ) const;

public slots:
	virtual ControllerDialog * createDialog( QWidget * _parent );

	virtual void setName( const QString & _new_name )
	{
		m_name = _new_name;
	}

protected:
	// The internal per-controller get-value function
	virtual float value( int _offset );

	virtual void updateValueBuffer();

	// buffer for storing sample-exact values in case there
	// are more than one model wanting it, so we don't have to create it
	// again every time
	ValueBuffer m_valueBuffer;
	// when we last updated the valuebuffer - so we know if we have to update it
	long m_bufferLastUpdated;

	float m_currentValue;
	bool  m_sampleExact;
	int m_connectionCount;

	QString m_name;
	ControllerTypes m_type;

	static ControllerVector s_controllers;

	static long s_periods;

signals:
	// The value changed while the mixer isn't running (i.e: MIDI CC)
	void valueChanged();

	friend class ControllerDialog;

} ;

#endif


code:
/*
 * ControllerConnection.h - declaration of a controller connect, which
 *              provides a definition of the link between a controller and
 *              model, also handles deferred creation of links while
 *              loading project
 *
 * Copyright (c) 2008 Paul Giblock <pgllama/at/gmail.com>
 * Copyright (c) 2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CONTROLLER_CONNECTION_H
#define CONTROLLER_CONNECTION_H

#include <QtCore/QObject>
#include <QtCore/QVector>

#include "Controller.h"
#include "JournallingObject.h"
#include "ValueBuffer.h"

class ControllerConnection;

typedef QVector<ControllerConnection *> ControllerConnectionVector;

class LMMS_EXPORT ControllerConnection : public QObject, public JournallingObject
{
	Q_OBJECT
public:

	ControllerConnection( Controller * _controller );
	ControllerConnection( int _controllerId );

	virtual ~ControllerConnection();

	inline Controller * getController()
	{
		return m_controller;
	}

	void setController( Controller * _controller );

	inline void setController( int _controllerId );

	float currentValue( int _offset )
	{
		return m_controller->currentValue( _offset );
	}

	ValueBuffer * valueBuffer()
	{
		return m_controller->valueBuffer();
	}

	inline void setTargetName( const QString & _name );

	inline QString targetName() const
	{
		return m_targetName;
	}

	inline bool isFinalized()
	{
		return m_controllerId < 0;
	}

	static void finalizeConnections();

	void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
	void loadSettings( const QDomElement & _this ) override;

	static inline const QString classNodeName()
	{
		return "connection";
	}

	QString nodeName() const override
	{
		return classNodeName();
	}

public slots:
	void deleteConnection();

protected:
	//virtual controllerDialog * createDialog( QWidget * _parent );
	Controller * m_controller;
	QString m_targetName;
	int m_controllerId;

	bool m_ownsController;

	static ControllerConnectionVector s_connections;

signals:
	// The value changed while the mixer isn't running (i.e: MIDI CC)
	void valueChanged();

	friend class ControllerConnectionDialog;
};

#endif


code:
/*
 * ControllerConnectionDialog.h - dialog allowing the user to create and
 *	modify links between controllers and models
 *
 * Copyright (c) 2008  Paul Giblock <drfaygo/at/gmail.com>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CONTROLLER_CONNECTION_DIALOG_H
#define CONTROLLER_CONNECTION_DIALOG_H

#include <QDialog>
#include <QSortFilterProxyModel>
#include <QStandardItemModel>

#include "Controller.h"
#include "AutomatableModel.h"

class QLineEdit;
class QListView;
class QScrollArea;
class AutoDetectMidiController;
class ComboBox;
class GroupBox;
class TabWidget;
class LcdSpinBox;
class LedCheckBox;
class MidiPortMenu;

class ControllerConnectionDialog : public QDialog
{
	Q_OBJECT
public:
	ControllerConnectionDialog( QWidget * _parent,
			const AutomatableModel * _target_model );
	virtual ~ControllerConnectionDialog();

	Controller * chosenController()
	{
		return m_controller;
	}

public slots:
//	void setSelection( const effectKey & _selection );
	void selectController();
	void midiToggled();
	void userToggled();
	void userSelected();
	void autoDetectToggled();
	void enableAutoDetect( QAction * _a );

protected slots:
	void midiValueChanged();

private:
	// Midi
	GroupBox * m_midiGroupBox;
	LcdSpinBox * m_midiChannelSpinBox;
	LcdSpinBox * m_midiControllerSpinBox;
	LedCheckBox * m_midiAutoDetectCheckBox;
	MidiPortMenu * m_readablePorts;
	BoolModel m_midiAutoDetect;

	// User
	GroupBox * m_userGroupBox;
	ComboBox * m_userController;

	// Mapping
	TabWidget * m_mappingBox;
	QLineEdit * m_mappingFunction;

	Controller * m_controller;
	const AutomatableModel * m_targetModel;

	// Temporary midiController
	AutoDetectMidiController * m_midiController;
} ;

#endif


code:
/*
 * ControllerDialog.h - per-controller-specific view for changing a
 *                      controller's settings
 *
 * Copyright (c) 2008-2009 Paul Giblock <drfaygo/at/gmail.com>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CONTROLLER_DIALOG_H
#define CONTROLLER_DIALOG_H

#include <QWidget>

#include "ModelView.h"

class Controller;

class ControllerDialog : public QWidget, public ModelView
{
    Q_OBJECT
public:
	ControllerDialog( Controller * _controller, QWidget * _parent );

	virtual ~ControllerDialog();

signals:
	void closed();

protected:
	void closeEvent( QCloseEvent * _ce ) override;

} ;

#endif


code:
/*
 * ControllerRackView.h - view for song's controllers
 *
 * Copyright (c) 2008-2009 Paul Giblock <drfaygo/at/gmail.com>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CONTROLLER_RACK_VIEW_H
#define CONTROLLER_RACK_VIEW_H

#include <QWidget>
#include <QCloseEvent>

#include "SerializingObject.h"
#include "lmms_basics.h"

class QPushButton;
class QScrollArea;
class QVBoxLayout;

class ControllerView;
class Controller;

class ControllerRackView : public QWidget, public SerializingObject
{
	Q_OBJECT
public:
	ControllerRackView();
	virtual ~ControllerRackView();

	void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
	void loadSettings( const QDomElement & _this ) override;

	inline QString nodeName() const override
	{
		return "ControllerRackView";
	}

public slots:
	void deleteController( ControllerView * _view );
	void onControllerAdded( Controller * );
	void onControllerRemoved( Controller * );

protected:
	void closeEvent( QCloseEvent * _ce ) override;

private slots:
	void addController();

private:
	QVector<ControllerView *> m_controllerViews;

	QScrollArea * m_scrollArea;
	QVBoxLayout * m_scrollAreaLayout;
	QPushButton * m_addButton;

	// Stores the index of where to insert the next ControllerView.
	// Needed so that the StretchItem always stays at the last position.
	int m_nextIndex;
} ;

#endif


code:
/*
 * ControllerView.h - view-component for an control
 *
 * Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail.com>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CONTROLLER_VIEW_H
#define CONTROLLER_VIEW_H

#include <QFrame>

#include "AutomatableModel.h"
#include "Controller.h"
#include "ModelView.h"

class QGroupBox;
class QLabel;
class QPushButton;
class QMdiSubWindow;

class LedCheckBox;

class ControllerView : public QFrame, public ModelView
{
	Q_OBJECT
public:
	ControllerView( Controller * _controller, QWidget * _parent );
	virtual ~ControllerView();

	inline Controller * getController()
	{
		return( castModel<Controller>() );
	}

	inline const Controller * getController() const
	{
		return( castModel<Controller>() );
	}

public slots:
	void editControls();
	void deleteController();
	void closeControls();
	void renameController();

signals:
	void deleteController( ControllerView * _view );

protected:
	void contextMenuEvent( QContextMenuEvent * _me ) override;
	void modelChanged() override;
	void mouseDoubleClickEvent( QMouseEvent * event ) override;

private:
	QMdiSubWindow * m_subWindow;
	ControllerDialog * m_controllerDlg;
	QLabel * m_nameLabel;
	bool m_show;

} ;

#endif


code:
/*
 * Controls.h - labeled control widgets
 *
 * Copyright (c) 2019-2019 Johannes Lorenz <j.git$$$lorenz-ho.me, $$$=@>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef CONTROLS_H
#define CONTROLS_H

#include "Model.h"

// headers only required for covariance
#include "AutomatableModel.h"
#include "ComboBoxModel.h"

class QString;
class QWidget;
class AutomatableModel;

/**
	These classes provide
	- a control with a text label
	- a type safe way to set a model
		(justification: setting the wrong typed model to a widget will cause
		hard-to-find runtime errors)
*/
class Control
{
public:
	virtual QWidget* topWidget() = 0;
	virtual void setText(const QString& text) = 0;

	virtual void setModel(AutomatableModel* model) = 0;
	virtual AutomatableModel* model() = 0;
	virtual class AutomatableModelView* modelView() = 0;

	virtual ~Control();
};

class KnobControl : public Control
{
	class Knob* m_knob;

public:
	void setText(const QString& text) override;
	QWidget* topWidget() override;

	void setModel(AutomatableModel* model) override;
	FloatModel* model() override;
	class AutomatableModelView* modelView() override;

	KnobControl(QWidget* parent = nullptr);
	~KnobControl() override;
};

class ComboControl : public Control
{
	QWidget* m_widget;
	class ComboBox* m_combo;
	class QLabel* m_label;

public:
	void setText(const QString& text) override;
	QWidget* topWidget() override { return m_widget; }

	void setModel(AutomatableModel* model) override;
	ComboBoxModel* model() override;
	class AutomatableModelView* modelView() override;

	ComboControl(QWidget* parent = nullptr);
	~ComboControl() override;
};

class LcdControl : public Control
{
	class LcdSpinBox* m_lcd;

public:
	void setText(const QString& text) override;
	QWidget* topWidget() override;

	void setModel(AutomatableModel* model) override;
	IntModel* model() override;
	class AutomatableModelView* modelView() override;

	LcdControl(int numDigits, QWidget* parent = nullptr);
	~LcdControl() override;
};

class CheckControl : public Control
{
	QWidget* m_widget;
	class LedCheckBox* m_checkBox;
	QLabel* m_label;

public:
	void setText(const QString& text) override;
	QWidget* topWidget() override;

	void setModel(AutomatableModel* model) override;
	BoolModel *model() override;
	class AutomatableModelView* modelView() override;

	CheckControl(QWidget* parent = nullptr);
	~CheckControl() override;
};

#endif // CONTROLS_H


code:
/* Text customizable knob */
#ifndef CUSTOM_TEXT_KNOB_H
#define CUSTOM_TEXT_KNOB_H

#include "Knob.h"

class LMMS_EXPORT CustomTextKnob : public Knob
{
protected:
	inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible
public:
	CustomTextKnob( knobTypes _knob_num, QWidget * _parent = NULL, const QString & _name = QString(), const QString & _value_text = QString() );

	CustomTextKnob( QWidget * _parent = NULL, const QString & _name = QString(), const QString & _value_text = QString() ); //!< default ctor

	CustomTextKnob( const Knob& other ) = delete;

	inline void setValueText(const QString & _value_text)
	{
		m_value_text = _value_text;
	}

private:
	virtual QString displayValue() const;

protected:
	QString m_value_text;
} ;

#endif


code:
/*
 * DataFile.h - class for reading and writing LMMS data files
 *
 * Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 * Copyright (c) 2012-2013 Paul Giblock <p/at/pgiblock.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef DATA_FILE_H
#define DATA_FILE_H

#include <QDomDocument>

#include "lmms_export.h"
#include "MemoryManager.h"
#include "ProjectVersion.h"

class QTextStream;

class LMMS_EXPORT DataFile : public QDomDocument
{
	MM_OPERATORS

	using UpgradeMethod = void(DataFile::*)();

public:
	enum Types
	{
		UnknownType,
		SongProject,
		SongProjectTemplate,
		InstrumentTrackSettings,
		DragNDropData,
		ClipboardData,
		JournalData,
		EffectSettings,
		TypeCount
	} ;
	typedef Types Type;

	DataFile( const QString& fileName );
	DataFile( const QByteArray& data );
	DataFile( Type type );

	virtual ~DataFile();

	///
	/// \brief validate
	/// performs basic validation, compared to file extension.
	///
	bool validate( QString extension );

	QString nameWithExtension( const QString& fn ) const;

	void write( QTextStream& strm );
	bool writeFile( const QString& fn );

	QDomElement& content()
	{
		return m_content;
	}

	QDomElement& head()
	{
		return m_head;
	}

	Type type() const
	{
		return m_type;
	}

	unsigned int legacyFileVersion();

private:
	static Type type( const QString& typeName );
	static QString typeName( Type type );

	void cleanMetaNodes( QDomElement de );

	// helper upgrade routines
	void upgrade_0_2_1_20070501();
	void upgrade_0_2_1_20070508();
	void upgrade_0_3_0_rc2();
	void upgrade_0_3_0();
	void upgrade_0_4_0_20080104();
	void upgrade_0_4_0_20080118();
	void upgrade_0_4_0_20080129();
	void upgrade_0_4_0_20080409();
	void upgrade_0_4_0_20080607();
	void upgrade_0_4_0_20080622();
	void upgrade_0_4_0_beta1();
	void upgrade_0_4_0_rc2();
	void upgrade_1_0_99();
	void upgrade_1_1_0();
	void upgrade_1_1_91();
	void upgrade_1_2_0_rc3();
	void upgrade_1_3_0();
	void upgrade_noHiddenClipNames();

	// List of all upgrade methods
	static const std::vector<UpgradeMethod> UPGRADE_METHODS;
	// List of ProjectVersions for the legacyFileVersion method
	static const std::vector<ProjectVersion> UPGRADE_VERSIONS;

	void upgrade();

	void loadData( const QByteArray & _data, const QString & _sourceFile );

	struct LMMS_EXPORT typeDescStruct
	{
		Type m_type;
		QString m_name;
	} ;
	static typeDescStruct s_types[TypeCount];

	QDomElement m_content;
	QDomElement m_head;
	Type m_type;
	unsigned int m_fileVersion;

} ;

#endif


code:
/*
 * 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 - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef 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


code:
/*
 * DeprecationHelper.h - This file contains the declarations of helper functions
 * which helps centralize the #ifdefs preprocessors regarding deprecation based on Qt versions.
 * The functions are defined differently based on the callers' Qt versions.
 *
 * Copyright (c) 2020 Tien Dat Nguyen <ntd.bk.k56/at/gmail.com>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef DEPRECATIONHELPER_H
#define DEPRECATIONHELPER_H

#include <QFontMetrics>
#include <QWheelEvent>

/**
 * @brief horizontalAdvance is a backwards-compatible adapter for
 * QFontMetrics::horizontalAdvance and width functions.
 * @param metrics
 * @param text
 * @return text's horizontal advance based on metrics.
 */
inline int horizontalAdvance(const QFontMetrics& metrics, const QString& text)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
	return metrics.horizontalAdvance(text);
#else
	return metrics.width(text);
#endif
}

/**
 * @brief position is a backwards-compatible adapter for
 * QWheelEvent::position and pos functions.
 * @param wheelEvent
 * @return the position of wheelEvent
 */
inline QPoint position(QWheelEvent *wheelEvent)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
	return wheelEvent->position().toPoint();
#else
	return wheelEvent->pos();
#endif
}
#endif // DEPRECATIONHELPER_H


code:
/*
 * DetuningHelper.h - detuning automation helper
 *
 * Copyright (c) 2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
 * Copyright (c) 2008-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef DETUNING_HELPER_H
#define DETUNING_HELPER_H

#include "InlineAutomation.h"
#include "MemoryManager.h"

class DetuningHelper : public InlineAutomation
{
	Q_OBJECT
	MM_OPERATORS
public:
	DetuningHelper() :
		InlineAutomation()
	{
	}

	virtual ~DetuningHelper()
	{
	}

	float defaultValue() const override
	{
		return 0;
	}

	QString displayName() const override
	{
		return tr( "Note detuning" );
	}

	inline QString nodeName() const override
	{
		return "detuning";
	}

} ;

#endif


code:
/*
 * DrumSynth.h - DrumSynth DS file renderer
 *
 * Copyright (c) 1998-2000 Paul Kellett (mda-vst.com)
 * Copyright (c) 2007 Paul Giblock <drfaygo/at/gmail.com>
 *
 * This file is part of LMMS - https://lmms.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program (see COPYING); if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 */

#ifndef _DRUMSYNTH_H__
#define _DRUMSYNTH_H__

#include <stdint.h>
#include "lmms_basics.h"

class QString;

class DrumSynth {
    public:
        DrumSynth() {};
        int GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sample_rate_t Fs);

    private:
        float LoudestEnv(void);
        int   LongestEnv(void);
        void  UpdateEnv(int e, long t);
        void  GetEnv(int env, const char *sec, const char *key, QString ini);

        float waveform(float ph, int form);

        int GetPrivateProfileString(const char *sec, const char *key, const char *def, char *buffer, int size, QString file);
        int GetPrivateProfileInt(const char *sec, const char *key, int def, QString file);
        float GetPrivateProfileFloat(const char *sec, const char *key, float def, QString file);

};

#endif