code:
/*
 * VstSyncController.h - type declarations needed for VST to lmms host sync
 *
 * Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 * Copyright (c) 2013 Mike Choi <rdavidian71/at/gmail/dot/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 VST_SYNC_CONTROLLER_H
#define VST_SYNC_CONTROLLER_H

#include <QtCore/QObject>
#include <QtCore/QSharedMemory>

#include "VstSyncData.h"

class VstSyncController : public QObject
{
	Q_OBJECT
public:
	VstSyncController();
	~VstSyncController();

	void setAbsolutePosition( double ticks );

	void setPlaybackState( bool enabled )
	{
		m_syncData->isPlaying = enabled;
	}

	void setTempo( int newTempo );

	void setTimeSignature( int num, int denom )
	{
		m_syncData->timeSigNumer = num;
		m_syncData->timeSigDenom = denom;
	}

	void startCycle( int startTick, int endTick );

	void stopCycle()
	{
		m_syncData->isCycle = false;
	}

	void setPlaybackJumped( bool jumped )
	{
		m_syncData->m_playbackJumped = jumped;
	}

	void update();

private slots:
	void updateSampleRate();

private:
	VstSyncData* m_syncData;

	int m_shmID;

	QSharedMemory m_shm;

};

#endif


code:
/*
 * VstSyncData.h - type declarations needed for VST to lmms host sync
 *
 * Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 * Copyright (c) 2013 Mike Choi <rdavidian71/at/gmail/dot/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 VST_SYNC_DATA_H
#define VST_SYNC_DATA_H

// VST sync frequency (in ms), how often will be VST plugin synced
// keep it power of two if possible (not used by now)
//#define VST_SNC_TIMER 1

// When defined, latency should be subtracted from song PPQ position
//#define VST_SNC_LATENCY

// define file for ftok as shared memory shmget key
#define VST_SNC_SHM_KEY_FILE "/dev/null"
//#define VST_SNC_SHM_RND_KEY 3561653564469

struct VstSyncData
{
	double ppqPos;
	int timeSigNumer;
	int timeSigDenom;
	bool isPlaying;
	bool isCycle;
	bool hasSHM;
	float cycleStart;
	float cycleEnd;
	bool m_playbackJumped;
	int m_bufferSize;
	int m_sampleRate;
	int m_bpm;

#ifdef VST_SNC_LATENCY
	float m_latency;
#endif
} ;

#endif

repo_name: CYBERDEViL/LMMS

license: mit


code:
/*
 * aeffectx.h - simple header to allow VeSTige compilation and eventually work
 *
 * Copyright (c) 2006 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 AEFFECTX_H
#define AEFFECTX_H

#include <stdint.h>

// Calling convention
#define VST_CALL_CONV __cdecl

#define CCONST(a, b, c, d)( ( ( (int32_t) a ) << 24 ) |		\
				( ( (int32_t) b ) << 16 ) |		\
				( ( (int32_t) c ) << 8 ) |		\
				( ( (int32_t) d ) << 0 ) )

const int audioMasterAutomate = 0;
const int audioMasterVersion = 1;
const int audioMasterCurrentId = 2;
const int audioMasterIdle = 3;
const int audioMasterPinConnected = 4;
// unsupported? 5
const int audioMasterWantMidi = 6;
const int audioMasterGetTime = 7;
const int audioMasterProcessEvents = 8;
const int audioMasterSetTime = 9;
const int audioMasterTempoAt = 10;
const int audioMasterGetNumAutomatableParameters = 11;
const int audioMasterGetParameterQuantization = 12;
const int audioMasterIOChanged = 13;
const int audioMasterNeedIdle = 14;
const int audioMasterSizeWindow = 15;
const int audioMasterGetSampleRate = 16;
const int audioMasterGetBlockSize = 17;
const int audioMasterGetInputLatency = 18;
const int audioMasterGetOutputLatency = 19;
const int audioMasterGetPreviousPlug = 20;
const int audioMasterGetNextPlug = 21;
const int audioMasterWillReplaceOrAccumulate = 22;
const int audioMasterGetCurrentProcessLevel = 23;
const int audioMasterGetAutomationState = 24;
const int audioMasterOfflineStart = 25;
const int audioMasterOfflineRead = 26;
const int audioMasterOfflineWrite = 27;
const int audioMasterOfflineGetCurrentPass = 28;
const int audioMasterOfflineGetCurrentMetaPass = 29;
const int audioMasterSetOutputSampleRate = 30;
// unsupported? 31
const int audioMasterGetSpeakerArrangement = 31; // deprecated in 2.4?
const int audioMasterGetVendorString = 32;
const int audioMasterGetProductString = 33;
const int audioMasterGetVendorVersion = 34;
const int audioMasterVendorSpecific = 35;
const int audioMasterSetIcon = 36;
const int audioMasterCanDo = 37;
const int audioMasterGetLanguage = 38;
const int audioMasterOpenWindow = 39;
const int audioMasterCloseWindow = 40;
const int audioMasterGetDirectory = 41;
const int audioMasterUpdateDisplay = 42;
const int audioMasterBeginEdit = 43;
const int audioMasterEndEdit = 44;
const int audioMasterOpenFileSelector = 45;
const int audioMasterCloseFileSelector = 46; // currently unused
const int audioMasterEditFile = 47; // currently unused
const int audioMasterGetChunkFile = 48; // currently unused
const int audioMasterGetInputSpeakerArrangement = 49; // currently unused

const int effFlagsHasEditor = 1;
const int effFlagsCanReplacing = 1 << 4; // very likely
const int effFlagsIsSynth = 1 << 8; // currently unused

const int effOpen = 0;
const int effClose = 1; // currently unused
const int effSetProgram = 2; // currently unused
const int effGetProgram = 3; // currently unused
const int effGetProgramName = 5; // currently unused
const int effGetParamLabel = 6;
const int effGetParamDisplay = 7;
const int effGetParamName = 8; // currently unused
const int effSetSampleRate = 10;
const int effSetBlockSize = 11;
const int effMainsChanged = 12;
const int effEditGetRect = 13;
const int effEditOpen = 14;
const int effEditClose = 15;
const int effEditIdle = 19;
const int effEditTop = 20;
const int effSetChunk = 24;
const int effProcessEvents = 25;
const int effGetEffectName = 45;
const int effGetVendorString = 47;
const int effGetProductString = 48;
const int effGetVendorVersion = 49;
const int effCanDo = 51; // currently unused
const int effGetVstVersion = 58; // currently unused

const int kEffectMagic = CCONST( 'V', 's', 't', 'P' );
const int kVstLangEnglish = 1;
const int kVstMidiType = 1;

const int kVstTransportChanged = 1;
const int kVstTransportPlaying = 1 << 1;
const int kVstTransportCycleActive = 1 << 2;
const int kVstTransportRecording = 1 << 3; // currently unused
const int kVstPpqPosValid = 1 << 9;
const int kVstTempoValid = 1 << 10;
const int kVstBarsValid = 1 << 11;
const int kVstCyclePosValid = 1 << 12;
const int kVstTimeSigValid = 1 << 13;
const int kVstSmpteValid = 1 << 14; // currently unused
const int kVstClockValid = 1 << 15; // currently unused

// currently unused
const int kVstSmpte24fps = 0;
const int kVstSmpte25fps = 1;
const int kVstSmpte2997fps = 2;
const int kVstSmpte30fps = 3;
const int kVstSmpte2997dfps = 4;
const int kVstSmpte30dfps = 5;
const int kVstSmpteFilm16mm = 6; // very likely
const int kVstSmpteFilm35mm = 7; // very likely
const int kVstSmpte239fps = 10;
const int kVstSmpte249fps = 11;
const int kVstSmpte599fps = 12;
const int kVstSmpte60fps = 13;

class VstMidiEvent
{
public:
	// 00
	int32_t type;
	// 04
	int32_t byteSize;
	// 08
	int32_t deltaFrames;
	// 0c?
	int32_t flags;
	// 10?
	int32_t noteLength;
	// 14?
	int32_t noteOffset;
	// 18
	char midiData[4];
	// 1c?
	char detune;
	// 1d?
	char noteOffVelocity;
	// 1e?
	char reserved1;
	// 1f?
	char reserved2;

} ;

class VstEvent
{
	char dump[sizeof( VstMidiEvent )];

} ;

class VstEvents
{
public:
	// 00
	int32_t numEvents;
	// 04
	void *reserved;
	// 08
	VstEvent* events[1];

} ;

class AEffect
{
public:
	// Never use virtual functions!!!
	// 00-03
	int32_t magic;
	// dispatcher 04-07
	intptr_t (VST_CALL_CONV * dispatcher)( AEffect * , int32_t , int32_t , intptr_t, void * , float );
	// process, quite sure 08-0b
	void (VST_CALL_CONV * process)( AEffect * , float * * , float * * , int32_t );
	// setParameter 0c-0f
	void (VST_CALL_CONV * setParameter)( AEffect * , int32_t , float );
	// getParameter 10-13
	float (VST_CALL_CONV * getParameter)( AEffect * , int32_t );
	// programs 14-17
	int32_t numPrograms;
	// Params 18-1b
	int32_t numParams;
	// Input 1c-1f
	int32_t numInputs;
	// Output 20-23
	int32_t numOutputs;
	// flags 24-27
	int32_t flags;
	// Fill somewhere 28-2b
	void *ptr1;
	void *ptr2;
	// Zeroes 2c-2f 30-33 34-37 38-3b
	char empty3[4 + 4 + 4];
	// 1.0f 3c-3f
	float unknown_float;
	// An object? pointer 40-43
	void *ptr3;
	// Zeroes 44-47
	void *user;
	// Id 48-4b
	int32_t uniqueID;
	// Don't know 4c-4f
	char unknown1[4];
	// processReplacing 50-53
	void (VST_CALL_CONV * processReplacing)( AEffect * , float * * , float * * , int );

} ;

class VstTimeInfo
{
public:
	// 00
	double samplePos;
	// 08
	double sampleRate;
	// unconfirmed 10
	double nanoSeconds;
	// 18
	double ppqPos;
	// 20
	double tempo;
	// 28
	double barStartPos;
	// 30
	double cycleStartPos;
	// 38
	double cycleEndPos;
	// 40
	int32_t timeSigNumerator;
	// 44
	int32_t timeSigDenominator;
	// 48 unused
	int32_t smpteOffset;
	// 4c unused
	int32_t smpteFrameRate;
	// 50? unused, where does this come from?
	int32_t samplesToNextClock;
	// 54
	int32_t flags;

} ;

typedef intptr_t (VST_CALL_CONV * audioMasterCallback)( AEffect * , int32_t, int32_t, intptr_t, void * , float );

#endif


code:
/*
 * base64.h - namespace base64 with methods for encoding/decoding binary data
 *            to/from base64
 *
 * Copyright (c) 2006-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 _BASE64_H
#define _BASE64_H

#include <QtCore/QByteArray>
#include <QtCore/QString>
#include <QtCore/QVariant>

namespace base64
{
	inline void encode( const char * _data, const int _size,
								QString & _dst )
	{
		_dst = QByteArray( _data, _size ).toBase64();
	}

	template<class T>
	inline void decode( const QString & _b64, T * * _data, int * _size )
	{
		QByteArray data = QByteArray::fromBase64( _b64.toUtf8() );
		*_size = data.size();
		*_data = new T[*_size / sizeof(T)];
		memcpy( *_data, data.constData(), *_size );
	}
	// for compatibility-code only
	QVariant decode( const QString & _b64,
			QVariant::Type _force_type = QVariant::Invalid );

}

#endif


code:
/*
 * debug.h - header file to be included for debugging purposes
 *
 * Copyright (c) 2004-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 DEBUG_H
#define DEBUG_H

#include "lmmsconfig.h"

// set whether debug-stuff (like messages on the console, asserts and other
// additional range-checkings) should be compiled

#ifdef LMMS_DEBUG
	#include <assert.h>
#else
	#ifndef assert
		#define assert(x) ((void)(x))
	#endif
#endif
#include <cstdio>

#endif


code:
// Denormals stripping.
// These snippets should be common enough to be considered public domain.

#ifndef DENORMALS_H
#define DENORMALS_H

#ifdef __SSE__
#include <xmmintrin.h>
#endif
#ifdef __SSE3__
#include <pmmintrin.h>
#endif

// Set denormal protection for this thread.
// To be on the safe side, don't set the DAZ flag for SSE2 builds,
// even if most SSE2 CPUs can handle it.
void inline disable_denormals() {
#ifdef __SSE3__
	/* DAZ flag */
	_MM_SET_DENORMALS_ZERO_MODE( _MM_DENORMALS_ZERO_ON );
#endif

#ifdef __SSE__
	/* FTZ flag */
	_MM_SET_FLUSH_ZERO_MODE( _MM_FLUSH_ZERO_ON );
#endif
}

#endif


code:
/*
 * embed.h - misc. stuff for using embedded data (resources linked into binary)
 *
 * 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 EMBED_H
#define EMBED_H

#include <QPixmap>
#include <QtCore/QString>

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

namespace embed
{

/**
 * Return an image for the icon pixmap cache.
 *
 * @param _name Identifier for the pixmap. If it is not in the icon pixmap
 *   cache, it will be loaded from the artwork QDir search paths (exceptions are
 *   compiled-in XPMs, you need to provide @p xpm for loading them).
 * @param xpm Must be XPM data if the source should be raw XPM data instead of
 *   a file
 */
QPixmap LMMS_EXPORT getIconPixmap( const QString&  _name,
	int _w = -1, int _h = -1 , const char** xpm = nullptr );
QString LMMS_EXPORT getText( const char * _name );

}

#ifdef PLUGIN_NAME
namespace PLUGIN_NAME
{

inline QPixmap getIconPixmap( const QString&  _name,
	int _w = -1, int _h = -1, const char** xpm = nullptr )
{
	return embed::getIconPixmap(QString("%1/%2").arg(STRINGIFY(PLUGIN_NAME), _name), _w, _h, xpm);
}
//QString getText( const char * _name );

}
#endif

class PixmapLoader
{
public:
	PixmapLoader( const PixmapLoader * _ref ) :
		m_name( _ref != NULL ? _ref->m_name : QString() ),
		m_xpm( _ref->m_xpm )
	{
	}

	PixmapLoader( const QString & _name = QString(),
		const char** xpm = nullptr ) :
		m_name( _name ),
		m_xpm(xpm)
	{
	}

	virtual QPixmap pixmap() const
	{
		if( !m_name.isEmpty() )
		{
			return( embed::getIconPixmap(
				m_name.toLatin1().constData(), -1, -1, m_xpm ));
		}
		return( QPixmap() );
	}

	virtual ~PixmapLoader()
	{
	}

	virtual QString pixmapName() const
	{
		return m_name;
	}

protected:
	QString m_name;
	const char** m_xpm = nullptr;
} ;

#ifdef PLUGIN_NAME
class PluginPixmapLoader : public PixmapLoader
{
public:
	PluginPixmapLoader( const QString & _name = QString() ) :
		PixmapLoader( _name )
	{
	}

	virtual QPixmap pixmap() const
	{
		if( !m_name.isEmpty() )
		{
			return( PLUGIN_NAME::getIconPixmap(
					m_name.toLatin1().constData() ) );
		}
		return( QPixmap() );
	}

	virtual QString pixmapName() const
	{
		return QString( STRINGIFY(PLUGIN_NAME) ) + "::" + m_name;
	}

} ;
#endif

#endif


code:
/*
 * endian_handling.h - handle endianess
 *
 * 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 ENDIAN_HANDLING_H
#define ENDIAN_HANDLING_H

#include <QtCore/QSysInfo>

#include "lmms_basics.h"

inline bool isLittleEndian()
{
	return( QSysInfo::ByteOrder == QSysInfo::LittleEndian );
}

inline int16_t swap16IfBE( int16_t i )
{
	return( isLittleEndian() ? i : ( ( i & 0xFF ) << 8) | ( ( i >> 8 ) & 0xFF ) );
}

inline int32_t swap32IfBE( int32_t i )
{
	return( isLittleEndian() ? i : ( ( i & 0xff000000 ) >> 24 ) |
					( ( i & 0x00ff0000 ) >> 8 )  |
					( ( i & 0x0000ff00 ) << 8 )  |
					( ( i & 0x000000ff ) << 24 ) );
}

#endif


code:
#pragma once

#include_next <fenv.h>

#if defined(__APPLE__) && defined(__MACH__)

// Public domain polyfill for feenableexcept on OS X
// http://www-personal.umich.edu/~williams/archive/computation/fe-handling-example.c

inline int feenableexcept(unsigned int excepts)
{
    static fenv_t fenv;
    unsigned int new_excepts = excepts & FE_ALL_EXCEPT;
    // previous masks
    unsigned int old_excepts;

    if (fegetenv(&fenv)) {
        return -1;
    }
    old_excepts = fenv.__control & FE_ALL_EXCEPT;

    // unmask
    fenv.__control &= ~new_excepts;
    fenv.__mxcsr   &= ~(new_excepts << 7);

    return fesetenv(&fenv) ? -1 : old_excepts;
}

inline int fedisableexcept(unsigned int excepts)
{
    static fenv_t fenv;
    unsigned int new_excepts = excepts & FE_ALL_EXCEPT;
    // all previous masks
    unsigned int old_excepts;

    if (fegetenv(&fenv)) {
        return -1;
    }
    old_excepts = fenv.__control & FE_ALL_EXCEPT;

    // mask
    fenv.__control |= new_excepts;
    fenv.__mxcsr   |= new_excepts << 7;

    return fesetenv(&fenv) ? -1 : old_excepts;
}

#endif


code:
/*
 * fft_helpers.h - some functions around FFT analysis
 *
 * Copyright (c) 2008-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 * Copyright (c) 2019 Martin Pavelek <he29.HS/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 FFT_HELPERS_H
#define FFT_HELPERS_H

#include "lmms_export.h"

#include <vector>
#include <fftw3.h>

// NOTE: FFT_BUFFER_SIZE should be considered deprecated!
// It is used by Eq plugin and some older code here, but this should be a user
// switchable parameter, not a constant. Use a value from FFT_BLOCK_SIZES
const unsigned int FFT_BUFFER_SIZE = 2048;

// Allowed FFT block sizes. Ranging from barely useful to barely acceptable
// because of performance and latency reasons.
const std::vector<unsigned int> FFT_BLOCK_SIZES = {256, 512, 1024, 2048, 4096, 8192, 16384};

// List of FFT window functions supported by precomputeWindow()
enum FFT_WINDOWS
{
	RECTANGULAR = 0,
	BLACKMAN_HARRIS,
	HAMMING,
	HANNING
};

/**	Returns biggest value from abs_spectrum[spec_size] array.
 *
 *	@return -1 on error, 0 on success
 */
float LMMS_EXPORT maximum(const float *abs_spectrum, unsigned int spec_size);
float LMMS_EXPORT maximum(const std::vector<float> &abs_spectrum);

/** Normalize the abs_spectrum array of absolute values to a 0..1 range
 *	based on supplied energy and stores it in the norm_spectrum array.
 *
 *	@return -1 on error
 */
int LMMS_EXPORT normalize(const float *abs_spectrum, float *norm_spectrum, unsigned int bin_count, unsigned int block_size);
int LMMS_EXPORT normalize(const std::vector<float> &abs_spectrum, std::vector<float> &norm_spectrum, unsigned int block_size);

/**	Check if the spectrum contains any non-zero value.
 *
 *	@return 1 if spectrum contains any non-zero value
 *	@return 0 otherwise
 */
int LMMS_EXPORT notEmpty(const std::vector<float> &spectrum);

/**	Precompute a window function for later real-time use.
 *	Set normalized to false if you do not want to apply amplitude correction.
 *
 *	@return -1 on error
 */
int LMMS_EXPORT precomputeWindow(float *window, unsigned int length, FFT_WINDOWS type, bool normalized = true);

/**	Compute absolute values of complex_buffer, save to absspec_buffer.
 *	Take care that - compl_len is not bigger than complex_buffer!
 *				   - absspec buffer is big enough!
 *
 *	@return 0 on success, else -1
 */
int LMMS_EXPORT absspec(const fftwf_complex *complex_buffer, float *absspec_buffer,
						unsigned int compl_length);

/**	Build fewer subbands from many absolute spectrum values.
 *	Take care that - compressedbands[] array num_new elements long
 *				   - num_old > num_new
 *
 *	@return 0 on success, else -1
 */
int LMMS_EXPORT compressbands(const float * _absspec_buffer, float * _compressedband,
			int _num_old, int _num_new, int _bottom, int _top);

#endif


code:
/*
 * gui_templates.h - GUI-specific templates
 *
 * 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 GUI_TEMPLATES_H
#define GUI_TEMPLATES_H

#include "lmmsconfig.h"

#include <QApplication>
#include <QFont>
#include <QDesktopWidget>

// return DPI-independent font-size - font with returned font-size has always
// the same size in pixels
template<int SIZE>
inline QFont pointSize( QFont _f )
{
	static const float DPI = 96;
#ifdef LMMS_BUILD_WIN32
	_f.setPointSizeF( ((float) SIZE+0.5f) * DPI /
			QApplication::desktop()->logicalDpiY() );
#else
	_f.setPointSizeF( (float) SIZE * DPI /
			QApplication::desktop()->logicalDpiY() );
#endif
	return( _f );
}

inline QFont pointSizeF( QFont _f, float SIZE )
{
	static const float DPI = 96;
#ifdef LMMS_BUILD_WIN32
	_f.setPointSizeF( (SIZE+0.5f) * DPI /
			QApplication::desktop()->logicalDpiY() );
#else
	_f.setPointSizeF( SIZE * DPI /
			QApplication::desktop()->logicalDpiY() );
#endif
	return( _f );
}

#endif


code:
/*
 * interpolation.h - fast implementations of several interpolation-algorithms
 *
 * Copyright (c) 2004-2005 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 INTERPOLATION_H
#define INTERPOLATION_H

#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif

#include <math.h>
#include "lmms_constants.h"
#include "lmms_math.h"

inline float hermiteInterpolate( float x0, float x1, float x2, float x3,
								float frac_pos )
{
	const float frsq = frac_pos*frac_pos;
	const float frsq2 = 2*frsq;
	return( ( (x2-x0) *0.5f ) * ( frac_pos * (frsq+1) -frsq2 ) +
				( frsq2*frac_pos - 3*frsq ) * ( x1-x2 ) +
			frsq2 * (frac_pos-1) * ( ( x3-x1 ) * 0.25f ) + x1 );

/*
   const float frsq	= frac_pos*frac_pos;
   //const float frsq2	= 2*frsq;
   frac_pos *= 0.5;
   const float frcu	= frsq*frac_pos;
   return (

   (frcu - frsq + frac_pos) * ((x2 - x0)) +

   (4*frcu - 3*frsq) * (x1 - x2)
   //frsq*(2*frac_pos-3) * (x1 - x2)

   + (frcu - 0.5*frsq)*((x3 - x1))

   + x1

   );
*/
}

inline float cubicInterpolate( float v0, float v1, float v2, float v3, float x )
{
	float frsq = x*x;
	float frcu = frsq*v0;
	float t1 = v3 + 3*v1;

	return( v1 + fastFmaf( 0.5f, frcu, x ) * ( v2 - frcu * ( 1.0f/6.0f ) -
		fastFmaf( t1, ( 1.0f/6.0f ), -v0 ) * ( 1.0f/3.0f ) ) + frsq * x * ( t1 *
		( 1.0f/6.0f ) - 0.5f * v2 ) + frsq * fastFmaf( 0.5f, v2, -v1 ) );
}

inline float cosinusInterpolate( float v0, float v1, float x )
{
	const float f = ( 1.0f - cosf( x * F_PI ) ) * 0.5f;
	return fastFmaf( f, v1-v0, v0 );
}

inline float linearInterpolate( float v0, float v1, float x )
{
	return fastFmaf( x, v1-v0, v0 );
}

inline float optimalInterpolate( float v0, float v1, float x )
{
	const float z = x - 0.5f;
	const float even = v1 + v0;
	const float odd = v1 - v0;

	const float c0 = even * 0.50037842517188658;
	const float c1 = odd * 1.00621089801788210;
	const float c2 = even * -0.004541102062639801;
	const float c3 = odd * -1.57015627178718420;

	return fastFmaf( fastFmaf( fastFmaf( c3, z, c2 ), z, c1 ), z, c0 );
}

inline float optimal4pInterpolate( float v0, float v1, float v2, float v3, float x )
{
	const float z = x - 0.5f;
	const float even1 = v2 + v1;
	const float odd1 = v2 - v1;
	const float even2 = v3 + v0;
	const float odd2 = v3 - v0;

	const float c0 = even1 * 0.45868970870461956 + even2 * 0.04131401926395584;
	const float c1 = odd1 * 0.48068024766578432 + odd2 * 0.17577925564495955;
	const float c2 = even1 * -0.246185007019907091 + even2 * 0.24614027139700284;
	const float c3 = odd1 * -0.36030925263849456 + odd2 * 0.10174985775982505;

	return fastFmaf( fastFmaf( fastFmaf( c3, z, c2 ), z, c1 ), z, c0 );
}

inline float lagrangeInterpolate( float v0, float v1, float v2, float v3, float x )
{
	const float c0 = v1;
	const float c1 = v2 - v0 * ( 1.0f / 3.0f ) - v1 * 0.5f - v3 * ( 1.0f / 6.0f );
	const float c2 = 0.5f * (v0 + v2) - v1;
	const float c3 = ( 1.0f/6.0f ) * ( v3 - v0 ) + 0.5f * ( v1 - v2 );
	return fastFmaf( fastFmaf( fastFmaf( c3, x, c2 ), x, c1 ), x, c0 );
}

#endif


code:
/* ladspa.h

   Linux Audio Developer's Simple Plugin API Version 1.1[LGPL].
   Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis,
   Stefan Westerfeld.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1 of
   the License, or (at your option) any later version.

   This library 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA. */

#ifndef LADSPA_INCLUDED
#define LADSPA_INCLUDED

#define LADSPA_VERSION "1.1"
#define LADSPA_VERSION_MAJOR 1
#define LADSPA_VERSION_MINOR 1

#ifdef __cplusplus
extern "C" {
#endif

/*****************************************************************************/

/* Overview:

   There is a large number of synthesis packages in use or development
   on the Linux platform at this time. This API (`The Linux Audio
   Developer's Simple Plugin API') attempts to give programmers the
   ability to write simple `plugin' audio processors in C/C++ and link
   them dynamically (`plug') into a range of these packages (`hosts').
   It should be possible for any host and any plugin to communicate
   completely through this interface.

   This API is deliberately short and simple. To achieve compatibility
   with a range of promising Linux sound synthesis packages it
   attempts to find the `greatest common divisor' in their logical
   behaviour. Having said this, certain limiting decisions are
   implicit, notably the use of a fixed type (LADSPA_Data) for all
   data transfer and absence of a parameterised `initialisation'
   phase. See below for the LADSPA_Data typedef.

   Plugins are expected to distinguish between control and audio
   data. Plugins have `ports' that are inputs or outputs for audio or
   control data and each plugin is `run' for a `block' corresponding
   to a short time interval measured in samples. Audio data is
   communicated using arrays of LADSPA_Data, allowing a block of audio
   to be processed by the plugin in a single pass. Control data is
   communicated using single LADSPA_Data values. Control data has a
   single value at the start of a call to the `run()' or `run_adding()'
   function, and may be considered to remain this value for its
   duration. The plugin may assume that all its input and output ports
   have been connected to the relevant data location (see the
   `connect_port()' function below) before it is asked to run.

   Plugins will reside in shared object files suitable for dynamic
   linking by dlopen() and family. The file will provide a number of
   `plugin types' that can be used to instantiate actual plugins
   (sometimes known as `plugin instances') that can be connected
   together to perform tasks.

   This API contains very limited error-handling. */

/*****************************************************************************/

/* Fundamental data type passed in and out of plugin. This data type
   is used to communicate audio samples and control values. It is
   assumed that the plugin will work sensibly given any numeric input
   value although it may have a preferred range (see hints below).

   For audio it is generally assumed that 1.0f is the `0dB' reference
   amplitude and is a `normal' signal level. */

typedef float LADSPA_Data;

/*****************************************************************************/

/* Special Plugin Properties:

   Optional features of the plugin type are encapsulated in the
   LADSPA_Properties type. This is assembled by ORing individual
   properties together. */

typedef int LADSPA_Properties;

/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a
   real-time dependency (e.g. listens to a MIDI device) and so its
   output must not be cached or subject to significant latency. */
#define LADSPA_PROPERTY_REALTIME        0x1

/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin
   may cease to work correctly if the host elects to use the same data
   location for both input and output (see connect_port()). This
   should be avoided as enabling this flag makes it impossible for
   hosts to use the plugin to process audio `in-place.' */
#define LADSPA_PROPERTY_INPLACE_BROKEN  0x2

/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin
   is capable of running not only in a conventional host but also in a
   `hard real-time' environment. To qualify for this the plugin must
   satisfy all of the following:

   (1) The plugin must not use malloc(), free() or other heap memory
   management within its run() or run_adding() functions. All new
   memory used in run() must be managed via the stack. These
   restrictions only apply to the run() function.

   (2) The plugin will not attempt to make use of any library
   functions with the exceptions of functions in the ANSI standard C
   and C maths libraries, which the host is expected to provide.

   (3) The plugin will not access files, devices, pipes, sockets, IPC
   or any other mechanism that might result in process or thread
   blocking.

   (4) The plugin will take an amount of time to execute a run() or
   run_adding() call approximately of form (A+B*SampleCount) where A
   and B depend on the machine and host in use. This amount of time
   may not depend on input signals or plugin state. The host is left
   the responsibility to perform timings to estimate upper bounds for
   A and B. */
#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4

#define LADSPA_IS_REALTIME(x)        ((x) & LADSPA_PROPERTY_REALTIME)
#define LADSPA_IS_INPLACE_BROKEN(x)  ((x) & LADSPA_PROPERTY_INPLACE_BROKEN)
#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE)

/*****************************************************************************/

/* Plugin Ports:

   Plugins have `ports' that are inputs or outputs for audio or
   data. Ports can communicate arrays of LADSPA_Data (for audio
   inputs/outputs) or single LADSPA_Data values (for control
   input/outputs). This information is encapsulated in the
   LADSPA_PortDescriptor type which is assembled by ORing individual
   properties together.

   Note that a port must be an input or an output port but not both
   and that a port must be a control or audio port but not both. */

typedef int LADSPA_PortDescriptor;

/* Property LADSPA_PORT_INPUT indicates that the port is an input. */
#define LADSPA_PORT_INPUT   0x1

/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */
#define LADSPA_PORT_OUTPUT  0x2

/* Property LADSPA_PORT_CONTROL indicates that the port is a control
   port. */
#define LADSPA_PORT_CONTROL 0x4

/* Property LADSPA_PORT_AUDIO indicates that the port is a audio
   port. */
#define LADSPA_PORT_AUDIO   0x8

#define LADSPA_IS_PORT_INPUT(x)   ((x) & LADSPA_PORT_INPUT)
#define LADSPA_IS_PORT_OUTPUT(x)  ((x) & LADSPA_PORT_OUTPUT)
#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL)
#define LADSPA_IS_PORT_AUDIO(x)   ((x) & LADSPA_PORT_AUDIO)

/*****************************************************************************/

/* Plugin Port Range Hints:

   The host may wish to provide a representation of data entering or
   leaving a plugin (e.g. to generate a GUI automatically). To make
   this more meaningful, the plugin should provide `hints' to the host
   describing the usual values taken by the data.

   Note that these are only hints. The host may ignore them and the
   plugin must not assume that data supplied to it is meaningful. If
   the plugin receives invalid input data it is expected to continue
   to run without failure and, where possible, produce a sensible
   output (e.g. a high-pass filter given a negative cutoff frequency
   might switch to an all-pass mode).

   Hints are meaningful for all input and output ports but hints for
   input control ports are expected to be particularly useful.

   More hint information is encapsulated in the
   LADSPA_PortRangeHintDescriptor type which is assembled by ORing
   individual hint types together. Hints may require further
   LowerBound and UpperBound information.

   All the hint information for a particular port is aggregated in the
   LADSPA_PortRangeHint structure. */

typedef int LADSPA_PortRangeHintDescriptor;

/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field
   of the LADSPA_PortRangeHint should be considered meaningful. The
   value in this field should be considered the (inclusive) lower
   bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
   specified then the value of LowerBound should be multiplied by the
   sample rate. */
#define LADSPA_HINT_BOUNDED_BELOW   0x1

/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field
   of the LADSPA_PortRangeHint should be considered meaningful. The
   value in this field should be considered the (inclusive) upper
   bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
   specified then the value of UpperBound should be multiplied by the
   sample rate. */
#define LADSPA_HINT_BOUNDED_ABOVE   0x2

/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be
   considered a Boolean toggle. Data less than or equal to zero should
   be considered `off' or `false,' and data above zero should be
   considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in
   conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or
   LADSPA_HINT_DEFAULT_1. */
#define LADSPA_HINT_TOGGLED         0x4

/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified
   should be interpreted as multiples of the sample rate. For
   instance, a frequency range from 0Hz to the Nyquist frequency (half
   the sample rate) could be requested by this hint in conjunction
   with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds
   at all must support this hint to retain meaning. */
#define LADSPA_HINT_SAMPLE_RATE     0x8

/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the
   user will find it more intuitive to view values using a logarithmic
   scale. This is particularly useful for frequencies and gains. */
#define LADSPA_HINT_LOGARITHMIC     0x10

/* Hint LADSPA_HINT_INTEGER indicates that a user interface would
   probably wish to provide a stepped control taking only integer
   values. Any bounds set should be slightly wider than the actual
   integer range required to avoid floating point rounding errors. For
   instance, the integer set {0,1,2,3} might be described as [-0.1,
   3.1]. */
#define LADSPA_HINT_INTEGER         0x20

/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal'
   value for the port that is sensible as a default. For instance,
   this value is suitable for use as an initial value in a user
   interface or as a value the host might assign to a control port
   when the user has not provided one. Defaults are encoded using a
   mask so only one default may be specified for a port. Some of the
   hints make use of lower and upper bounds, in which case the
   relevant bound or bounds must be available and
   LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting
   default must be rounded if LADSPA_HINT_INTEGER is present. Default
   values were introduced in LADSPA v1.1. */
#define LADSPA_HINT_DEFAULT_MASK    0x3C0

/* This default values indicates that no default is provided. */
#define LADSPA_HINT_DEFAULT_NONE    0x0

/* This default hint indicates that the suggested lower bound for the
   port should be used. */
#define LADSPA_HINT_DEFAULT_MINIMUM 0x40

/* This default hint indicates that a low value between the suggested
   lower and upper bounds should be chosen. For ports with
   LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 +
   log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper
   * 0.25). */
#define LADSPA_HINT_DEFAULT_LOW     0x80

/* This default hint indicates that a middle value between the
   suggested lower and upper bounds should be chosen. For ports with
   LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 +
   log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper *
   0.5). */
#define LADSPA_HINT_DEFAULT_MIDDLE  0xC0

/* This default hint indicates that a high value between the suggested
   lower and upper bounds should be chosen. For ports with
   LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 +
   log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper
   * 0.75). */
#define LADSPA_HINT_DEFAULT_HIGH    0x100

/* This default hint indicates that the suggested upper bound for the
   port should be used. */
#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140

/* This default hint indicates that the number 0 should be used. Note
   that this default may be used in conjunction with
   LADSPA_HINT_TOGGLED. */
#define LADSPA_HINT_DEFAULT_0       0x200

/* This default hint indicates that the number 1 should be used. Note
   that this default may be used in conjunction with
   LADSPA_HINT_TOGGLED. */
#define LADSPA_HINT_DEFAULT_1       0x240

/* This default hint indicates that the number 100 should be used. */
#define LADSPA_HINT_DEFAULT_100     0x280

/* This default hint indicates that the Hz frequency of `concert A'
   should be used. This will be 440 unless the host uses an unusual
   tuning convention, in which case it may be within a few Hz. */
#define LADSPA_HINT_DEFAULT_440     0x2C0

#define LADSPA_IS_HINT_BOUNDED_BELOW(x)   ((x) & LADSPA_HINT_BOUNDED_BELOW)
#define LADSPA_IS_HINT_BOUNDED_ABOVE(x)   ((x) & LADSPA_HINT_BOUNDED_ABOVE)
#define LADSPA_IS_HINT_TOGGLED(x)         ((x) & LADSPA_HINT_TOGGLED)
#define LADSPA_IS_HINT_SAMPLE_RATE(x)     ((x) & LADSPA_HINT_SAMPLE_RATE)
#define LADSPA_IS_HINT_LOGARITHMIC(x)     ((x) & LADSPA_HINT_LOGARITHMIC)
#define LADSPA_IS_HINT_INTEGER(x)         ((x) & LADSPA_HINT_INTEGER)

#define LADSPA_IS_HINT_HAS_DEFAULT(x)     ((x) & LADSPA_HINT_DEFAULT_MASK)
#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK)   \
                                           == LADSPA_HINT_DEFAULT_MINIMUM)
#define LADSPA_IS_HINT_DEFAULT_LOW(x)     (((x) & LADSPA_HINT_DEFAULT_MASK)   \
                                           == LADSPA_HINT_DEFAULT_LOW)
#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x)  (((x) & LADSPA_HINT_DEFAULT_MASK)   \
                                           == LADSPA_HINT_DEFAULT_MIDDLE)
#define LADSPA_IS_HINT_DEFAULT_HIGH(x)    (((x) & LADSPA_HINT_DEFAULT_MASK)   \
                                           == LADSPA_HINT_DEFAULT_HIGH)
#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK)   \
                                           == LADSPA_HINT_DEFAULT_MAXIMUM)
#define LADSPA_IS_HINT_DEFAULT_0(x)       (((x) & LADSPA_HINT_DEFAULT_MASK)   \
                                           == LADSPA_HINT_DEFAULT_0)
#define LADSPA_IS_HINT_DEFAULT_1(x)       (((x) & LADSPA_HINT_DEFAULT_MASK)   \
                                           == LADSPA_HINT_DEFAULT_1)
#define LADSPA_IS_HINT_DEFAULT_100(x)     (((x) & LADSPA_HINT_DEFAULT_MASK)   \
                                           == LADSPA_HINT_DEFAULT_100)
#define LADSPA_IS_HINT_DEFAULT_440(x)     (((x) & LADSPA_HINT_DEFAULT_MASK)   \
                                            == LADSPA_HINT_DEFAULT_440)

typedef struct _LADSPA_PortRangeHint {

  /* Hints about the port. */
  LADSPA_PortRangeHintDescriptor HintDescriptor;

  /* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When
     LADSPA_HINT_SAMPLE_RATE is also active then this value should be
     multiplied by the relevant sample rate. */
  LADSPA_Data LowerBound;

  /* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When
     LADSPA_HINT_SAMPLE_RATE is also active then this value should be
     multiplied by the relevant sample rate. */
  LADSPA_Data UpperBound;

} LADSPA_PortRangeHint;

/*****************************************************************************/

/* Plugin Handles:

   This plugin handle indicates a particular instance of the plugin
   concerned. It is valid to compare this to NULL (0 for C++) but
   otherwise the host should not attempt to interpret it. The plugin
   may use it to reference internal instance data. */

typedef void * LADSPA_Handle;

/*****************************************************************************/

/* Descriptor for a Type of Plugin:

   This structure is used to describe a plugin type. It provides a
   number of functions to examine the type, instantiate it, link it to
   buffers and workspaces and to run it. */

typedef struct _LADSPA_Descriptor {

  /* This numeric identifier indicates the plugin type
     uniquely. Plugin programmers may reserve ranges of IDs from a
     central body to avoid clashes. Hosts may assume that IDs are
     below 0x1000000. */
  unsigned long UniqueID;

  /* This identifier can be used as a unique, case-sensitive
     identifier for the plugin type within the plugin file. Plugin
     types should be identified by file and label rather than by index
     or plugin name, which may be changed in new plugin
     versions. Labels must not contain white-space characters. */
  const char * Label;

  /* This indicates a number of properties of the plugin. */
  LADSPA_Properties Properties;

  /* This member points to the null-terminated name of the plugin
     (e.g. "Sine Oscillator"). */
  const char * Name;

  /* This member points to the null-terminated string indicating the
     maker of the plugin. This can be an empty string but not NULL. */
  const char * Maker;

  /* This member points to the null-terminated string indicating any
     copyright applying to the plugin. If no Copyright applies the
     string "None" should be used. */
  const char * Copyright;

  /* This indicates the number of ports (input AND output) present on
     the plugin. */
  unsigned long PortCount;

  /* This member indicates an array of port descriptors. Valid indices
     vary from 0 to PortCount-1. */
  const LADSPA_PortDescriptor * PortDescriptors;

  /* This member indicates an array of null-terminated strings
     describing ports (e.g. "Frequency (Hz)"). Valid indices vary from
     0 to PortCount-1. */
  const char * const * PortNames;

  /* This member indicates an array of range hints for each port (see
     above). Valid indices vary from 0 to PortCount-1. */
  const LADSPA_PortRangeHint * PortRangeHints;

  /* This may be used by the plugin developer to pass any custom
     implementation data into an instantiate call. It must not be used
     or interpreted by the host. It is expected that most plugin
     writers will not use this facility as LADSPA_Handle should be
     used to hold instance data. */
  void * ImplementationData;

  /* This member is a function pointer that instantiates a plugin. A
     handle is returned indicating the new plugin instance. The
     instantiation function accepts a sample rate as a parameter. The
     plugin descriptor from which this instantiate function was found
     must also be passed. This function must return NULL if
     instantiation fails.

     Note that instance initialisation should generally occur in
     activate() rather than here. */
  LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor,
                               unsigned long                     SampleRate);

  /* This member is a function pointer that connects a port on an
     instantiated plugin to a memory location at which a block of data
     for the port will be read/written. The data location is expected
     to be an array of LADSPA_Data for audio ports or a single
     LADSPA_Data value for control ports. Memory issues will be
     managed by the host. The plugin must read/write the data at these
     locations every time run() or run_adding() is called and the data
     present at the time of this connection call should not be
     considered meaningful.

     connect_port() may be called more than once for a plugin instance
     to allow the host to change the buffers that the plugin is
     reading or writing. These calls may be made before or after
     activate() or deactivate() calls.

     connect_port() must be called at least once for each port before
     run() or run_adding() is called. When working with blocks of
     LADSPA_Data the plugin should pay careful attention to the block
     size passed to the run function as the block allocated may only
     just be large enough to contain the block of samples.

     Plugin writers should be aware that the host may elect to use the
     same buffer for more than one port and even use the same buffer
     for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN).
     However, overlapped buffers or use of a single buffer for both
     audio and control data may result in unexpected behaviour. */
   void (*connect_port)(LADSPA_Handle Instance,
                        unsigned long Port,
                        LADSPA_Data * DataLocation);

  /* This member is a function pointer that initialises a plugin
     instance and activates it for use. This is separated from
     instantiate() to aid real-time support and so that hosts can
     reinitialise a plugin instance by calling deactivate() and then
     activate(). In this case the plugin instance must reset all state
     information dependent on the history of the plugin instance
     except for any data locations provided by connect_port() and any
     gain set by set_run_adding_gain(). If there is nothing for
     activate() to do then the plugin writer may provide a NULL rather
     than an empty function.

     When present, hosts must call this function once before run() (or
     run_adding()) is called for the first time. This call should be
     made as close to the run() call as possible and indicates to
     real-time plugins that they are now live. Plugins should not rely
     on a prompt call to run() after activate(). activate() may not be
     called again unless deactivate() is called first. Note that
     connect_port() may be called before or after a call to
     activate(). */
  void (*activate)(LADSPA_Handle Instance);

  /* This method is a function pointer that runs an instance of a
     plugin for a block. Two parameters are required: the first is a
     handle to the particular instance to be run and the second
     indicates the block size (in samples) for which the plugin
     instance may run.

     Note that if an activate() function exists then it must be called
     before run() or run_adding(). If deactivate() is called for a
     plugin instance then the plugin instance may not be reused until
     activate() has been called again.

     If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE
     then there are various things that the plugin should not do
     within the run() or run_adding() functions (see above). */
  void (*run)(LADSPA_Handle Instance,
              unsigned long SampleCount);

  /* This method is a function pointer that runs an instance of a
     plugin for a block. This has identical behaviour to run() except
     in the way data is output from the plugin. When run() is used,
     values are written directly to the memory areas associated with
     the output ports. However when run_adding() is called, values
     must be added to the values already present in the memory
     areas. Furthermore, output values written must be scaled by the
     current gain set by set_run_adding_gain() (see below) before
     addition.

     run_adding() is optional. When it is not provided by a plugin,
     this function pointer must be set to NULL. When it is provided,
     the function set_run_adding_gain() must be provided also. */
  void (*run_adding)(LADSPA_Handle Instance,
                     unsigned long SampleCount);

  /* This method is a function pointer that sets the output gain for
     use when run_adding() is called (see above). If this function is
     never called the gain is assumed to default to 1. Gain
     information should be retained when activate() or deactivate()
     are called.

     This function should be provided by the plugin if and only if the
     run_adding() function is provided. When it is absent this
     function pointer must be set to NULL. */
  void (*set_run_adding_gain)(LADSPA_Handle Instance,
                              LADSPA_Data   Gain);

  /* This is the counterpart to activate() (see above). If there is
     nothing for deactivate() to do then the plugin writer may provide
     a NULL rather than an empty function.

     Hosts must deactivate all activated units after they have been
     run() (or run_adding()) for the last time. This call should be
     made as close to the last run() call as possible and indicates to
     real-time plugins that they are no longer live. Plugins should
     not rely on prompt deactivation. Note that connect_port() may be
     called before or after a call to deactivate().

     Deactivation is not similar to pausing as the plugin instance
     will be reinitialised when activate() is called to reuse it. */
  void (*deactivate)(LADSPA_Handle Instance);

  /* Once an instance of a plugin has been finished with it can be
     deleted using the following function. The instance handle passed
     ceases to be valid after this call.

     If activate() was called for a plugin instance then a
     corresponding call to deactivate() must be made before cleanup()
     is called. */
  void (*cleanup)(LADSPA_Handle Instance);

} LADSPA_Descriptor;

/**********************************************************************/

/* Accessing a Plugin: */

/* The exact mechanism by which plugins are loaded is host-dependent,
   however all most hosts will need to know is the name of shared
   object file containing the plugin types. To allow multiple hosts to
   share plugin types, hosts may wish to check for environment
   variable LADSPA_PATH. If present, this should contain a
   colon-separated path indicating directories that should be searched
   (in order) when loading plugin types.

   A plugin programmer must include a function called
   "ladspa_descriptor" with the following function prototype within
   the shared object file. This function will have C-style linkage (if
   you are using C++ this is taken care of by the `extern "C"' clause
   at the top of the file).

   A host will find the plugin shared object file by one means or
   another, find the ladspa_descriptor() function, call it, and
   proceed from there.

   Plugin types are accessed by index (not ID) using values from 0
   upwards. Out of range indexes must result in this function
   returning NULL, so the plugin count can be determined by checking
   for the least index that results in NULL being returned. */

const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index);

/* Datatype corresponding to the ladspa_descriptor() function. */
typedef const LADSPA_Descriptor *
(*LADSPA_Descriptor_Function)(unsigned long Index);

/**********************************************************************/

#ifdef __cplusplus
}
#endif

#endif /* LADSPA_INCLUDED */

/* EOF */


code:
/*
 * lmms_basics.h - typedefs for common types that are used in the whole app
 *
 * 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 TYPES_H
#define TYPES_H

#include <limits>

#include "lmmsconfig.h"

#ifdef LMMS_HAVE_STDINT_H
#include <cstdint>
#include <array>
#endif

typedef int32_t bar_t;
typedef int32_t tick_t;
typedef uint8_t volume_t;
typedef int8_t panning_t;

typedef float sample_t;			// standard sample-type
typedef int16_t int_sample_t;		// 16-bit-int-sample

typedef uint32_t sample_rate_t;		// sample-rate
typedef int16_t fpp_t;			// frames per period (0-16384)
typedef int32_t f_cnt_t;			// standard frame-count
typedef uint8_t ch_cnt_t;			// channel-count (0-SURROUND_CHANNELS)
typedef uint16_t bpm_t;			// tempo (MIN_BPM to MAX_BPM)
typedef uint16_t bitrate_t;		// bitrate in kbps
typedef uint16_t fx_ch_t;			// FX-channel (0 to MAX_EFFECT_CHANNEL)

typedef uint32_t jo_id_t;			// (unique) ID of a journalling object

// windows headers define "min" and "max" macros, breaking the methods bwloe
#undef min
#undef max

template<typename T>
struct typeInfo
{
	static inline T min()
	{
		return std::numeric_limits<T>::min();
	}

	static inline T max()
	{
		return std::numeric_limits<T>::max();
	}

	static inline T minEps()
	{
		return 1;
	}

	static inline bool isEqual( T x, T y )
	{
		return x == y;
	}

	static inline T absVal( T t )
	{
		return t >= 0 ? t : -t;
	}
} ;

template<>
inline float typeInfo<float>::minEps()
{
	return 1.0e-10f;
}

template<>
inline bool typeInfo<float>::isEqual( float x, float y )
{
	if( x == y )
	{
		return true;
	}
	return absVal( x - y ) < minEps();
}

const ch_cnt_t DEFAULT_CHANNELS = 2;

const ch_cnt_t SURROUND_CHANNELS =
#define LMMS_DISABLE_SURROUND
#ifndef LMMS_DISABLE_SURROUND
				4;
#else
				2;
#endif

#ifdef LMMS_BUILD_WIN32
#define LADSPA_PATH_SEPERATOR ';'
#else
#define LADSPA_PATH_SEPERATOR ':'
#endif

using         sampleFrame = std::array<sample_t,  DEFAULT_CHANNELS>;
using surroundSampleFrame = std::array<sample_t, SURROUND_CHANNELS>;
#define ALIGN_SIZE 16

#define STRINGIFY(s) STR(s)
#define STR(PN)	#PN

// Abstract away GUI CTRL key (linux/windows) vs ⌘ (apple)
#ifdef LMMS_BUILD_APPLE
# define UI_CTRL_KEY "⌘"
#else
# define UI_CTRL_KEY "Ctrl"
#endif

#endif


code:
/*
 * lmms_constants.h - defines system constants
 *
 * Copyright (c) 2006 Danny McRae <khjklujn/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 LMMS_CONSTANTS_H
#define LMMS_CONSTANTS_H

const long double LD_PI = 3.14159265358979323846264338327950288419716939937510;
const long double LD_2PI = LD_PI * 2.0;
const long double LD_PI_2 = LD_PI * 0.5;
const long double LD_PI_R = 1.0 / LD_PI;
const long double LD_PI_SQR = LD_PI * LD_PI;
const long double LD_E = 2.71828182845904523536028747135266249775724709369995;
const long double LD_E_R = 1.0 / LD_E;

const double D_PI = (double) LD_PI;
const double D_2PI = (double) LD_2PI;
const double D_PI_2 = (double) LD_PI_2;
const double D_PI_R = (double) LD_PI_R;
const double D_PI_SQR = (double) LD_PI_SQR;
const double D_E = (double) LD_E;
const double D_E_R = (double) LD_E_R;

const float F_PI = (float) LD_PI;
const float F_2PI = (float) LD_2PI;
const float F_PI_2 = (float) LD_PI_2;
const float F_PI_R = (float) LD_PI_R;
const float F_PI_SQR = (float) LD_PI_SQR;
const float F_E = (float) LD_E;
const float F_E_R = (float) LD_E_R;

// Frequency ranges (in Hz).
// Arbitrary low limit for logarithmic frequency scale; >1 Hz.
const int LOWEST_LOG_FREQ = 10;

// Full range is defined by LOWEST_LOG_FREQ and current sample rate.
enum FREQUENCY_RANGES
{
	FRANGE_FULL = 0,
	FRANGE_AUDIBLE,
	FRANGE_BASS,
	FRANGE_MIDS,
	FRANGE_HIGH
};

const int FRANGE_AUDIBLE_START = 20;
const int FRANGE_AUDIBLE_END = 20000;
const int FRANGE_BASS_START = 20;
const int FRANGE_BASS_END = 300;
const int FRANGE_MIDS_START = 200;
const int FRANGE_MIDS_END = 5000;
const int FRANGE_HIGH_START = 4000;
const int FRANGE_HIGH_END = 20000;

// Amplitude ranges (in dBFS).
// Reference: full scale sine wave (-1.0 to 1.0) is 0 dB.
// Doubling or halving the amplitude produces 3 dB difference.
enum AMPLITUDE_RANGES
{
	ARANGE_EXTENDED = 0,
	ARANGE_AUDIBLE,
	ARANGE_LOUD,
	ARANGE_SILENT
};

const int ARANGE_EXTENDED_START = -80;
const int ARANGE_EXTENDED_END = 20;
const int ARANGE_AUDIBLE_START = -50;
const int ARANGE_AUDIBLE_END = 0;
const int ARANGE_LOUD_START = -30;
const int ARANGE_LOUD_END = 0;
const int ARANGE_SILENT_START = -60;
const int ARANGE_SILENT_END = -10;

#endif


code:
/*
 * lmms_math.h - defines math functions
 *
 * Copyright (c) 2004-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 LMMS_MATH_H
#define LMMS_MATH_H

#include <cstdint>
#include "lmms_constants.h"
#include "lmmsconfig.h"
#include <QtCore/QtGlobal>

#include <cmath>
using namespace std;

#ifndef exp10
#define exp10(x) std::pow( 10.0, x )
#endif

#ifdef __INTEL_COMPILER

static inline float absFraction( const float _x )
{
	return( _x - floorf( _x ) );
}

static inline float fraction( const float _x )
{
	return( _x - floorf( _x ) - ( _x >= 0.0f ? 0.0 : 1.0 ) );
}

#else

/*!
 * @brief Returns the wrapped fractional part of a float, a value between 0.0f and 1.0f.
 *
 * absFraction( 2.3) =>  0.3
 * absFraction(-2.3) =>  0.7
 *
 * Note that this not the same as the absolute value of the fraction (as the function name suggests).
 * If the result is interpreted as a phase of an oscillator, it makes that negative phases are
 * converted to positive phases.
 */
static inline float absFraction( const float _x )
{
	return( _x - ( _x >= 0.0f ? static_cast<int>( _x ) :
						static_cast<int>( _x ) - 1 ) );
}

/*!
 * @brief Returns the fractional part of a float, a value between -1.0f and 1.0f.
 *
 * fraction( 2.3) =>  0.3
 * fraction(-2.3) => -0.3
 *
 * Note that if the return value is used as a phase of an oscillator, that the oscillator must support
 * negative phases.
 */
static inline float fraction( const float _x )
{
	return( _x - static_cast<int>( _x ) );
}

#if 0
// SSE3-version
static inline float absFraction( float _x )
{
	unsigned int tmp;
	asm(
		"fld %%st\n\t"
		"fisttp %1\n\t"
		"fild %1\n\t"
		"ftst\n\t"
		"sahf\n\t"
		"jae 1f\n\t"
		"fld1\n\t"
		"fsubrp %%st, %%st(1)\n\t"
	"1:\n\t"
		"fsubrp %%st, %%st(1)"
		: "+t"( _x ), "=m"( tmp )
		:
		: "st(1)", "cc" );
	return( _x );
}

static inline float absFraction( float _x )
{
	unsigned int tmp;
	asm(
		"fld %%st\n\t"
		"fisttp %1\n\t"
		"fild %1\n\t"
		"fsubrp %%st, %%st(1)"
		: "+t"( _x ), "=m"( tmp )
		:
		: "st(1)" );
	return( _x );
}
#endif

#endif

#define FAST_RAND_MAX 32767
static inline int fast_rand()
{
	static unsigned long next = 1;
	next = next * 1103515245 + 12345;
	return( (unsigned)( next / 65536 ) % 32768 );
}

static inline double fastRand( double range )
{
	static const double fast_rand_ratio = 1.0 / FAST_RAND_MAX;
	return fast_rand() * range * fast_rand_ratio;
}

static inline float fastRandf( float range )
{
	static const float fast_rand_ratio = 1.0f / FAST_RAND_MAX;
	return fast_rand() * range * fast_rand_ratio;
}

//! @brief Takes advantage of fmal() function if present in hardware
static inline long double fastFmal( long double a, long double b, long double c )
{
#ifdef FP_FAST_FMAL
	#ifdef __clang__
		return fma( a, b, c );
	#else
		return fmal( a, b, c );
	#endif
#else
	return a * b + c;
#endif
}

//! @brief Takes advantage of fmaf() function if present in hardware
static inline float fastFmaf( float a, float b, float c )
{
#ifdef FP_FAST_FMAF
	#ifdef __clang__
		return fma( a, b, c );
	#else
		return fmaf( a, b, c );
	#endif
#else
	return a * b + c;
#endif
}

//! @brief Takes advantage of fma() function if present in hardware
static inline double fastFma( double a, double b, double c )
{
#ifdef FP_FAST_FMA
	return fma( a, b, c );
#else
	return a * b + c;
#endif
}

// source: http://martin.ankerl.com/2007/10/04/optimized-pow-approximation-for-java-and-c-c/
static inline double fastPow( double a, double b )
{
	union
	{
		double d;
		int32_t x[2];
	} u = { a };
	u.x[1] = static_cast<int32_t>( b * ( u.x[1] - 1072632447 ) + 1072632447 );
	u.x[0] = 0;
	return u.d;
}

// sinc function
static inline double sinc( double _x )
{
	return _x == 0.0 ? 1.0 : sin( F_PI * _x ) / ( F_PI * _x );
}

//! @brief Exponential function that deals with negative bases
static inline float signedPowf( float v, float e )
{
	return v < 0
		? powf( -v, e ) * -1.0f
		: powf( v, e );
}

//! @brief Scales @value from linear to logarithmic.
//! Value should be within [0,1]
static inline float logToLinearScale( float min, float max, float value )
{
	if( min < 0 )
	{
		const float mmax = qMax( qAbs( min ), qAbs( max ) );
		const float val = value * ( max - min ) + min;
		float result = signedPowf( val / mmax, F_E ) * mmax;
		return isnan( result ) ? 0 : result;
	}
	float result = powf( value, F_E ) * ( max - min ) + min;
	return isnan( result ) ? 0 : result;
}

//! @brief Scales value from logarithmic to linear. Value should be in min-max range.
static inline float linearToLogScale( float min, float max, float value )
{
	static const float EXP = 1.0f / F_E;
	const float valueLimited = qBound( min, value, max);
	const float val = ( valueLimited - min ) / ( max - min );
	if( min < 0 )
	{
		const float mmax = qMax( qAbs( min ), qAbs( max ) );
		float result = signedPowf( valueLimited / mmax, EXP ) * mmax;
		return isnan( result ) ? 0 : result;
	}
	float result = powf( val, EXP ) * ( max - min ) + min;
	return isnan( result ) ? 0 : result;
}

//! @brief Converts linear amplitude (0-1.0) to dBFS scale. Handles zeroes as -inf.
//! @param amp Linear amplitude, where 1.0 = 0dBFS.
//! @return Amplitude in dBFS. -inf for 0 amplitude.
static inline float safeAmpToDbfs( float amp )
{
	return amp == 0.0f
		? -INFINITY
		: log10f( amp ) * 20.0f;
}

//! @brief Converts dBFS-scale to linear amplitude with 0dBFS = 1.0. Handles infinity as zero.
//! @param dbfs The dBFS value to convert: all infinites are treated as -inf and result in 0
//! @return Linear amplitude
static inline float safeDbfsToAmp( float dbfs )
{
	return isinf( dbfs )
		? 0.0f
		: exp10( dbfs * 0.05f );
}

//! @brief Converts linear amplitude (>0-1.0) to dBFS scale.
//! @param amp Linear amplitude, where 1.0 = 0dBFS. ** Must be larger than zero! **
//! @return Amplitude in dBFS.
static inline float ampToDbfs( float amp )
{
	return log10f( amp ) * 20.0f;
}

//! @brief Converts dBFS-scale to linear amplitude with 0dBFS = 1.0
//! @param dbfs The dBFS value to convert. ** Must be a real number - not inf/nan! **
//! @return Linear amplitude
static inline float dbfsToAmp( float dbfs )
{
	return exp10( dbfs * 0.05f );
}

//! returns 1.0f if val >= 0.0f, -1.0 else
static inline float sign( float val )
{
	return val >= 0.0f ? 1.0f : -1.0f;
}

//! if val >= 0.0f, returns sqrtf(val), else: -sqrtf(-val)
static inline float sqrt_neg( float val )
{
	return sqrtf( fabs( val ) ) * sign( val );
}

// fast approximation of square root
static inline float fastSqrt( float n )
{
	union
	{
		int32_t i;
		float f;
	} u;
	u.f = n;
	u.i = ( u.i + ( 127 << 23 ) ) >> 1;
	return u.f;
}

//! returns value furthest from zero
template<class T>
static inline T absMax( T a, T b )
{
	return qAbs<T>(a) > qAbs<T>(b) ? a : b;
}

//! returns value nearest to zero
template<class T>
static inline T absMin( T a, T b )
{
	return qAbs<T>(a) < qAbs<T>(b) ? a : b;
}

#endif


code:
/*
 * panning.h - declaration of some types, concerning the
 *             panning of a note
 *
 * 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 PANNING_H
#define PANNING_H

#include "lmms_basics.h"
#include "panning_constants.h"
#include "Midi.h"
#include "volume.h"

inline stereoVolumeVector panningToVolumeVector( panning_t _p,
							float _scale = 1.0f )
{
	stereoVolumeVector v = { { _scale, _scale } };
	const float pf = _p / 100.0f;
	v.vol[_p >= PanningCenter ? 0 : 1] *= 1.0f - qAbs<float>( pf );
	return v;
}

inline int panningToMidi( panning_t _p )
{
	return MidiMinPanning + (int) (
			  ( (float)( _p - PanningLeft ) ) /
			  ( (float)( PanningRight - PanningLeft ) ) *
			  ( (float)( MidiMaxPanning - MidiMinPanning ) ) );
}

#endif


code:
/*
 * panning_constants.h - declaration of some constants, concerning the
 *             panning of a note
 *
 * 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 PANNING_CONSTANTS_H
#define PANNING_CONSTANTS_H

const panning_t PanningRight = ( 0 + 100 );
const panning_t PanningLeft = - PanningRight;
const panning_t PanningCenter = 0;
const panning_t DefaultPanning = PanningCenter;

#endif


code:
/*
 * shared_object.h - class sharedObject for use among other objects
 *
 * Copyright (c) 2006-2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
 * 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 SHARED_OBJECT_H
#define SHARED_OBJECT_H

#include <atomic>

class sharedObject
{
public:
	sharedObject() :
		m_referenceCount(1)
	{
	}

	virtual ~sharedObject()
	{
	}

	template<class T>
	static T* ref( T* object )
	{
		// Incrementing an atomic reference count can be relaxed since no action
		// is ever taken as a result of increasing the count.
		// Other loads and stores can be reordered around this without consequence.
		object->m_referenceCount.fetch_add(1, std::memory_order_relaxed);
		return object;
	}

	template<class T>
	static void unref( T* object )
	{
		// When decrementing an atomic reference count, we need to provide
		// two ordering guarantees:
		// 1. All reads and writes to the referenced object occur before
		//    the count reaches zero.
		// 2. Deletion occurs after the count reaches zero.
		//
		// To accomplish this, each decrement must be store-released,
		// and the final thread (which is deleting the referenced data)
		// must load-acquire those stores.
		// The simplest way to do this to give the decrement acquire-release
		// semantics.
		//
		// See https://www.boost.org/doc/libs/1_67_0/doc/html/atomic/usage_examples.html
		// for further discussion, along with a slightly more complicated
		// (but possibly more performant on weakly-ordered hardware like ARM)
		// approach.
		const bool deleteObject =
			object->m_referenceCount.fetch_sub(1, std::memory_order_acq_rel) == 1;

		if ( deleteObject )
		{
			object->deleteLater();
		}
	}

private:
	std::atomic_int m_referenceCount;
} ;

#endif


code:
//! Shims for std:: functions that aren't available in the current C++ versions
//! we target.

#ifndef STDSHIMS_H
#define STDSHIMS_H

#include <type_traits>
#include <utility>

#if (__cplusplus >= 201703L || _MSC_VER >= 1914)
#ifndef _MSC_VER
#warning "This part of this file should now be removed! The functions it provides are part of the C++17 standard."
#endif
using std::as_const;

#else

/// Shim for http://en.cppreference.com/w/cpp/utility/as_const
template <typename T>
constexpr typename std::add_const<T>::type& as_const(T& t) noexcept
{
    return t;
}

template <typename T>
void as_const(const T&&) = delete;
#endif

#endif // include guard


code:
#include "lmms_basics.h"

#ifdef __GNUC__
#define COMPILER_VERSION "GCC " __VERSION__
#elif defined(_MSC_VER)
#define COMPILER_VERSION "MSVC " STRINGIFY(_MSC_FULL_VER)
#else
#define COMPILER_VERSION "unknown compiler"
#endif

#ifdef LMMS_HOST_X86
#define MACHINE "i386"
#endif

#ifdef LMMS_HOST_X86_64
#define MACHINE "x86_64"
#endif

#ifndef MACHINE
#define MACHINE "unknown processor"
#endif

#ifdef LMMS_BUILD_LINUX
#define PLATFORM "Linux"
#endif

#ifdef LMMS_BUILD_APPLE
#define PLATFORM "OS X"
#endif

#ifdef LMMS_BUILD_OPENBSD
#define PLATFORM "OpenBSD"
#endif

#ifdef LMMS_BUILD_FREEBSD
#define PLATFORM "FreeBSD"
#endif

#ifdef LMMS_BUILD_WIN32
#define PLATFORM "win32"
#endif

#ifdef LMMS_BUILD_HAIKU
#define PLATFORM "Haiku"
#endif


code:
/*
 * volume.h - declaration of some constants and types, concerning the volume
 *            of a note
 *
 * 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 VOLUME_H
#define VOLUME_H

#include "lmms_basics.h"

const volume_t MinVolume = 0;
const volume_t MaxVolume = 200;
const volume_t DefaultVolume = 100;

typedef struct
{
	float vol[2];
} stereoVolumeVector;

#endif


code:
/*
 * Amplifier.cpp - A native amplifier effect plugin with sample-exact amplification
 *
 * 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.
 *
 */

#include "Amplifier.h"

#include "embed.h"
#include "plugin_export.h"

extern "C"
{

Plugin::Descriptor PLUGIN_EXPORT amplifier_plugin_descriptor =
{
	STRINGIFY( PLUGIN_NAME ),
	"Amplifier",
	QT_TRANSLATE_NOOP( "PluginBrowser", "A native amplifier plugin" ),
	"Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>",
	0x0100,
	Plugin::Effect,
	new PluginPixmapLoader("logo"),
	NULL,
	NULL
} ;

}

AmplifierEffect::AmplifierEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ) :
	Effect( &amplifier_plugin_descriptor, parent, key ),
	m_ampControls( this )
{
}

AmplifierEffect::~AmplifierEffect()
{
}

bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
{
	if( !isEnabled() || !isRunning () )
	{
		return( false );
	}

	double outSum = 0.0;
	const float d = dryLevel();
	const float w = wetLevel();

	const ValueBuffer * volBuf = m_ampControls.m_volumeModel.valueBuffer();
	const ValueBuffer * panBuf = m_ampControls.m_panModel.valueBuffer();
	const ValueBuffer * leftBuf = m_ampControls.m_leftModel.valueBuffer();
	const ValueBuffer * rightBuf = m_ampControls.m_rightModel.valueBuffer();

	for( fpp_t f = 0; f < frames; ++f )
	{
//		qDebug( "offset %d, value %f", f, m_ampControls.m_volumeModel.value( f ) );

		sample_t s[2] = { buf[f][0], buf[f][1] };

		// vol knob
		if( volBuf )
		{
			s[0] *= volBuf->value( f ) * 0.01f;
			s[1] *= volBuf->value( f ) * 0.01f;
		}
		else
		{
			s[0] *= m_ampControls.m_volumeModel.value() * 0.01f;
			s[1] *= m_ampControls.m_volumeModel.value() * 0.01f;
		}

		// convert pan values to left/right values
		const float pan = panBuf
			? panBuf->value( f )
			: m_ampControls.m_panModel.value();
		const float left1 = pan <= 0
			? 1.0
			: 1.0 - pan * 0.01f;
		const float right1 = pan >= 0
			? 1.0
			: 1.0 + pan * 0.01f;

		// second stage amplification
		const float left2 = leftBuf
			? leftBuf->value( f )
			: m_ampControls.m_leftModel.value();
		const float right2 = rightBuf
			? rightBuf->value( f )
			: m_ampControls.m_rightModel.value();

		s[0] *= left1 * left2 * 0.01;
		s[1] *= right1 * right2 * 0.01;

		buf[f][0] = d * buf[f][0] + w * s[0];
		buf[f][1] = d * buf[f][1] + w * s[1];
		outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1];
	}

	checkGate( outSum / frames );

	return isRunning();
}

extern "C"
{

// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* parent, void* data )
{
	return new AmplifierEffect( parent, static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>( data ) );
}

}


code:
/*
 * Amplifier.h - amplifier-effect-plugin
 *
 * 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 AMPLIFIER_H
#define AMPLIFIER_H

#include "Effect.h"
#include "AmplifierControls.h"
#include "ValueBuffer.h"

class AmplifierEffect : public Effect
{
public:
	AmplifierEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
	virtual ~AmplifierEffect();
	virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames );

	virtual EffectControls* controls()
	{
		return &m_ampControls;
	}

private:
	AmplifierControls m_ampControls;

	friend class AmplifierControls;

} ;

#endif


code:
/*
 * AmplifierControlDialog.cpp - control dialog for amplifier effect
 *
 * 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.
 *
 */

#include <QLayout>

#include "AmplifierControlDialog.h"
#include "AmplifierControls.h"
#include "embed.h"

AmplifierControlDialog::AmplifierControlDialog( AmplifierControls* controls ) :
	EffectControlDialog( controls )
{
	setAutoFillBackground( true );
	QPalette pal;
	pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
	setPalette( pal );
	setFixedSize( 100, 110 );

	Knob * volumeKnob = new Knob( knobBright_26, this);
	volumeKnob -> move( 16, 10 );
	volumeKnob -> setVolumeKnob( true );
	volumeKnob->setModel( &controls->m_volumeModel );
	volumeKnob->setLabel( tr( "VOL" ) );
	volumeKnob->setHintText( tr( "Volume:" ) , "%" );

	Knob * panKnob = new Knob( knobBright_26, this);
	panKnob -> move( 57, 10 );
	panKnob->setModel( &controls->m_panModel );
	panKnob->setLabel( tr( "PAN" ) );
	panKnob->setHintText( tr( "Panning:" ) , "" );

	Knob * leftKnob = new Knob( knobBright_26, this);
	leftKnob -> move( 16, 65 );
	leftKnob -> setVolumeKnob( true );
	leftKnob->setModel( &controls->m_leftModel );
	leftKnob->setLabel( tr( "LEFT" ) );
	leftKnob->setHintText( tr( "Left gain:" ) , "%" );

	Knob * rightKnob = new Knob( knobBright_26, this);
	rightKnob -> move( 57, 65 );
	rightKnob -> setVolumeKnob( true );
	rightKnob->setModel( &controls->m_rightModel );
	rightKnob->setLabel( tr( "RIGHT" ) );
	rightKnob->setHintText( tr( "Right gain:" ) , "%" );
}


code:
/*
 * AmplifierControlDialog.h - control dialog for amplifier effect
 *
 * 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 AMPLIFIER_CONTROL_DIALOG_H
#define AMPLIFIER_CONTROL_DIALOG_H

#include "EffectControlDialog.h"

class AmplifierControls;

class AmplifierControlDialog : public EffectControlDialog
{
	Q_OBJECT
public:
	AmplifierControlDialog( AmplifierControls* controls );
	virtual ~AmplifierControlDialog()
	{
	}

} ;

#endif


code:
/*
 * AmplifierControls.cpp - controls for amplifier effect
 *
 * Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
 * 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.
 *
 */

#include <QDomElement>

#include "AmplifierControls.h"
#include "Amplifier.h"
#include "Engine.h"
#include "Song.h"

AmplifierControls::AmplifierControls( AmplifierEffect* effect ) :
	EffectControls( effect ),
	m_effect( effect ),
	m_volumeModel( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume" ) ),
	m_panModel( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning" ) ),
	m_leftModel( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Left gain" ) ),
	m_rightModel( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Right gain" ) )
{
/*	connect( &m_volumeModel, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) );
	connect( &m_panModel, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) );
	connect( &m_leftModel, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) );
	connect( &m_rightModel, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) );*/
}

void AmplifierControls::changeControl()
{
//	engine::getSong()->setModified();
}

void AmplifierControls::loadSettings( const QDomElement& _this )
{
	m_volumeModel.loadSettings( _this, "volume" );
	m_panModel.loadSettings( _this, "pan" );
	m_leftModel.loadSettings( _this, "left" );
	m_rightModel.loadSettings( _this, "right" );
}

void AmplifierControls::saveSettings( QDomDocument& doc, QDomElement& _this )
{
	m_volumeModel.saveSettings( doc, _this, "volume" );
	m_panModel.saveSettings( doc, _this, "pan" );
	m_leftModel.saveSettings( doc, _this, "left" );
	m_rightModel.saveSettings( doc, _this, "right" );
}


code:
/*
 * AmplifierControls.h - controls for bassboosterx -effect
 *
 * Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
 * 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 AMPLIFIER_CONTROLS_H
#define AMPLIFIER_CONTROLS_H

#include "EffectControls.h"
#include "AmplifierControlDialog.h"
#include "Knob.h"

class AmplifierEffect;

class AmplifierControls : public EffectControls
{
	Q_OBJECT
public:
	AmplifierControls( AmplifierEffect* effect );
	virtual ~AmplifierControls()
	{
	}

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

	virtual int controlCount()
	{
		return 4;
	}

	virtual EffectControlDialog* createView()
	{
		return new AmplifierControlDialog( this );
	}

private slots:
	void changeControl();

private:
	AmplifierEffect* m_effect;
	FloatModel m_volumeModel;
	FloatModel m_panModel;
	FloatModel m_leftModel;
	FloatModel m_rightModel;

	friend class AmplifierControlDialog;
	friend class AmplifierEffect;

} ;

#endif


code:
INCLUDE(BuildPlugin)

BUILD_PLUGIN(amplifier Amplifier.cpp AmplifierControls.cpp AmplifierControlDialog.cpp MOCFILES AmplifierControls.h AmplifierControlDialog.h EMBEDDED_RESOURCES artwork.png logo.png)


code:
/*
 * BassBooster.cpp - bass booster effect plugin
 *
 * 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.
 *
 */

#include "BassBooster.h"

#include "embed.h"
#include "plugin_export.h"

extern "C"
{

Plugin::Descriptor PLUGIN_EXPORT bassbooster_plugin_descriptor =
{
	STRINGIFY( PLUGIN_NAME ),
	"BassBooster",
	QT_TRANSLATE_NOOP( "PluginBrowser", "Boost your bass the fast and simple way" ),
	"Tobias Doerffel <tobydox/at/users.sf.net>",
	0x0100,
	Plugin::Effect,
	new PluginPixmapLoader("logo"),
	NULL,
	NULL
} ;

}

BassBoosterEffect::BassBoosterEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ) :
	Effect( &bassbooster_plugin_descriptor, parent, key ),
	m_frequencyChangeNeeded( false ),
	m_bbFX( DspEffectLibrary::FastBassBoost( 70.0f, 1.0f, 2.8f ) ),
	m_bbControls( this )
{
	changeFrequency();
	changeGain();
	changeRatio();
}

BassBoosterEffect::~BassBoosterEffect()
{
}

bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
{
	if( !isEnabled() || !isRunning () )
	{
		return( false );
	}
	// check out changed controls
	if( m_frequencyChangeNeeded || m_bbControls.m_freqModel.isValueChanged() )
	{
		changeFrequency();
		m_frequencyChangeNeeded = false;
	}
	if( m_bbControls.m_gainModel.isValueChanged() ) { changeGain(); }
	if( m_bbControls.m_ratioModel.isValueChanged() ) { changeRatio(); }

	const float const_gain = m_bbControls.m_gainModel.value();
	const ValueBuffer *gainBuffer = m_bbControls.m_gainModel.valueBuffer();

	double outSum = 0.0;
	const float d = dryLevel();
	const float w = wetLevel();

	for( fpp_t f = 0; f < frames; ++f )
	{
		float gain = const_gain;
		if (gainBuffer) {
			//process period using sample exact data
			gain = gainBuffer->value( f );
		}
		//float gain = gainBuffer ? gainBuffer[f] : gain;
		m_bbFX.leftFX().setGain( gain );
		m_bbFX.rightFX().setGain( gain);

		sample_t s[2] = { buf[f][0], buf[f][1] };
		m_bbFX.nextSample( s[0], s[1] );

		buf[f][0] = d * buf[f][0] + w * s[0];
		buf[f][1] = d * buf[f][1] + w * s[1];
		outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1];
	}

	checkGate( outSum / frames );

	return isRunning();
}

inline void BassBoosterEffect::changeFrequency()
{
	const sample_t fac = Engine::mixer()->processingSampleRate() / 44100.0f;

	m_bbFX.leftFX().setFrequency( m_bbControls.m_freqModel.value() * fac );
	m_bbFX.rightFX().setFrequency( m_bbControls.m_freqModel.value() * fac );
}

inline void BassBoosterEffect::changeGain()
{
	m_bbFX.leftFX().setGain( m_bbControls.m_gainModel.value() );
	m_bbFX.rightFX().setGain( m_bbControls.m_gainModel.value() );
}

inline void BassBoosterEffect::changeRatio()
{
	m_bbFX.leftFX().setRatio( m_bbControls.m_ratioModel.value() );
	m_bbFX.rightFX().setRatio( m_bbControls.m_ratioModel.value() );
}

extern "C"
{

// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* parent, void* data )
{
	return new BassBoosterEffect( parent, static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>( data ) );
}

}


code:
/*
 * BassBooster.h - bass-booster-effect-plugin
 *
 * 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 BASS_BOOSTER_H
#define BASS_BOOSTER_H

#include "Effect.h"
#include "DspEffectLibrary.h"
#include "BassBoosterControls.h"

class BassBoosterEffect : public Effect
{
public:
	BassBoosterEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
	virtual ~BassBoosterEffect();
	virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames );

	virtual EffectControls* controls()
	{
		return &m_bbControls;
	}

protected:
	void changeFrequency();
	void changeGain();
	void changeRatio();

	bool m_frequencyChangeNeeded;

private:
	DspEffectLibrary::MonoToStereoAdaptor<DspEffectLibrary::FastBassBoost> m_bbFX;

	BassBoosterControls m_bbControls;

	friend class BassBoosterControls;

} ;

#endif