Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
427e0d6727 | ||
|
|
d9490f9203 | ||
|
|
57c79759c8 | ||
|
|
ad1124cde9 | ||
|
|
3e62853de5 | ||
|
|
9a4cfedf67 | ||
|
|
e714a68fe5 | ||
|
|
a4f9682069 | ||
|
|
5138ed6722 | ||
|
|
9eed60c068 | ||
|
|
e109f3e550 | ||
|
|
93a456c67a | ||
|
|
d7df990e6c | ||
|
|
5891a37635 | ||
|
|
8485cf3157 | ||
|
|
84e0dc1b81 | ||
|
|
99791ddf25 | ||
|
|
31b2b00ba4 | ||
|
|
d536d851a4 | ||
|
|
852976ed74 | ||
|
|
edf2d4d104 | ||
|
|
f969b7d892 | ||
|
|
6d6bbe3b32 | ||
|
|
7bddad1895 | ||
|
|
3504e49119 | ||
|
|
42b1584cbe | ||
|
|
54dadfcf48 | ||
|
|
29d0d2b43a | ||
|
|
6883e0479c | ||
|
|
598d1dc816 | ||
|
|
9fc0d8962d | ||
|
|
91912e143a | ||
|
|
00ca278f2f | ||
|
|
0424c5cec8 | ||
|
|
9b2e3fc262 | ||
|
|
c66fa25dfe | ||
|
|
c1f5075e16 | ||
|
|
d555db6109 | ||
|
|
a0b198fb38 | ||
|
|
c0f221e984 | ||
|
|
f50d5ce943 | ||
|
|
3c80a079a2 | ||
|
|
fb56b6757d | ||
|
|
8fd507bcff | ||
|
|
7c2b3e6240 | ||
|
|
d8c616afcf | ||
|
|
4e81299729 | ||
|
|
7ef61b04d7 | ||
|
|
33917e4340 | ||
|
|
1e0acbef85 | ||
|
|
798c179b58 | ||
|
|
12aaffe149 | ||
|
|
cfe9c35f41 | ||
|
|
fa21cf10a9 | ||
|
|
35eeb55704 | ||
|
|
facab0c2d8 | ||
|
|
c222c062c5 | ||
|
|
7a632277b8 | ||
|
|
87e44aa241 | ||
|
|
0098ff874a | ||
|
|
621512a7b7 | ||
|
|
0faaab4521 | ||
|
|
cafb24fe9a | ||
|
|
33dd77f55c | ||
|
|
93a19e43f1 | ||
|
|
57c4a5abc5 | ||
|
|
3d9dc25f0b | ||
|
|
5bb9af15ab | ||
|
|
66147bebf0 | ||
|
|
6b71db0640 | ||
|
|
0c8fdec27c | ||
|
|
ca5ba2971b | ||
|
|
e0bb2cd043 | ||
|
|
41efb51518 | ||
|
|
168a68c1b3 | ||
|
|
6066209ef3 | ||
|
|
5cd54b3f20 | ||
|
|
1c38473255 | ||
|
|
a6f8e11128 | ||
|
|
27a828e579 | ||
|
|
2f5dd60fd9 | ||
|
|
03ecb86494 | ||
|
|
1bc94beae6 |
@@ -15,7 +15,7 @@ INCLUDE(FindPkgConfig)
|
||||
|
||||
SET(VERSION_MAJOR "0")
|
||||
SET(VERSION_MINOR "4")
|
||||
SET(VERSION_PATCH "4")
|
||||
SET(VERSION_PATCH "5")
|
||||
#SET(VERSION_SUFFIX "")
|
||||
SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||
IF(VERSION_SUFFIX)
|
||||
@@ -33,6 +33,7 @@ ELSE(LMMS_HOST_X86_64)
|
||||
ENDIF(LMMS_HOST_X86_64)
|
||||
|
||||
OPTION(WANT_ALSA "Include ALSA (Advanced Linux Sound Architecture) support" ON)
|
||||
OPTION(WANT_CALF "Include CALF LADSPA plugins" ON)
|
||||
OPTION(WANT_CAPS "Include C* Audio Plugin Suite (LADSPA plugins)" ON)
|
||||
OPTION(WANT_CMT "Include Computer Music Toolkit LADSPA plugins" ON)
|
||||
OPTION(WANT_FFTW3F "Include SpectrumAnalyzer and ZynAddSubFX plugin" ON)
|
||||
@@ -118,6 +119,13 @@ IF(NOT SNDFILE_FOUND)
|
||||
MESSAGE(FATAL_ERROR "LMMS requires libsndfile1 and libsndfile1-dev >= 1.0.11 - please install, remove CMakeCache.txt and try again!")
|
||||
ENDIF(NOT SNDFILE_FOUND)
|
||||
|
||||
IF(WANT_CALF)
|
||||
SET(LMMS_HAVE_CALF TRUE)
|
||||
SET(STATUS_CALF "OK")
|
||||
ELSE(WANT_CALF)
|
||||
SET(STATUS_CALF "not built as requested")
|
||||
ENDIF(WANT_CALF)
|
||||
|
||||
IF(WANT_CAPS)
|
||||
SET(LMMS_HAVE_CAPS TRUE)
|
||||
SET(STATUS_CAPS "OK")
|
||||
@@ -446,7 +454,9 @@ IF(LMMS_BUILD_WIN32)
|
||||
ENDIF(LMMS_BUILD_WIN64)
|
||||
|
||||
ELSE(LMMS_BUILD_WIN32)
|
||||
SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E")
|
||||
IF(NOT LMMS_BUILD_APPLE)
|
||||
SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E")
|
||||
ENDIF(NOT LMMS_BUILD_APPLE)
|
||||
|
||||
INSTALL(TARGETS lmms RUNTIME DESTINATION bin)
|
||||
INSTALL(FILES ${CMAKE_BINARY_DIR}/lmms.1.gz DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1/ PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
|
||||
@@ -602,6 +612,7 @@ MESSAGE(
|
||||
"* VST-instrument hoster : ${STATUS_VST}\n"
|
||||
"* VST-effect hoster : ${STATUS_VST}\n"
|
||||
"* SpectrumAnalyzer : ${STATUS_FFTW3F}\n"
|
||||
"* CALF LADSPA plugins : ${STATUS_CALF}\n"
|
||||
"* CAPS LADSPA plugins : ${STATUS_CAPS}\n"
|
||||
"* CMT LADSPA plugins : ${STATUS_CMT}\n"
|
||||
"* TAP LADSPA plugins : ${STATUS_TAP}\n"
|
||||
|
||||
9
INSTALL
@@ -5,11 +5,10 @@ then run
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../ -DCMAKE_INSTALL_PREFIX=/usr
|
||||
cmake ../
|
||||
make
|
||||
sudo make install
|
||||
|
||||
|
||||
This way an out-of-tree build is performed. You can also run "cmake ." directly
|
||||
in the root of source-tree although this is not recommended. When performing an
|
||||
out-of-tree build after there's already an in-tree build, make sure to run
|
||||
@@ -23,3 +22,9 @@ that are going to be built into LMMS or built as plugins. Install the
|
||||
according libraries and development files if a certain feature is not enabled.
|
||||
Then remove CMakeCache.txt and run cmake again.
|
||||
|
||||
If you want to supply an install prefix to cmake, add the flag:
|
||||
|
||||
-DCMAKE_INSTALL_PREFIX=<prefix>
|
||||
|
||||
Where <prefix> can be /usr, /usr/local, /opt, etc. The default is /usr/local.
|
||||
|
||||
|
||||
2
README
@@ -1,4 +1,4 @@
|
||||
Linux MultiMedia Studio 0.4.4
|
||||
Linux MultiMedia Studio 0.4.5
|
||||
==============================
|
||||
|
||||
Copyright (c) 2004-2009 by LMMS-developers
|
||||
|
||||
72
TODO
@@ -1,52 +1,32 @@
|
||||
- do not process effects when playing frozen patterns
|
||||
- select number of channels in export-project-dialog
|
||||
- try to make vestige-plugin-dlls relative
|
||||
- do song-editor-tempo-connection to vst-plugin inside remoteVSTPlugin
|
||||
- add/remove-steps button in bb-editor for adding/removing according number of steps to/from all patterns of visible beat/baseline
|
||||
- replace rest of wizard by simple directory-selection-dialog for working-dir when running the first time
|
||||
- correctly load steps/dots from FLP-files
|
||||
- convert FL-Plucked!-parameters to Vibed-parameters
|
||||
- in flp-import-filter: merge play-list-items if possible
|
||||
- integrated sample-browser in context-menu of sample-track/-tco
|
||||
- make note able of journalling
|
||||
- before calling undoStep/redoStep from journallingObject, save journalling-state-context and disabled journalling, restore afterwards
|
||||
- intelligent journal-entry-merging
|
||||
- undo/redo-support in note/track etc.
|
||||
- save tco-settings in trackContentWidget::saveSettings() etc. instead of track::...
|
||||
- restore stacking-order of windows when loading project
|
||||
- bristol-bindings?
|
||||
- resample sample-track-tcos when using hq-mode
|
||||
- add support for panes-interface (like blender) (instead of MDI etc.)
|
||||
Version 0.4.x
|
||||
=============
|
||||
|
||||
- save tco-settings in trackContentWidget::saveSettings() etc. instead of
|
||||
track::...
|
||||
- resample sample-track-tcos when exporting at different samplerate
|
||||
- message to user when importing unsupported MIDI-file (track-count = 0)
|
||||
- AMS/OMS-bindings
|
||||
- remove binary-embed-system (Qt4-resource-system?)
|
||||
- recording-functionality
|
||||
- do not hang when saving while loading VST-plugin (because then we call dispatcher while the load-process is still going on)
|
||||
- tempo-recogn. and sync of beat-samples
|
||||
- make color-scheme switchable: LMMS / user
|
||||
- piano roll: mouse cursor isn't updated correctly in selection mode
|
||||
(from resizing note edit area)
|
||||
- when you add vestige, have it automatically pop the find VST plugin dialog
|
||||
- try to make vestige-plugin-dlls relative
|
||||
- select all MIDI devices by default when you bring up the "connect to controller"
|
||||
window and wait for first event - then uncheck all other MIDI devices that no
|
||||
events were detected from
|
||||
- load asdlol.mmpz. if you render it without playing it, or if you play it
|
||||
the first time, you hear unwanted artifacts. (solution: apply automation
|
||||
before playing)
|
||||
- autosave every 30s (configurable!) and offer recovery at startup after crash
|
||||
- make piano-roll use rubberband instead of implementing a simple one on it's own
|
||||
- level-meters in output-graph and instrument-track
|
||||
- MIDI-program/MIDI-mapping/process program-/channel-change-events from MIDI-files
|
||||
- DSSI-support
|
||||
- use drawLineF() for drawing notes in pattern::paintEvent() in qt4-version
|
||||
- only redraw region given by paint-event in pattern, bbTCO, sampleTCO etc.
|
||||
- pre-listen when opening sample with QFileDialog
|
||||
- panning-editing in piano-roll
|
||||
- speed up painting of sampleTCO
|
||||
- panning env+lfo
|
||||
- rewrite export-project-dialog using layout-mechanism
|
||||
- make piano-roll use the global clipboard??
|
||||
- add more localizations:
|
||||
- Swedish
|
||||
- Norwegian
|
||||
- Greece
|
||||
- ...
|
||||
- do not process effects when playing frozen patterns
|
||||
- copy-pasted automation patterns have to be manually linked back to
|
||||
their knob for some reason
|
||||
- improve TrackLabelButton: split 80%-20% (80%=name, 20%=button showing a popup
|
||||
menu with track operations, make the midi input a top-level menu item)
|
||||
- when you click and drag a mixer bar, it doesn't click and drag, it sets
|
||||
absolutely. this is annoying
|
||||
|
||||
|
||||
- effect-board -> live-fx from input
|
||||
- chord-editor?
|
||||
- WAVE/OGG/MP3-Import -> FFT-analysis -> write notes
|
||||
- classical note-edit-window -> also ability of printing and maybe later scanning & recognition of notes
|
||||
- add FLAC as export-format?
|
||||
See TODO file in master branch and/or the TODO list in the Wiki for details
|
||||
regarding the development series.
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
MINGW=/opt/mingw
|
||||
MINGW=/opt/mingw32
|
||||
export PATH=$PATH:$MINGW/bin
|
||||
#./configure --prefix=$MINGW --host=i586-mingw32 CC=$MINGW/bin/i586-mingw32-gcc CXX=$MINGW/bin/i586-mingw32-g++ DLLTOOL=$MINGW/bin/i586-mingw32-dlltool OBJDUMP=$MINGW/bin/i586-mingw32-objdump RANLIB=$MINGW/bin/i586-mingw32-ranlib AR=$MINGW/bin/i586-mingw32-ar AS=$MINGW/bin/i586-mingw32-as STRIP=$MINGW/bin/i586-mingw32-strip --with-qtdir=$MINGW --with-win32 CFLAGS="-mtune=generic -mmmx -fno-strict-aliasing" CXXFLAGS="-mtune=generic -mmmx -fno-strict-aliasing"
|
||||
#./configure --prefix=$MINGW --host=i586-mingw32 --build=i586-mingw32 CC=$MINGW/bin/i586-mingw32-gcc CXX=$MINGW/bin/i586-mingw32-g++ --with-qtdir=$MINGW --with-win32
|
||||
|
||||
cmake . -DCMAKE_TOOLCHAIN_FILE=cmake/modules/Win32Toolchain.cmake
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=cmake/modules/Win32Toolchain.cmake
|
||||
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
SET(MINGW_PREFIX /opt/mingw32)
|
||||
|
||||
# this one is important
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
#this one not so much
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
|
||||
SET(CMAKE_SYSTEM_PROCESSOR i686)
|
||||
SET(CMAKE_INSTALL_PREFIX /opt/mingw32)
|
||||
SET(CMAKE_INSTALL_PREFIX ${MINGW_PREFIX})
|
||||
|
||||
SET(CC_PREFIX /opt/mingw32)
|
||||
|
||||
# specify the cross compiler
|
||||
SET(CMAKE_C_COMPILER ${CC_PREFIX}/bin/i586-pc-mingw32-gcc)
|
||||
SET(CMAKE_CXX_COMPILER ${CC_PREFIX}/bin/i586-pc-mingw32-g++)
|
||||
SET(CMAKE_C_COMPILER ${MINGW_PREFIX}/bin/i586-pc-mingw32-gcc)
|
||||
SET(CMAKE_CXX_COMPILER ${MINGW_PREFIX}/bin/i586-pc-mingw32-g++)
|
||||
|
||||
# where is the target environment
|
||||
SET(CMAKE_FIND_ROOT_PATH /opt/mingw32)
|
||||
|
||||
SET(QT_BINARY_DIR ${CC_PREFIX}/bin)
|
||||
SET(QT_LIBRARY_DIR ${CC_PREFIX}/lib)
|
||||
SET(QT_QTCORE_LIBRARY ${CC_PREFIX}/lib/libQtCore4.a)
|
||||
SET(QT_INCLUDE_DIR ${CC_PREFIX}/include/qt4)
|
||||
SET(QT_QTCORE_INCLUDE_DIR ${CC_PREFIX}/include/qt4/QtCore)
|
||||
SET(QT_MKSPECS_DIR ${CC_PREFIX}/share/qt4/mkspecs)
|
||||
SET(QT_BINARY_DIR ${MINGW_PREFIX}/bin)
|
||||
SET(QT_LIBRARY_DIR ${MINGW_PREFIX}/lib)
|
||||
SET(QT_QTCORE_LIBRARY ${MINGW_PREFIX}/lib/libQtCore4.a)
|
||||
SET(QT_INCLUDE_DIR ${MINGW_PREFIX}/include/qt4)
|
||||
SET(QT_HEADERS_DIR ${MINGW_PREFIX}/include/qt4)
|
||||
SET(QT_QTCORE_INCLUDE_DIR ${MINGW_PREFIX}/include/qt4/QtCore)
|
||||
SET(QT_MKSPECS_DIR ${MINGW_PREFIX}/share/qt4/mkspecs)
|
||||
SET(QT_MOC_EXECUTABLE ${QT_BINARY_DIR}/moc.exe)
|
||||
SET(QT_RCC_EXECUTABLE ${QT_BINARY_DIR}/rcc.exe)
|
||||
SET(QT_QMAKE_EXECUTABLE /usr/bin/qmake)
|
||||
@@ -32,8 +34,8 @@ SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
SET(PKG_CONFIG_EXECUTABLE ${CC_PREFIX}/bin/pkg-config)
|
||||
SET(PKG_CONFIG_EXECUTABLE ${MINGW_PREFIX}/bin/pkg-config)
|
||||
|
||||
INCLUDE_DIRECTORIES(${CC_PREFIX}/include)
|
||||
LINK_DIRECTORIES(${CC_PREFIX}/lib ${CC_PREFIX}/bin)
|
||||
INCLUDE_DIRECTORIES(${MINGW_PREFIX}/include)
|
||||
LINK_DIRECTORIES(${MINGW_PREFIX}/lib ${MINGW_PREFIX}/bin)
|
||||
|
||||
|
||||
2316
data/locale/de.ts
|
Before Width: | Height: | Size: 411 B After Width: | Height: | Size: 339 B |
|
Before Width: | Height: | Size: 389 B After Width: | Height: | Size: 348 B |
|
Before Width: | Height: | Size: 528 B After Width: | Height: | Size: 413 B |
BIN
data/themes/default/pr_black_key_pressed.png
Normal file
|
After Width: | Height: | Size: 414 B |
|
Before Width: | Height: | Size: 524 B After Width: | Height: | Size: 324 B |
BIN
data/themes/default/pr_white_key_big_pressed.png
Normal file
|
After Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 391 B After Width: | Height: | Size: 312 B |
BIN
data/themes/default/pr_white_key_small_pressed.png
Normal file
|
After Width: | Height: | Size: 354 B |
|
Before Width: | Height: | Size: 116 B After Width: | Height: | Size: 145 B |
|
Before Width: | Height: | Size: 214 B After Width: | Height: | Size: 305 B |
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* controller.h - declaration of class controller, which provides a
|
||||
* Controller.h - declaration of class controller, which provides a
|
||||
* standard for all controllers and controller plugins
|
||||
*
|
||||
* Copyright (c) 2008 Paul Giblock <pgllama/at/gmail.com>
|
||||
* Copyright (c) 2008-2009 Paul Giblock <pgllama/at/gmail.com>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -32,13 +32,13 @@
|
||||
#include "mv_base.h"
|
||||
#include "journalling_object.h"
|
||||
|
||||
class controllerDialog;
|
||||
class controller;
|
||||
class ControllerDialog;
|
||||
class Controller;
|
||||
|
||||
typedef QVector<controller *> controllerVector;
|
||||
typedef QVector<Controller *> ControllerVector;
|
||||
|
||||
|
||||
class controller : public model, public journallingObject
|
||||
class Controller : public model, public journallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -55,10 +55,10 @@ public:
|
||||
NumControllerTypes
|
||||
} ;
|
||||
|
||||
controller( ControllerTypes _type, model * _parent,
|
||||
Controller( ControllerTypes _type, model * _parent,
|
||||
const QString & _display_name );
|
||||
|
||||
virtual ~controller();
|
||||
virtual ~Controller();
|
||||
|
||||
virtual float currentValue( int _offset );
|
||||
|
||||
@@ -103,8 +103,8 @@ public:
|
||||
virtual void loadSettings( const QDomElement & _this );
|
||||
virtual QString nodeName( void ) const;
|
||||
|
||||
static controller * create( ControllerTypes _tt, model * _parent );
|
||||
static controller * create( const QDomElement & _this,
|
||||
static Controller * create( ControllerTypes _tt, model * _parent );
|
||||
static Controller * create( const QDomElement & _this,
|
||||
model * _parent );
|
||||
|
||||
inline static float fittedValue( float _val )
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
|
||||
|
||||
public slots:
|
||||
virtual controllerDialog * createDialog( QWidget * _parent );
|
||||
virtual ControllerDialog * createDialog( QWidget * _parent );
|
||||
|
||||
virtual void setName( const QString & _new_name )
|
||||
{
|
||||
@@ -140,7 +140,7 @@ protected:
|
||||
QString m_name;
|
||||
ControllerTypes m_type;
|
||||
|
||||
static controllerVector s_controllers;
|
||||
static ControllerVector s_controllers;
|
||||
|
||||
static unsigned int s_frames;
|
||||
|
||||
@@ -149,7 +149,7 @@ signals:
|
||||
// The value changed while the mixer isn't running (i.e: MIDI CC)
|
||||
void valueChanged( void );
|
||||
|
||||
friend class controllerDialog;
|
||||
friend class ControllerDialog;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* controller_connection.h - declaration of a controller connect, which
|
||||
* ControllerConnection.h - declaration of a controller connect, which
|
||||
* provides a definition of the link between a controller and
|
||||
* model, also handles deferred creation of links while
|
||||
* loading project
|
||||
@@ -32,30 +32,30 @@
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVector>
|
||||
|
||||
#include "controller.h"
|
||||
#include "Controller.h"
|
||||
#include "journalling_object.h"
|
||||
|
||||
class controllerConnection;
|
||||
class ControllerConnection;
|
||||
|
||||
typedef QVector<controllerConnection *> controllerConnectionVector;
|
||||
typedef QVector<ControllerConnection *> ControllerConnectionVector;
|
||||
|
||||
|
||||
class EXPORT controllerConnection : public QObject, public journallingObject
|
||||
class EXPORT ControllerConnection : public QObject, public journallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
controllerConnection( controller * _controller );
|
||||
controllerConnection( int _controllerId );
|
||||
ControllerConnection( Controller * _controller );
|
||||
ControllerConnection( int _controllerId );
|
||||
|
||||
virtual ~controllerConnection();
|
||||
virtual ~ControllerConnection();
|
||||
|
||||
inline controller * getController( void )
|
||||
inline Controller * getController( void )
|
||||
{
|
||||
return m_controller;
|
||||
}
|
||||
|
||||
void setController( controller * _controller );
|
||||
void setController( Controller * _controller );
|
||||
|
||||
inline void setController( int _controllerId );
|
||||
|
||||
@@ -87,19 +87,19 @@ public slots:
|
||||
|
||||
protected:
|
||||
//virtual controllerDialog * createDialog( QWidget * _parent );
|
||||
controller * m_controller;
|
||||
Controller * m_controller;
|
||||
QString m_targetName;
|
||||
int m_controllerId;
|
||||
|
||||
bool m_ownsController;
|
||||
|
||||
static controllerConnectionVector s_connections;
|
||||
static ControllerConnectionVector s_connections;
|
||||
|
||||
signals:
|
||||
// The value changed while the mixer isn't running (i.e: MIDI CC)
|
||||
void valueChanged( void );
|
||||
|
||||
friend class controllerConnectionDialog;
|
||||
friend class ControllerConnectionDialog;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* controller_connection_dialog.h - dialog allowing the user to create and
|
||||
* ControllerConnectionDialog.h - dialog allowing the user to create and
|
||||
* modify links between controllers and models
|
||||
*
|
||||
* Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail.com>
|
||||
@@ -31,14 +31,14 @@
|
||||
#include <QtGui/QSortFilterProxyModel>
|
||||
#include <QtGui/QStandardItemModel>
|
||||
|
||||
#include "controller.h"
|
||||
#include "Controller.h"
|
||||
#include "automatable_model.h"
|
||||
|
||||
|
||||
class QLineEdit;
|
||||
class QListView;
|
||||
class QScrollArea;
|
||||
class autoDetectMidiController;
|
||||
class AutoDetectMidiController;
|
||||
class comboBox;
|
||||
class groupBox;
|
||||
class tabWidget;
|
||||
@@ -48,15 +48,15 @@ class midiPortMenu;
|
||||
|
||||
|
||||
|
||||
class controllerConnectionDialog : public QDialog
|
||||
class ControllerConnectionDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
controllerConnectionDialog( QWidget * _parent,
|
||||
ControllerConnectionDialog( QWidget * _parent,
|
||||
const automatableModel * _target_model );
|
||||
virtual ~controllerConnectionDialog();
|
||||
virtual ~ControllerConnectionDialog();
|
||||
|
||||
controller * chosenController( void )
|
||||
Controller * chosenController( void )
|
||||
{
|
||||
return m_controller;
|
||||
}
|
||||
@@ -91,11 +91,11 @@ private:
|
||||
tabWidget * m_mappingBox;
|
||||
QLineEdit * m_mappingFunction;
|
||||
|
||||
controller * m_controller;
|
||||
Controller * m_controller;
|
||||
const automatableModel * m_targetModel;
|
||||
|
||||
// Temporary midiController
|
||||
autoDetectMidiController * m_midiController;
|
||||
AutoDetectMidiController * m_midiController;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* controller_dialog.h - per-controller-specific view for changing a
|
||||
* ControllerDialog.h - per-controller-specific view for changing a
|
||||
* controller's settings
|
||||
*
|
||||
* Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail.com>
|
||||
* Copyright (c) 2008-2009 Paul Giblock <drfaygo/at/gmail.com>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -30,25 +30,22 @@
|
||||
|
||||
#include "mv_base.h"
|
||||
|
||||
class controller;
|
||||
class Controller;
|
||||
|
||||
|
||||
class controllerDialog : public QWidget, public modelView
|
||||
class ControllerDialog : public QWidget, public modelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
controllerDialog( controller * _controller, QWidget * _parent );
|
||||
ControllerDialog( Controller * _controller, QWidget * _parent );
|
||||
|
||||
virtual ~controllerDialog();
|
||||
virtual ~ControllerDialog();
|
||||
|
||||
signals:
|
||||
void closed();
|
||||
|
||||
|
||||
protected:
|
||||
/* virtual void contextMenuEvent( QContextMenuEvent * _me ) {};
|
||||
virtual void paintEvent( QPaintEvent * _pe ) {};
|
||||
virtual void modelChanged( void ) {};*/
|
||||
virtual void closeEvent( QCloseEvent * _ce );
|
||||
|
||||
} ;
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* controller_rack_view.h - view for song's controllers
|
||||
* ControllerRackView.h - view for song's controllers
|
||||
*
|
||||
* Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail.com>
|
||||
* Copyright (c) 2008-2009 Paul Giblock <drfaygo/at/gmail.com>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -33,29 +33,28 @@
|
||||
|
||||
class QPushButton;
|
||||
class QScrollArea;
|
||||
//class QVBoxLayout;
|
||||
|
||||
class controllerView;
|
||||
class ControllerView;
|
||||
|
||||
|
||||
class controllerRackView : public QWidget, public serializingObject
|
||||
class ControllerRackView : public QWidget, public serializingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
controllerRackView();
|
||||
virtual ~controllerRackView();
|
||||
ControllerRackView();
|
||||
virtual ~ControllerRackView();
|
||||
|
||||
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
|
||||
virtual void loadSettings( const QDomElement & _this );
|
||||
|
||||
inline virtual QString nodeName( void ) const
|
||||
{
|
||||
return( "controllerrackview" );
|
||||
return( "ControllerRackView" );
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
void deleteController( controllerView * _view );
|
||||
void deleteController( ControllerView * _view );
|
||||
|
||||
|
||||
private slots:
|
||||
@@ -64,7 +63,7 @@ private slots:
|
||||
|
||||
|
||||
private:
|
||||
QVector<controllerView *> m_controllerViews;
|
||||
QVector<ControllerView *> m_controllerViews;
|
||||
|
||||
QVBoxLayout * m_mainLayout;
|
||||
QScrollArea * m_scrollArea;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* controller_view.h - view-component for an control
|
||||
* ControllerView.h - view-component for an control
|
||||
*
|
||||
* Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail.com>
|
||||
*
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
#include "automatable_model.h"
|
||||
#include "controller.h"
|
||||
#include "Controller.h"
|
||||
#include "mv_base.h"
|
||||
|
||||
class QGroupBox;
|
||||
@@ -39,21 +39,21 @@ class QMdiSubWindow;
|
||||
class ledCheckBox;
|
||||
|
||||
|
||||
class controllerView : public QWidget, public modelView
|
||||
class ControllerView : public QWidget, public modelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
controllerView( controller * _controller, QWidget * _parent );
|
||||
virtual ~controllerView();
|
||||
ControllerView( Controller * _controller, QWidget * _parent );
|
||||
virtual ~ControllerView();
|
||||
|
||||
inline controller * getController( void )
|
||||
inline Controller * getController( void )
|
||||
{
|
||||
return( castModel<controller>() );
|
||||
return( castModel<Controller>() );
|
||||
}
|
||||
|
||||
inline const controller * getController( void ) const
|
||||
inline const Controller * getController( void ) const
|
||||
{
|
||||
return( castModel<controller>() );
|
||||
return( castModel<Controller>() );
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public slots:
|
||||
|
||||
|
||||
signals:
|
||||
void deleteController( controllerView * _view );
|
||||
void deleteController( ControllerView * _view );
|
||||
|
||||
|
||||
protected:
|
||||
@@ -79,7 +79,7 @@ private:
|
||||
QPixmap m_bg;
|
||||
ledCheckBox * m_bypass;
|
||||
QMdiSubWindow * m_subWindow;
|
||||
controllerDialog * m_controllerDlg;
|
||||
ControllerDialog * m_controllerDlg;
|
||||
bool m_show;
|
||||
|
||||
} ;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* lfo_controller.h - A LFO-based controller and dialog
|
||||
* LfoController.h - A LFO-based controller and dialog
|
||||
*
|
||||
* Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail.com>
|
||||
*
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
#include "mv_base.h"
|
||||
#include "automatable_model.h"
|
||||
#include "controller.h"
|
||||
#include "controller_dialog.h"
|
||||
#include "Controller.h"
|
||||
#include "ControllerDialog.h"
|
||||
#include "tempo_sync_knob.h"
|
||||
#include "oscillator.h"
|
||||
|
||||
@@ -42,13 +42,13 @@ class tempoSyncKnob;
|
||||
class pixmapButton;
|
||||
class oscillator;
|
||||
|
||||
class lfoController : public controller
|
||||
class LfoController : public Controller
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
lfoController( model * _parent );
|
||||
LfoController( model * _parent );
|
||||
|
||||
virtual ~lfoController();
|
||||
virtual ~LfoController();
|
||||
|
||||
virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
|
||||
virtual void loadSettings( const QDomElement & _this );
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
|
||||
|
||||
public slots:
|
||||
virtual controllerDialog * createDialog( QWidget * _parent );
|
||||
virtual ControllerDialog * createDialog( QWidget * _parent );
|
||||
|
||||
|
||||
protected:
|
||||
@@ -80,24 +80,24 @@ protected:
|
||||
protected slots:
|
||||
void updateSampleFunction( void );
|
||||
|
||||
friend class lfoControllerDialog;
|
||||
friend class LfoControllerDialog;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
class lfoControllerDialog : public controllerDialog
|
||||
class LfoControllerDialog : public ControllerDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
lfoControllerDialog( controller * _controller, QWidget * _parent );
|
||||
virtual ~lfoControllerDialog();
|
||||
LfoControllerDialog( Controller * _controller, QWidget * _parent );
|
||||
virtual ~LfoControllerDialog();
|
||||
|
||||
|
||||
protected:
|
||||
virtual void contextMenuEvent( QContextMenuEvent * _me );
|
||||
virtual void modelChanged( void );
|
||||
|
||||
lfoController * m_lfo;
|
||||
LfoController * m_lfo;
|
||||
|
||||
knob * m_baseKnob;
|
||||
tempoSyncKnob * m_speedKnob;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* midi_controller.h - A controller to receive MIDI control-changes
|
||||
* MidiController.h - A controller to receive MIDI control-changes
|
||||
*
|
||||
* Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail.com>
|
||||
*
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
#include "automatable_model.h"
|
||||
#include "controller.h"
|
||||
#include "Controller.h"
|
||||
#include "midi_event_processor.h"
|
||||
#include "midi_port.h"
|
||||
|
||||
@@ -36,12 +36,12 @@
|
||||
class midiPort;
|
||||
|
||||
|
||||
class midiController : public controller, public midiEventProcessor
|
||||
class MidiController : public Controller, public MidiEventProcessor
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
midiController( model * _parent );
|
||||
virtual ~midiController();
|
||||
MidiController( model * _parent );
|
||||
virtual ~MidiController();
|
||||
|
||||
virtual void processInEvent( const midiEvent & _me,
|
||||
const midiTime & _time );
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
|
||||
|
||||
public slots:
|
||||
virtual controllerDialog * createDialog( QWidget * _parent );
|
||||
virtual ControllerDialog * createDialog( QWidget * _parent );
|
||||
void updateName( void );
|
||||
|
||||
|
||||
@@ -75,8 +75,8 @@ protected:
|
||||
|
||||
float m_lastValue;
|
||||
|
||||
friend class controllerConnectionDialog;
|
||||
friend class autoDetectMidiController;
|
||||
friend class ControllerConnectionDialog;
|
||||
friend class AutoDetectMidiController;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* peak_controller.h - peak-controller class
|
||||
* PeakController.h - peak-controller class
|
||||
*
|
||||
* Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail.com>
|
||||
* Copyright (c) 2008-2009 Paul Giblock <drfaygo/at/gmail.com>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
#include "mv_base.h"
|
||||
#include "automatable_model.h"
|
||||
#include "controller.h"
|
||||
#include "controller_dialog.h"
|
||||
#include "Controller.h"
|
||||
#include "ControllerDialog.h"
|
||||
|
||||
class automatableButtonGroup;
|
||||
class knob;
|
||||
@@ -39,15 +39,15 @@ class peakControllerEffect;
|
||||
typedef QVector<peakControllerEffect *> peakControllerEffectVector;
|
||||
|
||||
|
||||
class EXPORT peakController : public controller
|
||||
class EXPORT PeakController : public Controller
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
peakController( model * _parent,
|
||||
PeakController( model * _parent,
|
||||
peakControllerEffect *_peak_effect = NULL );
|
||||
|
||||
|
||||
virtual ~peakController();
|
||||
virtual ~PeakController();
|
||||
|
||||
virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
|
||||
virtual void loadSettings( const QDomElement & _this );
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
|
||||
|
||||
public slots:
|
||||
virtual controllerDialog * createDialog( QWidget * _parent );
|
||||
virtual ControllerDialog * createDialog( QWidget * _parent );
|
||||
void handleDestroyedEffect( );
|
||||
|
||||
protected:
|
||||
@@ -67,24 +67,24 @@ protected:
|
||||
|
||||
peakControllerEffect * m_peakEffect;
|
||||
|
||||
friend class peakControllerDialog;
|
||||
friend class PeakControllerDialog;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
class peakControllerDialog : public controllerDialog
|
||||
class PeakControllerDialog : public ControllerDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
peakControllerDialog( controller * _controller, QWidget * _parent );
|
||||
virtual ~peakControllerDialog();
|
||||
PeakControllerDialog( Controller * _controller, QWidget * _parent );
|
||||
virtual ~PeakControllerDialog();
|
||||
|
||||
protected:
|
||||
virtual void contextMenuEvent( QContextMenuEvent * _me );
|
||||
virtual void paintEvent( QPaintEvent * _pe );
|
||||
virtual void modelChanged( void );
|
||||
|
||||
peakController * m_peakController;
|
||||
PeakController * m_peakController;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -118,7 +118,7 @@ const int kVstTempoValid = 1 << 10;
|
||||
const int kVstTransportPlaying = 1 << 1;
|
||||
|
||||
|
||||
class remoteVstPlugin;
|
||||
class RemoteVstPlugin;
|
||||
|
||||
|
||||
class VstMidiEvent
|
||||
@@ -221,7 +221,7 @@ public:
|
||||
// flags 24-27
|
||||
int flags;
|
||||
// Fill somewhere 28-2b
|
||||
remoteVstPlugin * user;
|
||||
RemoteVstPlugin * user;
|
||||
// Zeroes 2c-2f 30-33 34-37 38-3b
|
||||
char empty3[4 + 4 + 4 + 4];
|
||||
// 1.0f 3c-3f
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
|
||||
|
||||
class controllerConnection;
|
||||
class ControllerConnection;
|
||||
|
||||
|
||||
class EXPORT automatableModel : public model, public journallingObject
|
||||
@@ -94,13 +94,13 @@ public:
|
||||
|
||||
bool isAutomated( void ) const;
|
||||
|
||||
inline controllerConnection * getControllerConnection( void ) const
|
||||
inline ControllerConnection * getControllerConnection( void ) const
|
||||
{
|
||||
return m_controllerConnection;
|
||||
}
|
||||
|
||||
|
||||
void setControllerConnection( controllerConnection * _c );
|
||||
void setControllerConnection( ControllerConnection * _c );
|
||||
|
||||
|
||||
template<class T>
|
||||
@@ -250,7 +250,7 @@ private:
|
||||
bool m_hasLinkedModels;
|
||||
|
||||
|
||||
controllerConnection * m_controllerConnection;
|
||||
ControllerConnection * m_controllerConnection;
|
||||
|
||||
|
||||
static float __copiedValue;
|
||||
|
||||
@@ -46,7 +46,7 @@ class projectNotes;
|
||||
class song;
|
||||
class songEditor;
|
||||
class ladspa2LMMS;
|
||||
class controllerRackView;
|
||||
class ControllerRackView;
|
||||
|
||||
|
||||
class EXPORT engine
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
return( s_dummyTC );
|
||||
}
|
||||
|
||||
static controllerRackView * getControllerRackView( void )
|
||||
static ControllerRackView * getControllerRackView( void )
|
||||
{
|
||||
return( s_controllerRackView );
|
||||
}
|
||||
@@ -171,7 +171,7 @@ private:
|
||||
static bbTrackContainer * s_bbTrackContainer;
|
||||
static projectJournal * s_projectJournal;
|
||||
static dummyTrackContainer * s_dummyTC;
|
||||
static controllerRackView * s_controllerRackView;
|
||||
static ControllerRackView * s_controllerRackView;
|
||||
|
||||
// GUI
|
||||
static mainWindow * s_mainWindow;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
* instrument.h - declaration of class instrument, which provides a
|
||||
* standard interface for all instrument plugins
|
||||
*
|
||||
* Copyright (c) 2005-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -23,7 +23,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _INSTRUMENT_H
|
||||
#define _INSTRUMENT_H
|
||||
|
||||
@@ -80,20 +79,20 @@ public:
|
||||
// if no envelope is active - such instruments can re-implement this
|
||||
// method for returning how many frames they at least like to have for
|
||||
// release
|
||||
virtual f_cnt_t desiredReleaseFrames( void ) const
|
||||
virtual f_cnt_t desiredReleaseFrames() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return false if instrument is not bendable
|
||||
inline virtual bool isBendable( void ) const
|
||||
inline virtual bool isBendable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// return true if instruments reacts to MIDI events passed to
|
||||
// handleMidiEvent() rather than playNote() & Co
|
||||
inline virtual bool isMidiBased( void ) const
|
||||
inline virtual bool isMidiBased() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -106,7 +105,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual QString fullDisplayName( void ) const;
|
||||
virtual QString fullDisplayName() const;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// provided functions:
|
||||
@@ -121,7 +120,7 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
inline instrumentTrack * getInstrumentTrack( void ) const
|
||||
inline instrumentTrack * getInstrumentTrack() const
|
||||
{
|
||||
return m_instrumentTrack;
|
||||
}
|
||||
@@ -137,5 +136,4 @@ private:
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "instrument_sound_shaping.h"
|
||||
#include "midi_event_processor.h"
|
||||
#include "midi_port.h"
|
||||
#include "note_play_handle.h"
|
||||
#include "piano.h"
|
||||
#include "track.h"
|
||||
|
||||
@@ -53,12 +54,11 @@ class midiPortMenu;
|
||||
class multimediaProject;
|
||||
class notePlayHandle;
|
||||
class pluginView;
|
||||
class presetPreviewPlayHandle;
|
||||
class tabWidget;
|
||||
class trackLabelButton;
|
||||
|
||||
|
||||
class EXPORT instrumentTrack : public track, public midiEventProcessor
|
||||
class EXPORT instrumentTrack : public track, public MidiEventProcessor
|
||||
{
|
||||
Q_OBJECT
|
||||
mapPropertyFromModel(int,getVolume,setVolume,m_volumeModel);
|
||||
@@ -76,7 +76,8 @@ public:
|
||||
const midiTime & _time );
|
||||
virtual void processOutEvent( const midiEvent & _me,
|
||||
const midiTime & _time );
|
||||
|
||||
// silence all running notes played by this track
|
||||
void silenceAllNotes();
|
||||
|
||||
f_cnt_t beatLen( notePlayHandle * _n ) const;
|
||||
|
||||
@@ -195,8 +196,6 @@ protected:
|
||||
{
|
||||
return "instrumenttrack";
|
||||
}
|
||||
// invalidates all note-play-handles linked to this instrument
|
||||
void invalidateAllMyNPH( void );
|
||||
|
||||
|
||||
protected slots:
|
||||
@@ -213,8 +212,7 @@ private:
|
||||
|
||||
intModel m_baseNoteModel;
|
||||
|
||||
QList<notePlayHandle *> m_processHandles;
|
||||
|
||||
NotePlayHandleList m_processHandles;
|
||||
|
||||
floatModel m_volumeModel;
|
||||
floatModel m_panningModel;
|
||||
@@ -233,7 +231,6 @@ private:
|
||||
friend class instrumentTrackView;
|
||||
friend class instrumentTrackWindow;
|
||||
friend class notePlayHandle;
|
||||
friend class presetPreviewPlayHandle;
|
||||
friend class flpImport;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* midi.h - constants, structs etc. concerning MIDI
|
||||
*
|
||||
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -22,7 +22,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _MIDI_H
|
||||
#define _MIDI_H
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* midi_event_processor.h - base-class for midi-processing classes
|
||||
*
|
||||
* Copyright (c) 2005-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -22,7 +22,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _MIDI_EVENT_PROCESSOR_H
|
||||
#define _MIDI_EVENT_PROCESSOR_H
|
||||
|
||||
@@ -31,14 +30,14 @@ class midiTime;
|
||||
|
||||
|
||||
// all classes being able to process MIDI-events should inherit from this
|
||||
class midiEventProcessor
|
||||
class MidiEventProcessor
|
||||
{
|
||||
public:
|
||||
inline midiEventProcessor( void )
|
||||
inline MidiEventProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
virtual inline ~midiEventProcessor()
|
||||
virtual inline ~MidiEventProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
|
||||
class midiClient;
|
||||
class midiEventProcessor;
|
||||
class MidiEventProcessor;
|
||||
class midiPortMenu;
|
||||
class midiTime;
|
||||
|
||||
@@ -74,30 +74,34 @@ public:
|
||||
|
||||
midiPort( const QString & _name,
|
||||
midiClient * _mc,
|
||||
midiEventProcessor * _mep,
|
||||
MidiEventProcessor * _mep,
|
||||
model * _parent = NULL,
|
||||
Modes _mode = Disabled );
|
||||
virtual ~midiPort();
|
||||
|
||||
void setName( const QString & _name );
|
||||
|
||||
inline Modes mode( void ) const
|
||||
inline Modes mode() const
|
||||
{
|
||||
return( m_mode );
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
void setMode( Modes _mode );
|
||||
|
||||
inline bool inputEnabled( void ) const
|
||||
inline bool inputEnabled() const
|
||||
{
|
||||
return( mode() == Input || mode() == Duplex );
|
||||
return mode() == Input || mode() == Duplex;
|
||||
}
|
||||
|
||||
inline bool outputEnabled( void ) const
|
||||
inline bool outputEnabled() const
|
||||
{
|
||||
return( mode() == Output || mode() == Duplex );
|
||||
return mode() == Output || mode() == Duplex;
|
||||
}
|
||||
|
||||
inline int realOutputChannel() const
|
||||
{
|
||||
return outputChannel() - 1;
|
||||
}
|
||||
|
||||
void processInEvent( const midiEvent & _me, const midiTime & _time );
|
||||
void processOutEvent( const midiEvent & _me, const midiTime & _time );
|
||||
@@ -106,9 +110,9 @@ public:
|
||||
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
|
||||
virtual void loadSettings( const QDomElement & _this );
|
||||
|
||||
virtual QString nodeName( void ) const
|
||||
virtual QString nodeName() const
|
||||
{
|
||||
return( "midiport" );
|
||||
return "midiport";
|
||||
}
|
||||
|
||||
void subscribeReadablePort( const QString & _port,
|
||||
@@ -116,14 +120,14 @@ public:
|
||||
void subscribeWritablePort( const QString & _port,
|
||||
bool _subscribe = TRUE );
|
||||
|
||||
const map & readablePorts( void ) const
|
||||
const map & readablePorts() const
|
||||
{
|
||||
return( m_readablePorts );
|
||||
return m_readablePorts;
|
||||
}
|
||||
|
||||
const map & writablePorts( void ) const
|
||||
const map & writablePorts() const
|
||||
{
|
||||
return( m_writablePorts );
|
||||
return m_writablePorts;
|
||||
}
|
||||
|
||||
midiPortMenu * m_readablePortsMenu;
|
||||
@@ -131,18 +135,18 @@ public:
|
||||
|
||||
|
||||
public slots:
|
||||
void updateMidiPortMode( void );
|
||||
void updateMidiPortMode();
|
||||
|
||||
|
||||
private slots:
|
||||
void updateReadablePorts( void );
|
||||
void updateWritablePorts( void );
|
||||
void updateOutputProgram( void );
|
||||
void updateReadablePorts();
|
||||
void updateWritablePorts();
|
||||
void updateOutputProgram();
|
||||
|
||||
|
||||
private:
|
||||
midiClient * m_midiClient;
|
||||
midiEventProcessor * m_midiEventProcessor;
|
||||
MidiEventProcessor * m_midiEventProcessor;
|
||||
|
||||
Modes m_mode;
|
||||
|
||||
@@ -160,14 +164,14 @@ private:
|
||||
map m_writablePorts;
|
||||
|
||||
|
||||
friend class controllerConnectionDialog;
|
||||
friend class ControllerConnectionDialog;
|
||||
friend class instrumentMidiIOView;
|
||||
|
||||
|
||||
signals:
|
||||
void readablePortsChanged( void );
|
||||
void writablePortsChanged( void );
|
||||
void modeChanged( void );
|
||||
void readablePortsChanged();
|
||||
void writablePortsChanged();
|
||||
void modeChanged();
|
||||
|
||||
|
||||
} ;
|
||||
|
||||
@@ -135,7 +135,7 @@ public:
|
||||
|
||||
static int stepsPerTact( void )
|
||||
{
|
||||
return ticksPerTact() / DefaultBeatsPerTact;
|
||||
return qMax( 1, ticksPerTact() / DefaultBeatsPerTact );
|
||||
}
|
||||
|
||||
static void setTicksPerTact( tick_t _tpt )
|
||||
|
||||
@@ -234,7 +234,7 @@ public:
|
||||
|
||||
void removePlayHandle( playHandle * _ph );
|
||||
|
||||
inline playHandleVector & playHandles( void )
|
||||
inline PlayHandleList & playHandles( void )
|
||||
{
|
||||
return m_playHandles;
|
||||
}
|
||||
@@ -443,8 +443,8 @@ private:
|
||||
QWaitCondition m_queueReadyWaitCond;
|
||||
|
||||
|
||||
playHandleVector m_playHandles;
|
||||
constPlayHandleVector m_playHandlesToRemove;
|
||||
PlayHandleList m_playHandles;
|
||||
ConstPlayHandleList m_playHandlesToRemove;
|
||||
|
||||
struct qualitySettings m_qualitySettings;
|
||||
float m_masterGain;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* mmp.h - class for reading and writing multimedia-project-files
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -52,9 +52,8 @@ public:
|
||||
} ;
|
||||
|
||||
|
||||
multimediaProject( const QString & _in_file_name,
|
||||
bool _is_filename = TRUE,
|
||||
bool _upgrade = TRUE );
|
||||
multimediaProject( const QString & _fileName );
|
||||
multimediaProject( const QByteArray & _data );
|
||||
multimediaProject( ProjectTypes _project_type );
|
||||
virtual ~multimediaProject();
|
||||
|
||||
@@ -76,8 +75,6 @@ public:
|
||||
return( m_type );
|
||||
}
|
||||
|
||||
static ProjectTypes typeOfFile( const QString & _fn );
|
||||
|
||||
|
||||
private:
|
||||
static ProjectTypes type( const QString & _type_name );
|
||||
@@ -87,6 +84,8 @@ private:
|
||||
|
||||
void upgrade( void );
|
||||
|
||||
void loadData( const QByteArray & _data, const QString & _sourceFile );
|
||||
|
||||
|
||||
struct EXPORT typeDescStruct
|
||||
{
|
||||
|
||||
@@ -243,7 +243,7 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
typedef QVector<note *> noteVector;
|
||||
typedef QVector<note *> NoteVector;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* note_play_handle.h - declaration of class notePlayHandle which is needed
|
||||
* by LMMS-Play-Engine
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -30,16 +30,16 @@
|
||||
#include "lmmsconfig.h"
|
||||
#include "mixer.h"
|
||||
#include "note.h"
|
||||
#include "instrument.h"
|
||||
#include "instrument_track.h"
|
||||
#include "engine.h"
|
||||
#include "track.h"
|
||||
|
||||
|
||||
class instrumentTrack;
|
||||
class notePlayHandle;
|
||||
|
||||
template<ch_cnt_t=DEFAULT_CHANNELS> class basicFilters;
|
||||
typedef QVector<notePlayHandle *> notePlayHandleVector;
|
||||
typedef QVector<const notePlayHandle *> constNotePlayHandleVector;
|
||||
typedef QList<notePlayHandle *> NotePlayHandleList;
|
||||
typedef QList<const notePlayHandle *> ConstNotePlayHandleList;
|
||||
|
||||
|
||||
class EXPORT notePlayHandle : public playHandle, public note
|
||||
@@ -79,55 +79,6 @@ public:
|
||||
return( m_released && framesLeft() <= 0 );
|
||||
}
|
||||
|
||||
bool willFinishThisPeriod( void ) const
|
||||
{
|
||||
f_cnt_t rftd = m_releaseFramesToDo;
|
||||
f_cnt_t fbr = m_framesBeforeRelease;
|
||||
f_cnt_t rfd = m_releaseFramesDone;
|
||||
if( m_released == TRUE )
|
||||
{
|
||||
f_cnt_t todo = engine::getMixer()->framesPerPeriod();
|
||||
if( isArpeggioBaseNote() )
|
||||
{
|
||||
rftd = rfd + 2 *
|
||||
engine::getMixer()->framesPerPeriod();
|
||||
}
|
||||
if( fbr )
|
||||
{
|
||||
if( fbr <=
|
||||
engine::getMixer()->framesPerPeriod() )
|
||||
{
|
||||
todo -= fbr;
|
||||
fbr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
todo = 0;
|
||||
fbr -=
|
||||
engine::getMixer()->framesPerPeriod();
|
||||
}
|
||||
}
|
||||
if( todo && rfd < rftd )
|
||||
{
|
||||
if( rftd - rfd >= todo )
|
||||
{
|
||||
rfd += todo;
|
||||
}
|
||||
else
|
||||
{
|
||||
rfd = rftd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( isArpeggioBaseNote() && m_subNotes.size() == 0 )
|
||||
{
|
||||
rfd = rftd;
|
||||
}
|
||||
|
||||
return( ( m_released && fbr == 0 && rfd >= rftd ) );
|
||||
}
|
||||
|
||||
f_cnt_t framesLeft( void ) const;
|
||||
|
||||
inline fpp_t framesLeftForCurrentPeriod( void ) const
|
||||
@@ -202,11 +153,7 @@ public:
|
||||
}
|
||||
|
||||
// returns whether note is base-note for arpeggio
|
||||
inline bool isArpeggioBaseNote( void ) const
|
||||
{
|
||||
return( isBaseNote() && ( m_partOfArpeggio ||
|
||||
m_instrumentTrack->arpeggiatorEnabled() ) );
|
||||
}
|
||||
bool isArpeggioBaseNote( void ) const;
|
||||
|
||||
inline bool isMuted( void ) const
|
||||
{
|
||||
@@ -219,15 +166,15 @@ public:
|
||||
// belonging to this instrument-track - used by arpeggiator
|
||||
int index( void ) const;
|
||||
|
||||
// note-play-handles belonging to given channel, if _all_ph = TRUE,
|
||||
// note-play-handles belonging to given channel, if _all_ph = true,
|
||||
// also released note-play-handles are returned
|
||||
static constNotePlayHandleVector nphsOfInstrumentTrack(
|
||||
const instrumentTrack * _ct, bool _all_ph = FALSE );
|
||||
static ConstNotePlayHandleList nphsOfInstrumentTrack(
|
||||
const instrumentTrack * _ct, bool _all_ph = false );
|
||||
|
||||
// return whether given note-play-handle is equal to *this
|
||||
bool operator==( const notePlayHandle & _nph ) const;
|
||||
|
||||
bool bbTrackMuted( void )
|
||||
inline bool bbTrackMuted( void )
|
||||
{
|
||||
return( m_bbTrack && m_bbTrack->isMuted() );
|
||||
}
|
||||
@@ -288,7 +235,7 @@ private:
|
||||
// played after release
|
||||
f_cnt_t m_releaseFramesDone; // number of frames done after
|
||||
// release of note
|
||||
notePlayHandleVector m_subNotes;// used for chords and arpeggios
|
||||
NotePlayHandleList m_subNotes; // used for chords and arpeggios
|
||||
volatile bool m_released; // indicates whether note is released
|
||||
bool m_baseNote; // indicates whether note is a
|
||||
// base-note (i.e. no sub-note)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* panning of a note
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -41,9 +41,10 @@ inline stereoVolumeVector panningToVolumeVector( panning_t _p,
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Sint16 panningToMidi( panning_t _p )
|
||||
|
||||
inline int panningToMidi( panning_t _p )
|
||||
{
|
||||
return MidiMinPanning + (panning_t) (
|
||||
return MidiMinPanning + (int) (
|
||||
( (float)( _p - PanningLeft ) ) /
|
||||
( (float)( PanningRight - PanningLeft ) ) *
|
||||
( (float)( MidiMaxPanning - MidiMinPanning ) ) );
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
void rearrangeAllNotes( void );
|
||||
void clearNotes( void );
|
||||
|
||||
inline const noteVector & notes( void )
|
||||
inline const NoteVector & notes( void ) const
|
||||
{
|
||||
return m_notes;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ private:
|
||||
PatternTypes m_patternType;
|
||||
|
||||
// data-stuff
|
||||
noteVector m_notes;
|
||||
NoteVector m_notes;
|
||||
int m_steps;
|
||||
|
||||
// pattern freezing
|
||||
|
||||
@@ -109,7 +109,7 @@ protected:
|
||||
int _width, note * _n );
|
||||
void removeSelection( void );
|
||||
void selectAll( void );
|
||||
void getSelectedNotes( noteVector & _selected_notes );
|
||||
void getSelectedNotes( NoteVector & _selected_notes );
|
||||
|
||||
|
||||
protected slots:
|
||||
@@ -150,7 +150,7 @@ private:
|
||||
ModeDraw,
|
||||
ModeErase,
|
||||
ModeSelect,
|
||||
ModeOpen
|
||||
ModeEditDetuning,
|
||||
};
|
||||
|
||||
enum actions
|
||||
@@ -306,13 +306,12 @@ private:
|
||||
timeLine * m_timeLine;
|
||||
bool m_scrollBack;
|
||||
|
||||
void copy_to_clipboard( const noteVector & _notes ) const;
|
||||
void copy_to_clipboard( const NoteVector & _notes ) const;
|
||||
|
||||
void drawDetuningInfo( QPainter & _p, note * _n, int _x, int _y );
|
||||
bool mouseOverNote( void );
|
||||
note * noteUnderMouse( void );
|
||||
noteVector::const_iterator noteIteratorUnderMouse( void );
|
||||
|
||||
|
||||
// turn a selection rectangle into selected notes
|
||||
void computeSelectedNotes( bool shift );
|
||||
void clearSelectedNotes( void );
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* play_handle.h - base-class playHandle - core of rendering engine
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -22,7 +22,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _PLAY_HANDLE_H
|
||||
#define _PLAY_HANDLE_H
|
||||
|
||||
@@ -98,8 +97,8 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
typedef QVector<playHandle *> playHandleVector;
|
||||
typedef QVector<const playHandle *> constPlayHandleVector;
|
||||
typedef QList<playHandle *> PlayHandleList;
|
||||
typedef QList<const playHandle *> ConstPlayHandleList;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
|
||||
static void init( void );
|
||||
static void cleanup( void );
|
||||
static constNotePlayHandleVector nphsOfInstrumentTrack(
|
||||
static ConstNotePlayHandleList nphsOfInstrumentTrack(
|
||||
const instrumentTrack * _ct );
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,16 @@
|
||||
#include <cassert>
|
||||
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#define USE_QT_SEMAPHORES
|
||||
#define USE_QT_SHMEM
|
||||
#endif
|
||||
|
||||
#ifdef LMMS_BUILD_APPLE
|
||||
#define USE_QT_SEMAPHORES
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
|
||||
#ifdef LMMS_HAVE_PROCESS_H
|
||||
#include <process.h>
|
||||
@@ -44,22 +54,38 @@
|
||||
#include <Qt/qglobal.h>
|
||||
|
||||
#if QT_VERSION >= 0x040400
|
||||
#include <QtCore/QSharedMemory>
|
||||
#include <QtCore/QSystemSemaphore>
|
||||
#else
|
||||
#error win32-build requires at least Qt 4.4.0
|
||||
#error building LMMS on this platform requires at least Qt 4.4.0
|
||||
#endif
|
||||
|
||||
typedef int32_t key_t;
|
||||
|
||||
#else
|
||||
|
||||
#define USE_NATIVE_SHMEM
|
||||
#else /* USE_QT_SEMAPHORES */
|
||||
|
||||
#ifdef LMMS_HAVE_SYS_IPC_H
|
||||
#include <sys/ipc.h>
|
||||
#endif
|
||||
|
||||
#ifdef LMMS_HAVE_SEMAPHORE_H
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_QT_SHMEM
|
||||
|
||||
#include <Qt/qglobal.h>
|
||||
|
||||
#if QT_VERSION >= 0x040400
|
||||
#include <QtCore/QSharedMemory>
|
||||
#else
|
||||
#error building LMMS on this platform requires at least Qt 4.4.0
|
||||
#endif
|
||||
|
||||
typedef int32_t key_t;
|
||||
|
||||
#else /* USE_QT_SHMEM */
|
||||
|
||||
#ifdef LMMS_HAVE_SYS_SHM_H
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
@@ -71,9 +97,6 @@ typedef int32_t key_t;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LMMS_HAVE_SEMAPHORE_H
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#ifdef LMMS_HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
@@ -102,7 +125,7 @@ class shmFifo
|
||||
// and 64 bit platforms
|
||||
union sem32_t
|
||||
{
|
||||
#ifdef LMMS_HAVE_SEMAPHORE_H
|
||||
#ifndef USE_QT_SEMAPHORES
|
||||
sem_t sem;
|
||||
#endif
|
||||
int semKey;
|
||||
@@ -124,13 +147,13 @@ public:
|
||||
m_invalid( false ),
|
||||
m_master( true ),
|
||||
m_shmKey( 0 ),
|
||||
#ifdef USE_NATIVE_SHMEM
|
||||
m_shmID( -1 ),
|
||||
#else
|
||||
#ifdef USE_QT_SHMEM
|
||||
m_shmObj(),
|
||||
#else
|
||||
m_shmID( -1 ),
|
||||
#endif
|
||||
m_data( NULL ),
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
m_dataSem( QString::null ),
|
||||
m_messageSem( QString::null ),
|
||||
#else
|
||||
@@ -139,13 +162,7 @@ public:
|
||||
#endif
|
||||
m_lockDepth( 0 )
|
||||
{
|
||||
#ifdef USE_NATIVE_SHMEM
|
||||
while( ( m_shmID = shmget( ++m_shmKey, sizeof( shmData ),
|
||||
IPC_CREAT | IPC_EXCL | 0600 ) ) == -1 )
|
||||
{
|
||||
}
|
||||
m_data = (shmData *) shmat( m_shmID, 0, 0 );
|
||||
#else
|
||||
#ifdef USE_QT_SHMEM
|
||||
do
|
||||
{
|
||||
m_shmObj.setKey( QString( "%1" ).arg( ++m_shmKey ) );
|
||||
@@ -153,10 +170,16 @@ public:
|
||||
} while( m_shmObj.error() != QSharedMemory::NoError );
|
||||
|
||||
m_data = (shmData *) m_shmObj.data();
|
||||
#else
|
||||
while( ( m_shmID = shmget( ++m_shmKey, sizeof( shmData ),
|
||||
IPC_CREAT | IPC_EXCL | 0600 ) ) == -1 )
|
||||
{
|
||||
}
|
||||
m_data = (shmData *) shmat( m_shmID, 0, 0 );
|
||||
#endif
|
||||
assert( m_data != NULL );
|
||||
m_data->startPtr = m_data->endPtr = 0;
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
static int k = 0;
|
||||
m_data->dataSem.semKey = ( getpid()<<10 ) + ++k;
|
||||
m_data->messageSem.semKey = ( getpid()<<10 ) + ++k;
|
||||
@@ -187,13 +210,13 @@ public:
|
||||
m_invalid( false ),
|
||||
m_master( false ),
|
||||
m_shmKey( 0 ),
|
||||
#ifdef USE_NATIVE_SHMEM
|
||||
m_shmID( shmget( _shm_key, 0, 0 ) ),
|
||||
#else
|
||||
#ifdef USE_QT_SHMEM
|
||||
m_shmObj( QString::number( _shm_key ) ),
|
||||
#else
|
||||
m_shmID( shmget( _shm_key, 0, 0 ) ),
|
||||
#endif
|
||||
m_data( NULL ),
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
m_dataSem( QString::null ),
|
||||
m_messageSem( QString::null ),
|
||||
#else
|
||||
@@ -202,19 +225,19 @@ public:
|
||||
#endif
|
||||
m_lockDepth( 0 )
|
||||
{
|
||||
#ifdef USE_NATIVE_SHMEM
|
||||
if( m_shmID != -1 )
|
||||
{
|
||||
m_data = (shmData *) shmat( m_shmID, 0, 0 );
|
||||
}
|
||||
#else
|
||||
#ifdef USE_QT_SHMEM
|
||||
if( m_shmObj.attach() )
|
||||
{
|
||||
m_data = (shmData *) m_shmObj.data();
|
||||
}
|
||||
#else
|
||||
if( m_shmID != -1 )
|
||||
{
|
||||
m_data = (shmData *) shmat( m_shmID, 0, 0 );
|
||||
}
|
||||
#endif
|
||||
assert( m_data != NULL );
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
m_dataSem.setKey( QString::number( m_data->dataSem.semKey ) );
|
||||
m_messageSem.setKey( QString::number(
|
||||
m_data->messageSem.semKey ) );
|
||||
@@ -226,16 +249,16 @@ public:
|
||||
|
||||
~shmFifo()
|
||||
{
|
||||
#ifdef USE_NATIVE_SHMEM
|
||||
#ifndef USE_QT_SHMEM
|
||||
shmdt( m_data );
|
||||
#endif
|
||||
// master?
|
||||
if( m_master )
|
||||
{
|
||||
#ifdef USE_NATIVE_SHMEM
|
||||
#ifndef USE_QT_SHMEM
|
||||
shmctl( m_shmID, IPC_RMID, NULL );
|
||||
#endif
|
||||
#ifndef LMMS_BUILD_WIN32
|
||||
#ifndef USE_QT_SEMAPHORES
|
||||
sem_destroy( m_dataSem );
|
||||
sem_destroy( m_messageSem );
|
||||
#endif
|
||||
@@ -263,7 +286,7 @@ public:
|
||||
{
|
||||
if( !isInvalid() && ++m_lockDepth == 1 )
|
||||
{
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
m_dataSem.acquire();
|
||||
#else
|
||||
sem_wait( m_dataSem );
|
||||
@@ -278,7 +301,7 @@ public:
|
||||
{
|
||||
if( --m_lockDepth == 0 )
|
||||
{
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
m_dataSem.release();
|
||||
#else
|
||||
sem_post( m_dataSem );
|
||||
@@ -292,7 +315,7 @@ public:
|
||||
{
|
||||
if( !isInvalid() )
|
||||
{
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
m_messageSem.acquire();
|
||||
#else
|
||||
sem_wait( m_messageSem );
|
||||
@@ -303,7 +326,7 @@ public:
|
||||
// increase message-semaphore
|
||||
inline void messageSent( void )
|
||||
{
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
m_messageSem.release();
|
||||
#else
|
||||
sem_post( m_messageSem );
|
||||
@@ -353,7 +376,7 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
lock();
|
||||
const bool empty = ( m_data->startPtr == m_data->endPtr );
|
||||
unlock();
|
||||
@@ -447,14 +470,14 @@ private:
|
||||
volatile bool m_invalid;
|
||||
bool m_master;
|
||||
key_t m_shmKey;
|
||||
#ifdef USE_NATIVE_SHMEM
|
||||
int m_shmID;
|
||||
#else
|
||||
#ifdef USE_QT_SHMEM
|
||||
QSharedMemory m_shmObj;
|
||||
#else
|
||||
int m_shmID;
|
||||
#endif
|
||||
size_t m_shmSize;
|
||||
shmData * m_data;
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifdef USE_QT_SEMAPHORES
|
||||
QSystemSemaphore m_dataSem;
|
||||
QSystemSemaphore m_messageSem;
|
||||
#else
|
||||
@@ -755,10 +778,10 @@ private:
|
||||
|
||||
QMutex m_commMutex;
|
||||
bool m_splitChannels;
|
||||
#ifdef USE_NATIVE_SHMEM
|
||||
int m_shmID;
|
||||
#else
|
||||
#ifdef USE_QT_SHMEM
|
||||
QSharedMemory m_shmObj;
|
||||
#else
|
||||
int m_shmID;
|
||||
#endif
|
||||
size_t m_shmSize;
|
||||
float * m_shm;
|
||||
@@ -845,7 +868,7 @@ private:
|
||||
void setShmKey( key_t _key, int _size );
|
||||
void doProcessing( void );
|
||||
|
||||
#ifndef USE_NATIVE_SHMEM
|
||||
#ifdef USE_QT_SHMEM
|
||||
QSharedMemory m_shmObj;
|
||||
#endif
|
||||
float * m_shm;
|
||||
@@ -972,7 +995,7 @@ remotePluginBase::message remotePluginBase::waitForMessage(
|
||||
remotePluginClient::remotePluginClient( key_t _shm_in, key_t _shm_out ) :
|
||||
remotePluginBase( new shmFifo( _shm_in ),
|
||||
new shmFifo( _shm_out ) ),
|
||||
#ifndef USE_NATIVE_SHMEM
|
||||
#ifdef USE_QT_SHMEM
|
||||
m_shmObj(),
|
||||
#endif
|
||||
m_shm( NULL ),
|
||||
@@ -992,7 +1015,7 @@ remotePluginClient::~remotePluginClient()
|
||||
{
|
||||
sendMessage( IdQuit );
|
||||
|
||||
#ifdef USE_NATIVE_SHMEM
|
||||
#ifndef USE_QT_SHMEM
|
||||
shmdt( m_shm );
|
||||
#endif
|
||||
}
|
||||
@@ -1063,7 +1086,17 @@ bool remotePluginClient::processMessage( const message & _m )
|
||||
|
||||
void remotePluginClient::setShmKey( key_t _key, int _size )
|
||||
{
|
||||
#ifdef USE_NATIVE_SHMEM
|
||||
#ifdef USE_QT_SHMEM
|
||||
m_shmObj.setKey( QString::number( _key ) );
|
||||
if( m_shmObj.attach() )
|
||||
{
|
||||
m_shm = (float *) m_shmObj.data();
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( stderr, "failed getting shared memory\n" );
|
||||
}
|
||||
#else
|
||||
if( m_shm != NULL )
|
||||
{
|
||||
shmdt( m_shm );
|
||||
@@ -1085,16 +1118,6 @@ void remotePluginClient::setShmKey( key_t _key, int _size )
|
||||
{
|
||||
m_shm = (float *) shmat( shm_id, 0, 0 );
|
||||
}
|
||||
#else
|
||||
m_shmObj.setKey( QString::number( _key ) );
|
||||
if( m_shmObj.attach() )
|
||||
{
|
||||
m_shm = (float *) m_shmObj.data();
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( stderr, "failed getting shared memory\n" );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1115,4 +1138,6 @@ void remotePluginClient::doProcessing( void )
|
||||
|
||||
#endif
|
||||
|
||||
#define QSTR_TO_STDSTR(s) std::string( s.toUtf8().constData() )
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* sample_buffer.h - container-class sampleBuffer
|
||||
*
|
||||
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
class EXPORT handleState
|
||||
{
|
||||
public:
|
||||
handleState( bool _varying_pitch = FALSE );
|
||||
handleState( bool _varying_pitch = false );
|
||||
virtual ~handleState();
|
||||
|
||||
|
||||
@@ -66,16 +66,16 @@ public:
|
||||
// constructor which either loads sample _audio_file or decodes
|
||||
// base64-data out of string
|
||||
sampleBuffer( const QString & _audio_file = QString(),
|
||||
bool _is_base64_data = FALSE );
|
||||
bool _is_base64_data = false );
|
||||
sampleBuffer( const sampleFrame * _data, const f_cnt_t _frames );
|
||||
sampleBuffer( const f_cnt_t _frames );
|
||||
|
||||
|
||||
virtual ~sampleBuffer();
|
||||
|
||||
bool play( sampleFrame * _ab, handleState * _state,
|
||||
const fpp_t _frames,
|
||||
const float _freq,
|
||||
const bool _looped = FALSE );
|
||||
const bool _looped = false );
|
||||
|
||||
void visualize( QPainter & _p, const QRect & _dr, const QRect & _clip );
|
||||
inline void visualize( QPainter & _p, const QRect & _dr )
|
||||
@@ -83,17 +83,17 @@ public:
|
||||
visualize( _p, _dr, _dr );
|
||||
}
|
||||
|
||||
inline const QString & audioFile( void ) const
|
||||
inline const QString & audioFile() const
|
||||
{
|
||||
return m_audioFile;
|
||||
}
|
||||
|
||||
inline f_cnt_t startFrame( void ) const
|
||||
inline f_cnt_t startFrame() const
|
||||
{
|
||||
return m_startFrame;
|
||||
}
|
||||
|
||||
inline f_cnt_t endFrame( void ) const
|
||||
inline f_cnt_t endFrame() const
|
||||
{
|
||||
return m_endFrame;
|
||||
}
|
||||
@@ -112,22 +112,22 @@ public:
|
||||
m_varLock.unlock();
|
||||
}
|
||||
|
||||
inline f_cnt_t frames( void ) const
|
||||
inline f_cnt_t frames() const
|
||||
{
|
||||
return m_frames;
|
||||
}
|
||||
|
||||
inline float amplification( void ) const
|
||||
inline float amplification() const
|
||||
{
|
||||
return m_amplification;
|
||||
}
|
||||
|
||||
inline bool reversed( void ) const
|
||||
inline bool reversed() const
|
||||
{
|
||||
return m_reversed;
|
||||
}
|
||||
|
||||
inline float frequency( void ) const
|
||||
inline float frequency() const
|
||||
{
|
||||
return m_frequency;
|
||||
}
|
||||
@@ -146,12 +146,12 @@ public:
|
||||
m_varLock.unlock();
|
||||
}
|
||||
|
||||
inline const sampleFrame * data( void ) const
|
||||
inline const sampleFrame * data() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
QString openAudioFile( void ) const;
|
||||
QString openAudioFile() const;
|
||||
|
||||
QString & toBase64( QString & _dst ) const;
|
||||
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
}
|
||||
|
||||
void normalizeSampleRate( const sample_rate_t _src_sr,
|
||||
bool _keep_settings = FALSE );
|
||||
bool _keep_settings = false );
|
||||
|
||||
inline sample_t userWaveSample( const float _sample ) const
|
||||
{
|
||||
@@ -207,7 +207,7 @@ public slots:
|
||||
|
||||
|
||||
private:
|
||||
void update( bool _keep_settings = FALSE );
|
||||
void update( bool _keep_settings = false );
|
||||
|
||||
|
||||
f_cnt_t decodeSampleSF( const char * _f, int_sample_t * & _buf,
|
||||
@@ -222,7 +222,6 @@ private:
|
||||
ch_cnt_t & _channels,
|
||||
sample_rate_t & _sample_rate );
|
||||
|
||||
|
||||
QString m_audioFile;
|
||||
sampleFrame * m_origData;
|
||||
f_cnt_t m_origFrames;
|
||||
@@ -245,7 +244,7 @@ private:
|
||||
|
||||
|
||||
signals:
|
||||
void sampleUpdated( void );
|
||||
void sampleUpdated();
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "track_container.h"
|
||||
#include "automatable_model.h"
|
||||
#include "controller.h"
|
||||
#include "Controller.h"
|
||||
#include "meter_model.h"
|
||||
|
||||
|
||||
@@ -177,11 +177,11 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
void addController( controller * _c );
|
||||
void removeController( controller * _c );
|
||||
void addController( Controller * _c );
|
||||
void removeController( Controller * _c );
|
||||
|
||||
|
||||
const controllerVector & controllers( void ) const
|
||||
const ControllerVector & controllers( void ) const
|
||||
{
|
||||
return m_controllers;
|
||||
}
|
||||
@@ -270,7 +270,7 @@ private:
|
||||
intModel m_masterVolumeModel;
|
||||
intModel m_masterPitchModel;
|
||||
|
||||
controllerVector m_controllers;
|
||||
ControllerVector m_controllers;
|
||||
|
||||
|
||||
QString m_fileName;
|
||||
@@ -308,7 +308,8 @@ private:
|
||||
|
||||
friend class engine;
|
||||
friend class songEditor;
|
||||
friend class controllerRackView;
|
||||
friend class mainWindow;
|
||||
friend class ControllerRackView;
|
||||
|
||||
signals:
|
||||
void lengthChanged( int _tacts );
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
class QMenu;
|
||||
class QPushButton;
|
||||
|
||||
class bbTrack;
|
||||
class pixmapButton;
|
||||
class textFloat;
|
||||
class track;
|
||||
|
||||
@@ -17,7 +17,7 @@ BEGIN
|
||||
VALUE "CompanyName", "LMMS Developers\0"
|
||||
VALUE "FileDescription", "Linux MultiMedia Studio\0"
|
||||
VALUE "FileVersion", "@VERSION@\0"
|
||||
VALUE "LegalCopyright", "Copyright (c) 2004-2008 LMMS Developers\0"
|
||||
VALUE "LegalCopyright", "Copyright (c) 2004-2009 LMMS Developers\0"
|
||||
VALUE "OriginalFilename", "lmms.exe\0"
|
||||
VALUE "ProductName", "LMMS\0"
|
||||
VALUE "ProductVersion", "@VERSION@\0"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* audio_file_processor.cpp - instrument for using audio-files
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -41,8 +41,6 @@
|
||||
#include "string_pair_drag.h"
|
||||
#include "mmp.h"
|
||||
|
||||
|
||||
#undef SINGLE_SOURCE_COMPILE
|
||||
#include "embed.cpp"
|
||||
|
||||
|
||||
@@ -212,13 +210,13 @@ pluginView * audioFileProcessor::instantiateView( QWidget * _parent )
|
||||
|
||||
|
||||
void audioFileProcessor::setAudioFile( const QString & _audio_file,
|
||||
bool _rename )
|
||||
bool _rename )
|
||||
{
|
||||
// is current channel-name equal to previous-filename??
|
||||
if( _rename &&
|
||||
if( _rename &&
|
||||
( getInstrumentTrack()->name() ==
|
||||
QFileInfo( m_sampleBuffer.audioFile() ).fileName() ||
|
||||
m_sampleBuffer.audioFile() == "" ) )
|
||||
m_sampleBuffer.audioFile().isEmpty() ) )
|
||||
{
|
||||
// then set it to new one
|
||||
getInstrumentTrack()->setName( QFileInfo( _audio_file
|
||||
@@ -424,7 +422,7 @@ void audioFileProcessorView::dropEvent( QDropEvent * _de )
|
||||
}
|
||||
else if( type == QString( "tco_%1" ).arg( track::SampleTrack ) )
|
||||
{
|
||||
multimediaProject mmp( value, FALSE );
|
||||
multimediaProject mmp( value.toUtf8() );
|
||||
castModel<audioFileProcessor>()->setAudioFile( mmp.content().
|
||||
firstChild().toElement().attribute( "src" ) );
|
||||
_de->accept();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* bass_booster.cpp - bass-booster-effect-plugin
|
||||
*
|
||||
* Copyright (c) 2006-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
#include "bass_booster.h"
|
||||
|
||||
|
||||
#undef SINGLE_SOURCE_COMPILE
|
||||
#include "embed.cpp"
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "tooltip.h"
|
||||
#include "song.h"
|
||||
|
||||
#undef SINGLE_SOURCE_COMPILE
|
||||
#include "embed.cpp"
|
||||
|
||||
extern "C"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* flp_import.cpp - support for importing FLP-files
|
||||
*
|
||||
* Copyright (c) 2006-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -22,7 +22,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <QtXml/QDomDocument>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QProgressDialog>
|
||||
@@ -105,9 +104,9 @@ static void dump_mem( const void * buffer, uint n_bytes )
|
||||
uchar * cp = (uchar *) buffer;
|
||||
for( uint k = 0; k < n_bytes; ++k )
|
||||
{
|
||||
printf( "%02x ", (unsigned int)cp[k] );//( cp[k] > 31 || cp[k] < 7 ) ? cp[k] : '.' );
|
||||
qDebug( "%02x ", (unsigned int)cp[k] );//( cp[k] > 31 || cp[k] < 7 ) ? cp[k] : '.' );
|
||||
}
|
||||
printf( "\n" );
|
||||
qDebug( "\n" );
|
||||
}
|
||||
|
||||
|
||||
@@ -586,6 +585,8 @@ flpImport::~flpImport()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool flpImport::tryImport( trackContainer * _tc )
|
||||
{
|
||||
const int mappedFilter[] =
|
||||
@@ -676,21 +677,21 @@ bool flpImport::tryImport( trackContainer * _tc )
|
||||
|
||||
if( readID() != makeID( 'F', 'L', 'h', 'd' ) )
|
||||
{
|
||||
printf( "flpImport::tryImport(): not a valid FL project\n" );
|
||||
qWarning( "flpImport::tryImport(): not a valid FL project\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
const int header_len = read32LE();
|
||||
if( header_len != 6 )
|
||||
{
|
||||
printf( "flpImport::tryImport(): invalid file format\n" );
|
||||
qWarning( "flpImport::tryImport(): invalid file format\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
const int type = read16LE();
|
||||
if( type != 0 )
|
||||
{
|
||||
printf( "flpImport::tryImport(): type %d format is not "
|
||||
qWarning( "flpImport::tryImport(): type %d format is not "
|
||||
"supported\n", type );
|
||||
return false;
|
||||
}
|
||||
@@ -698,7 +699,7 @@ bool flpImport::tryImport( trackContainer * _tc )
|
||||
p.numChannels = read16LE();
|
||||
if( p.numChannels < 1 || p.numChannels > 1000 )
|
||||
{
|
||||
printf( "flpImport::tryImport(): invalid number of channels "
|
||||
qWarning( "flpImport::tryImport(): invalid number of channels "
|
||||
"(%d)\n", p.numChannels );
|
||||
return false;
|
||||
}
|
||||
@@ -706,7 +707,7 @@ bool flpImport::tryImport( trackContainer * _tc )
|
||||
const int ppq = read16LE();
|
||||
if( ppq < 0 )
|
||||
{
|
||||
printf( "flpImport::tryImport(): invalid ppq\n" );
|
||||
qWarning( "flpImport::tryImport(): invalid ppq\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -725,14 +726,14 @@ bool flpImport::tryImport( trackContainer * _tc )
|
||||
const int len = read32LE();
|
||||
if( file().atEnd() )
|
||||
{
|
||||
printf( "flpImport::tryImport(): unexpected "
|
||||
"end of file\n" );
|
||||
qWarning( "flpImport::tryImport(): unexpected "
|
||||
"end of file\n" );
|
||||
return false;
|
||||
}
|
||||
if( len < 0 || len >= 0x10000000 )
|
||||
{
|
||||
printf( "flpImport::tryImport(): invalid "
|
||||
"chunk length %d\n", len );
|
||||
qWarning( "flpImport::tryImport(): invalid "
|
||||
"chunk length %d\n", len );
|
||||
return false;
|
||||
}
|
||||
if( id == makeID( 'F', 'L', 'd', 't' ) )
|
||||
@@ -753,7 +754,7 @@ bool flpImport::tryImport( trackContainer * _tc )
|
||||
p.channels += FL_Channel();
|
||||
}
|
||||
|
||||
printf( "channels: %d\n", p.numChannels );
|
||||
qDebug( "channels: %d\n", p.numChannels );
|
||||
|
||||
|
||||
char * text = NULL;
|
||||
@@ -798,8 +799,8 @@ bool flpImport::tryImport( trackContainer * _tc )
|
||||
text = new char[text_len+1];
|
||||
if( readBlock( text, text_len ) <= 0 )
|
||||
{
|
||||
printf( "could not read string (len: %d)\n",
|
||||
text_len );
|
||||
qWarning( "could not read string (len: %d)\n",
|
||||
text_len );
|
||||
}
|
||||
|
||||
text[text_len] = 0;
|
||||
@@ -815,32 +816,32 @@ bool flpImport::tryImport( trackContainer * _tc )
|
||||
{
|
||||
// BYTE EVENTS
|
||||
case FLP_Byte:
|
||||
printf( "undefined byte %d\n", data );
|
||||
qDebug( "undefined byte %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_NoteOn:
|
||||
printf( "note on: %d\n", data );
|
||||
qDebug( "note on: %d\n", data );
|
||||
// data = pos how to handle?
|
||||
break;
|
||||
|
||||
case FLP_Vol:
|
||||
printf( "vol %d\n", data );
|
||||
qDebug( "vol %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_Pan:
|
||||
printf( "pan %d\n", data );
|
||||
qDebug( "pan %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_LoopActive:
|
||||
printf( "active loop: %d\n", data );
|
||||
qDebug( "active loop: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_ShowInfo:
|
||||
printf( "show info: %d\n", data );
|
||||
qDebug( "show info: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_Shuffle:
|
||||
printf( "shuffle: %d\n", data );
|
||||
qDebug( "shuffle: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_MainVol:
|
||||
@@ -848,11 +849,11 @@ bool flpImport::tryImport( trackContainer * _tc )
|
||||
break;
|
||||
|
||||
case FLP_PatLength:
|
||||
printf( "pattern length: %d\n", data );
|
||||
qDebug( "pattern length: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_BlockLength:
|
||||
printf( "block length: %d\n", data );
|
||||
qDebug( "block length: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_UseLoopPoints:
|
||||
@@ -860,11 +861,11 @@ bool flpImport::tryImport( trackContainer * _tc )
|
||||
break;
|
||||
|
||||
case FLP_LoopType:
|
||||
printf( "loop type: %d\n", data );
|
||||
qDebug( "loop type: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_ChanType:
|
||||
printf( "channel type: %d\n", data );
|
||||
qDebug( "channel type: %d\n", data );
|
||||
if( cc )
|
||||
{
|
||||
switch( data )
|
||||
@@ -895,7 +896,7 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
// WORD EVENTS
|
||||
case FLP_NewChan:
|
||||
cur_channel = data;
|
||||
printf( "new channel: %d\n", data );
|
||||
qDebug( "new channel: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_NewPat:
|
||||
@@ -915,7 +916,7 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
break;
|
||||
|
||||
case FLP_FX:
|
||||
printf( "FX: %d\n", data );
|
||||
qDebug( "FX: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_Fade_Stereo:
|
||||
@@ -927,11 +928,11 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
{
|
||||
cc->sampleReverseStereo = true;
|
||||
}
|
||||
printf( "fade stereo: %d\n", data );
|
||||
qDebug( "fade stereo: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_CutOff:
|
||||
printf( "cutoff (sample): %d\n", data );
|
||||
qDebug( "cutoff (sample): %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_PreAmp:
|
||||
@@ -939,11 +940,11 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
break;
|
||||
|
||||
case FLP_Decay:
|
||||
printf( "decay (sample): %d\n", data );
|
||||
qDebug( "decay (sample): %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_Attack:
|
||||
printf( "attack (sample): %d\n", data );
|
||||
qDebug( "attack (sample): %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_MainPitch:
|
||||
@@ -951,23 +952,23 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
break;
|
||||
|
||||
case FLP_Resonance:
|
||||
printf( "reso (sample): %d\n", data );
|
||||
qDebug( "reso (sample): %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_LoopBar:
|
||||
printf( "loop bar: %d\n", data );
|
||||
qDebug( "loop bar: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_StDel:
|
||||
printf( "stdel (delay?): %d\n", data );
|
||||
qDebug( "stdel (delay?): %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_FX3:
|
||||
printf( "FX 3: %d\n", data );
|
||||
qDebug( "FX 3: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_ShiftDelay:
|
||||
printf( "shift delay: %d\n", data );
|
||||
qDebug( "shift delay: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_Dot:
|
||||
@@ -999,11 +1000,11 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
}
|
||||
|
||||
case FLP_FXSine:
|
||||
printf( "fx sine: %d\n", data );
|
||||
qDebug( "fx sine: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_CutCutBy:
|
||||
printf( "cut cut by: %d\n", data );
|
||||
qDebug( "cut cut by: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_MiddleNote:
|
||||
@@ -1011,15 +1012,15 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
break;
|
||||
|
||||
case FLP_DelayReso:
|
||||
printf( "delay resonance: %d\n", data );
|
||||
qDebug( "delay resonance: %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_Reverb:
|
||||
printf( "reverb (sample): %d\n", data );
|
||||
qDebug( "reverb (sample): %d\n", data );
|
||||
break;
|
||||
|
||||
case FLP_IntStretch:
|
||||
printf( "int stretch (sample): %d\n", data );
|
||||
qDebug( "int stretch (sample): %d\n", data );
|
||||
break;
|
||||
|
||||
// TEXT EVENTS
|
||||
@@ -1082,7 +1083,7 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
|
||||
case FLP_Text_Version:
|
||||
{
|
||||
printf( "FLP version: %s\n", text );
|
||||
qDebug( "FLP version: %s\n", text );
|
||||
p.versionString = text;
|
||||
QStringList l = p.versionString.split( '.' );
|
||||
p.version = ( l[0].toInt() << 8 ) +
|
||||
@@ -1103,36 +1104,32 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
mappedPluginTypes[QString( text ).toLower()] );
|
||||
if( t > FL_Plugin::EffectPlugin )
|
||||
{
|
||||
printf( "recognized new "
|
||||
"effect %s\n", text );
|
||||
p.effects.push_back(
|
||||
FL_Effect( t ) );
|
||||
qDebug( "recognized new effect %s\n", text );
|
||||
p.effects.push_back( FL_Effect( t ) );
|
||||
}
|
||||
else if( cc )
|
||||
{
|
||||
printf( "recognized new "
|
||||
"plugin %s\n", text );
|
||||
qDebug( "recognized new plugin %s\n", text );
|
||||
cc->pluginType = t;
|
||||
}
|
||||
last_plugin_type = t;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "unsupported plugin: %s!\n",
|
||||
text );
|
||||
qDebug( "unsupported plugin: %s!\n", text );
|
||||
}
|
||||
break;
|
||||
|
||||
case FLP_Text_EffectChanName:
|
||||
++p.currentEffectChannel;
|
||||
if( p.currentEffectChannel <= NumFxChannels )
|
||||
{
|
||||
p.effectChannels[p.currentEffectChannel].name = text;
|
||||
}
|
||||
++p.currentEffectChannel;
|
||||
if( p.currentEffectChannel <= NumFxChannels )
|
||||
{
|
||||
p.effectChannels[p.currentEffectChannel].name = text;
|
||||
}
|
||||
break;
|
||||
|
||||
case FLP_Text_Delay:
|
||||
printf( "delay data: " );
|
||||
qDebug( "delay data: " );
|
||||
// pi[1] seems to be volume or similiar and
|
||||
// needs to be divided
|
||||
// by p.versionSpecificFactor
|
||||
@@ -1140,30 +1137,27 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
break;
|
||||
|
||||
case FLP_Text_TS404Params:
|
||||
if( cc && cc->pluginType ==
|
||||
FL_Plugin::UnknownPlugin &&
|
||||
if( cc && cc->pluginType == FL_Plugin::UnknownPlugin &&
|
||||
cc->pluginSettings == NULL )
|
||||
{
|
||||
cc->pluginSettings = new char[text_len];
|
||||
memcpy( cc->pluginSettings, text,
|
||||
text_len );
|
||||
memcpy( cc->pluginSettings, text, text_len );
|
||||
cc->pluginSettingsLength = text_len;
|
||||
cc->pluginType =
|
||||
FL_Plugin::TS404;
|
||||
cc->pluginType = FL_Plugin::TS404;
|
||||
}
|
||||
break;
|
||||
|
||||
case FLP_Text_NewPlugin:
|
||||
if( last_plugin_type > FL_Plugin::EffectPlugin )
|
||||
{
|
||||
FL_Effect * e = &p.effects.last();
|
||||
e->fxChannel = puc[0];
|
||||
e->fxPos = puc[4];
|
||||
printf( "new effect: " );
|
||||
FL_Effect * e = &p.effects.last();
|
||||
e->fxChannel = puc[0];
|
||||
e->fxPos = puc[4];
|
||||
qDebug( "new effect: " );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "new plugin: " );
|
||||
qDebug( "new plugin: " );
|
||||
}
|
||||
dump_mem( text, text_len );
|
||||
break;
|
||||
@@ -1176,7 +1170,7 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
text_len );
|
||||
cc->pluginSettingsLength = text_len;
|
||||
}
|
||||
printf( "plugin params: " );
|
||||
qDebug( "plugin params: " );
|
||||
dump_mem( text, text_len );
|
||||
break;
|
||||
|
||||
@@ -1194,7 +1188,7 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
cc->arpGate = ( pi[14] * 100.0f ) / 48.0f;
|
||||
cc->arpEnabled = pi[10] > 0;
|
||||
|
||||
printf( "channel params: " );
|
||||
qDebug( "channel params: " );
|
||||
dump_mem( text, text_len );
|
||||
break;
|
||||
|
||||
@@ -1235,7 +1229,7 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
// e.lfoAmount = pi[11] / 128.0f;
|
||||
cc->envelopes.push_back( e );
|
||||
|
||||
printf( "envelope and lfo params:\n" );
|
||||
qDebug( "envelope and lfo params:\n" );
|
||||
dump_mem( text, text_len );
|
||||
|
||||
break;
|
||||
@@ -1256,7 +1250,7 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
cc->filterCut *= 0.5f;
|
||||
}
|
||||
}
|
||||
printf( "basic chan params: " );
|
||||
qDebug( "basic chan params: " );
|
||||
dump_mem( text, text_len );
|
||||
break;
|
||||
|
||||
@@ -1269,7 +1263,7 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
{
|
||||
cc->filterCut *= 0.5;
|
||||
}
|
||||
printf( "old filter params: " );
|
||||
qDebug( "old filter params: " );
|
||||
dump_mem( text, text_len );
|
||||
break;
|
||||
|
||||
@@ -1277,7 +1271,7 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
{
|
||||
const int bpae = 12;
|
||||
const int imax = text_len / bpae;
|
||||
printf( "automation data (%d items)\n", imax );
|
||||
qDebug( "automation data (%d items)\n", imax );
|
||||
for( int i = 0; i < imax; ++i )
|
||||
{
|
||||
FL_Automation a;
|
||||
@@ -1289,8 +1283,9 @@ if( p.currentEffectChannel <= NumFxChannels )
|
||||
if( a.channel >= 0 &&
|
||||
a.channel < p.numChannels )
|
||||
{
|
||||
printf("add channel %d at %d val %d control:%d\n", a.channel, a.pos, a.value, a.control );
|
||||
p.channels[a.channel].automationData += a;
|
||||
qDebug( "add channel %d at %d val %d control:%d\n",
|
||||
a.channel, a.pos, a.value, a.control );
|
||||
p.channels[a.channel].automationData += a;
|
||||
}
|
||||
// dump_mem( text+i*bpae, bpae );
|
||||
}
|
||||
@@ -1315,15 +1310,22 @@ printf("add channel %d at %d val %d control:%d\n", a.channel, a.pos, a.value,
|
||||
len /= (4*ppq) / DefaultTicksPerTact;
|
||||
note n( len, pos, key, vol * 100 / 128,
|
||||
pan*200 / 128 - 100 );
|
||||
if( ch < p.numChannels )
|
||||
{
|
||||
p.channels[ch].notes.push_back( qMakePair( p.currentPattern, n ) );
|
||||
printf( "note: " );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug( "invalid " );
|
||||
}
|
||||
qDebug( "note: " );
|
||||
dump_mem( text+i*bpn, bpn );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FLP_Text_ChanGroupName:
|
||||
printf( "channel group name: %s\n", text );
|
||||
qDebug( "channel group name: %s\n", text );
|
||||
break;
|
||||
|
||||
// case 216: pi[2] /= p.versionSpecificFactor
|
||||
@@ -1354,7 +1356,7 @@ p.effectChannels[ch].volume = ( val / p.versionSpecificFactor ) * 100 / 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("FX-ch: %d param: %x value:%x\n", ch, param, val );
|
||||
qDebug( "FX-ch: %d param: %x value:%x\n", ch, param, val );
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1379,7 +1381,7 @@ if( pat > 2146 && pat <= 2278 ) // whatever these magic numbers are for...
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "playlist item: " );
|
||||
qDebug( "unknown playlist item: " );
|
||||
dump_mem( text+i*bpi, bpi );
|
||||
}
|
||||
}
|
||||
@@ -1389,25 +1391,18 @@ else
|
||||
default:
|
||||
if( ev >= FLP_Text )
|
||||
{
|
||||
printf( "!! unhandled text (ev: %d, "
|
||||
"len: %d): ",
|
||||
ev, text_len );
|
||||
qDebug( "!! unhandled text (ev: %d, len: %d): ",
|
||||
ev, text_len );
|
||||
dump_mem( text, text_len );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "!! handling of FLP-event %d "
|
||||
"not implemented yet "
|
||||
"(data=%d).\n", ev, data );
|
||||
qDebug( "!! handling of FLP-event %d not implemented yet "
|
||||
"(data=%d).\n", ev, data );
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* if( ev >= FLP_Text )
|
||||
{
|
||||
printf( "dump (ev: %d, len: %d): ", ev, text_len );
|
||||
dump_mem( text, text_len );
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now create a project from FL_Project data structure
|
||||
@@ -1424,7 +1419,7 @@ else
|
||||
|
||||
|
||||
progressDialog.setMaximum( p.maxPatterns + p.channels.size() +
|
||||
p.effects.size() );
|
||||
p.effects.size() );
|
||||
int cur_progress = 0;
|
||||
|
||||
// create BB tracks
|
||||
@@ -1480,8 +1475,7 @@ else
|
||||
case FL_Plugin::UnknownPlugin:
|
||||
default:
|
||||
it->instrumentPlugin =
|
||||
t->loadInstrument(
|
||||
"audiofileprocessor" );
|
||||
t->loadInstrument( "audiofileprocessor" );
|
||||
break;
|
||||
}
|
||||
processPluginParams( &( *it ) );
|
||||
@@ -1504,8 +1498,7 @@ else
|
||||
iss->m_filterResModel.minValue() );
|
||||
iss->m_filterEnabledModel.setValue( it->filterEnabled );
|
||||
|
||||
for( QList<FL_Channel_Envelope>::iterator jt =
|
||||
it->envelopes.begin();
|
||||
for( QList<FL_Channel_Envelope>::iterator jt = it->envelopes.begin();
|
||||
jt != it->envelopes.end(); ++jt )
|
||||
{
|
||||
if( jt->target != instrumentSoundShaping::NumTargets )
|
||||
@@ -1554,8 +1547,7 @@ else
|
||||
}
|
||||
|
||||
// process all notes
|
||||
for( FL_Channel::noteVector::const_iterator jt =
|
||||
it->notes.begin();
|
||||
for( FL_Channel::noteVector::const_iterator jt = it->notes.begin();
|
||||
jt != it->notes.end(); ++jt )
|
||||
{
|
||||
const int pat = jt->first;
|
||||
@@ -1564,8 +1556,7 @@ else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pattern * p = dynamic_cast<pattern *>(
|
||||
t->getTCO( pat ) );
|
||||
pattern * p = dynamic_cast<pattern *>( t->getTCO( pat ) );
|
||||
if( p != NULL )
|
||||
{
|
||||
p->addNote( jt->second, false );
|
||||
@@ -1584,8 +1575,7 @@ else
|
||||
{
|
||||
case FL_Automation::ControlVolume:
|
||||
m = t->volumeModel();
|
||||
value *= ( 100.0f / 128.0f ) /
|
||||
p.versionSpecificFactor;
|
||||
value *= ( 100.0f / 128.0f ) / p.versionSpecificFactor;
|
||||
break;
|
||||
case FL_Automation::ControlPanning:
|
||||
m = t->panningModel();
|
||||
@@ -1613,9 +1603,9 @@ else
|
||||
value = mappedFilter[jt->value];
|
||||
break;
|
||||
default:
|
||||
printf( "handling automation data of "
|
||||
"control %d not implemented "
|
||||
"yet\n", jt->control );
|
||||
qDebug( "handling automation data of "
|
||||
"control %d not implemented "
|
||||
"yet\n", jt->control );
|
||||
break;
|
||||
}
|
||||
if( m )
|
||||
@@ -1653,14 +1643,12 @@ p->putValue( jt->pos, value, false );
|
||||
else
|
||||
{
|
||||
effKeys << effectKey( &( *it ), it->name );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for( int fx_ch = 0; fx_ch <= NumFxChannels ; ++fx_ch )
|
||||
{
|
||||
fxChannel * ch = engine::getFxMixer()->getEffectChannel(
|
||||
fx_ch );
|
||||
fxChannel * ch = engine::getFxMixer()->getEffectChannel( fx_ch );
|
||||
if( !ch )
|
||||
{
|
||||
continue;
|
||||
@@ -1723,9 +1711,8 @@ p->putValue( jt->pos, value, false );
|
||||
continue;
|
||||
}
|
||||
effectChain * ec = &engine::getFxMixer()->
|
||||
getEffectChannel( it->fxChannel )->
|
||||
m_fxChain;
|
||||
printf("adding %s to %d\n", effName.toAscii().constData(),
|
||||
getEffectChannel( it->fxChannel )->m_fxChain;
|
||||
qDebug( "adding %s to %d\n", effName.toUtf8().constData(),
|
||||
it->fxChannel );
|
||||
for( effectKeyList::iterator jt = effKeys.begin();
|
||||
jt != effKeys.end(); ++jt )
|
||||
@@ -1735,7 +1722,7 @@ p->putValue( jt->pos, value, false );
|
||||
( jt->desc->sub_plugin_features != NULL &&
|
||||
jt->name.contains( effName ) ) )
|
||||
{
|
||||
printf("instantiate %s\n", jt->desc->name );
|
||||
qDebug( "instantiate %s\n", jt->desc->name );
|
||||
effect * e = effect::instantiate(
|
||||
jt->desc->name, ec, &( *jt ) );
|
||||
ec->appendEffect( e );
|
||||
@@ -1788,7 +1775,7 @@ p->putValue( jt->pos, value, false );
|
||||
|
||||
void flpImport::processPluginParams( FL_Channel * _ch )
|
||||
{
|
||||
printf( "plugin params for plugin %d (%d bytes): ", _ch->pluginType,
|
||||
qDebug( "plugin params for plugin %d (%d bytes): ", _ch->pluginType,
|
||||
_ch->pluginSettingsLength );
|
||||
dump_mem( _ch->pluginSettings, _ch->pluginSettingsLength );
|
||||
switch( _ch->pluginType )
|
||||
@@ -1877,7 +1864,7 @@ void flpImport::processPluginParams( FL_Channel * _ch )
|
||||
|
||||
case FL_Plugin::UnknownPlugin:
|
||||
default:
|
||||
printf( "handling of plugin params not implemented "
|
||||
qDebug( "handling of plugin params not implemented "
|
||||
"for current plugin\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -108,10 +108,10 @@ attr_express_begin (int attr, const char* param) {
|
||||
switch(attr)
|
||||
{
|
||||
case ATTR_BOLD:
|
||||
outstring+=QString().sprintf(op->bold_begin);
|
||||
outstring+=QString().sprintf("%s", op->bold_begin);
|
||||
break;
|
||||
case ATTR_ITALIC:
|
||||
outstring+=QString().sprintf(op->italic_begin);
|
||||
outstring+=QString().sprintf("%s", op->italic_begin);
|
||||
break;
|
||||
|
||||
/* Various underlines, they all resolve to HTML's <u> */
|
||||
@@ -123,11 +123,11 @@ attr_express_begin (int attr, const char* param) {
|
||||
case ATTR_2DOT_DASH_UL:
|
||||
case ATTR_WORD_UL:
|
||||
case ATTR_UNDERLINE:
|
||||
outstring+=QString().sprintf(op->underline_begin);
|
||||
outstring+=QString().sprintf("%s", op->underline_begin);
|
||||
break;
|
||||
|
||||
case ATTR_DOUBLE_UL:
|
||||
outstring+=QString().sprintf(op->dbl_underline_begin);
|
||||
outstring+=QString().sprintf("%s", op->dbl_underline_begin);
|
||||
break;
|
||||
|
||||
case ATTR_FONTSIZE:
|
||||
@@ -148,18 +148,18 @@ attr_express_begin (int attr, const char* param) {
|
||||
break;
|
||||
|
||||
case ATTR_SUPER:
|
||||
outstring+=QString().sprintf(op->superscript_begin);
|
||||
outstring+=QString().sprintf("%s", op->superscript_begin);
|
||||
break;
|
||||
case ATTR_SUB:
|
||||
outstring+=QString().sprintf(op->subscript_begin);
|
||||
outstring+=QString().sprintf("%s", op->subscript_begin);
|
||||
break;
|
||||
|
||||
case ATTR_STRIKE:
|
||||
outstring+=QString().sprintf(op->strikethru_begin);
|
||||
outstring+=QString().sprintf("%s", op->strikethru_begin);
|
||||
break;
|
||||
|
||||
case ATTR_DBL_STRIKE:
|
||||
outstring+=QString().sprintf(op->dbl_strikethru_begin);
|
||||
outstring+=QString().sprintf("%s", op->dbl_strikethru_begin);
|
||||
break;
|
||||
|
||||
case ATTR_EXPAND:
|
||||
@@ -167,16 +167,16 @@ attr_express_begin (int attr, const char* param) {
|
||||
break;
|
||||
|
||||
case ATTR_OUTLINE:
|
||||
outstring+=QString().sprintf(op->outline_begin);
|
||||
outstring+=QString().sprintf("%s", op->outline_begin);
|
||||
break;
|
||||
case ATTR_SHADOW:
|
||||
outstring+=QString().sprintf(op->shadow_begin);
|
||||
outstring+=QString().sprintf("%s", op->shadow_begin);
|
||||
break;
|
||||
case ATTR_EMBOSS:
|
||||
outstring+=QString().sprintf(op->emboss_begin);
|
||||
outstring+=QString().sprintf("%s", op->emboss_begin);
|
||||
break;
|
||||
case ATTR_ENGRAVE:
|
||||
outstring+=QString().sprintf(op->engrave_begin);
|
||||
outstring+=QString().sprintf("%s", op->engrave_begin);
|
||||
break;
|
||||
|
||||
case ATTR_CAPS:
|
||||
@@ -189,7 +189,7 @@ attr_express_begin (int attr, const char* param) {
|
||||
simulate_smallcaps = TRUE;
|
||||
else {
|
||||
if (op->small_caps_begin)
|
||||
outstring+=QString().sprintf(op->small_caps_begin);
|
||||
outstring+=QString().sprintf("%s", op->small_caps_begin);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -209,10 +209,10 @@ attr_express_end (int attr, char *param)
|
||||
switch(attr)
|
||||
{
|
||||
case ATTR_BOLD:
|
||||
outstring+=QString().sprintf(op->bold_end);
|
||||
outstring+=QString().sprintf("%s", op->bold_end);
|
||||
break;
|
||||
case ATTR_ITALIC:
|
||||
outstring+=QString().sprintf(op->italic_end);
|
||||
outstring+=QString().sprintf("%s", op->italic_end);
|
||||
break;
|
||||
|
||||
/* Various underlines, they all resolve to HTML's </u> */
|
||||
@@ -224,11 +224,11 @@ attr_express_end (int attr, char *param)
|
||||
case ATTR_2DOT_DASH_UL:
|
||||
case ATTR_WORD_UL:
|
||||
case ATTR_UNDERLINE:
|
||||
outstring+=QString().sprintf(op->underline_end);
|
||||
outstring+=QString().sprintf("%s", op->underline_end);
|
||||
break;
|
||||
|
||||
case ATTR_DOUBLE_UL:
|
||||
outstring+=QString().sprintf(op->dbl_underline_end);
|
||||
outstring+=QString().sprintf("%s", op->dbl_underline_end);
|
||||
break;
|
||||
|
||||
case ATTR_FONTSIZE:
|
||||
@@ -236,47 +236,47 @@ attr_express_end (int attr, char *param)
|
||||
break;
|
||||
|
||||
case ATTR_FONTFACE:
|
||||
outstring+=QString().sprintf(op->font_end);
|
||||
outstring+=QString().sprintf("%s", op->font_end);
|
||||
break;
|
||||
|
||||
case ATTR_FOREGROUND:
|
||||
outstring+=QString().sprintf(op->foreground_end);
|
||||
outstring+=QString().sprintf("%s", op->foreground_end);
|
||||
break;
|
||||
case ATTR_BACKGROUND:
|
||||
if (!simple_mode)
|
||||
outstring+=QString().sprintf(op->background_end);
|
||||
outstring+=QString().sprintf("%s", op->background_end);
|
||||
break;
|
||||
|
||||
case ATTR_SUPER:
|
||||
outstring+=QString().sprintf(op->superscript_end);
|
||||
outstring+=QString().sprintf("%s", op->superscript_end);
|
||||
break;
|
||||
case ATTR_SUB:
|
||||
outstring+=QString().sprintf(op->subscript_end);
|
||||
outstring+=QString().sprintf("%s", op->subscript_end);
|
||||
break;
|
||||
|
||||
case ATTR_STRIKE:
|
||||
outstring+=QString().sprintf(op->strikethru_end);
|
||||
outstring+=QString().sprintf("%s", op->strikethru_end);
|
||||
break;
|
||||
|
||||
case ATTR_DBL_STRIKE:
|
||||
outstring+=QString().sprintf(op->dbl_strikethru_end);
|
||||
outstring+=QString().sprintf("%s", op->dbl_strikethru_end);
|
||||
break;
|
||||
|
||||
case ATTR_OUTLINE:
|
||||
outstring+=QString().sprintf(op->outline_end);
|
||||
outstring+=QString().sprintf("%s", op->outline_end);
|
||||
break;
|
||||
case ATTR_SHADOW:
|
||||
outstring+=QString().sprintf(op->shadow_end);
|
||||
outstring+=QString().sprintf("%s", op->shadow_end);
|
||||
break;
|
||||
case ATTR_EMBOSS:
|
||||
outstring+=QString().sprintf(op->emboss_end);
|
||||
outstring+=QString().sprintf("%s", op->emboss_end);
|
||||
break;
|
||||
case ATTR_ENGRAVE:
|
||||
outstring+=QString().sprintf(op->engrave_end);
|
||||
outstring+=QString().sprintf("%s", op->engrave_end);
|
||||
break;
|
||||
|
||||
case ATTR_EXPAND:
|
||||
outstring+=QString().sprintf(op->expand_end);
|
||||
outstring+=QString().sprintf("%s", op->expand_end);
|
||||
break;
|
||||
|
||||
case ATTR_CAPS:
|
||||
@@ -289,7 +289,7 @@ attr_express_end (int attr, char *param)
|
||||
simulate_smallcaps = FALSE;
|
||||
else {
|
||||
if (op->small_caps_end)
|
||||
outstring+=QString().sprintf(op->small_caps_end);
|
||||
outstring+=QString().sprintf("%s", op->small_caps_end);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -650,8 +650,8 @@ starting_body ()
|
||||
{
|
||||
if (!have_printed_body) {
|
||||
if (!inline_mode) {
|
||||
outstring+=QString().sprintf(op->header_end);
|
||||
outstring+=QString().sprintf(op->body_begin);
|
||||
outstring+=QString().sprintf("%s", op->header_end);
|
||||
outstring+=QString().sprintf("%s", op->body_begin);
|
||||
}
|
||||
within_header = FALSE;
|
||||
have_printed_body = TRUE;
|
||||
@@ -926,7 +926,7 @@ process_info_group (Word *w)
|
||||
|
||||
if (!inline_mode) {
|
||||
if (!strcmp("\\title", s)) {
|
||||
outstring+=QString().sprintf(op->document_title_begin);
|
||||
outstring+=QString().sprintf("%s", op->document_title_begin);
|
||||
w2=child->next;
|
||||
while (w2) {
|
||||
char *s2 = word_string(w2);
|
||||
@@ -951,18 +951,18 @@ process_info_group (Word *w)
|
||||
s3 = op_translate_char (op, charset_type, charset_codepage, ch, numchar_table);
|
||||
if (!s3 || !*s3)
|
||||
{
|
||||
outstring+=QString().sprintf(op->comment_begin);
|
||||
outstring+=QString().sprintf("%s", op->comment_begin);
|
||||
outstring+=QString().sprintf("char 0x%02x",ch);
|
||||
outstring+=QString().sprintf(op->comment_end);
|
||||
outstring+=QString().sprintf("%s", op->comment_end);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (op->word_begin)
|
||||
outstring+=QString().sprintf(op->word_begin);
|
||||
outstring+=QString().sprintf("%s", op->word_begin);
|
||||
outstring+=QString().sprintf("%s", s3);
|
||||
if (op->word_end)
|
||||
outstring+=QString().sprintf(op->word_end);
|
||||
outstring+=QString().sprintf("%s", op->word_end);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -970,10 +970,10 @@ process_info_group (Word *w)
|
||||
#endif
|
||||
w2 = w2->next;
|
||||
}
|
||||
outstring+=QString().sprintf(op->document_title_end);
|
||||
outstring+=QString().sprintf("%s", op->document_title_end);
|
||||
}
|
||||
else if (!strcmp("\\keywords", s)) {
|
||||
outstring+=QString().sprintf(op->document_keywords_begin);
|
||||
outstring+=QString().sprintf("%s", op->document_keywords_begin);
|
||||
w2=child->next;
|
||||
while (w2) {
|
||||
char *s2 = word_string(w2);
|
||||
@@ -981,10 +981,10 @@ process_info_group (Word *w)
|
||||
outstring+=QString().sprintf("%s,", s2);
|
||||
w2 = w2->next;
|
||||
}
|
||||
outstring+=QString().sprintf(op->document_keywords_end);
|
||||
outstring+=QString().sprintf("%s", op->document_keywords_end);
|
||||
}
|
||||
else if (!strcmp("\\author", s)) {
|
||||
outstring+=QString().sprintf(op->document_author_begin);
|
||||
outstring+=QString().sprintf("%s", op->document_author_begin);
|
||||
w2=child->next;
|
||||
while (w2) {
|
||||
char *s2 = word_string(w2);
|
||||
@@ -992,7 +992,7 @@ process_info_group (Word *w)
|
||||
outstring+=QString().sprintf("%s", s2);
|
||||
w2 = w2->next;
|
||||
}
|
||||
outstring+=QString().sprintf(op->document_author_end);
|
||||
outstring+=QString().sprintf("%s", op->document_author_end);
|
||||
}
|
||||
else if (!strcmp("\\comment", s)) {
|
||||
outstring+=QString().sprintf("%s",op->comment_begin);
|
||||
@@ -1312,9 +1312,9 @@ cmd_field (Word *w, int align, char has_param, int num) {
|
||||
w4=w4->next;
|
||||
if (w4) {
|
||||
s4=word_string(w4);
|
||||
outstring+=QString().sprintf(op->hyperlink_begin);
|
||||
outstring+=QString().sprintf("%s", op->hyperlink_begin);
|
||||
outstring+=QString().sprintf("%s", s4);
|
||||
outstring+=QString().sprintf(op->hyperlink_end);
|
||||
outstring+=QString().sprintf("%s", op->hyperlink_end);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1423,7 +1423,7 @@ cmd_tab (Word *w, int align, char has_param, int param)
|
||||
int need= 8-(total_chars_this_line%8);
|
||||
total_chars_this_line += need;
|
||||
while(need>0) {
|
||||
outstring+=QString().sprintf(op->forced_space);
|
||||
outstring+=QString().sprintf("%s", op->forced_space);
|
||||
need--;
|
||||
}
|
||||
outstring+=QString().sprintf("\n");
|
||||
@@ -1643,7 +1643,7 @@ cmd_scaps (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_bullet (Word *w, int align, char has_param, int param) {
|
||||
if (op->chars.bullet) {
|
||||
outstring+=QString().sprintf(op->chars.bullet);
|
||||
outstring+=QString().sprintf("%s", op->chars.bullet);
|
||||
++total_chars_this_line; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1658,7 +1658,7 @@ cmd_bullet (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_ldblquote (Word *w, int align, char has_param, int param) {
|
||||
if (op->chars.left_dbl_quote) {
|
||||
outstring+=QString().sprintf(op->chars.left_dbl_quote);
|
||||
outstring+=QString().sprintf("%s", op->chars.left_dbl_quote);
|
||||
++total_chars_this_line; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1675,7 +1675,7 @@ cmd_ldblquote (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_rdblquote (Word *w, int align, char has_param, int param) {
|
||||
if (op->chars.right_dbl_quote) {
|
||||
outstring+=QString().sprintf(op->chars.right_dbl_quote);
|
||||
outstring+=QString().sprintf("%s", op->chars.right_dbl_quote);
|
||||
++total_chars_this_line; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1691,7 +1691,7 @@ cmd_rdblquote (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_lquote (Word *w, int align, char has_param, int param) {
|
||||
if (op->chars.left_quote) {
|
||||
outstring+=QString().sprintf(op->chars.left_quote);
|
||||
outstring+=QString().sprintf("%s", op->chars.left_quote);
|
||||
++total_chars_this_line; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1708,7 +1708,7 @@ cmd_lquote (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_nonbreaking_space (Word *w, int align, char has_param, int param) {
|
||||
if (op->chars.nonbreaking_space) {
|
||||
outstring+=QString().sprintf(op->chars.nonbreaking_space);
|
||||
outstring+=QString().sprintf("%s", op->chars.nonbreaking_space);
|
||||
++total_chars_this_line; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1725,7 +1725,7 @@ cmd_nonbreaking_space (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_nonbreaking_hyphen (Word *w, int align, char has_param, int param) {
|
||||
if (op->chars.nonbreaking_hyphen) {
|
||||
outstring+=QString().sprintf(op->chars.nonbreaking_hyphen);
|
||||
outstring+=QString().sprintf("%s", op->chars.nonbreaking_hyphen);
|
||||
++total_chars_this_line; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1742,7 +1742,7 @@ cmd_nonbreaking_hyphen (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_optional_hyphen (Word *w, int align, char has_param, int param) {
|
||||
if (op->chars.optional_hyphen) {
|
||||
outstring+=QString().sprintf(op->chars.optional_hyphen);
|
||||
outstring+=QString().sprintf("%s", op->chars.optional_hyphen);
|
||||
++total_chars_this_line; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1758,7 +1758,7 @@ cmd_optional_hyphen (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_emdash (Word *w, int align, char has_param, int param) {
|
||||
if (op->chars.emdash) {
|
||||
outstring+=QString().sprintf(op->chars.emdash);
|
||||
outstring+=QString().sprintf("%s", op->chars.emdash);
|
||||
++total_chars_this_line; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1775,7 +1775,7 @@ cmd_emdash (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_endash (Word *w, int align, char has_param, int param) {
|
||||
if (op->chars.endash) {
|
||||
outstring+=QString().sprintf(op->chars.endash);
|
||||
outstring+=QString().sprintf("%s", op->chars.endash);
|
||||
++total_chars_this_line; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1792,7 +1792,7 @@ cmd_endash (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_rquote (Word *w, int align, char has_param, int param) {
|
||||
if (op->chars.right_quote) {
|
||||
outstring+=QString().sprintf(op->chars.right_quote);
|
||||
outstring+=QString().sprintf("%s", op->chars.right_quote);
|
||||
++total_chars_this_line; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1808,7 +1808,7 @@ cmd_rquote (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_par (Word *w, int align, char has_param, int param) {
|
||||
if (op->line_break) {
|
||||
outstring+=QString().sprintf(op->line_break);
|
||||
outstring+=QString().sprintf("%s", op->line_break);
|
||||
total_chars_this_line = 0; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1825,7 +1825,7 @@ cmd_par (Word *w, int align, char has_param, int param) {
|
||||
static int
|
||||
cmd_line (Word *w, int align, char has_param, int param) {
|
||||
if (op->line_break) {
|
||||
outstring+=QString().sprintf(op->line_break);
|
||||
outstring+=QString().sprintf("%s", op->line_break);
|
||||
total_chars_this_line = 0; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1841,7 +1841,7 @@ cmd_line (Word *w, int align, char has_param, int param) {
|
||||
|
||||
static int cmd_page (Word *w, int align, char has_param, int param) {
|
||||
if (op->page_break) {
|
||||
outstring+=QString().sprintf(op->page_break);
|
||||
outstring+=QString().sprintf("%s", op->page_break);
|
||||
total_chars_this_line = 0; /* \tab */
|
||||
}
|
||||
return FALSE;
|
||||
@@ -2337,7 +2337,7 @@ static int cmd_s (Word *w, int align, char has_param, int param) {
|
||||
static int cmd_sect (Word *w, int align, char has_param, int param) {
|
||||
/* XX kludge */
|
||||
if (op->paragraph_begin) {
|
||||
outstring+=QString().sprintf(op->paragraph_begin);
|
||||
outstring+=QString().sprintf("%s", op->paragraph_begin);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -2351,9 +2351,9 @@ static int cmd_sect (Word *w, int align, char has_param, int param) {
|
||||
|
||||
static int cmd_shp (Word *w, int align, char has_param, int param) {
|
||||
if (op->comment_begin) {
|
||||
outstring+=QString().sprintf(op->comment_begin);
|
||||
outstring+=QString().sprintf("%s", op->comment_begin);
|
||||
outstring+=QString().sprintf("Drawn Shape (ignored--not implemented yet)");
|
||||
outstring+=QString().sprintf(op->comment_end); /* daved 0.20.2 */
|
||||
outstring+=QString().sprintf("%s", op->comment_end); /* daved 0.20.2 */
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -2404,17 +2404,17 @@ static int cmd_ansicpg (Word *w, int align, char has_param, int param) {
|
||||
charset_codepage = &codepages[i];
|
||||
if (charset_codepage->cp == param) {
|
||||
if (op->comment_begin) {
|
||||
outstring+=QString().sprintf(op->comment_begin);
|
||||
outstring+=QString().sprintf("%s", op->comment_begin);
|
||||
outstring+=QString().sprintf("document uses ANSI codepage %d character set", param);
|
||||
outstring+=QString().sprintf(op->comment_end);
|
||||
outstring+=QString().sprintf("%s", op->comment_end);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((charset_codepage == NULL || charset_codepage->cp == 0) && op->comment_begin) {
|
||||
outstring+=QString().sprintf(op->comment_begin);
|
||||
outstring+=QString().sprintf("%s", op->comment_begin);
|
||||
outstring+=QString().sprintf("document uses default ANSI codepage character set");
|
||||
outstring+=QString().sprintf(op->comment_end);
|
||||
outstring+=QString().sprintf("%s", op->comment_end);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -3106,7 +3106,7 @@ enum { SMALL=0, BIG=1 };
|
||||
if (simulate_smallcaps) {
|
||||
if (*s >= 'a' && *s <= 'z') {
|
||||
state=SMALL;
|
||||
outstring+=QString().sprintf(op->smaller_begin);
|
||||
outstring+=QString().sprintf("%s", op->smaller_begin);
|
||||
}
|
||||
else
|
||||
state=BIG;
|
||||
@@ -3136,13 +3136,13 @@ enum { SMALL=0, BIG=1 };
|
||||
ch = *s;
|
||||
if (ch >= 'a' && ch <= 'z') {
|
||||
if (state==BIG)
|
||||
outstring+=QString().sprintf(op->smaller_begin);
|
||||
outstring+=QString().sprintf("%s", op->smaller_begin);
|
||||
state=SMALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state==SMALL)
|
||||
outstring+=QString().sprintf(op->smaller_end);
|
||||
outstring+=QString().sprintf("%s", op->smaller_end);
|
||||
state=BIG;
|
||||
}
|
||||
}
|
||||
@@ -3168,7 +3168,7 @@ begin_table()
|
||||
have_printed_cell_end = FALSE;
|
||||
attrstack_push();
|
||||
starting_body();
|
||||
outstring+=QString().sprintf(op->table_begin);
|
||||
outstring+=QString().sprintf("%s", op->table_begin);
|
||||
}
|
||||
|
||||
|
||||
@@ -3186,12 +3186,12 @@ end_table ()
|
||||
if (within_table) {
|
||||
if (!have_printed_cell_end) {
|
||||
attr_pop_dump();
|
||||
outstring+=QString().sprintf(op->table_cell_end);
|
||||
outstring+=QString().sprintf("%s", op->table_cell_end);
|
||||
}
|
||||
if (!have_printed_row_end) {
|
||||
outstring+=QString().sprintf(op->table_row_end);
|
||||
outstring+=QString().sprintf("%s", op->table_row_end);
|
||||
}
|
||||
outstring+=QString().sprintf(op->table_end);
|
||||
outstring+=QString().sprintf("%s", op->table_end);
|
||||
within_table=FALSE;
|
||||
have_printed_row_begin = FALSE;
|
||||
have_printed_cell_begin = FALSE;
|
||||
@@ -3213,13 +3213,13 @@ void
|
||||
starting_text() {
|
||||
if (within_table) {
|
||||
if (!have_printed_row_begin) {
|
||||
outstring+=QString().sprintf(op->table_row_begin);
|
||||
outstring+=QString().sprintf("%s", op->table_row_begin);
|
||||
have_printed_row_begin=TRUE;
|
||||
have_printed_row_end=FALSE;
|
||||
have_printed_cell_begin=FALSE;
|
||||
}
|
||||
if (!have_printed_cell_begin) {
|
||||
outstring+=QString().sprintf(op->table_cell_begin);
|
||||
outstring+=QString().sprintf("%s", op->table_cell_begin);
|
||||
attrstack_express_all();
|
||||
have_printed_cell_begin=TRUE;
|
||||
have_printed_cell_end=FALSE;
|
||||
@@ -3246,15 +3246,15 @@ starting_paragraph_align (int align)
|
||||
switch (align)
|
||||
{
|
||||
case ALIGN_CENTER:
|
||||
outstring+=QString().sprintf(op->center_begin);
|
||||
outstring+=QString().sprintf("%s", op->center_begin);
|
||||
break;
|
||||
case ALIGN_LEFT:
|
||||
break;
|
||||
case ALIGN_RIGHT:
|
||||
outstring+=QString().sprintf(op->align_right_begin);
|
||||
outstring+=QString().sprintf("%s", op->align_right_begin);
|
||||
break;
|
||||
case ALIGN_JUSTIFY:
|
||||
outstring+=QString().sprintf(op->align_right_begin); /* This is WRONG! */
|
||||
outstring+=QString().sprintf("%s", op->align_right_begin); /* This is WRONG! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3273,16 +3273,16 @@ ending_paragraph_align (int align)
|
||||
{
|
||||
switch (align) {
|
||||
case ALIGN_CENTER:
|
||||
outstring+=QString().sprintf(op->center_end);
|
||||
outstring+=QString().sprintf("%s", op->center_end);
|
||||
break;
|
||||
case ALIGN_LEFT:
|
||||
/* outstring+=QString().sprintf(op->align_left_end); */
|
||||
/* outstring+=QString().sprintf("%s", op->align_left_end); */
|
||||
break;
|
||||
case ALIGN_RIGHT:
|
||||
outstring+=QString().sprintf(op->align_right_end);
|
||||
outstring+=QString().sprintf("%s", op->align_right_end);
|
||||
break;
|
||||
case ALIGN_JUSTIFY:
|
||||
outstring+=QString().sprintf(op->justify_end);
|
||||
outstring+=QString().sprintf("%s", op->justify_end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3391,12 +3391,12 @@ word_print_core (Word *w)
|
||||
total_chars_this_line += strlen(s);
|
||||
|
||||
if (op->word_begin)
|
||||
outstring+=QString().sprintf(op->word_begin);
|
||||
outstring+=QString().sprintf("%s", op->word_begin);
|
||||
|
||||
print_with_special_exprs (s);
|
||||
|
||||
if (op->word_end)
|
||||
outstring+=QString().sprintf(op->word_end);
|
||||
outstring+=QString().sprintf("%s", op->word_end);
|
||||
}
|
||||
|
||||
|
||||
@@ -3456,17 +3456,17 @@ word_print_core (Word *w)
|
||||
is_cell_group=TRUE;
|
||||
if (!have_printed_cell_begin) {
|
||||
/* Need this with empty cells */
|
||||
outstring+=QString().sprintf(op->table_cell_begin);
|
||||
outstring+=QString().sprintf("%s", op->table_cell_begin);
|
||||
attrstack_express_all();
|
||||
}
|
||||
attr_pop_dump();
|
||||
outstring+=QString().sprintf(op->table_cell_end);
|
||||
outstring+=QString().sprintf("%s", op->table_cell_end);
|
||||
have_printed_cell_begin = FALSE;
|
||||
have_printed_cell_end=TRUE;
|
||||
}
|
||||
else if (!strcmp (s, "row")) {
|
||||
if (within_table) {
|
||||
outstring+=QString().sprintf(op->table_row_end);
|
||||
outstring+=QString().sprintf("%s", op->table_row_end);
|
||||
have_printed_row_begin = FALSE;
|
||||
have_printed_row_end=TRUE;
|
||||
} else {
|
||||
@@ -3496,10 +3496,10 @@ word_print_core (Word *w)
|
||||
outstring+=QString().sprintf("%s",op->comment_end);
|
||||
} else {
|
||||
if (op->word_begin)
|
||||
outstring+=QString().sprintf(op->word_begin);
|
||||
outstring+=QString().sprintf("%s", op->word_begin);
|
||||
outstring+=QString().sprintf("%s", s2);
|
||||
if (op->word_end)
|
||||
outstring+=QString().sprintf(op->word_end);
|
||||
outstring+=QString().sprintf("%s", op->word_end);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3529,9 +3529,9 @@ word_print_core (Word *w)
|
||||
|
||||
if (!hip) {
|
||||
if (debug_mode) {
|
||||
outstring+=QString().sprintf(op->comment_begin);
|
||||
outstring+=QString().sprintf("%s", op->comment_begin);
|
||||
outstring+=QString().sprintf("Unfamiliar RTF command: %s (HashIndex not found)", s);
|
||||
outstring+=QString().sprintf(op->comment_end); /* daved 0.20.2 */
|
||||
outstring+=QString().sprintf("%s", op->comment_end); /* daved 0.20.2 */
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -3610,9 +3610,9 @@ word_print_core (Word *w)
|
||||
if (within_picture) {
|
||||
if(pictfile) {
|
||||
fclose(pictfile);
|
||||
outstring+=QString().sprintf(op->imagelink_begin);
|
||||
outstring+=QString().sprintf("%s", op->imagelink_begin);
|
||||
outstring+=QString().sprintf("%s", picture_path);
|
||||
outstring+=QString().sprintf(op->imagelink_end);
|
||||
outstring+=QString().sprintf("%s", op->imagelink_end);
|
||||
}
|
||||
within_picture=FALSE;
|
||||
}
|
||||
@@ -3665,8 +3665,8 @@ word_print (Word *w, QString & _s)
|
||||
|
||||
outstring = "";
|
||||
if (!inline_mode) {
|
||||
outstring+=QString().sprintf(op->document_begin);
|
||||
outstring+=QString().sprintf(op->header_begin);
|
||||
outstring+=QString().sprintf("%s", op->document_begin);
|
||||
outstring+=QString().sprintf("%s", op->header_begin);
|
||||
}
|
||||
|
||||
within_header=TRUE;
|
||||
@@ -3677,8 +3677,8 @@ word_print (Word *w, QString & _s)
|
||||
end_table();
|
||||
|
||||
if (!inline_mode) {
|
||||
outstring+=QString().sprintf(op->body_end);
|
||||
outstring+=QString().sprintf(op->document_end);
|
||||
outstring+=QString().sprintf("%s", op->body_end);
|
||||
outstring+=QString().sprintf("%s", op->document_end);
|
||||
}
|
||||
_s = outstring;
|
||||
}
|
||||
|
||||
@@ -238,49 +238,49 @@ op_begin_std_fontsize (OutputPersonality *op, int size)
|
||||
switch (size) {
|
||||
case 8:
|
||||
if (op->fontsize8_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize8_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize8_begin);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (op->fontsize10_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize10_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize10_begin);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
if (op->fontsize12_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize12_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize12_begin);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
if (op->fontsize14_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize14_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize14_begin);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
if (op->fontsize18_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize18_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize18_begin);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
if (op->fontsize24_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize24_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize24_begin);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 36:
|
||||
if (op->fontsize36_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize36_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize36_begin);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 48:
|
||||
if (op->fontsize48_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize48_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize48_begin);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
@@ -300,46 +300,46 @@ op_begin_std_fontsize (OutputPersonality *op, int size)
|
||||
* size.
|
||||
*/
|
||||
if (size<9 && op->fontsize8_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize8_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize8_begin);
|
||||
} else
|
||||
if (size<11 && op->fontsize10_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize10_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize10_begin);
|
||||
} else
|
||||
if (size<13 && op->fontsize12_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize12_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize12_begin);
|
||||
} else
|
||||
if (size<16 && op->fontsize14_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize14_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize14_begin);
|
||||
} else
|
||||
if (size<21 && op->fontsize18_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize18_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize18_begin);
|
||||
} else
|
||||
if (size<30 && op->fontsize24_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize24_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize24_begin);
|
||||
} else
|
||||
if (size<42 && op->fontsize36_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize36_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize36_begin);
|
||||
} else
|
||||
if (size>40 && op->fontsize48_begin) {
|
||||
outstring+=QString().sprintf(op->fontsize48_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize48_begin);
|
||||
} else
|
||||
/* If we can't even produce a good approximation,
|
||||
* just try to get a font size near 12 point.
|
||||
*/
|
||||
if (op->fontsize12_begin)
|
||||
outstring+=QString().sprintf(op->fontsize12_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize12_begin);
|
||||
else
|
||||
if (op->fontsize14_begin)
|
||||
outstring+=QString().sprintf(op->fontsize14_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize14_begin);
|
||||
else
|
||||
if (op->fontsize10_begin)
|
||||
outstring+=QString().sprintf(op->fontsize10_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize10_begin);
|
||||
else
|
||||
if (op->fontsize18_begin)
|
||||
outstring+=QString().sprintf(op->fontsize18_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize18_begin);
|
||||
else
|
||||
if (op->fontsize8_begin)
|
||||
outstring+=QString().sprintf(op->fontsize8_begin);
|
||||
outstring+=QString().sprintf("%s", op->fontsize8_begin);
|
||||
else
|
||||
error_handler ("output personality lacks sufficient font size change capability");
|
||||
}
|
||||
@@ -367,49 +367,49 @@ op_end_std_fontsize (OutputPersonality *op, int size)
|
||||
switch (size) {
|
||||
case 8:
|
||||
if (op->fontsize8_end) {
|
||||
outstring+=QString().sprintf(op->fontsize8_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize8_end);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (op->fontsize10_end) {
|
||||
outstring+=QString().sprintf(op->fontsize10_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize10_end);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
if (op->fontsize12_end) {
|
||||
outstring+=QString().sprintf(op->fontsize12_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize12_end);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
if (op->fontsize14_end) {
|
||||
outstring+=QString().sprintf(op->fontsize14_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize14_end);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
if (op->fontsize18_end) {
|
||||
outstring+=QString().sprintf(op->fontsize18_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize18_end);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
if (op->fontsize24_end) {
|
||||
outstring+=QString().sprintf(op->fontsize24_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize24_end);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 36:
|
||||
if (op->fontsize36_end) {
|
||||
outstring+=QString().sprintf(op->fontsize36_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize36_end);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
case 48:
|
||||
if (op->fontsize48_end) {
|
||||
outstring+=QString().sprintf(op->fontsize48_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize48_end);
|
||||
found_std_expr = TRUE;
|
||||
}
|
||||
break;
|
||||
@@ -429,46 +429,46 @@ op_end_std_fontsize (OutputPersonality *op, int size)
|
||||
* size.
|
||||
*/
|
||||
if (size<9 && op->fontsize8_end) {
|
||||
outstring+=QString().sprintf(op->fontsize8_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize8_end);
|
||||
} else
|
||||
if (size<11 && op->fontsize10_end) {
|
||||
outstring+=QString().sprintf(op->fontsize10_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize10_end);
|
||||
} else
|
||||
if (size<13 && op->fontsize12_end) {
|
||||
outstring+=QString().sprintf(op->fontsize12_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize12_end);
|
||||
} else
|
||||
if (size<16 && op->fontsize14_end) {
|
||||
outstring+=QString().sprintf(op->fontsize14_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize14_end);
|
||||
} else
|
||||
if (size<21 && op->fontsize18_end) {
|
||||
outstring+=QString().sprintf(op->fontsize18_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize18_end);
|
||||
} else
|
||||
if (size<30 && op->fontsize24_end) {
|
||||
outstring+=QString().sprintf(op->fontsize24_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize24_end);
|
||||
} else
|
||||
if (size<42 && op->fontsize36_end) {
|
||||
outstring+=QString().sprintf(op->fontsize36_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize36_end);
|
||||
} else
|
||||
if (size>40 && op->fontsize48_end) {
|
||||
outstring+=QString().sprintf(op->fontsize48_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize48_end);
|
||||
} else
|
||||
/* If we can't even produce a good approximation,
|
||||
* just try to get a font size near 12 point.
|
||||
*/
|
||||
if (op->fontsize12_end)
|
||||
outstring+=QString().sprintf(op->fontsize12_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize12_end);
|
||||
else
|
||||
if (op->fontsize14_end)
|
||||
outstring+=QString().sprintf(op->fontsize14_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize14_end);
|
||||
else
|
||||
if (op->fontsize10_end)
|
||||
outstring+=QString().sprintf(op->fontsize10_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize10_end);
|
||||
else
|
||||
if (op->fontsize18_end)
|
||||
outstring+=QString().sprintf(op->fontsize18_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize18_end);
|
||||
else
|
||||
if (op->fontsize8_end)
|
||||
outstring+=QString().sprintf(op->fontsize8_end);
|
||||
outstring+=QString().sprintf("%s", op->fontsize8_end);
|
||||
else
|
||||
error_handler ("output personality lacks sufficient font size change capability");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* kicker.cpp - bassdrum-synthesizer
|
||||
*
|
||||
* Copyright (c) 2006-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "note_play_handle.h"
|
||||
#include "sweep_oscillator.h"
|
||||
|
||||
#undef SINGLE_SOURCE_COMPILE
|
||||
#include "embed.cpp"
|
||||
|
||||
|
||||
|
||||
@@ -37,13 +37,10 @@
|
||||
#include "tab_bar.h"
|
||||
#include "tab_button.h"
|
||||
|
||||
|
||||
#undef SINGLE_SOURCE_COMPILE
|
||||
#include "embed.cpp"
|
||||
|
||||
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@ IF(WANT_CMT)
|
||||
ADD_SUBDIRECTORY(cmt)
|
||||
ENDIF(WANT_CMT)
|
||||
|
||||
IF(WANT_CALF)
|
||||
ADD_SUBDIRECTORY(calf)
|
||||
ENDIF(WANT_CALF)
|
||||
|
||||
|
||||
INCLUDE(BuildPlugin)
|
||||
|
||||
|
||||
9
plugins/ladspa_effect/calf/AUTHORS
Normal file
@@ -0,0 +1,9 @@
|
||||
Krzysztof Foltman <wdev@foltman.com>
|
||||
Hermann Meyer <brummer-@web.de>
|
||||
Thor Harald Johansen <thj@thj.no>
|
||||
Thorsten Wilms <t_w_@freenet.de>
|
||||
Hans Baier <hansfbaier@googlemail.com>
|
||||
Torben Hohn <torbenh@gmx.de>
|
||||
|
||||
Additional bugfixes/enhancement patches:
|
||||
David Täht <d@teklibre.com>
|
||||
15
plugins/ladspa_effect/calf/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
FILE(GLOB SOURCES *.cpp)
|
||||
ADD_LIBRARY(calf MODULE ${SOURCES})
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/calf)
|
||||
INSTALL(TARGETS calf LIBRARY DESTINATION ${PLUGIN_DIR}/ladspa)
|
||||
ADD_DEFINITIONS(-DUSE_LADSPA=1)
|
||||
SET_TARGET_PROPERTIES(calf PROPERTIES PREFIX "")
|
||||
SET_TARGET_PROPERTIES(calf PROPERTIES COMPILE_FLAGS "-O2 -finline-limit=80 -funroll-loops")
|
||||
|
||||
IF(LMMS_BUILD_WIN32)
|
||||
ADD_CUSTOM_COMMAND(TARGET calf POST_BUILD COMMAND ${STRIP} ${CMAKE_CURRENT_BINARY_DIR}/calf.dll)
|
||||
ENDIF(LMMS_BUILD_WIN32)
|
||||
IF(NOT LMMS_BUILD_APPLE)
|
||||
SET_TARGET_PROPERTIES(calf PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined")
|
||||
ENDIF(NOT LMMS_BUILD_APPLE)
|
||||
|
||||
504
plugins/ladspa_effect/calf/COPYING
Normal file
@@ -0,0 +1,504 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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 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
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
340
plugins/ladspa_effect/calf/COPYING.GPL
Normal file
@@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
170
plugins/ladspa_effect/calf/ChangeLog
Normal file
@@ -0,0 +1,170 @@
|
||||
Version 0.0.18.2
|
||||
|
||||
+ Organ: fix voice stealing of released notes, sort out GUI, add quadratic
|
||||
mode for amplitude envelope (enabled by default) - sounds more natural
|
||||
+ Monosynth: fix the bug that caused JACK to kick the client out due
|
||||
to precalculating waves in a completely wrong place, fix portamento
|
||||
for off-stack notes
|
||||
+ Presets: 3 new presets for Organ, 4 for Monosynth, 2 for Reverb
|
||||
|
||||
Version 0.0.18.1
|
||||
|
||||
+ Filter: fixed subtle redraw bugs
|
||||
+ Icons: fixed packaging-incompatible paths
|
||||
|
||||
Version 0.0.18
|
||||
|
||||
+ Filterclavier: new plugin (a MIDI controlled filter) by Hans Baier
|
||||
+ DSSI: added a basic implementation of live graphs. The graphs have a
|
||||
limited resolution (128 data points), and are rather inefficient
|
||||
(as the graph data need to be transmitted via OSC to a different
|
||||
process), but it's better than nothing
|
||||
+ GUI: Torben Hohn's drawing optimizations (critical for Intel graphics
|
||||
cards, but should also reduce CPU usage on other hardware)
|
||||
+ Phaser: added frequency response graph
|
||||
+ JACK host: discontinue the broken option -p; allow giving preset names
|
||||
after a colon sign (reverb:DiscoVerb instead of -p DiscoVerb reverb)
|
||||
+ Reverb: less modulation; tone controls; 2 more room types
|
||||
+ MultiChorus: add double bandpass filter on input
|
||||
+ GUI: added frequency grid
|
||||
+ Organ: added progress reporting on load (works with JACK host and LV2)
|
||||
+ JACK host: use sensible port names (possibly breaking new LASH sessions)
|
||||
+ Organ: added polyphony limit
|
||||
+ Small plugins: added support for polymorphic port extension to allow
|
||||
the same plugins to be used for control and audio signals
|
||||
+ DSSI: renamed all the plugins from "plugin LADSPA" to "plugin DSSI"
|
||||
+ LADSPA: more reasonable default value hints, fixed locale issue in LRDF
|
||||
+ JACK host: added icons by Thorsten Wilms (thanks!)
|
||||
+ Organ, Monosynth: better memory usage
|
||||
+ LV2: attempt at supporting configure-like parameters (key mapping curve
|
||||
in Organ) by the new String Port extension
|
||||
+ AutoHell: header files are not installed anymore (they are of little
|
||||
use anyway)
|
||||
+ AutoHell: configure script prints if --enable-experimental was specified
|
||||
|
||||
Version 0.0.17
|
||||
|
||||
+ Compressor: new plugin by Thor Harald Johansen
|
||||
+ GUI: control improvements (new LED control, improved VU meter, XML
|
||||
improvements, line graph with dots and grid lines - no legend yet), move
|
||||
autolayout code from the plugin libraries to makerdf executable,
|
||||
+ Most plugins: use custom GUI layouts instead of autogenerated ones
|
||||
+ Most plugins: add dry amount (for aux bus type uses)
|
||||
+ Flanger, Filter, MultiChorus: added live graphs displaying frequency
|
||||
response and (in case of MultiChorus) LFO positions
|
||||
+ LV2 GUI: added a way to display live graphs in Ardour and Zynjacku/LV2Rack
|
||||
(only works when the plugin and the GUI are in the same process)
|
||||
+ Framework: general improvements/cleanups to reduce the chance of the
|
||||
kind of errors that were introduced in 0.0.16 and reduce dependencies
|
||||
+ Monosynth: removed soft clipper on output
|
||||
|
||||
Version 0.0.16.3
|
||||
|
||||
+ Fixed compilation without LV2 core installed
|
||||
|
||||
Version 0.0.16.2
|
||||
|
||||
+ Fixed DSSI GUI for MultiChorus
|
||||
+ Fixed LV2 GUI for MultiChorus
|
||||
+ Make knob control mouse wheel handling work better in Ingen
|
||||
|
||||
Version 0.0.16
|
||||
|
||||
+ New MultiChorus plugin (stereo multitap chorus with maximum of 8 voices)
|
||||
+ Experimental set of plugins for modular synthesizers like Ingen by
|
||||
Dave Robillard (enabled using --enable-experimental option in configure
|
||||
script)
|
||||
+ Minor improvements to other plugins (like Rotary Speaker)
|
||||
+ More work on API documentation
|
||||
|
||||
Version 0.0.15
|
||||
|
||||
+ Organ: new percussive section, using 2-operator FM synthesis for
|
||||
monophonic or polyphonic percussive attack; added global transpose and
|
||||
detune; rearrangement of controls between sections
|
||||
+ Rotary Speaker: another attempt at making it useful (thanks FishB8)
|
||||
+ JACK host: eliminate deadlock on exit
|
||||
+ GUI: bipolar knobs now have a "dead zone" (magnet) in the middle point
|
||||
+ GUI: dragging a knob with SHIFT held allows for fine adjustments
|
||||
+ GUI: new controls - curve editor and keyboard
|
||||
+ LV2: improved extension support (supports my "extended port properties"
|
||||
extension now)
|
||||
+ Added some API documentation
|
||||
|
||||
Version 0.0.14
|
||||
+ OSC: totally new OSC wrapper, to allow for realtime-safe parsing (doesn't
|
||||
matter as far as functionality goes, will probably be rewritten again
|
||||
anyway)
|
||||
+ Everything: memory management fixes (should improve stability and
|
||||
compatibility)
|
||||
+ Organ: improved memory usage
|
||||
+ GUI: improved bipolar knobs, added endless knobs
|
||||
+ Presets: separate 'built-in' and 'user' presets (so that built-in presets
|
||||
can be upgraded without affecting user's own presets)
|
||||
+ Monosynth: new presets
|
||||
|
||||
Version 0.0.13
|
||||
+ Fixed several problems related to 64-bit environments and OpenSUSE (thanks
|
||||
oc2pus!)
|
||||
+ Added NOCONFIGURE environment variable support to autogen.sh
|
||||
|
||||
Version 0.0.12
|
||||
+ RotarySpeaker: work in progress; enabled by default just in case it's
|
||||
useful for anyone
|
||||
+ Organ: reworked to add a complete subtractive synth section, a selection
|
||||
of waveform (settable on a per-drawbar basis), individual settings of
|
||||
phase, detune, panning, routing for each drawbar, as well as improved(?)
|
||||
percussive section and vibrato/phaser section. It is usable (and sounds
|
||||
good!), but some parameters, waveform set etc. may change in future. May
|
||||
take up to 100 MB of RAM due to pre-calculated bandlimited waveforms.
|
||||
+ Added half-complete implementation of LV2 (including GUI and events).
|
||||
+ Lots of small "polishing" kind of fixes in many places (like proper
|
||||
rounding of values in the GUIs, another set of hold/sostenuto fixes etc)
|
||||
|
||||
Version 0.0.11
|
||||
|
||||
+ Fixed x86-64 bugs
|
||||
+ JackHost: implemented LASH support
|
||||
+ RotarySpeaker: fixed panning bug, implemented acceleration/decceleration
|
||||
for "off" state
|
||||
|
||||
Version 0.0.10
|
||||
|
||||
+ First attempt at DSSI GUI, does not support some features from JACK host,
|
||||
but that's inevitable because of API limitations
|
||||
+ Reverb: improvements (more parameters, fixed denormals)
|
||||
+ Knob: added custom support for scroll wheel (instead of one inherited from
|
||||
GtkRange)
|
||||
|
||||
Version 0.0.9
|
||||
|
||||
+ started creating an XML-based GUI
|
||||
+ LineGraph: new GTK+ control for displaying waveforms and filter response
|
||||
graphs in Monosynth (and maybe others in future)
|
||||
+ Monosynth: notch filter changes (made notch bandwidth proportional to Q,
|
||||
just for fun, might be a bad idea)
|
||||
+ Monosynth: more waveforms (these might be final?)
|
||||
+ Monosynth: capped Sustain level to 0.999 so that decay time actually means
|
||||
something with Sustain = 100% (not a great way to do it, but acceptable in
|
||||
this case)
|
||||
+ Monosynth: GUI refreshes less often (which means less CPU use)
|
||||
+ Monosynth: less clicks on sounds using LP filter with very low cutoff
|
||||
(using ramp of 256 samples instead of 64 samples as before)
|
||||
+ Knob: new GTK+ control based on GtkRange, with my primitive bitmap set
|
||||
(generated with Python and Cairo)
|
||||
+ Organ: added a GUI too, very provisional
|
||||
+ Organ: fixed Hold pedal (doesn't release the notes which are still depressed)
|
||||
+ RotarySpeaker: new effect (split off Organ)
|
||||
+ all: denormal fixes (still some denormals present in reverb)
|
||||
+ Reverb: better time setting (decay time somewhat corresponds to -60dB
|
||||
attenuation time)
|
||||
+ JackHost: -M switch allows for automatic connection to JACK MIDI event source
|
||||
(use -M system:midi_capture_2 or -M 2 for autoconnection to
|
||||
system:midi_capture_2; of course, the short numeric form only work for
|
||||
system:midi_capture_ ports)
|
||||
+ JackHost: -p switch selects a preset automatically
|
||||
+ JackHost: better size setting algorithm
|
||||
+ JackHost: duplicate client name (causing JACK to rename the client) doesn't
|
||||
break autoconnecting functionality
|
||||
+ autotools configuration update (detect Cairo and require newer GTK+)
|
||||
+ more presets
|
||||
254
plugins/ladspa_effect/calf/INSTALL
Normal file
@@ -0,0 +1,254 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright (C) 2007-2008 Krzysztof Foltman
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
|
||||
To compile and install Calf, you need:
|
||||
|
||||
- POSIX-compliant operating system
|
||||
- G++ version 4.0 or higher (tested with 4.1.3)
|
||||
- GTK+2 headers and libraries (glib 2.10, gtk+ 2.12)
|
||||
- Cairo headers and libraries
|
||||
- Glade 2 headers and libraries
|
||||
|
||||
Optional but recommended:
|
||||
- JACK header and libraries (tested with 0.109.0)
|
||||
- LADSPA header
|
||||
- DSSI header
|
||||
- LV2 core
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' if you want to change it or regenerate `configure' using
|
||||
a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not support the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a
|
||||
time in the source code directory. After you have installed the
|
||||
package for one architecture, use `make distclean' before reconfiguring
|
||||
for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script). Here is a another example:
|
||||
|
||||
/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
|
||||
configuration-related scripts to be executed by `/bin/bash'.
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
0
plugins/ladspa_effect/calf/NEWS
Normal file
49
plugins/ladspa_effect/calf/README
Normal file
@@ -0,0 +1,49 @@
|
||||
Calf is a pack of audio plugins - effects and instruments, currently in
|
||||
development. The goal is to create a set of plugins using decent algorithms
|
||||
and parameter settings, available in a form which is compatible with as many
|
||||
open source applications as possible.
|
||||
|
||||
How to use Calf plugins:
|
||||
|
||||
* LADSPA plugins
|
||||
|
||||
Calf is installed as calf.so library in your LADSPA directory (typically
|
||||
/usr/lib/ladspa). It means that typical LADSPA host should be able to find
|
||||
Calf's plugins.
|
||||
|
||||
* DSSI plugins
|
||||
|
||||
Calf .so module is also installed in your DSSI plugin directory, which means
|
||||
your DSSI host (like jack-dssi-host or rosegarden) should find it and
|
||||
include its plugins in the plugin list.
|
||||
|
||||
* JACK client application
|
||||
|
||||
You can also use Calf plugins as separate applications, connecting to other
|
||||
applications using JACK Audio Connection Kit (version 0.103 or newer is
|
||||
required). To run the client, type:
|
||||
|
||||
calfjackhost monosynth !
|
||||
|
||||
(! means "connect", last "!" means "connect to output")
|
||||
|
||||
Other examples:
|
||||
|
||||
calfjackhost monosynth ! vintagedelay ! flanger !
|
||||
|
||||
(runs monosynth into vintagedelay and vintagedelay into flanger, then to
|
||||
output)
|
||||
|
||||
calfjackhost ! reverb !
|
||||
|
||||
(takes signal from system:capture_1 and _2, puts it through reverb, and then
|
||||
sends to system:playback_1 and _2)
|
||||
|
||||
You can also change client name or input/output port names with command-line
|
||||
options (type calfjackhost --help). Use qjackctl, patchage or jack_connect
|
||||
to connect the Calf JACK client to your sound card or other applications, if
|
||||
"!" is inadequate for any reason (if I didn't explain it properly, or if it
|
||||
doesn't provide the connectivity options needed).
|
||||
|
||||
Keep in mind this project is in the early development phase. It is usable
|
||||
for certain purposes, but drop me a note if you need something.
|
||||
40
plugins/ladspa_effect/calf/TODO
Normal file
@@ -0,0 +1,40 @@
|
||||
1. More effects
|
||||
|
||||
- auto-wah (might be integrated into filter)
|
||||
- envelope follower
|
||||
- better reverb (more features, use nested allpasses, use 1-pole
|
||||
1-zero allpass instead of fractional delays)
|
||||
- dynamics processing (Thor already did the compressor)
|
||||
- distortion?
|
||||
- windy rotary speakery stuff
|
||||
- filter: more types
|
||||
|
||||
2. Some instruments
|
||||
|
||||
- some virtual analogue thing (something larger than Monosynth)
|
||||
- FM (by reusing my MMX code, or something)
|
||||
|
||||
3. DSP library
|
||||
|
||||
- profiling framework
|
||||
- optimized code (the one I have now only pretends to be optimized :) )
|
||||
- underflow handling
|
||||
|
||||
4. Wrappers
|
||||
|
||||
- LADSPA: proper rdf (get clearance from drobilla ;) )
|
||||
- better jack host (controls etc)
|
||||
- BSE
|
||||
- buzztard
|
||||
- Linux VST
|
||||
- LV2
|
||||
Message Context (for Organ)
|
||||
EPP (the rest of them)
|
||||
Mixing Controls
|
||||
|
||||
5. Organization stuff (autotools etc)
|
||||
|
||||
- correct compilation and installation of LADSPA plugins (current version is a hack!)
|
||||
- switch to -O3
|
||||
- get to work on 64-bit architectures
|
||||
- i18n (gettext or whatever)
|
||||
790
plugins/ladspa_effect/calf/calf/audio_fx.h
Normal file
@@ -0,0 +1,790 @@
|
||||
/* Calf DSP Library
|
||||
* Reusable audio effect classes.
|
||||
*
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef __CALF_AUDIOFX_H
|
||||
#define __CALF_AUDIOFX_H
|
||||
|
||||
#include <complex>
|
||||
#include <iostream>
|
||||
#include <calf/biquad.h>
|
||||
#include <calf/onepole.h>
|
||||
#include "primitives.h"
|
||||
#include "delay.h"
|
||||
#include "fixed_point.h"
|
||||
#include "inertia.h"
|
||||
|
||||
namespace dsp {
|
||||
#if 0
|
||||
}; to keep editor happy
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Audio effect base class. Not really useful until it gets more developed.
|
||||
*/
|
||||
class audio_effect
|
||||
{
|
||||
public:
|
||||
virtual void setup(int sample_rate)=0;
|
||||
virtual ~audio_effect() {}
|
||||
};
|
||||
|
||||
class modulation_effect: public audio_effect
|
||||
{
|
||||
protected:
|
||||
int sample_rate;
|
||||
float rate, wet, dry, odsr;
|
||||
gain_smoothing gs_wet, gs_dry;
|
||||
public:
|
||||
fixed_point<unsigned int, 20> phase, dphase;
|
||||
float get_rate() {
|
||||
return rate;
|
||||
}
|
||||
void set_rate(float rate) {
|
||||
this->rate = rate;
|
||||
dphase = rate/sample_rate*4096;
|
||||
}
|
||||
float get_wet() {
|
||||
return wet;
|
||||
}
|
||||
void set_wet(float wet) {
|
||||
this->wet = wet;
|
||||
gs_wet.set_inertia(wet);
|
||||
}
|
||||
float get_dry() {
|
||||
return dry;
|
||||
}
|
||||
void set_dry(float dry) {
|
||||
this->dry = dry;
|
||||
gs_dry.set_inertia(dry);
|
||||
}
|
||||
void reset_phase(float req_phase)
|
||||
{
|
||||
phase = req_phase * 4096.0;
|
||||
}
|
||||
void inc_phase(float req_phase)
|
||||
{
|
||||
phase += fixed_point<unsigned int, 20>(req_phase * 4096.0);
|
||||
}
|
||||
void setup(int sample_rate)
|
||||
{
|
||||
this->sample_rate = sample_rate;
|
||||
this->odsr = 1.0 / sample_rate;
|
||||
phase = 0;
|
||||
set_rate(get_rate());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A monophonic phaser. If you want stereo, combine two :)
|
||||
* Also, gave up on using template args for signal type.
|
||||
*/
|
||||
template<int MaxStages>
|
||||
class simple_phaser: public modulation_effect
|
||||
{
|
||||
protected:
|
||||
float base_frq, mod_depth, fb;
|
||||
float state;
|
||||
int cnt, stages;
|
||||
dsp::onepole<float, float> stage1;
|
||||
float x1[MaxStages], y1[MaxStages];
|
||||
public:
|
||||
simple_phaser()
|
||||
{
|
||||
set_base_frq(1000);
|
||||
set_mod_depth(1000);
|
||||
set_fb(0);
|
||||
state = 0;
|
||||
cnt = 0;
|
||||
stages = 0;
|
||||
set_stages(6);
|
||||
}
|
||||
float get_base_frq() {
|
||||
return base_frq;
|
||||
}
|
||||
void set_base_frq(float _base_frq) {
|
||||
base_frq = _base_frq;
|
||||
}
|
||||
int get_stages() {
|
||||
return stages;
|
||||
}
|
||||
void set_stages(int _stages) {
|
||||
if (_stages > stages)
|
||||
{
|
||||
for (int i = stages; i < _stages; i++)
|
||||
{
|
||||
x1[i] = x1[stages-1];
|
||||
y1[i] = y1[stages-1];
|
||||
}
|
||||
}
|
||||
stages = _stages;
|
||||
}
|
||||
float get_mod_depth() {
|
||||
return mod_depth;
|
||||
}
|
||||
void set_mod_depth(float _mod_depth) {
|
||||
mod_depth = _mod_depth;
|
||||
}
|
||||
float get_fb() {
|
||||
return fb;
|
||||
}
|
||||
void set_fb(float fb) {
|
||||
this->fb = fb;
|
||||
}
|
||||
virtual void setup(int sample_rate) {
|
||||
modulation_effect::setup(sample_rate);
|
||||
reset();
|
||||
}
|
||||
void reset()
|
||||
{
|
||||
cnt = 0;
|
||||
state = 0;
|
||||
phase.set(0);
|
||||
for (int i = 0; i < MaxStages; i++)
|
||||
x1[i] = y1[i] = 0;
|
||||
control_step();
|
||||
}
|
||||
inline void control_step()
|
||||
{
|
||||
cnt = 0;
|
||||
int v = phase.get() + 0x40000000;
|
||||
int sign = v >> 31;
|
||||
v ^= sign;
|
||||
// triangle wave, range from 0 to INT_MAX
|
||||
double vf = (double)((v >> 16) * (1.0 / 16384.0) - 1);
|
||||
|
||||
float freq = base_frq * pow(2.0, vf * mod_depth / 1200.0);
|
||||
freq = dsp::clip<float>(freq, 10.0, 0.49 * sample_rate);
|
||||
stage1.set_ap_w(freq * (M_PI / 2.0) * odsr);
|
||||
phase += dphase * 32;
|
||||
for (int i = 0; i < stages; i++)
|
||||
{
|
||||
dsp::sanitize(x1[i]);
|
||||
dsp::sanitize(y1[i]);
|
||||
}
|
||||
dsp::sanitize(state);
|
||||
}
|
||||
void process(float *buf_out, float *buf_in, int nsamples) {
|
||||
for (int i=0; i<nsamples; i++) {
|
||||
cnt++;
|
||||
if (cnt == 32)
|
||||
control_step();
|
||||
float in = *buf_in++;
|
||||
float fd = in + state * fb;
|
||||
for (int j = 0; j < stages; j++)
|
||||
fd = stage1.process_ap(fd, x1[j], y1[j]);
|
||||
state = fd;
|
||||
|
||||
float sdry = in * gs_dry.get();
|
||||
float swet = fd * gs_wet.get();
|
||||
*buf_out++ = sdry + swet;
|
||||
}
|
||||
}
|
||||
float freq_gain(float freq, float sr)
|
||||
{
|
||||
typedef std::complex<double> cfloat;
|
||||
freq *= 2.0 * M_PI / sr;
|
||||
cfloat z = 1.0 / exp(cfloat(0.0, freq)); // z^-1
|
||||
|
||||
cfloat p = cfloat(1.0);
|
||||
cfloat stg = stage1.h_z(z);
|
||||
|
||||
for (int i = 0; i < stages; i++)
|
||||
p = p * stg;
|
||||
|
||||
p = p / (cfloat(1.0) - cfloat(fb) * p);
|
||||
return std::abs(cfloat(gs_dry.get_last()) + cfloat(gs_wet.get_last()) * p);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for chorus and flanger. Wouldn't be needed if it wasn't
|
||||
* for odd behaviour of GCC when deriving templates from template
|
||||
* base classes (not seeing fields from base classes!).
|
||||
*/
|
||||
class chorus_base: public modulation_effect
|
||||
{
|
||||
protected:
|
||||
int min_delay_samples, mod_depth_samples;
|
||||
float min_delay, mod_depth;
|
||||
sine_table<int, 4096, 65536> sine;
|
||||
public:
|
||||
float get_min_delay() {
|
||||
return min_delay;
|
||||
}
|
||||
void set_min_delay(float min_delay) {
|
||||
this->min_delay = min_delay;
|
||||
this->min_delay_samples = (int)(min_delay * 65536.0 * sample_rate);
|
||||
}
|
||||
float get_mod_depth() {
|
||||
return mod_depth;
|
||||
}
|
||||
void set_mod_depth(float mod_depth) {
|
||||
this->mod_depth = mod_depth;
|
||||
// 128 because it's then multiplied by (hopefully) a value of 32768..-32767
|
||||
this->mod_depth_samples = (int)(mod_depth * 32.0 * sample_rate);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Single-tap chorus without feedback.
|
||||
* Perhaps MaxDelay should be a bit longer!
|
||||
*/
|
||||
template<class T, int MaxDelay=512>
|
||||
class simple_chorus: public chorus_base
|
||||
{
|
||||
protected:
|
||||
simple_delay<MaxDelay,T> delay;
|
||||
public:
|
||||
simple_chorus() {
|
||||
rate = 0.63f;
|
||||
dry = 0.5f;
|
||||
wet = 0.5f;
|
||||
min_delay = 0.005f;
|
||||
mod_depth = 0.0025f;
|
||||
setup(44100);
|
||||
}
|
||||
void reset() {
|
||||
delay.reset();
|
||||
}
|
||||
virtual void setup(int sample_rate) {
|
||||
modulation_effect::setup(sample_rate);
|
||||
delay.reset();
|
||||
set_min_delay(get_min_delay());
|
||||
set_mod_depth(get_mod_depth());
|
||||
}
|
||||
template<class OutIter, class InIter>
|
||||
void process(OutIter buf_out, InIter buf_in, int nsamples) {
|
||||
int mds = min_delay_samples + mod_depth_samples * 1024 + 2*65536;
|
||||
int mdepth = mod_depth_samples;
|
||||
for (int i=0; i<nsamples; i++) {
|
||||
phase += dphase;
|
||||
unsigned int ipart = phase.ipart();
|
||||
|
||||
float in = *buf_in++;
|
||||
int lfo = phase.lerp_by_fract_int<int, 14, int>(sine.data[ipart], sine.data[ipart+1]);
|
||||
int v = mds + (mdepth * lfo >> 6);
|
||||
// if (!(i & 7)) printf("%d\n", v);
|
||||
int ifv = v >> 16;
|
||||
delay.put(in);
|
||||
T fd; // signal from delay's output
|
||||
delay.get_interp(fd, ifv, (v & 0xFFFF)*(1.0/65536.0));
|
||||
T sdry = in * gs_dry.get();
|
||||
T swet = fd * gs_wet.get();
|
||||
*buf_out++ = sdry + swet;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Single-tap flanger (chorus plus feedback).
|
||||
*/
|
||||
template<class T, int MaxDelay=1024>
|
||||
class simple_flanger: public chorus_base
|
||||
{
|
||||
protected:
|
||||
simple_delay<MaxDelay,T> delay;
|
||||
float fb;
|
||||
int last_delay_pos, last_actual_delay_pos;
|
||||
int ramp_pos, ramp_delay_pos;
|
||||
public:
|
||||
simple_flanger()
|
||||
: fb(0) {}
|
||||
void reset() {
|
||||
delay.reset();
|
||||
last_delay_pos = last_actual_delay_pos = ramp_delay_pos = 0;
|
||||
ramp_pos = 1024;
|
||||
}
|
||||
virtual void setup(int sample_rate) {
|
||||
this->sample_rate = sample_rate;
|
||||
this->odsr = 1.0 / sample_rate;
|
||||
delay.reset();
|
||||
phase = 0;
|
||||
set_rate(get_rate());
|
||||
set_min_delay(get_min_delay());
|
||||
}
|
||||
float get_fb() {
|
||||
return fb;
|
||||
}
|
||||
void set_fb(float fb) {
|
||||
this->fb = fb;
|
||||
}
|
||||
template<class OutIter, class InIter>
|
||||
void process(OutIter buf_out, InIter buf_in, int nsamples) {
|
||||
if (!nsamples)
|
||||
return;
|
||||
int mds = this->min_delay_samples + this->mod_depth_samples * 1024 + 2 * 65536;
|
||||
int mdepth = this->mod_depth_samples;
|
||||
int delay_pos;
|
||||
unsigned int ipart = this->phase.ipart();
|
||||
int lfo = phase.lerp_by_fract_int<int, 14, int>(this->sine.data[ipart], this->sine.data[ipart+1]);
|
||||
delay_pos = mds + (mdepth * lfo >> 6);
|
||||
|
||||
if (delay_pos != last_delay_pos || ramp_pos < 1024)
|
||||
{
|
||||
if (delay_pos != last_delay_pos) {
|
||||
// we need to ramp from what the delay tap length actually was,
|
||||
// not from old (ramp_delay_pos) or desired (delay_pos) tap length
|
||||
ramp_delay_pos = last_actual_delay_pos;
|
||||
ramp_pos = 0;
|
||||
}
|
||||
|
||||
int64_t dp = 0;
|
||||
for (int i=0; i<nsamples; i++) {
|
||||
float in = *buf_in++;
|
||||
T fd; // signal from delay's output
|
||||
dp = (((int64_t)ramp_delay_pos) * (1024 - ramp_pos) + ((int64_t)delay_pos) * ramp_pos) >> 10;
|
||||
ramp_pos++;
|
||||
if (ramp_pos > 1024) ramp_pos = 1024;
|
||||
this->delay.get_interp(fd, dp >> 16, (dp & 0xFFFF)*(1.0/65536.0));
|
||||
sanitize(fd);
|
||||
T sdry = in * this->dry;
|
||||
T swet = fd * this->wet;
|
||||
*buf_out++ = sdry + swet;
|
||||
this->delay.put(in+fb*fd);
|
||||
|
||||
this->phase += this->dphase;
|
||||
ipart = this->phase.ipart();
|
||||
lfo = phase.lerp_by_fract_int<int, 14, int>(this->sine.data[ipart], this->sine.data[ipart+1]);
|
||||
delay_pos = mds + (mdepth * lfo >> 6);
|
||||
}
|
||||
last_actual_delay_pos = dp;
|
||||
}
|
||||
else {
|
||||
for (int i=0; i<nsamples; i++) {
|
||||
float in = *buf_in++;
|
||||
T fd; // signal from delay's output
|
||||
this->delay.get_interp(fd, delay_pos >> 16, (delay_pos & 0xFFFF)*(1.0/65536.0));
|
||||
sanitize(fd);
|
||||
T sdry = in * this->gs_dry.get();
|
||||
T swet = fd * this->gs_wet.get();
|
||||
*buf_out++ = sdry + swet;
|
||||
this->delay.put(in+fb*fd);
|
||||
|
||||
this->phase += this->dphase;
|
||||
ipart = this->phase.ipart();
|
||||
lfo = phase.lerp_by_fract_int<int, 14, int>(this->sine.data[ipart], this->sine.data[ipart+1]);
|
||||
delay_pos = mds + (mdepth * lfo >> 6);
|
||||
}
|
||||
last_actual_delay_pos = delay_pos;
|
||||
}
|
||||
last_delay_pos = delay_pos;
|
||||
}
|
||||
float freq_gain(float freq, float sr)
|
||||
{
|
||||
typedef std::complex<double> cfloat;
|
||||
freq *= 2.0 * M_PI / sr;
|
||||
cfloat z = 1.0 / exp(cfloat(0.0, freq)); // z^-1
|
||||
|
||||
float ldp = last_delay_pos / 65536.0;
|
||||
float fldp = floor(ldp);
|
||||
cfloat zn = std::pow(z, fldp); // z^-N
|
||||
cfloat zn1 = zn * z; // z^-(N+1)
|
||||
// simulate a lerped comb filter - H(z) = 1 / (1 + fb * (lerp(z^-N, z^-(N+1), fracpos))), N = int(pos), fracpos = pos - int(pos)
|
||||
cfloat delayed = zn + (zn1 - zn) * cfloat(ldp - fldp);
|
||||
cfloat h = cfloat(delayed) / (cfloat(1.0) - cfloat(fb) * delayed);
|
||||
// mix with dry signal
|
||||
float v = std::abs(cfloat(gs_dry.get_last()) + cfloat(gs_wet.get_last()) * h);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A classic allpass loop reverb with modulated allpass filter.
|
||||
* Just started implementing it, so there is no control over many
|
||||
* parameters.
|
||||
*/
|
||||
template<class T>
|
||||
class reverb: public audio_effect
|
||||
{
|
||||
simple_delay<2048, T> apL1, apL2, apL3, apL4, apL5, apL6;
|
||||
simple_delay<2048, T> apR1, apR2, apR3, apR4, apR5, apR6;
|
||||
fixed_point<unsigned int, 25> phase, dphase;
|
||||
sine_table<int, 128, 10000> sine;
|
||||
onepole<T> lp_left, lp_right;
|
||||
T old_left, old_right;
|
||||
int type;
|
||||
float time, fb, cutoff, diffusion;
|
||||
int tl[6], tr[6];
|
||||
float ldec[6], rdec[6];
|
||||
|
||||
int sr;
|
||||
public:
|
||||
reverb()
|
||||
{
|
||||
phase = 0.0;
|
||||
time = 1.0;
|
||||
cutoff = 9000;
|
||||
type = 2;
|
||||
diffusion = 1.f;
|
||||
setup(44100);
|
||||
}
|
||||
virtual void setup(int sample_rate) {
|
||||
sr = sample_rate;
|
||||
set_time(time);
|
||||
set_cutoff(cutoff);
|
||||
phase = 0.0;
|
||||
dphase = 0.5*128/sr;
|
||||
update_times();
|
||||
}
|
||||
void update_times()
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case 0:
|
||||
tl[0] = 397 << 16, tr[0] = 383 << 16;
|
||||
tl[1] = 457 << 16, tr[1] = 429 << 16;
|
||||
tl[2] = 549 << 16, tr[2] = 631 << 16;
|
||||
tl[3] = 649 << 16, tr[3] = 756 << 16;
|
||||
tl[4] = 773 << 16, tr[4] = 803 << 16;
|
||||
tl[5] = 877 << 16, tr[5] = 901 << 16;
|
||||
break;
|
||||
case 1:
|
||||
tl[0] = 697 << 16, tr[0] = 783 << 16;
|
||||
tl[1] = 957 << 16, tr[1] = 929 << 16;
|
||||
tl[2] = 649 << 16, tr[2] = 531 << 16;
|
||||
tl[3] = 1049 << 16, tr[3] = 1177 << 16;
|
||||
tl[4] = 473 << 16, tr[4] = 501 << 16;
|
||||
tl[5] = 587 << 16, tr[5] = 681 << 16;
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
tl[0] = 697 << 16, tr[0] = 783 << 16;
|
||||
tl[1] = 957 << 16, tr[1] = 929 << 16;
|
||||
tl[2] = 649 << 16, tr[2] = 531 << 16;
|
||||
tl[3] = 1249 << 16, tr[3] = 1377 << 16;
|
||||
tl[4] = 1573 << 16, tr[4] = 1671 << 16;
|
||||
tl[5] = 1877 << 16, tr[5] = 1781 << 16;
|
||||
break;
|
||||
case 3:
|
||||
tl[0] = 1097 << 16, tr[0] = 1087 << 16;
|
||||
tl[1] = 1057 << 16, tr[1] = 1031 << 16;
|
||||
tl[2] = 1049 << 16, tr[2] = 1039 << 16;
|
||||
tl[3] = 1083 << 16, tr[3] = 1055 << 16;
|
||||
tl[4] = 1075 << 16, tr[4] = 1099 << 16;
|
||||
tl[5] = 1003 << 16, tr[5] = 1073 << 16;
|
||||
break;
|
||||
case 4:
|
||||
tl[0] = 197 << 16, tr[0] = 133 << 16;
|
||||
tl[1] = 357 << 16, tr[1] = 229 << 16;
|
||||
tl[2] = 549 << 16, tr[2] = 431 << 16;
|
||||
tl[3] = 949 << 16, tr[3] = 1277 << 16;
|
||||
tl[4] = 1173 << 16, tr[4] = 1671 << 16;
|
||||
tl[5] = 1477 << 16, tr[5] = 1881 << 16;
|
||||
break;
|
||||
case 5:
|
||||
tl[0] = 197 << 16, tr[0] = 133 << 16;
|
||||
tl[1] = 257 << 16, tr[1] = 179 << 16;
|
||||
tl[2] = 549 << 16, tr[2] = 431 << 16;
|
||||
tl[3] = 619 << 16, tr[3] = 497 << 16;
|
||||
tl[4] = 1173 << 16, tr[4] = 1371 << 16;
|
||||
tl[5] = 1577 << 16, tr[5] = 1881 << 16;
|
||||
break;
|
||||
}
|
||||
|
||||
float fDec=1000 + 2400.f * diffusion;
|
||||
for (int i = 0 ; i < 6; i++) {
|
||||
ldec[i]=exp(-float(tl[i] >> 16) / fDec),
|
||||
rdec[i]=exp(-float(tr[i] >> 16) / fDec);
|
||||
}
|
||||
}
|
||||
float get_time() {
|
||||
return time;
|
||||
}
|
||||
void set_time(float time) {
|
||||
this->time = time;
|
||||
// fb = pow(1.0f/4096.0f, (float)(1700/(time*sr)));
|
||||
fb = 1.0 - 0.3 / (time * sr / 44100.0);
|
||||
}
|
||||
float get_type() {
|
||||
return type;
|
||||
}
|
||||
void set_type(int type) {
|
||||
this->type = type;
|
||||
update_times();
|
||||
}
|
||||
float get_diffusion() {
|
||||
return diffusion;
|
||||
}
|
||||
void set_diffusion(float diffusion) {
|
||||
this->diffusion = diffusion;
|
||||
update_times();
|
||||
}
|
||||
void set_type_and_diffusion(int type, float diffusion) {
|
||||
this->type = type;
|
||||
this->diffusion = diffusion;
|
||||
update_times();
|
||||
}
|
||||
float get_fb()
|
||||
{
|
||||
return this->fb;
|
||||
}
|
||||
void set_fb(float fb)
|
||||
{
|
||||
this->fb = fb;
|
||||
}
|
||||
float get_cutoff() {
|
||||
return cutoff;
|
||||
}
|
||||
void set_cutoff(float cutoff) {
|
||||
this->cutoff = cutoff;
|
||||
lp_left.set_lp(cutoff,sr);
|
||||
lp_right.set_lp(cutoff,sr);
|
||||
}
|
||||
void reset()
|
||||
{
|
||||
apL1.reset();apR1.reset();
|
||||
apL2.reset();apR2.reset();
|
||||
apL3.reset();apR3.reset();
|
||||
apL4.reset();apR4.reset();
|
||||
apL5.reset();apR5.reset();
|
||||
apL6.reset();apR6.reset();
|
||||
lp_left.reset();lp_right.reset();
|
||||
old_left = 0; old_right = 0;
|
||||
}
|
||||
void process(T &left, T &right)
|
||||
{
|
||||
unsigned int ipart = phase.ipart();
|
||||
|
||||
// the interpolated LFO might be an overkill here
|
||||
int lfo = phase.lerp_by_fract_int<int, 14, int>(sine.data[ipart], sine.data[ipart+1]) >> 2;
|
||||
phase += dphase;
|
||||
|
||||
left += old_right;
|
||||
left = apL1.process_allpass_comb_lerp16(left, tl[0] - 45*lfo, ldec[0]);
|
||||
left = apL2.process_allpass_comb_lerp16(left, tl[1] + 47*lfo, ldec[1]);
|
||||
float out_left = left;
|
||||
left = apL3.process_allpass_comb_lerp16(left, tl[2] + 54*lfo, ldec[2]);
|
||||
left = apL4.process_allpass_comb_lerp16(left, tl[3] - 69*lfo, ldec[3]);
|
||||
left = apL5.process_allpass_comb_lerp16(left, tl[4] + 69*lfo, ldec[4]);
|
||||
left = apL6.process_allpass_comb_lerp16(left, tl[5] - 46*lfo, ldec[5]);
|
||||
old_left = lp_left.process(left * fb);
|
||||
sanitize(old_left);
|
||||
|
||||
right += old_left;
|
||||
right = apR1.process_allpass_comb_lerp16(right, tr[0] - 45*lfo, rdec[0]);
|
||||
right = apR2.process_allpass_comb_lerp16(right, tr[1] + 47*lfo, rdec[1]);
|
||||
float out_right = right;
|
||||
right = apR3.process_allpass_comb_lerp16(right, tr[2] + 54*lfo, rdec[2]);
|
||||
right = apR4.process_allpass_comb_lerp16(right, tr[3] - 69*lfo, rdec[3]);
|
||||
right = apR5.process_allpass_comb_lerp16(right, tr[4] + 69*lfo, rdec[4]);
|
||||
right = apR6.process_allpass_comb_lerp16(right, tr[5] - 46*lfo, rdec[5]);
|
||||
old_right = lp_right.process(right * fb);
|
||||
sanitize(old_right);
|
||||
|
||||
left = out_left, right = out_right;
|
||||
}
|
||||
void extra_sanitize()
|
||||
{
|
||||
lp_left.sanitize();
|
||||
lp_right.sanitize();
|
||||
}
|
||||
};
|
||||
|
||||
class filter_module_iface
|
||||
{
|
||||
public:
|
||||
virtual void calculate_filter(float freq, float q, int mode, float gain = 1.0) = 0;
|
||||
virtual void filter_activate() = 0;
|
||||
virtual void sanitize() = 0;
|
||||
virtual int process_channel(uint16_t channel_no, float *in, float *out, uint32_t numsamples, int inmask) = 0;
|
||||
virtual float freq_gain(int subindex, float freq, float srate) = 0;
|
||||
|
||||
virtual ~filter_module_iface() {}
|
||||
};
|
||||
|
||||
|
||||
class biquad_filter_module: public filter_module_iface
|
||||
{
|
||||
private:
|
||||
dsp::biquad_d1<float> left[3], right[3];
|
||||
int order;
|
||||
|
||||
public:
|
||||
uint32_t srate;
|
||||
|
||||
enum { mode_12db_lp = 0, mode_24db_lp = 1, mode_36db_lp = 2,
|
||||
mode_12db_hp = 3, mode_24db_hp = 4, mode_36db_hp = 5,
|
||||
mode_6db_bp = 6, mode_12db_bp = 7, mode_18db_bp = 8,
|
||||
mode_6db_br = 9, mode_12db_br = 10, mode_18db_br = 11,
|
||||
mode_count
|
||||
};
|
||||
|
||||
public:
|
||||
biquad_filter_module() : order(0) {}
|
||||
|
||||
void calculate_filter(float freq, float q, int mode, float gain = 1.0)
|
||||
{
|
||||
if (mode <= mode_36db_lp) {
|
||||
order = mode + 1;
|
||||
left[0].set_lp_rbj(freq, pow(q, 1.0 / order), srate, gain);
|
||||
} else if ( mode_12db_hp <= mode && mode <= mode_36db_hp ) {
|
||||
order = mode - mode_12db_hp + 1;
|
||||
left[0].set_hp_rbj(freq, pow(q, 1.0 / order), srate, gain);
|
||||
} else if ( mode_6db_bp <= mode && mode <= mode_18db_bp ) {
|
||||
order = mode - mode_6db_bp + 1;
|
||||
left[0].set_bp_rbj(freq, pow(q, 1.0 / order), srate, gain);
|
||||
} else { // mode_6db_br <= mode <= mode_18db_br
|
||||
order = mode - mode_6db_br + 1;
|
||||
left[0].set_br_rbj(freq, order * 0.1 * q, srate, gain);
|
||||
}
|
||||
|
||||
right[0].copy_coeffs(left[0]);
|
||||
for (int i = 1; i < order; i++) {
|
||||
left[i].copy_coeffs(left[0]);
|
||||
right[i].copy_coeffs(left[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void filter_activate()
|
||||
{
|
||||
for (int i=0; i < order; i++) {
|
||||
left[i].reset();
|
||||
right[i].reset();
|
||||
}
|
||||
}
|
||||
|
||||
void sanitize()
|
||||
{
|
||||
for (int i=0; i < order; i++) {
|
||||
left[i].sanitize();
|
||||
right[i].sanitize();
|
||||
}
|
||||
}
|
||||
|
||||
inline int process_channel(uint16_t channel_no, float *in, float *out, uint32_t numsamples, int inmask) {
|
||||
dsp::biquad_d1<float> *filter;
|
||||
switch (channel_no) {
|
||||
case 0:
|
||||
filter = left;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
filter = right;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (inmask) {
|
||||
switch(order) {
|
||||
case 1:
|
||||
for (uint32_t i = 0; i < numsamples; i++)
|
||||
out[i] = filter[0].process(in[i]);
|
||||
break;
|
||||
case 2:
|
||||
for (uint32_t i = 0; i < numsamples; i++)
|
||||
out[i] = filter[1].process(filter[0].process(in[i]));
|
||||
break;
|
||||
case 3:
|
||||
for (uint32_t i = 0; i < numsamples; i++)
|
||||
out[i] = filter[2].process(filter[1].process(filter[0].process(in[i])));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (filter[order - 1].empty())
|
||||
return 0;
|
||||
switch(order) {
|
||||
case 1:
|
||||
for (uint32_t i = 0; i < numsamples; i++)
|
||||
out[i] = filter[0].process_zeroin();
|
||||
break;
|
||||
case 2:
|
||||
if (filter[0].empty())
|
||||
for (uint32_t i = 0; i < numsamples; i++)
|
||||
out[i] = filter[1].process_zeroin();
|
||||
else
|
||||
for (uint32_t i = 0; i < numsamples; i++)
|
||||
out[i] = filter[1].process(filter[0].process_zeroin());
|
||||
break;
|
||||
case 3:
|
||||
if (filter[1].empty())
|
||||
for (uint32_t i = 0; i < numsamples; i++)
|
||||
out[i] = filter[2].process_zeroin();
|
||||
else
|
||||
for (uint32_t i = 0; i < numsamples; i++)
|
||||
out[i] = filter[2].process(filter[1].process(filter[0].process_zeroin()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < order; i++)
|
||||
filter[i].sanitize();
|
||||
return filter[order - 1].empty() ? 0 : inmask;
|
||||
}
|
||||
|
||||
float freq_gain(int subindex, float freq, float srate)
|
||||
{
|
||||
float level = 1.0;
|
||||
for (int j = 0; j < order; j++)
|
||||
level *= left[j].freq_gain(freq, srate);
|
||||
return level;
|
||||
}
|
||||
};
|
||||
|
||||
class two_band_eq
|
||||
{
|
||||
private:
|
||||
dsp::onepole<float> lowcut, highcut;
|
||||
float low_gain, high_gain;
|
||||
|
||||
public:
|
||||
void reset()
|
||||
{
|
||||
lowcut.reset();
|
||||
highcut.reset();
|
||||
}
|
||||
|
||||
inline float process(float v)
|
||||
{
|
||||
v = dsp::lerp(lowcut.process_hp(v), v, low_gain);
|
||||
v = dsp::lerp(highcut.process_lp(v), v, high_gain);
|
||||
return v;
|
||||
}
|
||||
|
||||
inline void copy_coeffs(const two_band_eq &src)
|
||||
{
|
||||
lowcut.copy_coeffs(src.lowcut);
|
||||
highcut.copy_coeffs(src.highcut);
|
||||
low_gain = src.low_gain;
|
||||
high_gain = src.high_gain;
|
||||
}
|
||||
|
||||
void sanitize()
|
||||
{
|
||||
lowcut.sanitize();
|
||||
highcut.sanitize();
|
||||
}
|
||||
|
||||
void set(float _low_freq, float _low_gain, float _high_freq, float _high_gain, float sr)
|
||||
{
|
||||
lowcut.set_hp(_low_freq, sr);
|
||||
highcut.set_lp(_high_freq, sr);
|
||||
low_gain = _low_gain;
|
||||
high_gain = _high_gain;
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
{ to keep editor happy
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
580
plugins/ladspa_effect/calf/calf/biquad.h
Normal file
@@ -0,0 +1,580 @@
|
||||
/* Calf DSP Library
|
||||
* Biquad filters
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* Most of code in this file is based on freely
|
||||
* available other work of other people (filter equations).
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef __CALF_BIQUAD_H
|
||||
#define __CALF_BIQUAD_H
|
||||
|
||||
#include <complex>
|
||||
#include "primitives.h"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
/**
|
||||
* Coefficients for two-pole two-zero filter, for floating point values,
|
||||
* plus a bunch of functions to set them to typical values.
|
||||
*
|
||||
* Coefficient calculation is based on famous Robert Bristow-Johnson's equations,
|
||||
* except where it's not.
|
||||
* The coefficient calculation is NOT mine, the only exception is the lossy
|
||||
* optimization in Zoelzer and rbj HP filter code.
|
||||
*
|
||||
* See http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt for reference.
|
||||
*
|
||||
* don't use this for integers because it won't work
|
||||
*/
|
||||
template<class Coeff = float>
|
||||
class biquad_coeffs
|
||||
{
|
||||
public:
|
||||
// filter coefficients
|
||||
Coeff a0, a1, a2, b1, b2;
|
||||
typedef std::complex<double> cfloat;
|
||||
|
||||
biquad_coeffs()
|
||||
{
|
||||
set_null();
|
||||
}
|
||||
|
||||
inline void set_null()
|
||||
{
|
||||
a0 = 1.0;
|
||||
b1 = b2 = a1 = a2 = 0.f;
|
||||
}
|
||||
|
||||
/** Lowpass filter based on Robert Bristow-Johnson's equations
|
||||
* Perhaps every synth code that doesn't use SVF uses these
|
||||
* equations :)
|
||||
* @param fc resonant frequency
|
||||
* @param q resonance (gain at fc)
|
||||
* @param sr sample rate
|
||||
* @param gain amplification (gain at 0Hz)
|
||||
*/
|
||||
inline void set_lp_rbj(float fc, float q, float sr, float gain = 1.0)
|
||||
{
|
||||
float omega=(float)(2*M_PI*fc/sr);
|
||||
float sn=sin(omega);
|
||||
float cs=cos(omega);
|
||||
float alpha=(float)(sn/(2*q));
|
||||
float inv=(float)(1.0/(1.0+alpha));
|
||||
|
||||
a2 = a0 = (float)(gain*inv*(1 - cs)*0.5f);
|
||||
a1 = a0 + a0;
|
||||
b1 = (float)(-2*cs*inv);
|
||||
b2 = (float)((1 - alpha)*inv);
|
||||
}
|
||||
|
||||
// different lowpass filter, based on Zoelzer's equations, modified by
|
||||
// me (kfoltman) to use polynomials to approximate tangent function
|
||||
// not very accurate, but perhaps good enough for synth work :)
|
||||
// odsr is "one divided by samplerate"
|
||||
// from how it looks, it perhaps uses bilinear transform - but who knows :)
|
||||
inline void set_lp_zoelzer(float fc, float q, float odsr, float gain=1.0)
|
||||
{
|
||||
Coeff omega=(Coeff)(M_PI*fc*odsr);
|
||||
Coeff omega2=omega*omega;
|
||||
Coeff K=omega*(1+omega2*omega2*Coeff(1.0/1.45));
|
||||
Coeff KK=K*K;
|
||||
Coeff QK=q*(KK+1.f);
|
||||
Coeff iQK=1.0f/(QK+K);
|
||||
Coeff inv=q*iQK;
|
||||
b2 = (Coeff)(iQK*(QK-K));
|
||||
b1 = (Coeff)(2.f*(KK-1.f)*inv);
|
||||
a2 = a0 = (Coeff)(inv*gain*KK);
|
||||
a1 = a0 + a0;
|
||||
}
|
||||
|
||||
/** Highpass filter based on Robert Bristow-Johnson's equations
|
||||
* @param fc resonant frequency
|
||||
* @param q resonance (gain at fc)
|
||||
* @param sr sample rate
|
||||
* @param gain amplification (gain at sr/2)
|
||||
*/
|
||||
inline void set_hp_rbj(float fc, float q, float esr, float gain=1.0)
|
||||
{
|
||||
Coeff omega=(float)(2*M_PI*fc/esr);
|
||||
Coeff sn=sin(omega);
|
||||
Coeff cs=cos(omega);
|
||||
Coeff alpha=(float)(sn/(2*q));
|
||||
|
||||
float inv=(float)(1.0/(1.0+alpha));
|
||||
|
||||
a0 = (Coeff)(gain*inv*(1 + cs)/2);
|
||||
a1 = -2.f * a0;
|
||||
a2 = a0;
|
||||
b1 = (Coeff)(-2*cs*inv);
|
||||
b2 = (Coeff)((1 - alpha)*inv);
|
||||
}
|
||||
|
||||
// this replaces sin/cos with polynomial approximation
|
||||
inline void set_hp_rbj_optimized(float fc, float q, float esr, float gain=1.0)
|
||||
{
|
||||
Coeff omega=(float)(2*M_PI*fc/esr);
|
||||
Coeff sn=omega+omega*omega*omega*(1.0/6.0)+omega*omega*omega*omega*omega*(1.0/120);
|
||||
Coeff cs=1-omega*omega*(1.0/2.0)+omega*omega*omega*omega*(1.0/24);
|
||||
Coeff alpha=(float)(sn/(2*q));
|
||||
|
||||
float inv=(float)(1.0/(1.0+alpha));
|
||||
|
||||
a0 = (Coeff)(gain*inv*(1 + cs)*(1.0/2.0));
|
||||
a1 = -2.f * a0;
|
||||
a2 = a0;
|
||||
b1 = (Coeff)(-2*cs*inv);
|
||||
b2 = (Coeff)((1 - alpha)*inv);
|
||||
}
|
||||
|
||||
/** Bandpass filter based on Robert Bristow-Johnson's equations (normalized to 1.0 at center frequency)
|
||||
* @param fc center frequency (gain at fc = 1.0)
|
||||
* @param q =~ fc/bandwidth (not quite, but close) - 1/Q = 2*sinh(ln(2)/2*BW*w0/sin(w0))
|
||||
* @param sr sample rate
|
||||
* @param gain amplification (gain at sr/2)
|
||||
*/
|
||||
inline void set_bp_rbj(double fc, double q, double esr, double gain=1.0)
|
||||
{
|
||||
float omega=(float)(2*M_PI*fc/esr);
|
||||
float sn=sin(omega);
|
||||
float cs=cos(omega);
|
||||
float alpha=(float)(sn/(2*q));
|
||||
|
||||
float inv=(float)(1.0/(1.0+alpha));
|
||||
|
||||
a0 = (float)(gain*inv*alpha);
|
||||
a1 = 0.f;
|
||||
a2 = (float)(-gain*inv*alpha);
|
||||
b1 = (float)(-2*cs*inv);
|
||||
b2 = (float)((1 - alpha)*inv);
|
||||
}
|
||||
|
||||
// rbj's bandreject
|
||||
inline void set_br_rbj(double fc, double q, double esr, double gain=1.0)
|
||||
{
|
||||
float omega=(float)(2*M_PI*fc/esr);
|
||||
float sn=sin(omega);
|
||||
float cs=cos(omega);
|
||||
float alpha=(float)(sn/(2*q));
|
||||
|
||||
float inv=(float)(1.0/(1.0+alpha));
|
||||
|
||||
a0 = (Coeff)(gain*inv);
|
||||
a1 = (Coeff)(-gain*inv*2*cs);
|
||||
a2 = (Coeff)(gain*inv);
|
||||
b1 = (Coeff)(-2*cs*inv);
|
||||
b2 = (Coeff)((1 - alpha)*inv);
|
||||
}
|
||||
// this is mine (and, I guess, it sucks/doesn't work)
|
||||
void set_allpass(float freq, float pole_r, float sr)
|
||||
{
|
||||
float a=prewarp(freq, sr);
|
||||
float q=pole_r;
|
||||
set_bilinear(a*a+q*q, -2.0f*a, 1, a*a+q*q, 2.0f*a, 1);
|
||||
}
|
||||
/// prewarping for bilinear transform, maps given digital frequency to analog counterpart for analog filter design
|
||||
static inline float prewarp(float freq, float sr)
|
||||
{
|
||||
if (freq>sr*0.49) freq=(float)(sr*0.49);
|
||||
return (float)(tan(M_PI*freq/sr));
|
||||
}
|
||||
/// convert analog angular frequency value to digital
|
||||
static inline float unwarp(float omega, float sr)
|
||||
{
|
||||
float T = 1.0 / sr;
|
||||
return (2 / T) * atan(omega * T / 2);
|
||||
}
|
||||
/// convert analog filter time constant to digital counterpart
|
||||
static inline float unwarpf(float t, float sr)
|
||||
{
|
||||
// this is most likely broken and works by pure accident!
|
||||
float omega = 1.0 / t;
|
||||
omega = unwarp(omega, sr);
|
||||
// I really don't know why does it have to be M_PI and not 2 * M_PI!
|
||||
float f = M_PI / omega;
|
||||
return f / sr;
|
||||
}
|
||||
/// set digital filter parameters based on given analog filter parameters
|
||||
void set_bilinear(float aa0, float aa1, float aa2, float ab0, float ab1, float ab2)
|
||||
{
|
||||
float q=(float)(1.0/(ab0+ab1+ab2));
|
||||
a0 = (aa0+aa1+aa2)*q;
|
||||
a1 = 2*(aa0-aa2)*q;
|
||||
a2 = (aa0-aa1+aa2)*q;
|
||||
b1 = 2*(ab0-ab2)*q;
|
||||
b2 = (ab0-ab1+ab2)*q;
|
||||
}
|
||||
|
||||
/// RBJ peaking EQ
|
||||
/// @param freq peak frequency
|
||||
/// @param q q (correlated to freq/bandwidth, @see set_bp_rbj)
|
||||
/// @param peak peak gain (1.0 means no peak, >1.0 means a peak, less than 1.0 is a dip)
|
||||
inline void set_peakeq_rbj(float freq, float q, float peak, float sr)
|
||||
{
|
||||
float A = sqrt(peak);
|
||||
float w0 = freq * 2 * M_PI * (1.0 / sr);
|
||||
float alpha = sin(w0) / (2 * q);
|
||||
float ib0 = 1.0 / (1 + alpha/A);
|
||||
a1 = b1 = -2*cos(w0) * ib0;
|
||||
a0 = ib0 * (1 + alpha*A);
|
||||
a2 = ib0 * (1 - alpha*A);
|
||||
b2 = ib0 * (1 - alpha/A);
|
||||
}
|
||||
|
||||
/// RBJ low shelf EQ - amplitication of 'peak' at 0 Hz and of 1.0 (0dB) at sr/2 Hz
|
||||
/// @param freq corner frequency (gain at freq is sqrt(peak))
|
||||
/// @param q q (relates bandwidth and peak frequency), the higher q, the louder the resonant peak (situated below fc) is
|
||||
/// @param peak shelf gain (1.0 means no peak, >1.0 means a peak, less than 1.0 is a dip)
|
||||
inline void set_lowshelf_rbj(float freq, float q, float peak, float sr)
|
||||
{
|
||||
float A = sqrt(peak);
|
||||
float w0 = freq * 2 * M_PI * (1.0 / sr);
|
||||
float alpha = sin(w0) / (2 * q);
|
||||
float cw0 = cos(w0);
|
||||
float tmp = 2 * sqrt(A) * alpha;
|
||||
float b0 = 0.f, ib0 = 0.f;
|
||||
|
||||
a0 = A*( (A+1) - (A-1)*cw0 + tmp);
|
||||
a1 = 2*A*( (A-1) - (A+1)*cw0);
|
||||
a2 = A*( (A+1) - (A-1)*cw0 - tmp);
|
||||
b0 = (A+1) + (A-1)*cw0 + tmp;
|
||||
b1 = -2*( (A-1) + (A+1)*cw0);
|
||||
b2 = (A+1) + (A-1)*cw0 - tmp;
|
||||
|
||||
ib0 = 1.0 / b0;
|
||||
b1 *= ib0;
|
||||
b2 *= ib0;
|
||||
a0 *= ib0;
|
||||
a1 *= ib0;
|
||||
a2 *= ib0;
|
||||
}
|
||||
|
||||
/// RBJ high shelf EQ - amplitication of 0dB at 0 Hz and of peak at sr/2 Hz
|
||||
/// @param freq corner frequency (gain at freq is sqrt(peak))
|
||||
/// @param q q (relates bandwidth and peak frequency), the higher q, the louder the resonant peak (situated above fc) is
|
||||
/// @param peak shelf gain (1.0 means no peak, >1.0 means a peak, less than 1.0 is a dip)
|
||||
inline void set_highshelf_rbj(float freq, float q, float peak, float sr)
|
||||
{
|
||||
float A = sqrt(peak);
|
||||
float w0 = freq * 2 * M_PI * (1.0 / sr);
|
||||
float alpha = sin(w0) / (2 * q);
|
||||
float cw0 = cos(w0);
|
||||
float tmp = 2 * sqrt(A) * alpha;
|
||||
float b0 = 0.f, ib0 = 0.f;
|
||||
|
||||
a0 = A*( (A+1) + (A-1)*cw0 + tmp);
|
||||
a1 = -2*A*( (A-1) + (A+1)*cw0);
|
||||
a2 = A*( (A+1) + (A-1)*cw0 - tmp);
|
||||
b0 = (A+1) - (A-1)*cw0 + tmp;
|
||||
b1 = 2*( (A-1) - (A+1)*cw0);
|
||||
b2 = (A+1) - (A-1)*cw0 - tmp;
|
||||
|
||||
ib0 = 1.0 / b0;
|
||||
b1 *= ib0;
|
||||
b2 *= ib0;
|
||||
a0 *= ib0;
|
||||
a1 *= ib0;
|
||||
a2 *= ib0;
|
||||
}
|
||||
|
||||
/// copy coefficients from another biquad
|
||||
template<class U>
|
||||
inline void copy_coeffs(const biquad_coeffs<U> &src)
|
||||
{
|
||||
a0 = src.a0;
|
||||
a1 = src.a1;
|
||||
a2 = src.a2;
|
||||
b1 = src.b1;
|
||||
b2 = src.b2;
|
||||
}
|
||||
|
||||
/// Return the filter's gain at frequency freq
|
||||
/// @param freq Frequency to look up
|
||||
/// @param sr Filter sample rate (used to convert frequency to angular frequency)
|
||||
float freq_gain(float freq, float sr)
|
||||
{
|
||||
typedef std::complex<double> cfloat;
|
||||
freq *= 2.0 * M_PI / sr;
|
||||
cfloat z = 1.0 / exp(cfloat(0.0, freq));
|
||||
|
||||
return std::abs(h_z(z));
|
||||
}
|
||||
|
||||
/// Return H(z) the filter's gain at frequency freq
|
||||
/// @param z Z variable (e^jw)
|
||||
cfloat h_z(const cfloat &z)
|
||||
{
|
||||
|
||||
return (cfloat(a0) + double(a1) * z + double(a2) * z*z) / (cfloat(1.0) + double(b1) * z + double(b2) * z*z);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Two-pole two-zero filter, for floating point values.
|
||||
* Uses "traditional" Direct I form (separate FIR and IIR halves).
|
||||
* don't use this for integers because it won't work
|
||||
*/
|
||||
template<class Coeff = float, class T = float>
|
||||
struct biquad_d1: public biquad_coeffs<Coeff>
|
||||
{
|
||||
using biquad_coeffs<Coeff>::a0;
|
||||
using biquad_coeffs<Coeff>::a1;
|
||||
using biquad_coeffs<Coeff>::a2;
|
||||
using biquad_coeffs<Coeff>::b1;
|
||||
using biquad_coeffs<Coeff>::b2;
|
||||
/// input[n-1]
|
||||
T x1;
|
||||
/// input[n-2]
|
||||
T x2;
|
||||
/// output[n-1]
|
||||
T y1;
|
||||
/// output[n-2]
|
||||
T y2;
|
||||
/// Constructor (initializes state to all zeros)
|
||||
biquad_d1()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
/// direct I form with four state variables
|
||||
inline T process(T in)
|
||||
{
|
||||
T out = in * a0 + x1 * a1 + x2 * a2 - y1 * b1 - y2 * b2;
|
||||
x2 = x1;
|
||||
y2 = y1;
|
||||
x1 = in;
|
||||
y1 = out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// direct I form with zero input
|
||||
inline T process_zeroin()
|
||||
{
|
||||
T out = - y1 * b1 - y2 * b2;
|
||||
y2 = y1;
|
||||
y1 = out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// simplified version for lowpass case with two zeros at -1
|
||||
inline T process_lp(T in)
|
||||
{
|
||||
T out = a0*(in + x1 + x1 + x2) - y1 * b1 - y2 * b2;
|
||||
x2 = x1;
|
||||
y2 = y1;
|
||||
x1 = in;
|
||||
y1 = out;
|
||||
return out;
|
||||
}
|
||||
/// Sanitize (set to 0 if potentially denormal) filter state
|
||||
inline void sanitize()
|
||||
{
|
||||
dsp::sanitize(x1);
|
||||
dsp::sanitize(y1);
|
||||
dsp::sanitize(x2);
|
||||
dsp::sanitize(y2);
|
||||
}
|
||||
/// Reset state variables
|
||||
inline void reset()
|
||||
{
|
||||
dsp::zero(x1);
|
||||
dsp::zero(y1);
|
||||
dsp::zero(x2);
|
||||
dsp::zero(y2);
|
||||
}
|
||||
inline bool empty() {
|
||||
return (y1 == 0.f && y2 == 0.f);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Two-pole two-zero filter, for floating point values.
|
||||
* Uses slightly faster Direct II form (combined FIR and IIR halves).
|
||||
* However, when used with wildly varying coefficients, it may
|
||||
* make more zipper noise than Direct I form, so it's better to
|
||||
* use it when filter coefficients are not changed mid-stream.
|
||||
*/
|
||||
template<class Coeff = float, class T = float>
|
||||
struct biquad_d2: public biquad_coeffs<Coeff>
|
||||
{
|
||||
using biquad_coeffs<Coeff>::a0;
|
||||
using biquad_coeffs<Coeff>::a1;
|
||||
using biquad_coeffs<Coeff>::a2;
|
||||
using biquad_coeffs<Coeff>::b1;
|
||||
using biquad_coeffs<Coeff>::b2;
|
||||
/// state[n-1]
|
||||
float w1;
|
||||
/// state[n-2]
|
||||
float w2;
|
||||
/// Constructor (initializes state to all zeros)
|
||||
biquad_d2()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
/// direct II form with two state variables
|
||||
inline T process(T in)
|
||||
{
|
||||
T tmp = in - w1 * b1 - w2 * b2;
|
||||
T out = tmp * a0 + w1 * a1 + w2 * a2;
|
||||
w2 = w1;
|
||||
w1 = tmp;
|
||||
return out;
|
||||
}
|
||||
|
||||
// direct II form with two state variables, lowpass version
|
||||
// interesting fact: this is actually slower than the general version!
|
||||
inline T process_lp(T in)
|
||||
{
|
||||
T tmp = in - w1 * b1 - w2 * b2;
|
||||
T out = (tmp + w2 + w1* 2) * a0;
|
||||
w2 = w1;
|
||||
w1 = tmp;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Is the filter state completely silent? (i.e. set to 0 by sanitize function)
|
||||
inline bool empty() {
|
||||
return (w1 == 0.f && w2 == 0.f);
|
||||
}
|
||||
|
||||
|
||||
/// Sanitize (set to 0 if potentially denormal) filter state
|
||||
inline void sanitize()
|
||||
{
|
||||
dsp::sanitize(w1);
|
||||
dsp::sanitize(w2);
|
||||
}
|
||||
|
||||
/// Reset state variables
|
||||
inline void reset()
|
||||
{
|
||||
dsp::zero(w1);
|
||||
dsp::zero(w2);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Two-pole two-zero filter, for floating point values.
|
||||
* Uses "traditional" Direct I form (separate FIR and IIR halves).
|
||||
* don't use this for integers because it won't work
|
||||
*/
|
||||
template<class Coeff = float, class T = float>
|
||||
struct biquad_d1_lerp: public biquad_coeffs<Coeff>
|
||||
{
|
||||
using biquad_coeffs<Coeff>::a0;
|
||||
using biquad_coeffs<Coeff>::a1;
|
||||
using biquad_coeffs<Coeff>::a2;
|
||||
using biquad_coeffs<Coeff>::b1;
|
||||
using biquad_coeffs<Coeff>::b2;
|
||||
Coeff a0cur, a1cur, a2cur, b1cur, b2cur;
|
||||
Coeff a0delta, a1delta, a2delta, b1delta, b2delta;
|
||||
/// input[n-1]
|
||||
T x1;
|
||||
/// input[n-2]
|
||||
T x2;
|
||||
/// output[n-1]
|
||||
T y1;
|
||||
/// output[n-2]
|
||||
T y2;
|
||||
/// Constructor (initializes state to all zeros)
|
||||
biquad_d1_lerp()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
#define _DO_COEFF(coeff) coeff##delta = (coeff - coeff##cur) * (frac)
|
||||
void big_step(Coeff frac)
|
||||
{
|
||||
_DO_COEFF(a0);
|
||||
_DO_COEFF(a1);
|
||||
_DO_COEFF(a2);
|
||||
_DO_COEFF(b1);
|
||||
_DO_COEFF(b2);
|
||||
}
|
||||
#undef _DO_COEFF
|
||||
/// direct I form with four state variables
|
||||
inline T process(T in)
|
||||
{
|
||||
T out = in * a0cur + x1 * a1cur + x2 * a2cur - y1 * b1cur - y2 * b2cur;
|
||||
x2 = x1;
|
||||
y2 = y1;
|
||||
x1 = in;
|
||||
y1 = out;
|
||||
a0cur += a0delta;
|
||||
a1cur += a1delta;
|
||||
a2cur += a2delta;
|
||||
b1cur += b1delta;
|
||||
b2cur += b2delta;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// direct I form with zero input
|
||||
inline T process_zeroin()
|
||||
{
|
||||
T out = - y1 * b1 - y2 * b2;
|
||||
y2 = y1;
|
||||
y1 = out;
|
||||
b1cur += b1delta;
|
||||
b2cur += b2delta;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// simplified version for lowpass case with two zeros at -1
|
||||
inline T process_lp(T in)
|
||||
{
|
||||
T out = a0*(in + x1 + x1 + x2) - y1 * b1 - y2 * b2;
|
||||
x2 = x1;
|
||||
y2 = y1;
|
||||
x1 = in;
|
||||
y1 = out;
|
||||
return out;
|
||||
}
|
||||
/// Sanitize (set to 0 if potentially denormal) filter state
|
||||
inline void sanitize()
|
||||
{
|
||||
dsp::sanitize(x1);
|
||||
dsp::sanitize(y1);
|
||||
dsp::sanitize(x2);
|
||||
dsp::sanitize(y2);
|
||||
dsp::sanitize(a0cur);
|
||||
dsp::sanitize(a1cur);
|
||||
dsp::sanitize(a2cur);
|
||||
dsp::sanitize(b1cur);
|
||||
dsp::sanitize(b2cur);
|
||||
}
|
||||
/// Reset state variables
|
||||
inline void reset()
|
||||
{
|
||||
dsp::zero(x1);
|
||||
dsp::zero(y1);
|
||||
dsp::zero(x2);
|
||||
dsp::zero(y2);
|
||||
dsp::zero(a0cur);
|
||||
dsp::zero(a1cur);
|
||||
dsp::zero(a2cur);
|
||||
dsp::zero(b1cur);
|
||||
dsp::zero(b2cur);
|
||||
}
|
||||
inline bool empty() {
|
||||
return (y1 == 0.f && y2 == 0.f);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
229
plugins/ladspa_effect/calf/calf/buffer.h
Normal file
@@ -0,0 +1,229 @@
|
||||
/* Calf DSP Library
|
||||
* Buffer abstractions.
|
||||
*
|
||||
* Copyright (C) 2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef __BUFFER_H
|
||||
#define __BUFFER_H
|
||||
|
||||
namespace dsp {
|
||||
|
||||
/// decrease by N if >= N (useful for circular buffers)
|
||||
template<int N> inline int wrap_around(int a) {
|
||||
return (a >= N) ? a - N : a;
|
||||
}
|
||||
|
||||
// provide fast specializations for powers of 2
|
||||
template<> inline int wrap_around<2>(int a) { return a & 1; }
|
||||
template<> inline int wrap_around<4>(int a) { return a & 3; }
|
||||
template<> inline int wrap_around<8>(int a) { return a & 7; }
|
||||
template<> inline int wrap_around<16>(int a) { return a & 15; }
|
||||
template<> inline int wrap_around<32>(int a) { return a & 31; }
|
||||
template<> inline int wrap_around<64>(int a) { return a & 63; }
|
||||
template<> inline int wrap_around<128>(int a) { return a & 127; }
|
||||
template<> inline int wrap_around<256>(int a) { return a & 255; }
|
||||
template<> inline int wrap_around<512>(int a) { return a & 511; }
|
||||
template<> inline int wrap_around<1024>(int a) { return a & 1023; }
|
||||
template<> inline int wrap_around<2048>(int a) { return a & 2047; }
|
||||
template<> inline int wrap_around<4096>(int a) { return a & 4095; }
|
||||
template<> inline int wrap_around<8192>(int a) { return a & 8191; }
|
||||
template<> inline int wrap_around<16384>(int a) { return a & 16383; }
|
||||
template<> inline int wrap_around<32768>(int a) { return a & 32767; }
|
||||
template<> inline int wrap_around<65536>(int a) { return a & 65535; }
|
||||
|
||||
template<class Buf, class T>
|
||||
void fill(Buf &buf, T value) {
|
||||
T* data = buf.data();
|
||||
int size = buf.size();
|
||||
for (int i=0; i<size; i++)
|
||||
*data++ = value;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void fill(T *data, int size, T value) {
|
||||
for (int i=0; i<size; i++)
|
||||
*data++ = value;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void copy(T *dest, U *src, int size, T scale = 1, T add = 0) {
|
||||
for (int i=0; i<size; i++)
|
||||
*dest++ = (*src++) * scale + add;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct sample_traits {
|
||||
enum {
|
||||
channels = 1,
|
||||
bps = sizeof(T)*8
|
||||
};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sample_traits<stereo_sample<T> > {
|
||||
enum {
|
||||
channels = 2,
|
||||
bps = sizeof(T)*8
|
||||
};
|
||||
};
|
||||
|
||||
template<int N, class T = float>
|
||||
class fixed_size_buffer {
|
||||
public:
|
||||
typedef T data_type;
|
||||
enum { buffer_size = N };
|
||||
inline int size() { return N; }
|
||||
};
|
||||
|
||||
template<int N, class T = float>
|
||||
class mem_fixed_size_buffer: public fixed_size_buffer<N, T> {
|
||||
T *buf;
|
||||
public:
|
||||
mem_fixed_size_buffer(T ubuf[N]) { buf = ubuf; }
|
||||
void set_data(T buf[N]) { this->buf = buf; }
|
||||
inline T* data() { return buf; }
|
||||
inline const T* data() const { return buf; }
|
||||
inline T& operator[](int pos) { return buf[pos]; }
|
||||
inline const T& operator[](int pos) const { return buf[pos]; }
|
||||
};
|
||||
|
||||
template<int N, class T = float>
|
||||
class auto_buffer: public fixed_size_buffer<N, T> {
|
||||
T buf[N];
|
||||
public:
|
||||
T* data() const { return buf; }
|
||||
inline T& operator[](int pos) { return buf[pos]; }
|
||||
inline const T& operator[](int pos) const { return buf[pos]; }
|
||||
};
|
||||
|
||||
template<class T = float>
|
||||
class dynamic_buffer {
|
||||
T *buf;
|
||||
int buf_size;
|
||||
bool owns;
|
||||
public:
|
||||
dynamic_buffer() { owns = false; }
|
||||
dynamic_buffer(T *_buf, int _buf_size, bool _own)
|
||||
: buf(_buf), buf_size(_buf_size), owns(_own) {
|
||||
}
|
||||
dynamic_buffer(int _size) {
|
||||
buf = new T[_size];
|
||||
buf_size = _size;
|
||||
owns = true;
|
||||
}
|
||||
inline T* data() { return buf; }
|
||||
inline const T* data() const { return buf; }
|
||||
inline int size() { return buf_size; }
|
||||
void resize(int new_size, bool fill_with_zeros = false) {
|
||||
T *new_buf = new T[new_size];
|
||||
memcpy(new_buf, buf, std::min(buf_size, new_size));
|
||||
if (fill_with_zeros && buf_size < new_size)
|
||||
dsp::zero(new_buf + buf_size, new_size - buf_size);
|
||||
if (owns)
|
||||
delete []buf;
|
||||
buf = new_buf;
|
||||
buf_size = new_size;
|
||||
owns = true;
|
||||
}
|
||||
inline T& operator[](int pos) { return buf[pos]; }
|
||||
inline const T& operator[](int pos) const { return buf[pos]; }
|
||||
~dynamic_buffer() {
|
||||
if (owns)
|
||||
delete []buf;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
void copy_buf(T &dest_buf, const U &src_buf, T scale = 1, T add = 0) {
|
||||
typedef typename T::data_type data_type;
|
||||
data_type *dest = dest_buf.data();
|
||||
const data_type *src = src_buf.data();
|
||||
int size = src.size();
|
||||
for (int i=0; i<size; i++)
|
||||
*dest++ = (*src++) * scale + add;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct buffer_traits {
|
||||
};
|
||||
|
||||
/// this class template defines some basic position operations for fixed_size_buffers
|
||||
template<int N, class T>
|
||||
struct buffer_traits<fixed_size_buffer<N, T> > {
|
||||
int inc_wrap(int pos) const {
|
||||
return wrap_around<T::size>(pos+1);
|
||||
}
|
||||
|
||||
int pos_diff(int pos1, int pos2) const {
|
||||
int pos = pos1 - pos2;
|
||||
if (pos < 0) pos += T::size;
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
||||
/// this is useless for now (and untested too)
|
||||
template<class B>
|
||||
class circular_buffer: public B {
|
||||
typedef typename B::data_type data_type;
|
||||
typedef class buffer_traits<B> traits;
|
||||
B buffer;
|
||||
int rpos, wpos;
|
||||
circular_buffer() {
|
||||
clear();
|
||||
}
|
||||
void clear() {
|
||||
rpos = 0;
|
||||
wpos = 0;
|
||||
}
|
||||
inline void put(data_type data) {
|
||||
buffer[wpos] = data;
|
||||
wpos = traits::inc_wrap(wpos);
|
||||
}
|
||||
inline bool empty() {
|
||||
return rpos == wpos;
|
||||
}
|
||||
inline bool full() {
|
||||
return rpos == traits::inc_wrap(wpos);
|
||||
}
|
||||
inline const data_type& get() {
|
||||
int oldrpos = rpos;
|
||||
rpos = traits::inc_wrap(rpos);
|
||||
return buffer[oldrpos];
|
||||
}
|
||||
inline int get_rbytes() {
|
||||
return traits::pos_diff(wpos, rpos);
|
||||
}
|
||||
inline int get_wbytes() {
|
||||
if (full()) return 0;
|
||||
return traits::pos_diff(rpos, wpos);
|
||||
}
|
||||
};
|
||||
|
||||
/// this is useless for now
|
||||
template<int N, class T = float>
|
||||
class mono_auto_buffer: public auto_buffer<N, T> {
|
||||
};
|
||||
|
||||
/// this is useless for now
|
||||
template<int N, class T = float>
|
||||
class stereo_auto_buffer: public auto_buffer<N, stereo_sample<T> > {
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
185
plugins/ladspa_effect/calf/calf/delay.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/* Calf DSP Library
|
||||
* Reusable audio effect classes.
|
||||
*
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef __CALF_DELAY_H
|
||||
#define __CALF_DELAY_H
|
||||
|
||||
#include "primitives.h"
|
||||
#include "buffer.h"
|
||||
#include "onepole.h"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
/**
|
||||
* Delay primitive. Can be used for most delay stuff, including
|
||||
* variable (modulated) delays like chorus/flanger. Note that
|
||||
* for modulated delay effects use of GetInterp is preferred,
|
||||
* because it handles fractional positions and uses linear
|
||||
* interpolation, which sounds better most of the time.
|
||||
*
|
||||
* @param N maximum length
|
||||
* @param C number of channels read/written for each sample (1 mono, 2 stereo etc)
|
||||
*/
|
||||
template<int N, class T>
|
||||
struct simple_delay {
|
||||
auto_buffer<N, T> data;
|
||||
int pos;
|
||||
|
||||
simple_delay() {
|
||||
reset();
|
||||
}
|
||||
void reset() {
|
||||
pos = 0;
|
||||
for (int i=0; i<N; i++)
|
||||
zero(data[i]);
|
||||
}
|
||||
/** Write one C-channel sample from idata[0], idata[1] etc into buffer */
|
||||
inline void put(T idata) {
|
||||
data[pos] = idata;
|
||||
pos = wrap_around<N>(pos+1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read one C-channel sample into odata[0], odata[1] etc into buffer.
|
||||
* Don't use for modulated delays (chorus/flanger etc) unless you
|
||||
* want them to crackle and generally sound ugly
|
||||
* @param odata pointer to write into
|
||||
* @param delay delay relative to current writing pos
|
||||
*/
|
||||
template<class U>
|
||||
inline void get(U &odata, int delay) {
|
||||
assert(delay >= 0 && delay < N);
|
||||
int ppos = wrap_around<N>(pos + N - delay);
|
||||
odata = data[ppos];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and write during the same function call
|
||||
*/
|
||||
inline T process(T idata, int delay)
|
||||
{
|
||||
assert(delay >= 0 && delay < N);
|
||||
int ppos = wrap_around<N>(pos + N - delay);
|
||||
T odata = data[ppos];
|
||||
data[pos] = idata;
|
||||
pos = wrap_around<N>(pos+1);
|
||||
return odata;
|
||||
}
|
||||
|
||||
/** Read one C-channel sample at fractional position.
|
||||
* This version can be used for modulated delays, because
|
||||
* it uses linear interpolation.
|
||||
* @param odata value to write into
|
||||
* @param delay delay relative to current writing pos
|
||||
* @param udelay fractional delay (0..1)
|
||||
*/
|
||||
template<class U>
|
||||
inline void get_interp(U &odata, int delay, float udelay) {
|
||||
// assert(delay >= 0 && delay < N-1);
|
||||
int ppos = wrap_around<N>(pos + N - delay);
|
||||
int pppos = wrap_around<N>(ppos + N - 1);
|
||||
odata = lerp(data[ppos], data[pppos], udelay);
|
||||
}
|
||||
|
||||
/** Read one C-channel sample at fractional position.
|
||||
* This version can be used for modulated delays, because
|
||||
* it uses linear interpolation.
|
||||
* @param odata value to write into
|
||||
* @param delay delay relative to current writing pos
|
||||
* @param udelay fractional delay (0..1)
|
||||
*/
|
||||
inline T get_interp_1616(unsigned int delay) {
|
||||
float udelay = (float)((delay & 0xFFFF) * (1.0 / 65536.0));
|
||||
delay = delay >> 16;
|
||||
// assert(delay >= 0 && delay < N-1);
|
||||
int ppos = wrap_around<N>(pos + N - delay);
|
||||
int pppos = wrap_around<N>(ppos + N - 1);
|
||||
return lerp(data[ppos], data[pppos], udelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comb filter. Feedback delay line with given delay and feedback values
|
||||
* @param in input signal
|
||||
* @param delay delay length (must be <N and integer)
|
||||
* @param fb feedback (must be <1 or it will be unstable)
|
||||
*/
|
||||
inline T process_comb(T in, unsigned int delay, float fb)
|
||||
{
|
||||
T old, cur;
|
||||
get(old, delay);
|
||||
cur = in + fb*old;
|
||||
sanitize(cur);
|
||||
put(cur);
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comb filter with linear interpolation. Feedback delay line with given delay and feedback values
|
||||
* Note that linear interpolation introduces some weird effects in frequency response.
|
||||
* @param in input signal
|
||||
* @param delay fractional delay length (must be < 65536 * N)
|
||||
* @param fb feedback (must be <1 or it will be unstable)
|
||||
*/
|
||||
inline T process_comb_lerp16(T in, unsigned int delay, float udelay, float fb)
|
||||
{
|
||||
T old, cur;
|
||||
get_interp(old, delay>>16, dsp::fract16(delay));
|
||||
cur = in + fb*old;
|
||||
sanitize(cur);
|
||||
put(cur);
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comb allpass filter. The comb filter with additional direct path, which is supposed to cancel the coloration.
|
||||
* @param in input signal
|
||||
* @param delay delay length (must be <N and integer)
|
||||
* @param fb feedback (must be <1 or it will be unstable)
|
||||
*/
|
||||
inline T process_allpass_comb(T in, unsigned int delay, float fb)
|
||||
{
|
||||
T old, cur;
|
||||
get(old, delay);
|
||||
cur = in + fb*old;
|
||||
sanitize(cur);
|
||||
put(cur);
|
||||
return old - fb * cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comb allpass filter. The comb filter with additional direct path, which is supposed to cancel the coloration.
|
||||
* @param in input signal
|
||||
* @param delay fractional delay length (must be < 65536 * N)
|
||||
* @param fb feedback (must be <1 or it will be unstable)
|
||||
*/
|
||||
inline T process_allpass_comb_lerp16(T in, unsigned int delay, float fb)
|
||||
{
|
||||
T old, cur;
|
||||
get_interp(old, delay>>16, dsp::fract16(delay));
|
||||
cur = in + fb*old;
|
||||
sanitize(cur);
|
||||
put(cur);
|
||||
return old - fb * cur;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
206
plugins/ladspa_effect/calf/calf/envelope.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/* Calf DSP Library
|
||||
* ADSR envelope class (and other envelopes in future)
|
||||
*
|
||||
* Copyright (C) 2007-2008 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef __CALF_ENVELOPE_H
|
||||
#define __CALF_ENVELOPE_H
|
||||
|
||||
#include "primitives.h"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
/// Rate-based ADSFR envelope class. Note that if release rate is slower than decay
|
||||
/// rate, this envelope won't use release rate until output level falls below sustain level
|
||||
/// it's different to what certain hardware synth companies did, but it prevents the very
|
||||
/// un-musical (IMHO) behaviour known from (for example) SoundFont 2.
|
||||
class adsr
|
||||
{
|
||||
public:
|
||||
enum env_state {
|
||||
STOP, ///< envelope is stopped
|
||||
ATTACK, ///< attack - rise from 0 to 1
|
||||
DECAY, ///< decay - fall from 1 to sustain level
|
||||
SUSTAIN, ///< sustain - remain at sustain level (unless sustain is 0 - then it gets stopped); with fade != 0 it goes towards 0% (positive fade) or 100% (negative fade)
|
||||
RELEASE, ///< release - fall from sustain (or pre-sustain) level to 0
|
||||
LOCKDECAY, ///< locked decay
|
||||
};
|
||||
|
||||
/// Current envelope stage
|
||||
env_state state;
|
||||
/// @note these are *rates*, not times
|
||||
double attack, decay, sustain, release, fade;
|
||||
/// Requested release time (not the rate!) in frames, used for recalculating the rate if sustain is changed
|
||||
double release_time;
|
||||
/// Current envelope (output) level
|
||||
double value;
|
||||
/// Release rate used for the current note (calculated from this note's sustain level, and not the current sustain level,
|
||||
/// which may have changed after note has been released)
|
||||
double thisrelease;
|
||||
/// Sustain level used for the current note (used to calculate release rate if sustain changed during release stage
|
||||
/// of the current note)
|
||||
double thiss;
|
||||
/// Value from the time before advance() was called last time
|
||||
double old_value;
|
||||
|
||||
adsr()
|
||||
{
|
||||
attack = decay = sustain = release = thisrelease = thiss = 0.f;
|
||||
reset();
|
||||
}
|
||||
/// Stop (reset) the envelope
|
||||
inline void reset()
|
||||
{
|
||||
old_value = value = 0.0;
|
||||
thiss = 0.0;
|
||||
state = STOP;
|
||||
}
|
||||
/// Set the envelope parameters (updates rate member variables based on values passed)
|
||||
/// @param a attack time
|
||||
/// @param d decay time
|
||||
/// @param s sustain level
|
||||
/// @param r release time
|
||||
/// @param er Envelope (update) rate
|
||||
/// @param f fade time (if applicable)
|
||||
inline void set(float a, float d, float s, float r, float er, float f = 0.f)
|
||||
{
|
||||
attack = 1.0 / (a * er);
|
||||
decay = (1 - s) / (d * er);
|
||||
sustain = s;
|
||||
release_time = r * er;
|
||||
release = s / release_time;
|
||||
if (fabs(f) > small_value<float>())
|
||||
fade = 1.0 / (f * er);
|
||||
else
|
||||
fade = 0.0;
|
||||
// in release:
|
||||
// lock thiss setting (start of release for current note) and unlock thisrelease setting (current note's release rate)
|
||||
if (state != RELEASE)
|
||||
thiss = s;
|
||||
else
|
||||
thisrelease = thiss / release_time;
|
||||
}
|
||||
/// @retval true if envelope is in released state (forced decay, release or stopped)
|
||||
inline bool released() const
|
||||
{
|
||||
return state == LOCKDECAY || state == RELEASE || state == STOP;
|
||||
}
|
||||
/// @retval true if envelope is stopped (has not been started or has run till its end)
|
||||
inline bool stopped() const
|
||||
{
|
||||
return state == STOP;
|
||||
}
|
||||
/// Start the envelope
|
||||
inline void note_on()
|
||||
{
|
||||
state = ATTACK;
|
||||
thiss = sustain;
|
||||
}
|
||||
/// Release the envelope
|
||||
inline void note_off()
|
||||
{
|
||||
// Do nothing if envelope is already stopped
|
||||
if (state == STOP)
|
||||
return;
|
||||
// XXXKF what if envelope is already released? (doesn't happen in any current synth, but who knows?)
|
||||
// Raise sustain value if it has been changed... I'm not sure if it's needed
|
||||
thiss = std::max(sustain, value);
|
||||
// Calculate release rate from sustain level
|
||||
thisrelease = thiss / release_time;
|
||||
// we're in attack or decay, and if decay is faster than release
|
||||
if (value > sustain && decay > thisrelease) {
|
||||
// use standard release time later (because we'll be switching at sustain point)
|
||||
thisrelease = release;
|
||||
state = LOCKDECAY;
|
||||
} else {
|
||||
// in attack/decay, but use fixed release time
|
||||
// in case value fell below sustain, assume it didn't (for the purpose of calculating release rate only)
|
||||
state = RELEASE;
|
||||
}
|
||||
}
|
||||
/// Calculate next envelope value
|
||||
inline void advance()
|
||||
{
|
||||
old_value = value;
|
||||
// XXXKF This may use a state array instead of a switch some day (at least for phases other than attack and possibly sustain)
|
||||
switch(state)
|
||||
{
|
||||
case ATTACK:
|
||||
value += attack;
|
||||
if (value >= 1.0) {
|
||||
value = 1.0;
|
||||
state = DECAY;
|
||||
}
|
||||
break;
|
||||
case DECAY:
|
||||
value -= decay;
|
||||
if (value < sustain)
|
||||
{
|
||||
value = sustain;
|
||||
state = SUSTAIN;
|
||||
}
|
||||
break;
|
||||
case LOCKDECAY:
|
||||
value -= decay;
|
||||
if (value < sustain)
|
||||
{
|
||||
if (value < 0.f)
|
||||
value = 0.f;
|
||||
state = RELEASE;
|
||||
thisrelease = release;
|
||||
}
|
||||
break;
|
||||
case SUSTAIN:
|
||||
if (fade != 0.f)
|
||||
{
|
||||
value -= fade;
|
||||
if (value > 1.f)
|
||||
value = 1.f;
|
||||
}
|
||||
else
|
||||
value = sustain;
|
||||
if (value < 0.00001f) {
|
||||
value = 0;
|
||||
state = STOP;
|
||||
}
|
||||
break;
|
||||
case RELEASE:
|
||||
value -= thisrelease;
|
||||
if (value <= 0.f) {
|
||||
value = 0.f;
|
||||
state = STOP;
|
||||
}
|
||||
break;
|
||||
case STOP:
|
||||
value = 0.f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/// Return a value between old_value (previous step) and value (current step)
|
||||
/// @param pos between 0 and 1
|
||||
inline double interpolate(double pos)
|
||||
{
|
||||
return old_value + (value - old_value) * pos;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
113
plugins/ladspa_effect/calf/calf/fft.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* Calf DSP Library
|
||||
* FFT class
|
||||
*
|
||||
* Copyright (C) 2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CALF_FFT_H
|
||||
#define __CALF_FFT_H
|
||||
|
||||
#include <complex>
|
||||
|
||||
namespace dsp {
|
||||
|
||||
/// FFT routine copied from my old OneSignal library, modified to
|
||||
/// match Calf's style. It's not fast at all, just a straightforward
|
||||
/// implementation.
|
||||
template<class T, int O>
|
||||
class fft
|
||||
{
|
||||
typedef typename std::complex<T> complex;
|
||||
int scramble[1<<O];
|
||||
complex sines[1<<O];
|
||||
public:
|
||||
fft()
|
||||
{
|
||||
int N=1<<O;
|
||||
assert(N >= 4);
|
||||
for (int i=0; i<N; i++)
|
||||
{
|
||||
int v=0;
|
||||
for (int j=0; j<O; j++)
|
||||
if (i&(1<<j))
|
||||
v+=(N>>(j+1));
|
||||
scramble[i]=v;
|
||||
}
|
||||
int N90 = N >> 2;
|
||||
T divN = 2 * M_PI / N;
|
||||
// use symmetry
|
||||
for (int i=0; i<N90; i++)
|
||||
{
|
||||
T angle = divN * i;
|
||||
T c = cos(angle), s = sin(angle);
|
||||
sines[i + 3 * N90] = -(sines[i + N90] = complex(-s, c));
|
||||
sines[i + 2 * N90] = -(sines[i] = complex(c, s));
|
||||
}
|
||||
}
|
||||
void calculate(complex *input, complex *output, bool inverse)
|
||||
{
|
||||
int N=1<<O;
|
||||
int N1=N-1;
|
||||
int i;
|
||||
// Scramble the input data
|
||||
if (inverse)
|
||||
{
|
||||
float mf=1.0/N;
|
||||
for (i=0; i<N; i++)
|
||||
{
|
||||
complex &c=input[scramble[i]];
|
||||
output[i]=mf*complex(c.imag(),c.real());
|
||||
}
|
||||
}
|
||||
else
|
||||
for (i=0; i<N; i++)
|
||||
output[i]=input[scramble[i]];
|
||||
|
||||
// O butterfiles
|
||||
for (i=0; i<O; i++)
|
||||
{
|
||||
int PO=1<<i, PNO=1<<(O-i-1);
|
||||
int j,k;
|
||||
for (j=0; j<PNO; j++)
|
||||
{
|
||||
int base=j<<(i+1);
|
||||
for (k=0; k<PO; k++)
|
||||
{
|
||||
int B1=base+k;
|
||||
int B2=base+k+(1<<i);
|
||||
complex r1=output[B1];
|
||||
complex r2=output[B2];
|
||||
output[B1]=r1+r2*sines[(B1<<(O-i-1))&N1];
|
||||
output[B2]=r1+r2*sines[(B2<<(O-i-1))&N1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inverse)
|
||||
{
|
||||
for (i=0; i<N; i++)
|
||||
{
|
||||
const complex &c=output[i];
|
||||
output[i]=complex(c.imag(),c.real());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
269
plugins/ladspa_effect/calf/calf/fixed_point.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/* Calf DSP Library
|
||||
* DSP primitives.
|
||||
*
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_FIXED_POINT_H
|
||||
#define __CALF_FIXED_POINT_H
|
||||
|
||||
namespace dsp {
|
||||
|
||||
inline uint32_t shr(uint32_t v, int bits = 1) { return v>>bits; };
|
||||
inline int32_t shr(int32_t v, int bits = 1) { return v>>bits; };
|
||||
inline uint64_t shr(uint64_t v, int bits = 1) { return v>>bits; };
|
||||
inline int64_t shr(int64_t v, int bits = 1) { return v>>bits; };
|
||||
inline float shr(float v, int bits = 1) { return v*(1.0/(1<<bits)); };
|
||||
inline double shr(double v, int bits = 1) { return v*(1.0/(1<<bits)); };
|
||||
template<class T, int FracBits>
|
||||
inline T shr(T v, int bits = 1) {
|
||||
v.set(v >> bits);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<class T, int FracBits> class fixed_point {
|
||||
T value;
|
||||
enum { IntBits = (sizeof(T)/8) - FracBits };
|
||||
|
||||
public:
|
||||
/// default constructor, does not initialize the value, just like - say - float doesn't
|
||||
inline fixed_point() {
|
||||
}
|
||||
|
||||
/// copy constructor from any other fixed_point value
|
||||
template<class U, int FracBits2> inline fixed_point(const fixed_point<U, FracBits2> &v) {
|
||||
if (FracBits == FracBits2) value = v.get();
|
||||
else if (FracBits > FracBits2) value = v.get() << abs(FracBits - FracBits2);
|
||||
else value = v.get() >> abs(FracBits - FracBits2);
|
||||
}
|
||||
|
||||
/* this would be way too confusing, it wouldn't be obvious if it expects a whole fixed point or an integer part
|
||||
explicit inline fixed_point(T v) {
|
||||
this->value = v;
|
||||
}
|
||||
*/
|
||||
explicit inline fixed_point(double v) {
|
||||
value = (T)(v*one());
|
||||
}
|
||||
|
||||
/// Makes an instance from a representation value (ie. same type of value as is used for internal storage and get/set)
|
||||
static inline fixed_point from_base(const T &v)
|
||||
{
|
||||
fixed_point result;
|
||||
result.value = v;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline static T one() {
|
||||
return (T)(1) << FracBits;
|
||||
}
|
||||
|
||||
inline void set(T value) {
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
inline T get() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
inline operator double() const {
|
||||
return value * (1.0/one());
|
||||
}
|
||||
|
||||
inline fixed_point &operator=(double v) {
|
||||
value = (T)(v*one());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class U, int FracBits2> static inline T rebase(const fixed_point<U, FracBits2> &v) {
|
||||
if (FracBits == FracBits2)
|
||||
return v.get();
|
||||
if (FracBits > FracBits2)
|
||||
return v.get() << abs(FracBits - FracBits2);
|
||||
return v.get() >> abs(FracBits2 - FracBits);
|
||||
}
|
||||
|
||||
template<class U, int FracBits2> inline fixed_point &operator=(const fixed_point<U, FracBits2> &v) {
|
||||
value = rebase<U, FracBits2>(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class U, int FracBits2> inline fixed_point &operator+=(const fixed_point<U, FracBits2> &v) {
|
||||
value += rebase<U, FracBits2>(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class U, int FracBits2> inline fixed_point &operator-=(const fixed_point<U, FracBits2> &v) {
|
||||
value -= rebase<U, FracBits2>(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class U, int FracBits2> inline fixed_point operator+(const fixed_point<U, FracBits2> &v) const {
|
||||
fixed_point fpv;
|
||||
fpv.set(value + rebase<U, FracBits2>(v));
|
||||
return fpv;
|
||||
}
|
||||
|
||||
template<class U, int FracBits2> inline fixed_point operator-(const fixed_point<U, FracBits2> &v) const {
|
||||
fixed_point fpv;
|
||||
fpv.set(value - rebase<U, FracBits2>(v));
|
||||
return fpv;
|
||||
}
|
||||
|
||||
/// multiply two fixed point values, using long long int to store the temporary multiplication result
|
||||
template<class U, int FracBits2> inline fixed_point operator*(const fixed_point<U, FracBits2> &v) const {
|
||||
fixed_point tmp;
|
||||
tmp.set(((int64_t)value) * v.get() >> FracBits2);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/// multiply two fixed point values, using BigType (usually 64-bit int) to store the temporary multiplication result
|
||||
template<class U, int FracBits2, class BigType> inline fixed_point& operator*=(const fixed_point<U, FracBits2> &v) {
|
||||
value = (T)(((BigType)value) * v.get() >> FracBits2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline fixed_point operator+(int v) const {
|
||||
fixed_point tmp;
|
||||
tmp.set(value + (v << FracBits));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline fixed_point operator-(int v) const {
|
||||
fixed_point tmp;
|
||||
tmp.set(value - (v << FracBits));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline fixed_point operator*(int v) const {
|
||||
fixed_point tmp;
|
||||
tmp.value = value*v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline fixed_point& operator+=(int v) {
|
||||
value += (v << FracBits);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline fixed_point& operator-=(int v) {
|
||||
value -= (v << FracBits);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline fixed_point& operator*=(int v) {
|
||||
value *= v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// return integer part
|
||||
inline T ipart() const {
|
||||
return value >> FracBits;
|
||||
}
|
||||
|
||||
/// return integer part as unsigned int
|
||||
inline unsigned int uipart() const {
|
||||
return ((unsigned)value) >> FracBits;
|
||||
}
|
||||
|
||||
/// return integer part as unsigned int
|
||||
inline unsigned int ui64part() const {
|
||||
return ((uint64_t)value) >> FracBits;
|
||||
}
|
||||
|
||||
/// return fractional part as 0..(2^FracBits-1)
|
||||
inline T fpart() const {
|
||||
return value & ((1 << FracBits)-1);
|
||||
}
|
||||
|
||||
/// return fractional part as 0..(2^Bits-1)
|
||||
template<int Bits>
|
||||
inline T fpart() const {
|
||||
int fbits = value & ((1 << FracBits)-1);
|
||||
if (Bits == FracBits) return fbits;
|
||||
int shift = abs(Bits-FracBits);
|
||||
return (Bits < FracBits) ? (fbits >> shift) : (fbits << shift);
|
||||
}
|
||||
|
||||
/// return fractional part as 0..1
|
||||
inline double fpart_as_double() const {
|
||||
return (value & ((1 << FracBits)-1)) * (1.0 / (1 << FracBits));
|
||||
}
|
||||
|
||||
/// use fractional part (either whole or given number of most significant bits) for interpolating between two values
|
||||
/// note that it uses integer arithmetic only, and isn't suitable for floating point or fixed point U!
|
||||
/// @param UseBits can be used when there's a risk of exceeding range of U because max(fpart)*max(v1 or v2) > range of U
|
||||
template<class U, int UseBits, class MulType>
|
||||
inline U lerp_by_fract_int(U v1, U v2) const {
|
||||
int fp = fpart<UseBits>();
|
||||
assert ( fp >=0 && fp <= (1<<UseBits));
|
||||
// printf("diff =
|
||||
return v1 + shr(((MulType)(v2-v1) * fp), UseBits);
|
||||
}
|
||||
|
||||
template<class U, int UseBits>
|
||||
inline U lerp_table_lookup_int(U data[(1<<IntBits)+1]) const {
|
||||
unsigned int pos = uipart();
|
||||
return lerp_by_fract_int<U, UseBits>(data[pos], data[pos+1]);
|
||||
}
|
||||
|
||||
/// Untested... I've started it to get a sin/cos readout for rotaryorgan, but decided to use table-less solution instead
|
||||
/// Do not assume it works, because it most probably doesn't
|
||||
template<class U, int UseBits>
|
||||
inline U lerp_table_lookup_int_shift(U data[(1<<IntBits)+1], unsigned int shift) {
|
||||
unsigned int pos = (uipart() + shift) & ((1 << IntBits) - 1);
|
||||
return lerp_by_fract_int<U, UseBits>(data[pos], data[pos+1]);
|
||||
}
|
||||
|
||||
template<class U>
|
||||
inline U lerp_table_lookup_float(U data[(1<<IntBits)+1]) const {
|
||||
unsigned int pos = uipart();
|
||||
return data[pos] + (data[pos+1]-data[pos]) * fpart_as_double();
|
||||
}
|
||||
|
||||
template<class U>
|
||||
inline U lerp_table_lookup_float_mask(U data[(1<<IntBits)+1], unsigned int mask) const {
|
||||
unsigned int pos = ui64part() & mask;
|
||||
// printf("full = %lld pos = %d + %f\n", value, pos, fpart_as_double());
|
||||
return data[pos] + (data[pos+1]-data[pos]) * fpart_as_double();
|
||||
}
|
||||
|
||||
template<class U, int UseBits, class MulType>
|
||||
inline U lerp_ptr_lookup_int(U *data) const {
|
||||
unsigned int pos = ui64part();
|
||||
return lerp_by_fract_int<U, UseBits, MulType>(data[pos], data[pos+1]);
|
||||
}
|
||||
|
||||
template<class U>
|
||||
inline U lerp_ptr_lookup_float(U *data) const {
|
||||
unsigned int pos = ui64part();
|
||||
return data[pos] + (data[pos+1]-data[pos]) * fpart_as_double();
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, int FractBits>
|
||||
inline fixed_point<T, FractBits> operator*(int v, fixed_point<T, FractBits> v2) {
|
||||
v2 *= v;
|
||||
return v2;
|
||||
}
|
||||
|
||||
/// wave position (unsigned 64-bit int including 24-bit fractional part)
|
||||
typedef fixed_point<unsigned long long int, 24> wpos;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
561
plugins/ladspa_effect/calf/calf/giface.h
Normal file
@@ -0,0 +1,561 @@
|
||||
/* Calf DSP Library
|
||||
* Common plugin interface definitions (shared between LADSPA/LV2/DSSI/standalone).
|
||||
*
|
||||
* Copyright (C) 2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_GIFACE_H
|
||||
#define __CALF_GIFACE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include "primitives.h"
|
||||
#include "preset.h"
|
||||
|
||||
namespace osctl {
|
||||
struct osc_client;
|
||||
}
|
||||
|
||||
namespace calf_plugins {
|
||||
|
||||
enum {
|
||||
MAX_SAMPLE_RUN = 256
|
||||
};
|
||||
|
||||
/// Values ORed together for flags field in parameter_properties
|
||||
enum parameter_flags
|
||||
{
|
||||
PF_TYPEMASK = 0x000F, ///< bit mask for type
|
||||
PF_FLOAT = 0x0000, ///< any float value
|
||||
PF_INT = 0x0001, ///< integer value (still represented as float)
|
||||
PF_BOOL = 0x0002, ///< bool value (usually >=0.5f is treated as TRUE, which is inconsistent with LV2 etc. which treats anything >0 as TRUE)
|
||||
PF_ENUM = 0x0003, ///< enum value (min, min+1, ..., max, only guaranteed to work when min = 0)
|
||||
PF_ENUM_MULTI = 0x0004, ///< SET / multiple-choice
|
||||
PF_STRING = 0x0005, ///< see: http://lv2plug.in/docs/index.php?title=String_port
|
||||
|
||||
PF_SCALEMASK = 0xF0, ///< bit mask for scale
|
||||
PF_SCALE_DEFAULT = 0x00, ///< no scale given
|
||||
PF_SCALE_LINEAR = 0x10, ///< linear scale
|
||||
PF_SCALE_LOG = 0x20, ///< log scale
|
||||
PF_SCALE_GAIN = 0x30, ///< gain = -96dB..0 or -inf dB
|
||||
PF_SCALE_PERC = 0x40, ///< percent
|
||||
PF_SCALE_QUAD = 0x50, ///< quadratic scale (decent for some gain/amplitude values)
|
||||
PF_SCALE_LOG_INF = 0x60, ///< log scale + +inf (FAKE_INFINITY)
|
||||
|
||||
PF_CTLMASK = 0x0F00, ///< bit mask for control type
|
||||
PF_CTL_DEFAULT = 0x0000, ///< try to figure out automatically
|
||||
PF_CTL_KNOB = 0x0100, ///< knob
|
||||
PF_CTL_FADER = 0x0200, ///< fader (slider)
|
||||
PF_CTL_TOGGLE = 0x0300, ///< toggle button
|
||||
PF_CTL_COMBO = 0x0400, ///< combo box
|
||||
PF_CTL_RADIO = 0x0500, ///< radio button
|
||||
PF_CTL_BUTTON = 0x0600, ///< push button
|
||||
PF_CTL_METER = 0x0700, ///< volume meter
|
||||
PF_CTL_LED = 0x0800, ///< light emitting diode
|
||||
|
||||
PF_CTLOPTIONS = 0x00F000, ///< bit mask for control (widget) options
|
||||
PF_CTLO_HORIZ = 0x001000, ///< horizontal version of the control (unused)
|
||||
PF_CTLO_VERT = 0x002000, ///< vertical version of the control (unused)
|
||||
PF_CTLO_LABEL = 0x004000, ///< add a text display to the control (meters only)
|
||||
PF_CTLO_REVERSE = 0x008000, ///< use VU_MONOCHROME_REVERSE mode (meters only)
|
||||
|
||||
PF_PROP_NOBOUNDS = 0x010000, ///< no epp:hasStrictBounds
|
||||
PF_PROP_EXPENSIVE = 0x020000, ///< epp:expensive, may trigger expensive calculation
|
||||
PF_PROP_OUTPUT_GAIN=0x050000, ///< epp:outputGain + skip epp:hasStrictBounds
|
||||
PF_PROP_OUTPUT = 0x080000, ///< output port
|
||||
PF_PROP_OPTIONAL = 0x100000, ///< connection optional
|
||||
PF_PROP_GRAPH = 0x200000, ///< add graph
|
||||
PF_PROP_MSGCONTEXT= 0x400000, ///< message context
|
||||
|
||||
PF_UNITMASK = 0xFF000000, ///< bit mask for units \todo reduce to use only 5 bits
|
||||
PF_UNIT_DB = 0x01000000, ///< decibels
|
||||
PF_UNIT_COEF = 0x02000000, ///< multiply-by factor
|
||||
PF_UNIT_HZ = 0x03000000, ///< Hertz
|
||||
PF_UNIT_SEC = 0x04000000, ///< second
|
||||
PF_UNIT_MSEC = 0x05000000, ///< millisecond
|
||||
PF_UNIT_CENTS = 0x06000000, ///< cents (1/100 of a semitone, 1/1200 of an octave)
|
||||
PF_UNIT_SEMITONES = 0x07000000,///< semitones
|
||||
PF_UNIT_BPM = 0x08000000, ///< beats per minute
|
||||
PF_UNIT_DEG = 0x09000000, ///< degrees
|
||||
PF_UNIT_NOTE = 0x0A000000, ///< MIDI note number
|
||||
PF_UNIT_RPM = 0x0B000000, ///< revolutions per minute
|
||||
};
|
||||
|
||||
/// A fake infinity value (because real infinity may break some hosts)
|
||||
#define FAKE_INFINITY (65536.0 * 65536.0)
|
||||
/// Check for infinity (with appropriate-ish tolerance)
|
||||
#define IS_FAKE_INFINITY(value) (fabs(value-FAKE_INFINITY) < 1.0)
|
||||
|
||||
/// Information record about plugin's menu command
|
||||
struct plugin_command_info
|
||||
{
|
||||
const char *label; ///< short command name / label
|
||||
const char *name; ///< human-readable command name
|
||||
const char *description; ///< description (for status line etc.)
|
||||
};
|
||||
|
||||
/// Range, default value, flags and names for a parameter
|
||||
struct parameter_properties
|
||||
{
|
||||
/// default value
|
||||
float def_value;
|
||||
/// minimum value
|
||||
float min;
|
||||
/// maximum value
|
||||
float max;
|
||||
/// number of steps (for an integer value from 0 to 100 this will be 101; for 0/90/180/270/360 this will be 5), or 0 for continuous
|
||||
float step;
|
||||
/// logical OR of parameter_flags
|
||||
uint32_t flags;
|
||||
/// for PF_ENUM: array of text values (from min to max step 1), otherwise NULL
|
||||
const char **choices;
|
||||
/// parameter label (for use in LV2 label field etc.)
|
||||
const char *short_name;
|
||||
/// parameter human-readable name
|
||||
const char *name;
|
||||
/// convert from [0, 1] range to [min, max] (applying scaling)
|
||||
float from_01(double value01) const;
|
||||
/// convert from [min, max] to [0, 1] range (applying reverse scaling)
|
||||
double to_01(float value) const;
|
||||
/// stringify (in sensible way)
|
||||
std::string to_string(float value) const;
|
||||
/// get required width (for reserving GUI space)
|
||||
int get_char_count() const;
|
||||
/// get increment step based on step value (if specified) and other factors
|
||||
float get_increment() const;
|
||||
};
|
||||
|
||||
struct cairo_iface
|
||||
{
|
||||
virtual void set_source_rgba(float r, float g, float b, float a = 1.f) = 0;
|
||||
virtual void set_line_width(float width) = 0;
|
||||
virtual ~cairo_iface() {}
|
||||
};
|
||||
|
||||
struct progress_report_iface
|
||||
{
|
||||
virtual void report_progress(float percentage, const std::string &message) = 0;
|
||||
virtual ~progress_report_iface() {}
|
||||
};
|
||||
|
||||
/// 'provides live line graph values' interface
|
||||
struct line_graph_iface
|
||||
{
|
||||
/// Obtain subindex'th graph of parameter 'index'
|
||||
/// @param index parameter/graph number (usually tied to particular plugin control port)
|
||||
/// @param subindex graph number (there may be multiple overlaid graphs for one parameter, eg. for monosynth 2x12dB filters)
|
||||
/// @param data buffer for normalized output values
|
||||
/// @param points number of points to fill
|
||||
/// @param context cairo context to adjust (for multicolour graphs etc.)
|
||||
/// @retval true graph data was returned; subindex+1 graph may or may not be available
|
||||
/// @retval false graph data was not returned; subindex+1 graph does not exist either
|
||||
virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) { return false; }
|
||||
|
||||
/// Obtain subindex'th dot of parameter 'index'
|
||||
/// @param index parameter/dot number (usually tied to particular plugin control port)
|
||||
/// @param subindex dot number (there may be multiple dots graphs for one parameter)
|
||||
virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) { return false; }
|
||||
|
||||
/// Obtain subindex'th dot of parameter 'index'
|
||||
/// @param index parameter/dot number (usually tied to particular plugin control port)
|
||||
/// @param subindex dot number (there may be multiple dots graphs for one parameter)
|
||||
virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) { return false; }
|
||||
|
||||
/// Obtain subindex'th static graph of parameter index (static graphs are only dependent on parameter value, not plugin state)
|
||||
/// @param index parameter/graph number (usually tied to particular plugin control port)
|
||||
/// @param subindex graph number (there may be multiple overlaid graphs for one parameter, eg. for monosynth 2x12dB filters)
|
||||
/// @param value parameter value to pick the graph for
|
||||
/// @param data buffer for normalized output values
|
||||
/// @param points number of points to fill
|
||||
/// @param context cairo context to adjust (for multicolour graphs etc.)
|
||||
/// @retval true graph data was returned; subindex+1 graph may or may not be available
|
||||
/// @retval false graph data was not returned; subindex+1 graph does not exist either
|
||||
virtual bool get_static_graph(int index, int subindex, float value, float *data, int points, cairo_iface *context) { return false; }
|
||||
|
||||
/// Return which graphs need to be redrawn and which can be cached for later reuse
|
||||
/// @param generation 0 (at start) or the last value returned by the function (corresponds to a set of input values)
|
||||
/// @param subindex_graph First graph that has to be redrawn (because it depends on values that might have changed)
|
||||
/// @param subindex_dot First dot that has to be redrawn
|
||||
/// @param subindex_gridline First gridline/legend that has to be redrawn
|
||||
/// @retval Current generation (to pass when calling the function next time); if different than passed generation value, call the function again to retrieve which graph offsets should be put into cache
|
||||
virtual int get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) { subindex_graph = subindex_dot = subindex_gridline = 0; return 0; }
|
||||
|
||||
/// Standard destructor to make compiler happy
|
||||
virtual ~line_graph_iface() {}
|
||||
};
|
||||
|
||||
enum table_column_type
|
||||
{
|
||||
TCT_UNKNOWN, ///< guard invalid type
|
||||
TCT_FLOAT, ///< float value (encoded as C locale string)
|
||||
TCT_ENUM, ///< enum value (see: 'values' array in table_column_info) - encoded as string base 10 representation of integer
|
||||
TCT_STRING, ///< string value (encoded as C-escaped string)
|
||||
TCT_OBJECT, ///< external object, encoded as string
|
||||
TCT_LABEL, ///< string value (encoded as C-escaped string)
|
||||
};
|
||||
|
||||
/// parameters of
|
||||
struct table_column_info
|
||||
{
|
||||
const char *name; ///< column label
|
||||
table_column_type type; ///< column data type
|
||||
float min; ///< minimum value (for float)
|
||||
float max; ///< maximum value (for float and enum)
|
||||
float def_value; ///< default value (for float and enum)
|
||||
const char **values; ///< NULL unless a TCT_ENUM, where it represents a NULL-terminated list of choices
|
||||
};
|
||||
|
||||
/// 'has string parameters containing tabular data' interface
|
||||
struct table_edit_iface
|
||||
{
|
||||
/// retrieve the table layout for specific parameter
|
||||
virtual const table_column_info *get_table_columns(int param) = 0;
|
||||
|
||||
/// return the current number of rows
|
||||
virtual uint32_t get_table_rows(int param) = 0;
|
||||
|
||||
/// retrieve data item from the plugin
|
||||
virtual std::string get_cell(int param, int row, int column) { return calf_utils::i2s(row)+":"+calf_utils::i2s(column); }
|
||||
|
||||
/// set data item to the plugin
|
||||
virtual void set_cell(int param, int row, int column, const std::string &src, std::string &error) { error.clear(); }
|
||||
|
||||
/// return a line graph interface for a specific parameter/column (unused for now)
|
||||
virtual line_graph_iface *get_graph_iface(int param, int column) { return NULL; }
|
||||
|
||||
/// return an editor name for a specific grid cell (unused for now - I don't even know how editors be implemented)
|
||||
virtual const char *get_cell_editor(int param, int column) { return NULL; }
|
||||
|
||||
virtual ~table_edit_iface() {}
|
||||
};
|
||||
|
||||
/// 'may receive configure variables' interface
|
||||
struct send_configure_iface
|
||||
{
|
||||
/// Called to set configure variable
|
||||
/// @param key variable name
|
||||
/// @param value variable content
|
||||
virtual void send_configure(const char *key, const char *value) = 0;
|
||||
|
||||
virtual ~send_configure_iface() {}
|
||||
};
|
||||
|
||||
/// 'may receive new status values' interface
|
||||
struct send_updates_iface
|
||||
{
|
||||
/// Called to set configure variable
|
||||
/// @param key variable name
|
||||
/// @param value variable content
|
||||
virtual void send_status(const char *key, const char *value) = 0;
|
||||
|
||||
virtual ~send_updates_iface() {}
|
||||
};
|
||||
|
||||
struct plugin_command_info;
|
||||
|
||||
/// General information about the plugin - @todo XXXKF lacks the "new" id-label-name triple
|
||||
struct ladspa_plugin_info
|
||||
{
|
||||
/// LADSPA ID
|
||||
uint32_t unique_id;
|
||||
/// plugin short name (camel case)
|
||||
const char *label;
|
||||
/// plugin human-readable name
|
||||
const char *name;
|
||||
/// maker (author)
|
||||
const char *maker;
|
||||
/// copyright notice
|
||||
const char *copyright;
|
||||
/// plugin type for LRDF/LV2
|
||||
const char *plugin_type;
|
||||
};
|
||||
|
||||
/// An interface returning metadata about a plugin
|
||||
struct plugin_metadata_iface
|
||||
{
|
||||
/// @return plugin long name
|
||||
virtual const char *get_name() = 0;
|
||||
/// @return plugin LV2 label
|
||||
virtual const char *get_id() = 0;
|
||||
/// @return plugin human-readable label
|
||||
virtual const char *get_label() = 0;
|
||||
/// @return total number of parameters
|
||||
virtual int get_param_count() = 0;
|
||||
/// Return custom XML
|
||||
virtual const char *get_gui_xml() = 0;
|
||||
/// @return number of audio inputs
|
||||
virtual int get_input_count()=0;
|
||||
/// @return number of audio outputs
|
||||
virtual int get_output_count()=0;
|
||||
/// @return true if plugin can work in hard-realtime conditions
|
||||
virtual bool is_rt_capable()=0;
|
||||
/// @return true if plugin has MIDI input
|
||||
virtual bool get_midi()=0;
|
||||
/// @return true if plugin has MIDI input
|
||||
virtual bool requires_midi()=0;
|
||||
/// @return port offset of first control (parameter) port (= number of audio inputs + number of audio outputs in all existing plugins as for 1 Aug 2008)
|
||||
virtual int get_param_port_offset() = 0;
|
||||
/// @return line_graph_iface if any
|
||||
virtual line_graph_iface *get_line_graph_iface() = 0;
|
||||
/// @return table_edit_iface if any
|
||||
virtual table_edit_iface *get_table_edit_iface() = 0;
|
||||
/// @return NULL-terminated list of menu commands
|
||||
virtual plugin_command_info *get_commands() { return NULL; }
|
||||
/// @return description structure for given parameter
|
||||
virtual parameter_properties *get_param_props(int param_no) = 0;
|
||||
/// @return retrieve names of audio ports (@note control ports are named in parameter_properties, not here)
|
||||
virtual const char **get_port_names() = 0;
|
||||
/// @return description structure for the plugin
|
||||
virtual const ladspa_plugin_info &get_plugin_info() = 0;
|
||||
/// is a given parameter a control voltage?
|
||||
virtual bool is_cv(int param_no) = 0;
|
||||
/// is the given parameter non-interpolated?
|
||||
virtual bool is_noisy(int param_no) = 0;
|
||||
/// does the plugin require message context? (or DSSI configure) may be slow
|
||||
virtual bool requires_message_context() = 0;
|
||||
/// does the plugin require string port extension? (or DSSI configure) may be slow
|
||||
virtual bool requires_string_ports() = 0;
|
||||
/// add all message context parameter numbers to the ports vector
|
||||
virtual void get_message_context_parameters(std::vector<int> &ports) = 0;
|
||||
|
||||
/// Do-nothing destructor to silence compiler warning
|
||||
virtual ~plugin_metadata_iface() {}
|
||||
};
|
||||
|
||||
/// Interface for host-GUI-plugin interaction (should be really split in two, but ... meh)
|
||||
struct plugin_ctl_iface: public virtual plugin_metadata_iface
|
||||
{
|
||||
/// @return value of given parameter
|
||||
virtual float get_param_value(int param_no) = 0;
|
||||
/// Set value of given parameter
|
||||
virtual void set_param_value(int param_no, float value) = 0;
|
||||
/// Load preset with given number
|
||||
virtual bool activate_preset(int bank, int program) = 0;
|
||||
/// @return volume level for port'th port (if supported by the implementation, currently only jack_host<Module> implements that by measuring signal level on plugin ports)
|
||||
virtual float get_level(unsigned int port)=0;
|
||||
/// Execute menu command with given number
|
||||
virtual void execute(int cmd_no)=0;
|
||||
/// Set a configure variable on a plugin
|
||||
virtual char *configure(const char *key, const char *value) { return NULL; }
|
||||
/// Send all configure variables set within a plugin to given destination (which may be limited to only those that plugin understands)
|
||||
virtual void send_configures(send_configure_iface *)=0;
|
||||
/// Restore all state (parameters and configure vars) to default values - implemented in giface.cpp
|
||||
virtual void clear_preset();
|
||||
/// Call a named function in a plugin - this will most likely be redesigned soon - and never used
|
||||
/// @retval false call has failed, result contains an error message
|
||||
virtual bool blobcall(const char *command, const std::string &request, std::string &result) { result = "Call not supported"; return false; }
|
||||
/// Update status variables changed since last_serial
|
||||
/// @return new last_serial
|
||||
virtual int send_status_updates(send_updates_iface *sui, int last_serial) { return last_serial; }
|
||||
/// Do-nothing destructor to silence compiler warning
|
||||
virtual ~plugin_ctl_iface() {}
|
||||
};
|
||||
|
||||
struct plugin_list_info_iface;
|
||||
|
||||
/// Get a list of all "large" (effect/synthesizer) plugins
|
||||
extern void get_all_plugins(std::vector<plugin_metadata_iface *> &plugins);
|
||||
/// Get a list of all "small" (module) plugins
|
||||
extern void get_all_small_plugins(plugin_list_info_iface *plii);
|
||||
/// Load and strdup a text file with GUI definition
|
||||
extern const char *load_gui_xml(const std::string &plugin_id);
|
||||
|
||||
/// Empty implementations for plugin functions. Note, that functions aren't virtual, because they're called via the particular
|
||||
/// subclass (flanger_audio_module etc) via template wrappers (ladspa_wrapper<> etc), not via base class pointer/reference
|
||||
template<class Metadata>
|
||||
class audio_module: public Metadata
|
||||
{
|
||||
public:
|
||||
typedef Metadata metadata_type;
|
||||
|
||||
progress_report_iface *progress_report;
|
||||
|
||||
audio_module() {
|
||||
progress_report = NULL;
|
||||
}
|
||||
|
||||
/// Handle MIDI Note On
|
||||
inline void note_on(int note, int velocity) {}
|
||||
/// Handle MIDI Note Off
|
||||
inline void note_off(int note, int velocity) {}
|
||||
/// Handle MIDI Program Change
|
||||
inline void program_change(int program) {}
|
||||
/// Handle MIDI Control Change
|
||||
inline void control_change(int controller, int value) {}
|
||||
/// Handle MIDI Pitch Bend
|
||||
/// @param value pitch bend value (-8192 to 8191, defined as in MIDI ie. 8191 = 200 ct by default)
|
||||
inline void pitch_bend(int value) {}
|
||||
/// Handle MIDI Channel Pressure
|
||||
/// @param value channel pressure (0 to 127)
|
||||
inline void channel_pressure(int value) {}
|
||||
/// Called when params are changed (before processing)
|
||||
inline void params_changed() {}
|
||||
/// LADSPA-esque activate function, except it is called after ports are connected, not before
|
||||
inline void activate() {}
|
||||
/// LADSPA-esque deactivate function
|
||||
inline void deactivate() {}
|
||||
/// Set sample rate for the plugin
|
||||
inline void set_sample_rate(uint32_t sr) { }
|
||||
/// Execute menu command with given number
|
||||
inline void execute(int cmd_no) {}
|
||||
/// DSSI configure call
|
||||
virtual char *configure(const char *key, const char *value) { return NULL; }
|
||||
/// Send all understood configure vars (none by default)
|
||||
inline void send_configures(send_configure_iface *sci) {}
|
||||
/// Send all supported status vars (none by default)
|
||||
inline int send_status_updates(send_updates_iface *sui, int last_serial) { return last_serial; }
|
||||
/// Reset parameter values for epp:trigger type parameters (ones activated by oneshot push button instead of check box)
|
||||
inline void params_reset() {}
|
||||
/// Called after instantiating (after all the feature pointers are set - including interfaces like progress_report_iface)
|
||||
inline void post_instantiate() {}
|
||||
/// Handle 'message context' port message
|
||||
/// @arg output_ports pointer to bit array of output port "changed" flags, note that 0 = first audio input, not first parameter (use input_count + output_count)
|
||||
inline uint32_t message_run(const void *valid_ports, void *output_ports) {
|
||||
fprintf(stderr, "ERROR: message run not implemented\n");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
extern bool check_for_message_context_ports(parameter_properties *parameters, int count);
|
||||
extern bool check_for_string_ports(parameter_properties *parameters, int count);
|
||||
|
||||
#if USE_DSSI
|
||||
|
||||
enum line_graph_item
|
||||
{
|
||||
LGI_END = 0,
|
||||
LGI_GRAPH,
|
||||
LGI_SUBGRAPH,
|
||||
LGI_LEGEND,
|
||||
LGI_DOT,
|
||||
LGI_END_ITEM,
|
||||
LGI_SET_RGBA,
|
||||
LGI_SET_WIDTH,
|
||||
};
|
||||
|
||||
/// A class to send status updates via OSC
|
||||
struct dssi_feedback_sender
|
||||
{
|
||||
/// OSC client object used to send updates
|
||||
osctl::osc_client *client;
|
||||
/// Background thread handle
|
||||
pthread_t bg_thread;
|
||||
/// Quit flag (used to terminate the thread)
|
||||
bool quit;
|
||||
/// Indices of graphs to send
|
||||
std::vector<int> indices;
|
||||
/// Source for the graph data (interface to marshal)
|
||||
calf_plugins::line_graph_iface *graph;
|
||||
|
||||
dssi_feedback_sender(const char *URI, line_graph_iface *_graph, calf_plugins::parameter_properties *props, int num_params);
|
||||
void update();
|
||||
~dssi_feedback_sender();
|
||||
};
|
||||
#endif
|
||||
|
||||
/// Metadata base class template, to provide default versions of interface functions
|
||||
template<class Metadata>
|
||||
class plugin_metadata: public virtual plugin_metadata_iface
|
||||
{
|
||||
public:
|
||||
static const char *port_names[];
|
||||
static parameter_properties param_props[];
|
||||
static ladspa_plugin_info plugin_info;
|
||||
|
||||
// These below are stock implementations based on enums and static members in Metadata classes
|
||||
// they may be overridden to provide more interesting functionality
|
||||
|
||||
const char *get_name() { return Metadata::impl_get_name(); }
|
||||
const char *get_id() { return Metadata::impl_get_id(); }
|
||||
const char *get_label() { return Metadata::impl_get_label(); }
|
||||
int get_input_count() { return Metadata::in_count; }
|
||||
int get_output_count() { return Metadata::out_count; }
|
||||
int get_param_count() { return Metadata::param_count; }
|
||||
bool get_midi() { return Metadata::support_midi; }
|
||||
bool requires_midi() { return Metadata::require_midi; }
|
||||
bool is_rt_capable() { return Metadata::rt_capable; }
|
||||
line_graph_iface *get_line_graph_iface() { return dynamic_cast<line_graph_iface *>(this); }
|
||||
table_edit_iface *get_table_edit_iface() { return dynamic_cast<table_edit_iface *>(this); }
|
||||
int get_param_port_offset() { return Metadata::in_count + Metadata::out_count; }
|
||||
const char *get_gui_xml() { static const char *data_ptr = calf_plugins::load_gui_xml(get_id()); return data_ptr; }
|
||||
plugin_command_info *get_commands() { return NULL; }
|
||||
parameter_properties *get_param_props(int param_no) { return ¶m_props[param_no]; }
|
||||
const char **get_port_names() { return port_names; }
|
||||
bool is_cv(int param_no) { return true; }
|
||||
bool is_noisy(int param_no) { return false; }
|
||||
const ladspa_plugin_info &get_plugin_info() { return plugin_info; }
|
||||
bool requires_message_context() { return check_for_message_context_ports(param_props, Metadata::param_count); }
|
||||
bool requires_string_ports() { return check_for_string_ports(param_props, Metadata::param_count); }
|
||||
void get_message_context_parameters(std::vector<int> &ports) {
|
||||
for (int i = 0; i < get_param_count(); ++i) {
|
||||
if (get_param_props(i)->flags & PF_PROP_MSGCONTEXT)
|
||||
ports.push_back(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// A class for delegating metadata implementation to a "remote" metadata class.
|
||||
/// Used for GUI wrappers that cannot have a dependency on actual classes,
|
||||
/// and which instead take an "external" metadata object pointer, obtained
|
||||
/// through get_all_plugins.
|
||||
class plugin_metadata_proxy: public virtual plugin_metadata_iface
|
||||
{
|
||||
public:
|
||||
plugin_metadata_iface *impl;
|
||||
public:
|
||||
plugin_metadata_proxy(plugin_metadata_iface *_impl) { impl = _impl; }
|
||||
const char *get_name() { return impl->get_name(); }
|
||||
const char *get_id() { return impl->get_id(); }
|
||||
const char *get_label() { return impl->get_label(); }
|
||||
int get_input_count() { return impl->get_input_count(); }
|
||||
int get_output_count() { return impl->get_output_count(); }
|
||||
int get_param_count() { return impl->get_param_count(); }
|
||||
bool get_midi() { return impl->get_midi(); }
|
||||
bool requires_midi() { return impl->requires_midi(); }
|
||||
bool is_rt_capable() { return impl->is_rt_capable(); }
|
||||
line_graph_iface *get_line_graph_iface() { return impl->get_line_graph_iface(); }
|
||||
table_edit_iface *get_table_edit_iface() { return impl->get_table_edit_iface(); }
|
||||
int get_param_port_offset() { return impl->get_param_port_offset(); }
|
||||
const char *get_gui_xml() { return impl->get_gui_xml(); }
|
||||
plugin_command_info *get_commands() { return impl->get_commands(); }
|
||||
parameter_properties *get_param_props(int param_no) { return impl->get_param_props(param_no); }
|
||||
const char **get_port_names() { return impl->get_port_names(); }
|
||||
bool is_cv(int param_no) { return impl->is_cv(param_no); }
|
||||
bool is_noisy(int param_no) { return impl->is_noisy(param_no); }
|
||||
const ladspa_plugin_info &get_plugin_info() { return impl->get_plugin_info(); }
|
||||
bool requires_message_context() { return impl->requires_message_context(); }
|
||||
bool requires_string_ports() { return impl->requires_string_ports(); }
|
||||
void get_message_context_parameters(std::vector<int> &ports) { impl->get_message_context_parameters(ports); }
|
||||
};
|
||||
|
||||
#define CALF_PORT_NAMES(name) template<> const char *::plugin_metadata<name##_metadata>::port_names[]
|
||||
#define CALF_PORT_PROPS(name) template<> parameter_properties plugin_metadata<name##_metadata>::param_props[]
|
||||
#define CALF_PLUGIN_INFO(name) template<> calf_plugins::ladspa_plugin_info plugin_metadata<name##_metadata>::plugin_info
|
||||
#define PLUGIN_NAME_ID_LABEL(name, id, label) \
|
||||
static const char *impl_get_name() { return name; } \
|
||||
static const char *impl_get_id() { return id; } \
|
||||
static const char *impl_get_label() { return label; } \
|
||||
|
||||
|
||||
extern const char *calf_copyright_info;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
256
plugins/ladspa_effect/calf/calf/inertia.h
Normal file
@@ -0,0 +1,256 @@
|
||||
/* Calf DSP Library
|
||||
* Basic "inertia" (parameter smoothing) classes.
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_INERTIA_H
|
||||
#define __CALF_INERTIA_H
|
||||
|
||||
#include "primitives.h"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
/// Algorithm for a constant time linear ramp
|
||||
class linear_ramp
|
||||
{
|
||||
public:
|
||||
int ramp_len;
|
||||
float mul, delta;
|
||||
public:
|
||||
/// Construct for given ramp length
|
||||
linear_ramp(int _ramp_len) {
|
||||
ramp_len = _ramp_len;
|
||||
mul = (float)(1.0f / ramp_len);
|
||||
}
|
||||
/// Change ramp length
|
||||
inline void set_length(int _ramp_len) {
|
||||
ramp_len = _ramp_len;
|
||||
mul = (float)(1.0f / ramp_len);
|
||||
}
|
||||
inline int length()
|
||||
{
|
||||
return ramp_len;
|
||||
}
|
||||
inline void start_ramp(float start, float end)
|
||||
{
|
||||
delta = mul * (end - start);
|
||||
}
|
||||
/// Return value after single step
|
||||
inline float ramp(float value)
|
||||
{
|
||||
return value + delta;
|
||||
}
|
||||
/// Return value after many steps
|
||||
inline float ramp_many(float value, int count)
|
||||
{
|
||||
return value + delta * count;
|
||||
}
|
||||
};
|
||||
|
||||
/// Algorithm for a constant time linear ramp
|
||||
class exponential_ramp
|
||||
{
|
||||
public:
|
||||
int ramp_len;
|
||||
float root, delta;
|
||||
public:
|
||||
exponential_ramp(int _ramp_len) {
|
||||
ramp_len = _ramp_len;
|
||||
root = (float)(1.0f / ramp_len);
|
||||
}
|
||||
inline void set_length(int _ramp_len) {
|
||||
ramp_len = _ramp_len;
|
||||
root = (float)(1.0f / ramp_len);
|
||||
}
|
||||
inline int length()
|
||||
{
|
||||
return ramp_len;
|
||||
}
|
||||
inline void start_ramp(float start, float end)
|
||||
{
|
||||
delta = pow(end / start, root);
|
||||
}
|
||||
/// Return value after single step
|
||||
inline float ramp(float value)
|
||||
{
|
||||
return value * delta;
|
||||
}
|
||||
/// Return value after many steps
|
||||
inline float ramp_many(float value, float count)
|
||||
{
|
||||
return value * pow(delta, count);
|
||||
}
|
||||
};
|
||||
|
||||
/// Generic inertia using ramping algorithm specified as template argument. The basic idea
|
||||
/// is producing smooth(ish) output for discrete input, using specified algorithm to go from
|
||||
/// last output value to input value. It is not the same as classic running average lowpass
|
||||
/// filter, because ramping time is finite and pre-determined (it calls ramp algorithm's length()
|
||||
/// function to obtain the expected ramp length)
|
||||
template<class Ramp>
|
||||
class inertia
|
||||
{
|
||||
public:
|
||||
float old_value;
|
||||
float value;
|
||||
unsigned int count;
|
||||
Ramp ramp;
|
||||
|
||||
public:
|
||||
inertia(const Ramp &_ramp, float init_value = 0.f)
|
||||
: ramp(_ramp)
|
||||
{
|
||||
value = old_value = init_value;
|
||||
count = 0;
|
||||
}
|
||||
/// Set value immediately (no inertia)
|
||||
void set_now(float _value)
|
||||
{
|
||||
value = old_value = _value;
|
||||
count = 0;
|
||||
}
|
||||
/// Set with inertia
|
||||
void set_inertia(float source)
|
||||
{
|
||||
if (source != old_value) {
|
||||
ramp.start_ramp(value, source);
|
||||
count = ramp.length();
|
||||
old_value = source;
|
||||
}
|
||||
}
|
||||
/// Get smoothed value of given source value
|
||||
inline float get(float source)
|
||||
{
|
||||
if (source != old_value) {
|
||||
ramp.start_ramp(value, source);
|
||||
count = ramp.length();
|
||||
old_value = source;
|
||||
}
|
||||
if (!count)
|
||||
return old_value;
|
||||
value = ramp.ramp(value);
|
||||
count--;
|
||||
if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
|
||||
value = old_value;
|
||||
return value;
|
||||
}
|
||||
/// Get smoothed value assuming no new input
|
||||
inline float get()
|
||||
{
|
||||
if (!count)
|
||||
return old_value;
|
||||
value = ramp.ramp(value);
|
||||
count--;
|
||||
if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
|
||||
value = old_value;
|
||||
return value;
|
||||
}
|
||||
/// Do one inertia step, without returning the new value and without changing destination value
|
||||
inline void step()
|
||||
{
|
||||
if (count) {
|
||||
value = ramp.ramp(value);
|
||||
count--;
|
||||
if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
|
||||
value = old_value;
|
||||
}
|
||||
}
|
||||
/// Do many inertia steps, without returning the new value and without changing destination value
|
||||
inline void step_many(unsigned int steps)
|
||||
{
|
||||
if (steps < count) {
|
||||
// Skip only a part of the current ramping period
|
||||
value = ramp.ramp_many(value, steps);
|
||||
count -= steps;
|
||||
if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
|
||||
value = old_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The whole ramping period has been skipped, just go to destination
|
||||
value = old_value;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
/// Get last smoothed value, without affecting anything
|
||||
inline float get_last() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
/// Is it still ramping?
|
||||
inline bool active() const
|
||||
{
|
||||
return count > 0;
|
||||
}
|
||||
};
|
||||
|
||||
class once_per_n
|
||||
{
|
||||
public:
|
||||
unsigned int frequency;
|
||||
unsigned int left;
|
||||
public:
|
||||
once_per_n(unsigned int _frequency)
|
||||
: frequency(_frequency), left(_frequency)
|
||||
{}
|
||||
inline void start()
|
||||
{
|
||||
left = frequency;
|
||||
}
|
||||
/// Set timer to "elapsed" state (elapsed() will return true during next call)
|
||||
inline void signal()
|
||||
{
|
||||
left = 0;
|
||||
}
|
||||
inline unsigned int get(unsigned int desired)
|
||||
{
|
||||
if (desired > left) {
|
||||
desired = left;
|
||||
left = 0;
|
||||
return desired;
|
||||
}
|
||||
left -= desired;
|
||||
return desired;
|
||||
}
|
||||
inline bool elapsed()
|
||||
{
|
||||
if (!left) {
|
||||
left = frequency;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class gain_smoothing: public inertia<linear_ramp>
|
||||
{
|
||||
public:
|
||||
gain_smoothing()
|
||||
: inertia<linear_ramp>(linear_ramp(64))
|
||||
{
|
||||
}
|
||||
void set_sample_rate(int sr)
|
||||
{
|
||||
ramp = linear_ramp(sr / 441);
|
||||
}
|
||||
// to change param, use set_inertia(value)
|
||||
// to read param, use get()
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
516
plugins/ladspa_effect/calf/calf/ladspa_wrap.h
Normal file
@@ -0,0 +1,516 @@
|
||||
/* Calf DSP Library
|
||||
* API wrappers for LADSPA/DSSI
|
||||
*
|
||||
* Copyright (C) 2007-2008 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_LADSPA_WRAP_H
|
||||
#define __CALF_LADSPA_WRAP_H
|
||||
|
||||
#if USE_LADSPA
|
||||
|
||||
#include <ladspa.h>
|
||||
#if USE_DSSI
|
||||
#include <dssi.h>
|
||||
#endif
|
||||
#include "giface.h"
|
||||
|
||||
namespace calf_plugins {
|
||||
|
||||
template<class Module>
|
||||
inline int calc_real_param_count()
|
||||
{
|
||||
for (int i=0; i < Module::param_count; i++)
|
||||
{
|
||||
if ((Module::param_props[i].flags & PF_TYPEMASK) >= PF_STRING)
|
||||
return i;
|
||||
}
|
||||
return Module::param_count;
|
||||
}
|
||||
|
||||
/// A template implementing plugin_ctl_iface for a given plugin
|
||||
template<class Module>
|
||||
struct ladspa_instance: public Module, public plugin_ctl_iface
|
||||
{
|
||||
bool activate_flag;
|
||||
#if USE_DSSI
|
||||
dssi_feedback_sender *feedback_sender;
|
||||
#endif
|
||||
|
||||
static int real_param_count()
|
||||
{
|
||||
static int _real_param_count = calc_real_param_count<Module>();
|
||||
return _real_param_count;
|
||||
}
|
||||
ladspa_instance()
|
||||
{
|
||||
for (int i=0; i < Module::in_count; i++)
|
||||
Module::ins[i] = NULL;
|
||||
for (int i=0; i < Module::out_count; i++)
|
||||
Module::outs[i] = NULL;
|
||||
int rpc = real_param_count();
|
||||
for (int i=0; i < rpc; i++)
|
||||
Module::params[i] = NULL;
|
||||
activate_flag = true;
|
||||
#if USE_DSSI
|
||||
feedback_sender = NULL;
|
||||
#endif
|
||||
}
|
||||
virtual parameter_properties *get_param_props(int param_no)
|
||||
{
|
||||
return &Module::param_props[param_no];
|
||||
}
|
||||
virtual float get_param_value(int param_no)
|
||||
{
|
||||
// XXXKF hack
|
||||
if (param_no >= real_param_count())
|
||||
return 0;
|
||||
return *Module::params[param_no];
|
||||
}
|
||||
virtual void set_param_value(int param_no, float value)
|
||||
{
|
||||
// XXXKF hack
|
||||
if (param_no >= real_param_count())
|
||||
return;
|
||||
*Module::params[param_no] = value;
|
||||
}
|
||||
virtual int get_param_count()
|
||||
{
|
||||
return real_param_count();
|
||||
}
|
||||
virtual int get_param_port_offset()
|
||||
{
|
||||
return Module::in_count + Module::out_count;
|
||||
}
|
||||
virtual const char *get_gui_xml() {
|
||||
return Module::get_gui_xml();
|
||||
}
|
||||
virtual line_graph_iface *get_line_graph_iface()
|
||||
{
|
||||
return dynamic_cast<line_graph_iface *>(this);
|
||||
}
|
||||
virtual bool activate_preset(int bank, int program) {
|
||||
return false;
|
||||
}
|
||||
virtual const char *get_name()
|
||||
{
|
||||
return Module::get_name();
|
||||
}
|
||||
virtual const char *get_id()
|
||||
{
|
||||
return Module::get_id();
|
||||
}
|
||||
virtual const char *get_label()
|
||||
{
|
||||
return Module::get_label();
|
||||
}
|
||||
virtual char *configure(const char *key, const char *value)
|
||||
{
|
||||
#if USE_DSSI
|
||||
if (!strcmp(key, "OSC:FEEDBACK_URI"))
|
||||
{
|
||||
line_graph_iface *lgi = dynamic_cast<line_graph_iface *>(this);
|
||||
if (!lgi)
|
||||
return NULL;
|
||||
if (*value)
|
||||
{
|
||||
if (feedback_sender) {
|
||||
delete feedback_sender;
|
||||
feedback_sender = NULL;
|
||||
}
|
||||
feedback_sender = new dssi_feedback_sender(value, lgi, get_param_props(0), get_param_count());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (feedback_sender) {
|
||||
delete feedback_sender;
|
||||
feedback_sender = NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
if (!strcmp(key, "OSC:UPDATE"))
|
||||
{
|
||||
if (feedback_sender)
|
||||
feedback_sender->update();
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!strcmp(key, "ExecCommand"))
|
||||
{
|
||||
if (*value)
|
||||
{
|
||||
execute(atoi(value));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return Module::configure(key, value);
|
||||
}
|
||||
virtual int get_input_count() { return Module::in_count; }
|
||||
virtual int get_output_count() { return Module::out_count; }
|
||||
virtual bool get_midi() { return Module::support_midi; }
|
||||
virtual float get_level(unsigned int port) { return 0.f; }
|
||||
virtual void execute(int cmd_no) {
|
||||
Module::execute(cmd_no);
|
||||
}
|
||||
virtual void send_configures(send_configure_iface *sci) {
|
||||
Module::send_configures(sci);
|
||||
}
|
||||
};
|
||||
|
||||
/// A wrapper class for plugin class object (there is only one ladspa_wrapper for many instances of the same plugin)
|
||||
template<class Module>
|
||||
struct ladspa_wrapper
|
||||
{
|
||||
typedef ladspa_instance<Module> instance;
|
||||
|
||||
/// LADSPA descriptor
|
||||
static LADSPA_Descriptor descriptor;
|
||||
/// LADSPA descriptor for DSSI (uses a different name for the plugin, otherwise same as descriptor)
|
||||
static LADSPA_Descriptor descriptor_for_dssi;
|
||||
#if USE_DSSI
|
||||
/// Extended DSSI descriptor (points to descriptor_for_dssi for things like name/label/port info etc.)
|
||||
static DSSI_Descriptor dssi_descriptor;
|
||||
static DSSI_Program_Descriptor dssi_default_program;
|
||||
|
||||
static std::vector<plugin_preset> *presets;
|
||||
static std::vector<DSSI_Program_Descriptor> *preset_descs;
|
||||
#endif
|
||||
|
||||
ladspa_wrapper()
|
||||
{
|
||||
int ins = Module::in_count;
|
||||
int outs = Module::out_count;
|
||||
int params = ladspa_instance<Module>::real_param_count();
|
||||
ladspa_plugin_info &plugin_info = Module::plugin_info;
|
||||
descriptor.UniqueID = plugin_info.unique_id;
|
||||
descriptor.Label = plugin_info.label;
|
||||
descriptor.Name = strdup((std::string(plugin_info.name) + " LADSPA").c_str());
|
||||
descriptor.Maker = plugin_info.maker;
|
||||
descriptor.Copyright = plugin_info.copyright;
|
||||
descriptor.Properties = Module::rt_capable ? LADSPA_PROPERTY_HARD_RT_CAPABLE : 0;
|
||||
descriptor.PortCount = ins + outs + params;
|
||||
descriptor.PortNames = new char *[descriptor.PortCount];
|
||||
descriptor.PortDescriptors = new LADSPA_PortDescriptor[descriptor.PortCount];
|
||||
descriptor.PortRangeHints = new LADSPA_PortRangeHint[descriptor.PortCount];
|
||||
int i;
|
||||
for (i = 0; i < ins + outs; i++)
|
||||
{
|
||||
LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i];
|
||||
((int *)descriptor.PortDescriptors)[i] = i < ins ? LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO
|
||||
: i < ins + outs ? LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
|
||||
: LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
|
||||
prh.HintDescriptor = 0;
|
||||
((const char **)descriptor.PortNames)[i] = Module::port_names[i];
|
||||
}
|
||||
for (; i < ins + outs + params; i++)
|
||||
{
|
||||
LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i];
|
||||
parameter_properties &pp = Module::param_props[i - ins - outs];
|
||||
((int *)descriptor.PortDescriptors)[i] =
|
||||
LADSPA_PORT_CONTROL | (pp.flags & PF_PROP_OUTPUT ? LADSPA_PORT_OUTPUT : LADSPA_PORT_INPUT);
|
||||
prh.HintDescriptor = LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW;
|
||||
((const char **)descriptor.PortNames)[i] = pp.name;
|
||||
prh.LowerBound = pp.min;
|
||||
prh.UpperBound = pp.max;
|
||||
switch(pp.flags & PF_TYPEMASK) {
|
||||
case PF_BOOL:
|
||||
prh.HintDescriptor |= LADSPA_HINT_TOGGLED;
|
||||
prh.HintDescriptor &= ~(LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW);
|
||||
break;
|
||||
case PF_INT:
|
||||
case PF_ENUM:
|
||||
prh.HintDescriptor |= LADSPA_HINT_INTEGER;
|
||||
break;
|
||||
default: {
|
||||
int defpt = (int)(100 * (pp.def_value - pp.min) / (pp.max - pp.min));
|
||||
if ((pp.flags & PF_SCALEMASK) == PF_SCALE_LOG)
|
||||
defpt = (int)(100 * log(pp.def_value / pp.min) / log(pp.max / pp.min));
|
||||
if (defpt < 12)
|
||||
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM;
|
||||
else if (defpt < 37)
|
||||
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_LOW;
|
||||
else if (defpt < 63)
|
||||
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE;
|
||||
else if (defpt < 88)
|
||||
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH;
|
||||
else
|
||||
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM;
|
||||
}
|
||||
}
|
||||
if (pp.def_value == 0 || pp.def_value == 1 || pp.def_value == 100 || pp.def_value == 440 ) {
|
||||
prh.HintDescriptor &= ~LADSPA_HINT_DEFAULT_MASK;
|
||||
if (pp.def_value == 1)
|
||||
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_1;
|
||||
else if (pp.def_value == 100)
|
||||
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_100;
|
||||
else if (pp.def_value == 440)
|
||||
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_440;
|
||||
else
|
||||
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_0;
|
||||
}
|
||||
switch(pp.flags & PF_SCALEMASK) {
|
||||
case PF_SCALE_LOG:
|
||||
prh.HintDescriptor |= LADSPA_HINT_LOGARITHMIC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
descriptor.ImplementationData = this;
|
||||
descriptor.instantiate = cb_instantiate;
|
||||
descriptor.connect_port = cb_connect;
|
||||
descriptor.activate = cb_activate;
|
||||
descriptor.run = cb_run;
|
||||
descriptor.run_adding = NULL;
|
||||
descriptor.set_run_adding_gain = NULL;
|
||||
descriptor.deactivate = cb_deactivate;
|
||||
descriptor.cleanup = cb_cleanup;
|
||||
#if USE_DSSI
|
||||
memcpy(&descriptor_for_dssi, &descriptor, sizeof(descriptor));
|
||||
descriptor_for_dssi.Name = strdup((std::string(plugin_info.name) + " DSSI").c_str());
|
||||
memset(&dssi_descriptor, 0, sizeof(dssi_descriptor));
|
||||
dssi_descriptor.DSSI_API_Version = 1;
|
||||
dssi_descriptor.LADSPA_Plugin = &descriptor_for_dssi;
|
||||
dssi_descriptor.configure = cb_configure;
|
||||
dssi_descriptor.get_program = cb_get_program;
|
||||
dssi_descriptor.select_program = cb_select_program;
|
||||
if (Module::support_midi)
|
||||
dssi_descriptor.run_synth = cb_run_synth;
|
||||
|
||||
presets = new std::vector<plugin_preset>;
|
||||
preset_descs = new std::vector<DSSI_Program_Descriptor>;
|
||||
|
||||
preset_list plist_tmp, plist;
|
||||
plist.load_defaults(true);
|
||||
plist_tmp.load_defaults(false);
|
||||
plist.presets.insert(plist.presets.end(), plist_tmp.presets.begin(), plist_tmp.presets.end());
|
||||
|
||||
// XXXKF this assumes that plugin name in preset is case-insensitive equal to plugin label
|
||||
// if I forget about this, I'll be in a deep trouble
|
||||
dssi_default_program.Bank = 0;
|
||||
dssi_default_program.Program = 0;
|
||||
dssi_default_program.Name = "default";
|
||||
|
||||
int pos = 1;
|
||||
for (unsigned int i = 0; i < plist.presets.size(); i++)
|
||||
{
|
||||
plugin_preset &pp = plist.presets[i];
|
||||
if (strcasecmp(pp.plugin.c_str(), descriptor.Label))
|
||||
continue;
|
||||
DSSI_Program_Descriptor pd;
|
||||
pd.Bank = pos >> 7;
|
||||
pd.Program = pos++;
|
||||
pd.Name = pp.name.c_str();
|
||||
preset_descs->push_back(pd);
|
||||
presets->push_back(pp);
|
||||
}
|
||||
// printf("presets = %p:%d name = %s\n", presets, presets->size(), descriptor.Label);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
~ladspa_wrapper()
|
||||
{
|
||||
delete []descriptor.PortNames;
|
||||
delete []descriptor.PortDescriptors;
|
||||
delete []descriptor.PortRangeHints;
|
||||
#if USE_DSSI
|
||||
presets->clear();
|
||||
preset_descs->clear();
|
||||
delete presets;
|
||||
delete preset_descs;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// LADSPA instantiation function (create a plugin instance)
|
||||
static LADSPA_Handle cb_instantiate(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate)
|
||||
{
|
||||
instance *mod = new instance();
|
||||
mod->set_sample_rate(sample_rate);
|
||||
mod->post_instantiate();
|
||||
return mod;
|
||||
}
|
||||
|
||||
#if USE_DSSI
|
||||
/// DSSI get program descriptor function; for 0, it returns the default program (from parameter properties table), for others, it uses global or user preset
|
||||
static const DSSI_Program_Descriptor *cb_get_program(LADSPA_Handle Instance, unsigned long index) {
|
||||
if (index > presets->size())
|
||||
return NULL;
|
||||
if (index)
|
||||
return &(*preset_descs)[index - 1];
|
||||
return &dssi_default_program;
|
||||
}
|
||||
|
||||
/// DSSI select program function; for 0, it sets the defaults, for others, it sets global or user preset
|
||||
static void cb_select_program(LADSPA_Handle Instance, unsigned long Bank, unsigned long Program) {
|
||||
instance *mod = (instance *)Instance;
|
||||
unsigned int no = (Bank << 7) + Program - 1;
|
||||
// printf("no = %d presets = %p:%d\n", no, presets, presets->size());
|
||||
if (no == -1U) {
|
||||
int rpc = ladspa_instance<Module>::real_param_count();
|
||||
for (int i =0 ; i < rpc; i++)
|
||||
*mod->params[i] = Module::param_props[i].def_value;
|
||||
return;
|
||||
}
|
||||
if (no >= presets->size())
|
||||
return;
|
||||
plugin_preset &p = (*presets)[no];
|
||||
// printf("activating preset %s\n", p.name.c_str());
|
||||
p.activate(mod);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// LADSPA port connection function
|
||||
static void cb_connect(LADSPA_Handle Instance, unsigned long port, LADSPA_Data *DataLocation) {
|
||||
unsigned long ins = Module::in_count;
|
||||
unsigned long outs = Module::out_count;
|
||||
unsigned long params = ladspa_instance<Module>::real_param_count();
|
||||
instance *const mod = (instance *)Instance;
|
||||
if (port < ins)
|
||||
mod->ins[port] = DataLocation;
|
||||
else if (port < ins + outs)
|
||||
mod->outs[port - ins] = DataLocation;
|
||||
else if (port < ins + outs + params) {
|
||||
int i = port - ins - outs;
|
||||
mod->params[i] = DataLocation;
|
||||
*mod->params[i] = Module::param_props[i].def_value;
|
||||
}
|
||||
}
|
||||
|
||||
/// LADSPA activate function (note that at this moment the ports are not set)
|
||||
static void cb_activate(LADSPA_Handle Instance) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
mod->activate_flag = true;
|
||||
}
|
||||
|
||||
/// utility function: zero port values if mask is 0
|
||||
static inline void zero_by_mask(Module *module, uint32_t mask, uint32_t offset, uint32_t nsamples)
|
||||
{
|
||||
for (int i=0; i<Module::out_count; i++) {
|
||||
if ((mask & (1 << i)) == 0) {
|
||||
dsp::zero(module->outs[i] + offset, nsamples);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// LADSPA run function - does set sample rate / activate logic when it's run first time after activation
|
||||
static void cb_run(LADSPA_Handle Instance, unsigned long SampleCount) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
if (mod->activate_flag)
|
||||
{
|
||||
mod->activate();
|
||||
mod->activate_flag = false;
|
||||
}
|
||||
mod->params_changed();
|
||||
process_slice(mod, 0, SampleCount);
|
||||
}
|
||||
|
||||
/// utility function: call process, and if it returned zeros in output masks, zero out the relevant output port buffers
|
||||
static inline void process_slice(Module *mod, uint32_t offset, uint32_t end)
|
||||
{
|
||||
while(offset < end)
|
||||
{
|
||||
uint32_t newend = std::min(offset + MAX_SAMPLE_RUN, end);
|
||||
uint32_t out_mask = mod->process(offset, newend - offset, -1, -1);
|
||||
zero_by_mask(mod, out_mask, offset, newend - offset);
|
||||
offset = newend;
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_DSSI
|
||||
/// DSSI "run synth" function, same as run() except it allows for event delivery
|
||||
static void cb_run_synth(LADSPA_Handle Instance, unsigned long SampleCount,
|
||||
snd_seq_event_t *Events, unsigned long EventCount) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
if (mod->activate_flag)
|
||||
{
|
||||
mod->activate();
|
||||
mod->activate_flag = false;
|
||||
}
|
||||
mod->params_changed();
|
||||
|
||||
uint32_t offset = 0;
|
||||
for (uint32_t e = 0; e < EventCount; e++)
|
||||
{
|
||||
uint32_t timestamp = Events[e].time.tick;
|
||||
if (timestamp != offset)
|
||||
process_slice(mod, offset, timestamp);
|
||||
process_dssi_event(mod, Events[e]);
|
||||
offset = timestamp;
|
||||
}
|
||||
if (offset != SampleCount)
|
||||
process_slice(mod, offset, SampleCount);
|
||||
}
|
||||
|
||||
/// DSSI configure function (named properties)
|
||||
static char *cb_configure(LADSPA_Handle Instance,
|
||||
const char *Key,
|
||||
const char *Value)
|
||||
{
|
||||
instance *const mod = (instance *)Instance;
|
||||
return mod->configure(Key, Value);
|
||||
}
|
||||
|
||||
/// Utility function: handle MIDI event (only handles a subset in this version)
|
||||
static void process_dssi_event(Module *module, snd_seq_event_t &event)
|
||||
{
|
||||
switch(event.type) {
|
||||
case SND_SEQ_EVENT_NOTEON:
|
||||
module->note_on(event.data.note.note, event.data.note.velocity);
|
||||
break;
|
||||
case SND_SEQ_EVENT_NOTEOFF:
|
||||
module->note_off(event.data.note.note, event.data.note.velocity);
|
||||
break;
|
||||
case SND_SEQ_EVENT_PGMCHANGE:
|
||||
module->program_change(event.data.control.value);
|
||||
break;
|
||||
case SND_SEQ_EVENT_CONTROLLER:
|
||||
module->control_change(event.data.control.param, event.data.control.value);
|
||||
break;
|
||||
case SND_SEQ_EVENT_PITCHBEND:
|
||||
module->pitch_bend(event.data.control.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// LADSPA deactivate function
|
||||
static void cb_deactivate(LADSPA_Handle Instance) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
mod->deactivate();
|
||||
}
|
||||
|
||||
/// LADSPA cleanup (delete instance) function
|
||||
static void cb_cleanup(LADSPA_Handle Instance) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
delete mod;
|
||||
}
|
||||
|
||||
/// Get a wrapper singleton - used to prevent initialization order problems which were present in older versions
|
||||
static ladspa_wrapper &get() {
|
||||
static ladspa_wrapper instance;
|
||||
return instance;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
90
plugins/ladspa_effect/calf/calf/loudness.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* Calf DSP Library
|
||||
* A-weighting filter for
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* Most of code in this file is based on freely
|
||||
* available other work of other people (filter equations).
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_LOUDNESS_H
|
||||
#define __CALF_LOUDNESS_H
|
||||
|
||||
#include "biquad.h"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
class aweighter {
|
||||
public:
|
||||
biquad_d2<float> bq1, bq2, bq3;
|
||||
|
||||
/// Produce one output sample from one input sample
|
||||
float process(float sample)
|
||||
{
|
||||
return bq1.process(bq2.process(bq3.process(sample)));
|
||||
}
|
||||
|
||||
/// Set sample rate (updates filter coefficients)
|
||||
void set(float sr)
|
||||
{
|
||||
// analog coeffs taken from: http://www.diracdelta.co.uk/science/source/a/w/aweighting/source.html
|
||||
// first we need to adjust them by doing some obscene sort of reverse pre-warping (a broken one, too!)
|
||||
float f1 = biquad_coeffs<float>::unwarpf(20.6f, sr);
|
||||
float f2 = biquad_coeffs<float>::unwarpf(107.7f, sr);
|
||||
float f3 = biquad_coeffs<float>::unwarpf(738.f, sr);
|
||||
float f4 = biquad_coeffs<float>::unwarpf(12200.f, sr);
|
||||
// then map s domain to z domain using bilinear transform
|
||||
// note: f1 and f4 are double poles
|
||||
bq1.set_bilinear(0, 0, 1, f1*f1, 2 * f1, 1);
|
||||
bq2.set_bilinear(1, 0, 0, f2*f3, f2 + f3, 1);
|
||||
bq3.set_bilinear(0, 0, 1, f4*f4, 2 * f4, 1);
|
||||
// the coeffs above give non-normalized value, so it should be normalized to produce 0dB at 1 kHz
|
||||
// find actual gain
|
||||
float gain1kHz = freq_gain(1000.0, sr);
|
||||
// divide one filter's x[n-m] coefficients by that value
|
||||
float gc = 1.0 / gain1kHz;
|
||||
bq1.a0 *= gc;
|
||||
bq1.a1 *= gc;
|
||||
bq1.a2 *= gc;
|
||||
}
|
||||
|
||||
/// Reset to zero if at risk of denormals
|
||||
void sanitize()
|
||||
{
|
||||
bq1.sanitize();
|
||||
bq2.sanitize();
|
||||
bq3.sanitize();
|
||||
}
|
||||
|
||||
/// Reset state to zero
|
||||
void reset()
|
||||
{
|
||||
bq1.reset();
|
||||
bq2.reset();
|
||||
bq3.reset();
|
||||
}
|
||||
|
||||
/// Gain and a given frequency
|
||||
float freq_gain(float freq, float sr)
|
||||
{
|
||||
return bq1.freq_gain(freq, sr) * bq2.freq_gain(freq, sr) * bq3.freq_gain(freq, sr);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
281
plugins/ladspa_effect/calf/calf/lv2helpers.h
Normal file
@@ -0,0 +1,281 @@
|
||||
/* Calf DSP Library
|
||||
* LV2-related helper classes and functions
|
||||
*
|
||||
* Copyright (C) 2001-2008 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef CALF_LV2HELPERS_H
|
||||
#define CALF_LV2HELPERS_H
|
||||
|
||||
#if USE_LV2
|
||||
|
||||
#include <calf/lv2_event.h>
|
||||
#include <calf/lv2_uri_map.h>
|
||||
|
||||
class uri_map_access
|
||||
{
|
||||
public:
|
||||
/// URI map feature pointer (previously in a mixin, but polymorphic ports made it necessary for most plugins)
|
||||
LV2_URI_Map_Feature *uri_map;
|
||||
|
||||
uri_map_access()
|
||||
: uri_map(NULL)
|
||||
{}
|
||||
|
||||
/// Map an URI through an URI map
|
||||
uint32_t map_uri(const char *ns, const char *URI)
|
||||
{
|
||||
if (uri_map)
|
||||
return uri_map->uri_to_id(uri_map->callback_data, ns, URI);
|
||||
return 0;
|
||||
}
|
||||
/// Called on instantiation for every LV2 feature sent by a host
|
||||
void use_feature(const char *URI, void *data) {
|
||||
if (!strcmp(URI, LV2_URI_MAP_URI))
|
||||
{
|
||||
uri_map = (LV2_URI_Map_Feature *)data;
|
||||
map_uris();
|
||||
}
|
||||
}
|
||||
virtual void map_uris()
|
||||
{
|
||||
}
|
||||
virtual ~uri_map_access() {}
|
||||
};
|
||||
|
||||
/// A mixin for adding the event feature and URI map to the small plugin
|
||||
template<class T>
|
||||
class event_mixin: public T
|
||||
{
|
||||
public:
|
||||
/// Event feature pointer
|
||||
LV2_Event_Feature *event_feature;
|
||||
virtual void use_feature(const char *URI, void *data) {
|
||||
if (!strcmp(URI, LV2_EVENT_URI))
|
||||
{
|
||||
event_feature = (LV2_Event_Feature *)data;
|
||||
}
|
||||
T::use_feature(URI, data);
|
||||
}
|
||||
/// Create a reference
|
||||
inline void ref_event(LV2_Event *event) { event_feature->lv2_event_ref(event_feature->callback_data, event); }
|
||||
/// Destroy a reference
|
||||
inline void unref_event(LV2_Event *event) { event_feature->lv2_event_unref(event_feature->callback_data, event); }
|
||||
};
|
||||
|
||||
/// A mixin for adding the URI map and MIDI event type retrieval to small plugins
|
||||
template<class T>
|
||||
class midi_mixin: public virtual event_mixin<T>
|
||||
{
|
||||
public:
|
||||
/// MIDI event ID, as resolved using the URI map feature
|
||||
uint32_t midi_event_type;
|
||||
virtual void map_uris() {
|
||||
midi_event_type = this->map_uri("http://lv2plug.in/ns/ext/event", "http://lv2plug.in/ns/ext/midi#MidiEvent");
|
||||
printf("MIDI event type = %d\n", midi_event_type);
|
||||
event_mixin<T>::map_uris();
|
||||
}
|
||||
};
|
||||
|
||||
/// A mixin for adding the URI map and MIDI event type retrieval to small plugins
|
||||
template<class T>
|
||||
class message_mixin: public virtual event_mixin<T>
|
||||
{
|
||||
public:
|
||||
/// MIDI event ID, as resolved using the URI map feature
|
||||
uint32_t message_event_type;
|
||||
virtual void map_uris() {
|
||||
message_event_type = this->map_uri("http://lv2plug.in/ns/ext/event", "http://lv2plug.in/ns/dev/msg#MessageEvent");
|
||||
printf("Message event type = %d\n", message_event_type);
|
||||
event_mixin<T>::map_uris();
|
||||
}
|
||||
};
|
||||
|
||||
/// LV2 event structure + payload as 0-length array for easy access
|
||||
struct lv2_event: public LV2_Event
|
||||
{
|
||||
uint8_t data[];
|
||||
inline lv2_event &operator=(const lv2_event &src) {
|
||||
*(LV2_Event *)this = (const LV2_Event &)src;
|
||||
memcpy(data, src.data, src.size);
|
||||
return *this;
|
||||
}
|
||||
/// Returns a 64-bit timestamp for easy and inefficient comparison
|
||||
inline uint64_t timestamp() const {
|
||||
return ((uint64_t)frames << 32) | subframes;
|
||||
}
|
||||
private:
|
||||
/// forbid default constructor - this object cannot be constructed, only obtained via cast from LV2_Event* (or &) to lv2_event* (or &)
|
||||
lv2_event() {}
|
||||
/// forbid copy constructor - see default constructor
|
||||
lv2_event(const lv2_event &) {}
|
||||
};
|
||||
|
||||
/// A read-only iterator-like object for reading from event buffers
|
||||
class event_port_read_iterator
|
||||
{
|
||||
protected:
|
||||
const LV2_Event_Buffer *buffer;
|
||||
uint32_t offset;
|
||||
public:
|
||||
/// Default constructor creating a useless iterator you can assign to
|
||||
event_port_read_iterator()
|
||||
: buffer(NULL)
|
||||
, offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Create an iterator based on specified buffer and index/offset values
|
||||
event_port_read_iterator(const LV2_Event_Buffer *_buffer, uint32_t _offset = 0)
|
||||
: buffer(_buffer)
|
||||
, offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Are any data left to be read?
|
||||
inline operator bool() const {
|
||||
return offset < buffer->size;
|
||||
}
|
||||
|
||||
/// Read pointer
|
||||
inline const lv2_event &operator*() const {
|
||||
return *(const lv2_event *)(buffer->data + offset);
|
||||
}
|
||||
/// Pointer to member
|
||||
inline const lv2_event *operator->() const {
|
||||
return &**this;
|
||||
}
|
||||
|
||||
/// Move to the next element
|
||||
inline event_port_read_iterator operator++() {
|
||||
offset += ((**this).size + 19) &~7;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Move to the next element
|
||||
inline event_port_read_iterator operator++(int) {
|
||||
event_port_read_iterator old = *this;
|
||||
offset += ((**this).size + 19) &~7;
|
||||
return old;
|
||||
}
|
||||
};
|
||||
|
||||
/// A write-only iterator-like object for writing to event buffers
|
||||
class event_port_write_iterator
|
||||
{
|
||||
protected:
|
||||
LV2_Event_Buffer *buffer;
|
||||
public:
|
||||
/// Default constructor creating a useless iterator you can assign to
|
||||
event_port_write_iterator()
|
||||
: buffer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
/// Create a write iterator based on specified buffer and index/offset values
|
||||
event_port_write_iterator(LV2_Event_Buffer *_buffer)
|
||||
: buffer(_buffer)
|
||||
{
|
||||
}
|
||||
|
||||
/// @return the remaining buffer space
|
||||
inline uint32_t space_left() const {
|
||||
return buffer->capacity - buffer->size;
|
||||
}
|
||||
/// @return write pointer
|
||||
inline lv2_event &operator*() {
|
||||
return *(lv2_event *)(buffer->data + buffer->size);
|
||||
}
|
||||
/// Pointer to member
|
||||
inline lv2_event *operator->() {
|
||||
return &**this;
|
||||
}
|
||||
/// Move to the next element after the current one has been written (must be called after each write)
|
||||
inline event_port_write_iterator operator++() {
|
||||
buffer->size += ((**this).size + 19) &~7;
|
||||
buffer->event_count ++;
|
||||
return *this;
|
||||
}
|
||||
/// Move to the next element after the current one has been written
|
||||
inline lv2_event *operator++(int) {
|
||||
lv2_event *ptr = &**this;
|
||||
buffer->size += ((**this).size + 19) &~7;
|
||||
buffer->event_count ++;
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Iter1, class Iter2>
|
||||
class event_port_merge_iterator
|
||||
{
|
||||
public:
|
||||
Iter1 first;
|
||||
Iter2 second;
|
||||
public:
|
||||
event_port_merge_iterator() {}
|
||||
event_port_merge_iterator(const Iter1 &_first, const Iter2 &_second)
|
||||
: first(_first)
|
||||
, second(_second)
|
||||
{
|
||||
}
|
||||
/// @retval true if any of the iterators have any data left
|
||||
inline operator bool() const {
|
||||
return ((bool)first) || ((bool)second);
|
||||
}
|
||||
inline bool select_first() const
|
||||
{
|
||||
if (!(bool)second)
|
||||
return true;
|
||||
if (!(bool)first)
|
||||
return false;
|
||||
return first->timestamp() < second->timestamp();
|
||||
}
|
||||
/// Returns the earliest of (*first, *second)
|
||||
inline const lv2_event &operator*() const {
|
||||
if (select_first())
|
||||
{
|
||||
assert((bool)first);
|
||||
return *first;
|
||||
}
|
||||
assert((bool)second);
|
||||
return *second;
|
||||
}
|
||||
/// Pointer to member
|
||||
inline const lv2_event *operator->() const {
|
||||
return &**this;
|
||||
}
|
||||
/// Prefix increment
|
||||
inline event_port_merge_iterator operator++() {
|
||||
if (select_first())
|
||||
first++;
|
||||
else
|
||||
second++;
|
||||
return *this;
|
||||
}
|
||||
/// Postfix increment
|
||||
inline event_port_merge_iterator operator++(int) {
|
||||
event_port_merge_iterator ptr = *this;
|
||||
if (select_first())
|
||||
first++;
|
||||
else
|
||||
second++;
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
349
plugins/ladspa_effect/calf/calf/lv2wrap.h
Normal file
@@ -0,0 +1,349 @@
|
||||
/* Calf DSP Library
|
||||
* LV2 wrapper templates
|
||||
*
|
||||
* Copyright (C) 2001-2008 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef CALF_LV2WRAP_H
|
||||
#define CALF_LV2WRAP_H
|
||||
|
||||
#if USE_LV2
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <lv2.h>
|
||||
#include <calf/giface.h>
|
||||
#include <calf/lv2-midiport.h>
|
||||
#include <calf/lv2_contexts.h>
|
||||
#include <calf/lv2_event.h>
|
||||
#include <calf/lv2_progress.h>
|
||||
#include <calf/lv2_string_port.h>
|
||||
#include <calf/lv2_uri_map.h>
|
||||
|
||||
namespace calf_plugins {
|
||||
|
||||
template<class Module>
|
||||
struct lv2_instance: public plugin_ctl_iface, public progress_report_iface, public Module
|
||||
{
|
||||
bool set_srate;
|
||||
int srate_to_set;
|
||||
LV2_MIDI *midi_data;
|
||||
LV2_Event_Buffer *event_data;
|
||||
LV2_URI_Map_Feature *uri_map;
|
||||
LV2_Event_Feature *event_feature;
|
||||
uint32_t midi_event_type;
|
||||
std::vector<int> message_params;
|
||||
LV2_Progress *progress_report_feature;
|
||||
lv2_instance()
|
||||
{
|
||||
for (int i=0; i < Module::in_count; i++)
|
||||
Module::ins[i] = NULL;
|
||||
for (int i=0; i < Module::out_count; i++)
|
||||
Module::outs[i] = NULL;
|
||||
for (int i=0; i < Module::param_count; i++)
|
||||
Module::params[i] = NULL;
|
||||
uri_map = NULL;
|
||||
midi_data = NULL;
|
||||
event_data = NULL;
|
||||
midi_event_type = 0xFFFFFFFF;
|
||||
set_srate = true;
|
||||
srate_to_set = 44100;
|
||||
get_message_context_parameters(message_params);
|
||||
progress_report_feature = NULL;
|
||||
// printf("message params %d\n", (int)message_params.size());
|
||||
}
|
||||
/// This, and not Module::post_instantiate, is actually called by lv2_wrapper class
|
||||
void post_instantiate()
|
||||
{
|
||||
if (progress_report_feature)
|
||||
Module::progress_report = this;
|
||||
Module::post_instantiate();
|
||||
}
|
||||
virtual parameter_properties *get_param_props(int param_no)
|
||||
{
|
||||
return &Module::param_props[param_no];
|
||||
}
|
||||
virtual float get_param_value(int param_no)
|
||||
{
|
||||
return *Module::params[param_no];
|
||||
}
|
||||
virtual void set_param_value(int param_no, float value)
|
||||
{
|
||||
*Module::params[param_no] = value;
|
||||
}
|
||||
virtual int get_param_count()
|
||||
{
|
||||
return Module::param_count;
|
||||
}
|
||||
virtual int get_param_port_offset()
|
||||
{
|
||||
return Module::in_count + Module::out_count;
|
||||
}
|
||||
virtual const char *get_gui_xml() {
|
||||
return Module::get_gui_xml();
|
||||
}
|
||||
virtual line_graph_iface *get_line_graph_iface()
|
||||
{
|
||||
return dynamic_cast<line_graph_iface *>(this);
|
||||
}
|
||||
virtual bool activate_preset(int bank, int program) {
|
||||
return false;
|
||||
}
|
||||
virtual const char *get_name()
|
||||
{
|
||||
return Module::get_name();
|
||||
}
|
||||
virtual const char *get_id()
|
||||
{
|
||||
return Module::get_id();
|
||||
}
|
||||
virtual const char *get_label()
|
||||
{
|
||||
return Module::get_label();
|
||||
}
|
||||
virtual int get_input_count() { return Module::in_count; }
|
||||
virtual int get_output_count() { return Module::out_count; }
|
||||
virtual bool get_midi() { return Module::support_midi; }
|
||||
virtual float get_level(unsigned int port) { return 0.f; }
|
||||
virtual void execute(int cmd_no) {
|
||||
Module::execute(cmd_no);
|
||||
}
|
||||
virtual void report_progress(float percentage, const std::string &message) {
|
||||
if (progress_report_feature)
|
||||
(*progress_report_feature->progress)(progress_report_feature->context, percentage, !message.empty() ? message.c_str() : NULL);
|
||||
}
|
||||
void send_configures(send_configure_iface *sci) {
|
||||
Module::send_configures(sci);
|
||||
}
|
||||
uint32_t impl_message_run(const void *valid_inputs, void *output_ports) {
|
||||
for (unsigned int i = 0; i < message_params.size(); i++)
|
||||
{
|
||||
int pn = message_params[i];
|
||||
parameter_properties &pp = *get_param_props(pn);
|
||||
if ((pp.flags & PF_TYPEMASK) == PF_STRING
|
||||
&& (((LV2_String_Data *)Module::params[pn])->flags & LV2_STRING_DATA_CHANGED_FLAG)) {
|
||||
printf("Calling configure on %s\n", pp.short_name);
|
||||
configure(pp.short_name, ((LV2_String_Data *)Module::params[pn])->data);
|
||||
}
|
||||
}
|
||||
return Module::message_run(valid_inputs, output_ports);
|
||||
}
|
||||
char *configure(const char *key, const char *value) {
|
||||
// disambiguation - the plugin_ctl_iface version is just a stub, so don't use it
|
||||
return Module::configure(key, value);
|
||||
}
|
||||
#if 0
|
||||
// the default implementation should be fine
|
||||
virtual void clear_preset() {
|
||||
// This is never called in practice, at least for now
|
||||
// However, it will change when presets are implemented
|
||||
for (int i=0; i < Module::param_count; i++)
|
||||
*Module::params[i] = Module::param_props[i].def_value;
|
||||
/*
|
||||
const char **p = Module::get_default_configure_vars();
|
||||
if (p)
|
||||
{
|
||||
for(; p[0]; p += 2)
|
||||
configure(p[0], p[1]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
struct LV2_Calf_Descriptor {
|
||||
plugin_ctl_iface *(*get_pci)(LV2_Handle Instance);
|
||||
};
|
||||
|
||||
template<class Module>
|
||||
struct lv2_wrapper
|
||||
{
|
||||
typedef lv2_instance<Module> instance;
|
||||
static LV2_Descriptor descriptor;
|
||||
static LV2_Calf_Descriptor calf_descriptor;
|
||||
static LV2MessageContext message_context;
|
||||
std::string uri;
|
||||
|
||||
lv2_wrapper()
|
||||
{
|
||||
ladspa_plugin_info &info = Module::plugin_info;
|
||||
uri = "http://calf.sourceforge.net/plugins/" + std::string(info.label);
|
||||
descriptor.URI = uri.c_str();
|
||||
descriptor.instantiate = cb_instantiate;
|
||||
descriptor.connect_port = cb_connect;
|
||||
descriptor.activate = cb_activate;
|
||||
descriptor.run = cb_run;
|
||||
descriptor.deactivate = cb_deactivate;
|
||||
descriptor.cleanup = cb_cleanup;
|
||||
descriptor.extension_data = cb_ext_data;
|
||||
calf_descriptor.get_pci = cb_get_pci;
|
||||
message_context.message_connect_port = cb_connect;
|
||||
message_context.message_run = cb_message_run;
|
||||
}
|
||||
|
||||
static void cb_connect(LV2_Handle Instance, uint32_t port, void *DataLocation) {
|
||||
unsigned long ins = Module::in_count;
|
||||
unsigned long outs = Module::out_count;
|
||||
unsigned long params = Module::param_count;
|
||||
instance *const mod = (instance *)Instance;
|
||||
if (port < ins)
|
||||
mod->ins[port] = (float *)DataLocation;
|
||||
else if (port < ins + outs)
|
||||
mod->outs[port - ins] = (float *)DataLocation;
|
||||
else if (port < ins + outs + params) {
|
||||
int i = port - ins - outs;
|
||||
mod->params[i] = (float *)DataLocation;
|
||||
}
|
||||
else if (Module::support_midi && port == ins + outs + params) {
|
||||
mod->event_data = (LV2_Event_Buffer *)DataLocation;
|
||||
}
|
||||
}
|
||||
|
||||
static void cb_activate(LV2_Handle Instance) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
mod->set_srate = true;
|
||||
}
|
||||
|
||||
static void cb_deactivate(LV2_Handle Instance) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
mod->deactivate();
|
||||
}
|
||||
|
||||
static LV2_Handle cb_instantiate(const LV2_Descriptor * Descriptor, double sample_rate, const char *bundle_path, const LV2_Feature *const *features)
|
||||
{
|
||||
instance *mod = new instance();
|
||||
// XXXKF some people use fractional sample rates; we respect them ;-)
|
||||
mod->srate_to_set = (uint32_t)sample_rate;
|
||||
mod->set_srate = true;
|
||||
while(*features)
|
||||
{
|
||||
if (!strcmp((*features)->URI, LV2_URI_MAP_URI))
|
||||
{
|
||||
mod->uri_map = (LV2_URI_Map_Feature *)((*features)->data);
|
||||
mod->midi_event_type = mod->uri_map->uri_to_id(
|
||||
mod->uri_map->callback_data,
|
||||
"http://lv2plug.in/ns/ext/event",
|
||||
"http://lv2plug.in/ns/ext/midi#MidiEvent");
|
||||
}
|
||||
else if (!strcmp((*features)->URI, LV2_EVENT_URI))
|
||||
{
|
||||
mod->event_feature = (LV2_Event_Feature *)((*features)->data);
|
||||
}
|
||||
else if (!strcmp((*features)->URI, LV2_PROGRESS_URI))
|
||||
{
|
||||
mod->progress_report_feature = (LV2_Progress *)((*features)->data);
|
||||
}
|
||||
features++;
|
||||
}
|
||||
mod->post_instantiate();
|
||||
return mod;
|
||||
}
|
||||
static inline void zero_by_mask(Module *module, uint32_t mask, uint32_t offset, uint32_t nsamples)
|
||||
{
|
||||
for (int i=0; i<Module::out_count; i++) {
|
||||
if ((mask & (1 << i)) == 0) {
|
||||
dsp::zero(module->outs[i] + offset, nsamples);
|
||||
}
|
||||
}
|
||||
}
|
||||
static plugin_ctl_iface *cb_get_pci(LV2_Handle Instance)
|
||||
{
|
||||
return static_cast<plugin_ctl_iface *>(Instance);
|
||||
}
|
||||
|
||||
static inline void process_slice(Module *mod, uint32_t offset, uint32_t end)
|
||||
{
|
||||
while(offset < end)
|
||||
{
|
||||
uint32_t newend = std::min(offset + MAX_SAMPLE_RUN, end);
|
||||
uint32_t out_mask = mod->process(offset, newend - offset, -1, -1);
|
||||
zero_by_mask(mod, out_mask, offset, newend - offset);
|
||||
offset = newend;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t cb_message_run(LV2_Handle Instance, const void *valid_inputs, void *outputs_written) {
|
||||
instance *mod = (instance *)Instance;
|
||||
return mod->impl_message_run(valid_inputs, outputs_written);
|
||||
}
|
||||
static void cb_run(LV2_Handle Instance, uint32_t SampleCount) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
if (mod->set_srate) {
|
||||
mod->set_sample_rate(mod->srate_to_set);
|
||||
mod->activate();
|
||||
mod->set_srate = false;
|
||||
}
|
||||
mod->params_changed();
|
||||
uint32_t offset = 0;
|
||||
if (mod->event_data)
|
||||
{
|
||||
// printf("Event data: count %d\n", mod->event_data->event_count);
|
||||
struct LV2_Midi_Event: public LV2_Event {
|
||||
unsigned char data[1];
|
||||
};
|
||||
unsigned char *data = (unsigned char *)(mod->event_data->data);
|
||||
for (uint32_t i = 0; i < mod->event_data->event_count; i++) {
|
||||
LV2_Midi_Event *item = (LV2_Midi_Event *)data;
|
||||
uint32_t ts = item->frames;
|
||||
// printf("Event: timestamp %d subframes %d type %d vs %d\n", item->frames, item->subframes, item->type, mod->midi_event_type);
|
||||
if (ts > offset)
|
||||
{
|
||||
process_slice(mod, offset, ts);
|
||||
offset = ts;
|
||||
}
|
||||
if (item->type == mod->midi_event_type)
|
||||
{
|
||||
// printf("Midi message %x %x %x %x %d\n", item->data[0], item->data[1], item->data[2], item->data[3], item->size);
|
||||
switch(item->data[0] >> 4)
|
||||
{
|
||||
case 8: mod->note_off(item->data[1], item->data[2]); break;
|
||||
case 9: mod->note_on(item->data[1], item->data[2]); break;
|
||||
case 11: mod->control_change(item->data[1], item->data[2]); break;
|
||||
case 12: mod->program_change(item->data[1]); break;
|
||||
case 14: mod->pitch_bend(item->data[1] + 128 * item->data[2] - 8192); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (item->type == 0 && mod->event_feature)
|
||||
mod->event_feature->lv2_event_unref(mod->event_feature->callback_data, item);
|
||||
// printf("timestamp %f item size %d first byte %x\n", item->timestamp, item->size, item->data[0]);
|
||||
data += ((sizeof(LV2_Event) + item->size + 7))&~7;
|
||||
}
|
||||
}
|
||||
process_slice(mod, offset, SampleCount);
|
||||
}
|
||||
static void cb_cleanup(LV2_Handle Instance) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
delete mod;
|
||||
}
|
||||
static const void *cb_ext_data(const char *URI) {
|
||||
if (!strcmp(URI, "http://foltman.com/ns/calf-plugin-instance"))
|
||||
return &calf_descriptor;
|
||||
if (!strcmp(URI, LV2_CONTEXT_MESSAGE))
|
||||
return &message_context;
|
||||
return NULL;
|
||||
}
|
||||
static lv2_wrapper &get() {
|
||||
static lv2_wrapper instance;
|
||||
return instance;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
312
plugins/ladspa_effect/calf/calf/metadata.h
Normal file
@@ -0,0 +1,312 @@
|
||||
/* Calf DSP Library
|
||||
* Audio module (plugin) metadata - header file
|
||||
*
|
||||
* Copyright (C) 2007-2008 Krzysztof Foltman
|
||||
* Copyright (C) 2008 Thor Harald Johansen <thj@thj.no>
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CALF_METADATA_H
|
||||
#define __CALF_METADATA_H
|
||||
|
||||
#include "giface.h"
|
||||
|
||||
namespace calf_plugins {
|
||||
|
||||
struct flanger_metadata: public plugin_metadata<flanger_metadata>
|
||||
{
|
||||
public:
|
||||
enum { par_delay, par_depth, par_rate, par_fb, par_stereo, par_reset, par_amount, par_dryamount, param_count };
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
PLUGIN_NAME_ID_LABEL("flanger", "flanger", "Flanger")
|
||||
};
|
||||
|
||||
struct phaser_metadata: public plugin_metadata<phaser_metadata>
|
||||
{
|
||||
enum { par_freq, par_depth, par_rate, par_fb, par_stages, par_stereo, par_reset, par_amount, par_dryamount, param_count };
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
PLUGIN_NAME_ID_LABEL("phaser", "phaser", "Phaser")
|
||||
};
|
||||
|
||||
struct filter_metadata: public plugin_metadata<filter_metadata>
|
||||
{
|
||||
enum { par_cutoff, par_resonance, par_mode, par_inertia, param_count };
|
||||
enum { in_count = 2, out_count = 2, rt_capable = true, require_midi = false, support_midi = false };
|
||||
PLUGIN_NAME_ID_LABEL("filter", "filter", "Filter")
|
||||
/// do not export mode and inertia as CVs, as those are settings and not parameters
|
||||
bool is_cv(int param_no) { return param_no != par_mode && param_no != par_inertia; }
|
||||
};
|
||||
|
||||
/// Filterclavier - metadata
|
||||
struct filterclavier_metadata: public plugin_metadata<filterclavier_metadata>
|
||||
{
|
||||
enum { par_transpose, par_detune, par_max_resonance, par_mode, par_inertia, param_count };
|
||||
enum { in_count = 2, out_count = 2, rt_capable = true, require_midi = true, support_midi = true };
|
||||
PLUGIN_NAME_ID_LABEL("filterclavier", "filterclavier", "Filterclavier")
|
||||
/// do not export mode and inertia as CVs, as those are settings and not parameters
|
||||
bool is_cv(int param_no) { return param_no != par_mode && param_no != par_inertia; }
|
||||
};
|
||||
|
||||
struct reverb_metadata: public plugin_metadata<reverb_metadata>
|
||||
{
|
||||
enum { par_decay, par_hfdamp, par_roomsize, par_diffusion, par_amount, par_dry, par_predelay, par_basscut, par_treblecut, param_count };
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
PLUGIN_NAME_ID_LABEL("reverb", "reverb", "Reverb")
|
||||
};
|
||||
|
||||
struct vintage_delay_metadata: public plugin_metadata<vintage_delay_metadata>
|
||||
{
|
||||
enum { par_bpm, par_divide, par_time_l, par_time_r, par_feedback, par_amount, par_mixmode, par_medium, par_dryamount, param_count };
|
||||
enum { in_count = 2, out_count = 2, rt_capable = true, support_midi = false, require_midi = false };
|
||||
PLUGIN_NAME_ID_LABEL("vintage_delay", "vintagedelay", "Vintage Delay")
|
||||
};
|
||||
|
||||
struct rotary_speaker_metadata: public plugin_metadata<rotary_speaker_metadata>
|
||||
{
|
||||
public:
|
||||
enum { par_speed, par_spacing, par_shift, par_moddepth, par_treblespeed, par_bassspeed, par_micdistance, par_reflection, param_count };
|
||||
enum { in_count = 2, out_count = 2, support_midi = true, require_midi = false, rt_capable = true };
|
||||
PLUGIN_NAME_ID_LABEL("rotary_speaker", "rotaryspeaker", "Rotary Speaker")
|
||||
};
|
||||
|
||||
/// A multitap stereo chorus thing - metadata
|
||||
struct multichorus_metadata: public plugin_metadata<multichorus_metadata>
|
||||
{
|
||||
public:
|
||||
enum { par_delay, par_depth, par_rate, par_stereo, par_voices, par_vphase, par_amount, par_dryamount, par_freq, par_freq2, par_q, par_overlap, param_count };
|
||||
enum { in_count = 2, out_count = 2, rt_capable = true, support_midi = false, require_midi = false };
|
||||
PLUGIN_NAME_ID_LABEL("multichorus", "multichorus", "Multi Chorus")
|
||||
};
|
||||
|
||||
/// Monosynth - metadata
|
||||
struct monosynth_metadata: public plugin_metadata<monosynth_metadata>
|
||||
{
|
||||
enum { wave_saw, wave_sqr, wave_pulse, wave_sine, wave_triangle, wave_varistep, wave_skewsaw, wave_skewsqr, wave_test1, wave_test2, wave_test3, wave_test4, wave_test5, wave_test6, wave_test7, wave_test8, wave_count };
|
||||
enum { flt_lp12, flt_lp24, flt_2lp12, flt_hp12, flt_lpbr, flt_hpbr, flt_bp6, flt_2bp6 };
|
||||
enum { par_wave1, par_wave2, par_pw1, par_pw2, par_detune, par_osc2xpose, par_oscmode, par_oscmix, par_filtertype, par_cutoff, par_resonance, par_cutoffsep, par_envmod, par_envtores, par_envtoamp, par_attack, par_decay, par_sustain, par_fade, par_release,
|
||||
par_keyfollow, par_legato, par_portamento, par_vel2filter, par_vel2amp, par_master, par_pwhlrange,
|
||||
par_lforate, par_lfodelay, par_lfofilter, par_lfopitch, par_lfopw, par_mwhl_lfo, par_scaledetune,
|
||||
param_count };
|
||||
enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true };
|
||||
enum { step_size = 64, step_shift = 6 };
|
||||
enum {
|
||||
modsrc_none,
|
||||
modsrc_velocity,
|
||||
modsrc_pressure,
|
||||
modsrc_modwheel,
|
||||
modsrc_env1,
|
||||
modsrc_lfo1,
|
||||
modsrc_count,
|
||||
};
|
||||
enum {
|
||||
moddest_none,
|
||||
moddest_attenuation,
|
||||
moddest_oscmix,
|
||||
moddest_cutoff,
|
||||
moddest_resonance,
|
||||
moddest_o1detune,
|
||||
moddest_o2detune,
|
||||
moddest_o1pw,
|
||||
moddest_o2pw,
|
||||
moddest_count,
|
||||
};
|
||||
PLUGIN_NAME_ID_LABEL("monosynth", "monosynth", "Monosynth")
|
||||
};
|
||||
|
||||
/// Thor's compressor - metadata
|
||||
struct compressor_metadata: public plugin_metadata<compressor_metadata>
|
||||
{
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_aweighting, param_compression, param_peak, param_clip, param_bypass, // param_freq, param_bw,
|
||||
param_count };
|
||||
PLUGIN_NAME_ID_LABEL("compressor", "compressor", "Compressor")
|
||||
};
|
||||
|
||||
/// Organ - enums for parameter IDs etc. (this mess is caused by organ split between plugin and generic class - which was
|
||||
/// a bad design decision and should be sorted out some day) XXXKF @todo
|
||||
struct organ_enums
|
||||
{
|
||||
enum {
|
||||
par_drawbar1, par_drawbar2, par_drawbar3, par_drawbar4, par_drawbar5, par_drawbar6, par_drawbar7, par_drawbar8, par_drawbar9,
|
||||
par_frequency1, par_frequency2, par_frequency3, par_frequency4, par_frequency5, par_frequency6, par_frequency7, par_frequency8, par_frequency9,
|
||||
par_waveform1, par_waveform2, par_waveform3, par_waveform4, par_waveform5, par_waveform6, par_waveform7, par_waveform8, par_waveform9,
|
||||
par_detune1, par_detune2, par_detune3, par_detune4, par_detune5, par_detune6, par_detune7, par_detune8, par_detune9,
|
||||
par_phase1, par_phase2, par_phase3, par_phase4, par_phase5, par_phase6, par_phase7, par_phase8, par_phase9,
|
||||
par_pan1, par_pan2, par_pan3, par_pan4, par_pan5, par_pan6, par_pan7, par_pan8, par_pan9,
|
||||
par_routing1, par_routing2, par_routing3, par_routing4, par_routing5, par_routing6, par_routing7, par_routing8, par_routing9,
|
||||
par_foldover,
|
||||
par_percdecay, par_perclevel, par_percwave, par_percharm, par_percvel2amp,
|
||||
par_percfmdecay, par_percfmdepth, par_percfmwave, par_percfmharm, par_percvel2fm,
|
||||
par_perctrigger, par_percstereo,
|
||||
par_filterchain,
|
||||
par_filter1type,
|
||||
par_master,
|
||||
par_f1cutoff, par_f1res, par_f1env1, par_f1env2, par_f1env3, par_f1keyf,
|
||||
par_f2cutoff, par_f2res, par_f2env1, par_f2env2, par_f2env3, par_f2keyf,
|
||||
par_eg1attack, par_eg1decay, par_eg1sustain, par_eg1release, par_eg1velscl, par_eg1ampctl,
|
||||
par_eg2attack, par_eg2decay, par_eg2sustain, par_eg2release, par_eg2velscl, par_eg2ampctl,
|
||||
par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3release, par_eg3velscl, par_eg3ampctl,
|
||||
par_lforate, par_lfoamt, par_lfowet, par_lfophase, par_lfomode,
|
||||
par_transpose, par_detune,
|
||||
par_polyphony,
|
||||
par_quadenv,
|
||||
par_pwhlrange,
|
||||
par_bassfreq,
|
||||
par_bassgain,
|
||||
par_treblefreq,
|
||||
par_treblegain,
|
||||
par_var_mapcurve,
|
||||
param_count
|
||||
};
|
||||
enum {
|
||||
var_count = 1
|
||||
};
|
||||
enum organ_waveform {
|
||||
wave_sine,
|
||||
wave_sinepl1, wave_sinepl2, wave_sinepl3,
|
||||
wave_ssaw, wave_ssqr, wave_spls, wave_saw, wave_sqr, wave_pulse, wave_sinepl05, wave_sqr05, wave_halfsin, wave_clvg, wave_bell, wave_bell2,
|
||||
wave_w1, wave_w2, wave_w3, wave_w4, wave_w5, wave_w6, wave_w7, wave_w8, wave_w9,
|
||||
wave_dsaw, wave_dsqr, wave_dpls,
|
||||
wave_count_small,
|
||||
wave_strings = wave_count_small,
|
||||
wave_strings2,
|
||||
wave_sinepad,
|
||||
wave_bellpad,
|
||||
wave_space,
|
||||
wave_choir,
|
||||
wave_choir2,
|
||||
wave_choir3,
|
||||
wave_count,
|
||||
wave_count_big = wave_count - wave_count_small
|
||||
};
|
||||
enum {
|
||||
ampctl_none,
|
||||
ampctl_direct,
|
||||
ampctl_f1,
|
||||
ampctl_f2,
|
||||
ampctl_all,
|
||||
ampctl_count
|
||||
};
|
||||
enum {
|
||||
lfomode_off = 0,
|
||||
lfomode_direct,
|
||||
lfomode_filter1,
|
||||
lfomode_filter2,
|
||||
lfomode_voice,
|
||||
lfomode_global,
|
||||
lfomode_count
|
||||
};
|
||||
enum {
|
||||
perctrig_first = 0,
|
||||
perctrig_each,
|
||||
perctrig_eachplus,
|
||||
perctrig_polyphonic,
|
||||
perctrig_count
|
||||
};
|
||||
};
|
||||
|
||||
/// Organ - metadata
|
||||
struct organ_metadata: public organ_enums, public plugin_metadata<organ_metadata>
|
||||
{
|
||||
enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true };
|
||||
PLUGIN_NAME_ID_LABEL("organ", "organ", "Organ")
|
||||
plugin_command_info *get_commands();
|
||||
const char **get_default_configure_vars();
|
||||
};
|
||||
|
||||
/// FluidSynth - metadata
|
||||
struct fluidsynth_metadata: public plugin_metadata<fluidsynth_metadata>
|
||||
{
|
||||
enum { par_master, par_soundfont, par_interpolation, par_reverb, par_chorus, param_count };
|
||||
enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = false };
|
||||
PLUGIN_NAME_ID_LABEL("fluidsynth", "fluidsynth", "Fluidsynth")
|
||||
const char **get_default_configure_vars();
|
||||
};
|
||||
|
||||
/// Wavetable - metadata
|
||||
struct wavetable_metadata: public plugin_metadata<wavetable_metadata>
|
||||
{
|
||||
enum {
|
||||
wt_fmshiny,
|
||||
wt_fmshiny2,
|
||||
wt_rezo,
|
||||
wt_metal,
|
||||
wt_bell,
|
||||
wt_blah,
|
||||
wt_pluck,
|
||||
wt_stretch,
|
||||
wt_stretch2,
|
||||
wt_hardsync,
|
||||
wt_hardsync2,
|
||||
wt_softsync,
|
||||
wt_bell2,
|
||||
wt_bell3,
|
||||
wt_tine,
|
||||
wt_tine2,
|
||||
wt_clav,
|
||||
wt_clav2,
|
||||
wt_gtr,
|
||||
wt_gtr2,
|
||||
wt_gtr3,
|
||||
wt_gtr4,
|
||||
wt_gtr5,
|
||||
wt_reed,
|
||||
wt_reed2,
|
||||
wt_silver,
|
||||
wt_brass,
|
||||
wt_multi,
|
||||
wt_multi2,
|
||||
wt_count
|
||||
};
|
||||
enum {
|
||||
modsrc_none,
|
||||
modsrc_velocity,
|
||||
modsrc_pressure,
|
||||
modsrc_modwheel,
|
||||
modsrc_env1,
|
||||
modsrc_env2,
|
||||
modsrc_env3,
|
||||
modsrc_count,
|
||||
};
|
||||
enum {
|
||||
moddest_none,
|
||||
moddest_attenuation,
|
||||
moddest_oscmix,
|
||||
moddest_cutoff,
|
||||
moddest_resonance,
|
||||
moddest_o1shift,
|
||||
moddest_o2shift,
|
||||
moddest_o1detune,
|
||||
moddest_o2detune,
|
||||
moddest_count,
|
||||
};
|
||||
enum {
|
||||
par_o1wave, par_o1offset, par_o1transpose, par_o1detune, par_o1level,
|
||||
par_o2wave, par_o2offset, par_o2transpose, par_o2detune, par_o2level,
|
||||
par_eg1attack, par_eg1decay, par_eg1sustain, par_eg1fade, par_eg1release, par_eg1velscl,
|
||||
par_eg2attack, par_eg2decay, par_eg2sustain, par_eg2fade, par_eg2release, par_eg2velscl,
|
||||
par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3fade, par_eg3release, par_eg3velscl,
|
||||
par_pwhlrange,
|
||||
param_count };
|
||||
enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true };
|
||||
enum { step_size = 64 };
|
||||
PLUGIN_NAME_ID_LABEL("wavetable", "wavetable", "Wavetable")
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
112
plugins/ladspa_effect/calf/calf/modmatrix.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/* Calf DSP Library
|
||||
* Modulation matrix boilerplate code.
|
||||
*
|
||||
* Copyright (C) 2009 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_MODMATRIX_H
|
||||
#define __CALF_MODMATRIX_H
|
||||
|
||||
#include "giface.h"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
/// Mapping modes
|
||||
enum mapping_mode {
|
||||
map_positive, ///< 0..100%
|
||||
map_bipolar, ///< -100%..100%
|
||||
map_negative, ///< -100%..0%
|
||||
map_squared, ///< x^2
|
||||
map_squared_bipolar, ///< x^2 scaled to -100%..100%
|
||||
map_antisquared, ///< 1-(1-x)^2 scaled to 0..100%
|
||||
map_antisquared_bipolar, ///< 1-(1-x)^2 scaled to -100..100%
|
||||
map_parabola, ///< inverted parabola (peaks at 0.5, then decreases to 0)
|
||||
map_type_count
|
||||
};
|
||||
|
||||
/// Single entry in modulation matrix
|
||||
struct modulation_entry
|
||||
{
|
||||
/// Mapped source
|
||||
int src1;
|
||||
/// Source mapping mode
|
||||
mapping_mode mapping;
|
||||
/// Unmapped modulating source
|
||||
int src2;
|
||||
/// Modulation amount
|
||||
float amount;
|
||||
/// Modulation destination
|
||||
int dest;
|
||||
|
||||
modulation_entry() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/// Reset the row to default
|
||||
void reset() {
|
||||
src1 = 0;
|
||||
src2 = 0;
|
||||
mapping = map_positive;
|
||||
amount = 0.f;
|
||||
dest = 0;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
namespace calf_plugins {
|
||||
|
||||
class mod_matrix: public table_edit_iface
|
||||
{
|
||||
protected:
|
||||
/// Polynomials for different scaling modes (1, x, x^2)
|
||||
static const float scaling_coeffs[dsp::map_type_count][3];
|
||||
/// Column descriptions for table widget
|
||||
table_column_info table_columns[6];
|
||||
|
||||
dsp::modulation_entry *matrix;
|
||||
unsigned int matrix_rows;
|
||||
const char **mod_src_names, **mod_dest_names;
|
||||
|
||||
mod_matrix(dsp::modulation_entry *_matrix, unsigned int _rows, const char **_src_names, const char **_dest_names);
|
||||
public:
|
||||
virtual const table_column_info *get_table_columns(int param);
|
||||
virtual uint32_t get_table_rows(int param);
|
||||
virtual std::string get_cell(int param, int row, int column);
|
||||
virtual void set_cell(int param, int row, int column, const std::string &src, std::string &error);
|
||||
|
||||
/// Process modulation matrix, calculate outputs from inputs
|
||||
inline void calculate_modmatrix(float *moddest, int moddest_count, float *modsrc)
|
||||
{
|
||||
for (int i = 0; i < moddest_count; i++)
|
||||
moddest[i] = 0;
|
||||
for (unsigned int i = 0; i < matrix_rows; i++)
|
||||
{
|
||||
dsp::modulation_entry &slot = matrix[i];
|
||||
if (slot.dest) {
|
||||
float value = modsrc[slot.src1];
|
||||
const float *c = scaling_coeffs[slot.mapping];
|
||||
value = c[0] + c[1] * value + c[2] * value * value;
|
||||
moddest[slot.dest] += value * modsrc[slot.src2] * slot.amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
95
plugins/ladspa_effect/calf/calf/modulelist.h
Normal file
@@ -0,0 +1,95 @@
|
||||
#ifdef PER_MODULE_ITEM
|
||||
PER_MODULE_ITEM(filter, false, "filter")
|
||||
PER_MODULE_ITEM(filterclavier, false, "filterclavier")
|
||||
PER_MODULE_ITEM(flanger, false, "flanger")
|
||||
PER_MODULE_ITEM(reverb, false, "reverb")
|
||||
PER_MODULE_ITEM(monosynth, true, "monosynth")
|
||||
PER_MODULE_ITEM(vintage_delay, false, "vintagedelay")
|
||||
PER_MODULE_ITEM(organ, true, "organ")
|
||||
PER_MODULE_ITEM(rotary_speaker, false, "rotaryspeaker")
|
||||
PER_MODULE_ITEM(phaser, false, "phaser")
|
||||
PER_MODULE_ITEM(multichorus, false, "multichorus")
|
||||
PER_MODULE_ITEM(compressor, false, "compressor")
|
||||
#ifdef ENABLE_EXPERIMENTAL
|
||||
PER_MODULE_ITEM(fluidsynth, true, "fluidsynth")
|
||||
PER_MODULE_ITEM(wavetable, true, "wavetable")
|
||||
#endif
|
||||
#undef PER_MODULE_ITEM
|
||||
#endif
|
||||
#ifdef PER_SMALL_MODULE_ITEM
|
||||
#ifdef ENABLE_EXPERIMENTAL
|
||||
PER_SMALL_MODULE_ITEM(lp_filter, "lowpass12")
|
||||
PER_SMALL_MODULE_ITEM(hp_filter, "highpass12")
|
||||
PER_SMALL_MODULE_ITEM(bp_filter, "bandpass6")
|
||||
PER_SMALL_MODULE_ITEM(br_filter, "notch6")
|
||||
PER_SMALL_MODULE_ITEM(onepole_lp_filter, "lowpass6")
|
||||
PER_SMALL_MODULE_ITEM(onepole_hp_filter, "highpass6")
|
||||
PER_SMALL_MODULE_ITEM(onepole_ap_filter, "allpass")
|
||||
PER_SMALL_MODULE_ITEM(min, "min")
|
||||
PER_SMALL_MODULE_ITEM(max, "max")
|
||||
PER_SMALL_MODULE_ITEM(minus, "minus")
|
||||
PER_SMALL_MODULE_ITEM(mul, "mul")
|
||||
PER_SMALL_MODULE_ITEM(neg, "neg")
|
||||
PER_SMALL_MODULE_ITEM(min_c, "min_c")
|
||||
PER_SMALL_MODULE_ITEM(max_c, "max_c")
|
||||
PER_SMALL_MODULE_ITEM(minus_c, "minus_c")
|
||||
PER_SMALL_MODULE_ITEM(mul_c, "mul_c")
|
||||
PER_SMALL_MODULE_ITEM(neg_c, "neg_c")
|
||||
PER_SMALL_MODULE_ITEM(level2edge_c, "level2edge_c")
|
||||
PER_SMALL_MODULE_ITEM(map_lin2exp, "lin2exp")
|
||||
PER_SMALL_MODULE_ITEM(square_osc, "square_osc")
|
||||
PER_SMALL_MODULE_ITEM(saw_osc, "saw_osc")
|
||||
PER_SMALL_MODULE_ITEM(square_lfo, "square_lfo")
|
||||
PER_SMALL_MODULE_ITEM(saw_lfo, "saw_lfo")
|
||||
PER_SMALL_MODULE_ITEM(pulse_lfo, "pulse_lfo")
|
||||
PER_SMALL_MODULE_ITEM(print_a, "print_a")
|
||||
PER_SMALL_MODULE_ITEM(print_c, "print_c")
|
||||
PER_SMALL_MODULE_ITEM(print_e, "print_e")
|
||||
PER_SMALL_MODULE_ITEM(print_em, "print_em")
|
||||
PER_SMALL_MODULE_ITEM(copy_em, "copy_em")
|
||||
PER_SMALL_MODULE_ITEM(notefilter_m, "notefilter_m")
|
||||
PER_SMALL_MODULE_ITEM(ccfilter_m, "ccfilter_m")
|
||||
PER_SMALL_MODULE_ITEM(pcfilter_m, "pcfilter_m")
|
||||
PER_SMALL_MODULE_ITEM(pressurefilter_m, "pressurefilter_m")
|
||||
PER_SMALL_MODULE_ITEM(pitchbendfilter_m, "pitchbendfilter_m")
|
||||
PER_SMALL_MODULE_ITEM(systemfilter_m, "systemfilter_m")
|
||||
PER_SMALL_MODULE_ITEM(channelfilter_m, "channelfilter_m")
|
||||
PER_SMALL_MODULE_ITEM(keyfilter_m, "keyfilter_m")
|
||||
PER_SMALL_MODULE_ITEM(setchannel_m, "setchannel_m")
|
||||
PER_SMALL_MODULE_ITEM(key_less_than_m, "key_less_than_m")
|
||||
PER_SMALL_MODULE_ITEM(channel_less_than_m, "channel_less_than_m")
|
||||
PER_SMALL_MODULE_ITEM(transpose_m, "transpose_m")
|
||||
PER_SMALL_MODULE_ITEM(eventmerge_e, "eventmerge_e")
|
||||
PER_SMALL_MODULE_ITEM(quadpower_a, "quadpower_a")
|
||||
PER_SMALL_MODULE_ITEM(quadpower_c, "quadpower_c")
|
||||
PER_SMALL_MODULE_ITEM(crossfader2_a, "crossfader2_a")
|
||||
PER_SMALL_MODULE_ITEM(crossfader2_c, "crossfader2_c")
|
||||
PER_SMALL_MODULE_ITEM(linear_inertia_c, "linear_inertia_c")
|
||||
PER_SMALL_MODULE_ITEM(exp_inertia_c, "exp_inertia_c")
|
||||
PER_SMALL_MODULE_ITEM(sample_hold_edge_c, "sample_hold_edge_c")
|
||||
PER_SMALL_MODULE_ITEM(sample_hold_level_c, "sample_hold_level_c")
|
||||
PER_SMALL_MODULE_ITEM(bit_and_c, "bit_and_c")
|
||||
PER_SMALL_MODULE_ITEM(bit_or_c, "bit_or_c")
|
||||
PER_SMALL_MODULE_ITEM(bit_xor_c, "bit_xor_c")
|
||||
PER_SMALL_MODULE_ITEM(logical_and_c, "logical_and_c")
|
||||
PER_SMALL_MODULE_ITEM(logical_or_c, "logical_or_c")
|
||||
PER_SMALL_MODULE_ITEM(logical_xor_c, "logical_xor_c")
|
||||
PER_SMALL_MODULE_ITEM(logical_not_c, "logical_not_c")
|
||||
PER_SMALL_MODULE_ITEM(flipflop_c, "flipflop_c")
|
||||
PER_SMALL_MODULE_ITEM(schmitt_c, "schmitt_c")
|
||||
PER_SMALL_MODULE_ITEM(between_c, "between_c")
|
||||
PER_SMALL_MODULE_ITEM(less_c, "less_c")
|
||||
PER_SMALL_MODULE_ITEM(clip_c, "clip_c")
|
||||
PER_SMALL_MODULE_ITEM(trigger_a2c, "trigger_a2c")
|
||||
PER_SMALL_MODULE_ITEM(timer_c, "timer_c")
|
||||
PER_SMALL_MODULE_ITEM(prio_mux_c, "prio_mux_c")
|
||||
PER_SMALL_MODULE_ITEM(prio_enc8_c, "prio_enc8_c")
|
||||
PER_SMALL_MODULE_ITEM(ifthenelse_c, "ifthenelse_c")
|
||||
PER_SMALL_MODULE_ITEM(counter_c, "counter_c")
|
||||
PER_SMALL_MODULE_ITEM(mux4_c, "mux4_c")
|
||||
PER_SMALL_MODULE_ITEM(mux8_c, "mux8_c")
|
||||
PER_SMALL_MODULE_ITEM(mux16_c, "mux16_c")
|
||||
PER_SMALL_MODULE_ITEM(msgread_e, "msgread_e")
|
||||
#endif
|
||||
#undef PER_SMALL_MODULE_ITEM
|
||||
#endif
|
||||
1016
plugins/ladspa_effect/calf/calf/modules.h
Normal file
119
plugins/ladspa_effect/calf/calf/modules_dev.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/* Calf DSP Library
|
||||
* Prototype audio modules
|
||||
*
|
||||
* Copyright (C) 2008 Thor Harald Johansen <thj@thj.no>
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_MODULES_DEV_H
|
||||
#define __CALF_MODULES_DEV_H
|
||||
|
||||
#include <calf/metadata.h>
|
||||
#include <calf/modules.h>
|
||||
|
||||
#if ENABLE_EXPERIMENTAL
|
||||
#include <fluidsynth.h>
|
||||
#endif
|
||||
|
||||
namespace calf_plugins {
|
||||
|
||||
#if ENABLE_EXPERIMENTAL
|
||||
|
||||
/// Tiny wrapper for fluidsynth
|
||||
class fluidsynth_audio_module: public audio_module<fluidsynth_metadata>
|
||||
{
|
||||
public:
|
||||
float *ins[in_count];
|
||||
float *outs[out_count];
|
||||
float *params[param_count];
|
||||
|
||||
protected:
|
||||
/// Current sample rate
|
||||
uint32_t srate;
|
||||
/// FluidSynth Settings object
|
||||
fluid_settings_t *settings;
|
||||
/// FluidSynth Synth object
|
||||
fluid_synth_t *synth;
|
||||
/// Soundfont filename
|
||||
std::string soundfont;
|
||||
/// Soundfont filename (as received from Fluidsynth)
|
||||
std::string soundfont_name;
|
||||
/// TAB-separated preset list (preset+128*bank TAB preset name LF)
|
||||
std::string soundfont_preset_list;
|
||||
/// FluidSynth assigned SoundFont ID
|
||||
int sfid;
|
||||
/// Map of preset+128*bank to preset name
|
||||
std::map<uint32_t, std::string> sf_preset_names;
|
||||
/// Last selected preset+128*bank
|
||||
uint32_t last_selected_preset;
|
||||
/// Serial number of status data
|
||||
int status_serial;
|
||||
/// Preset number to set on next process() call
|
||||
volatile int set_preset;
|
||||
|
||||
/// Update last_selected_preset based on synth object state
|
||||
void update_preset_num();
|
||||
/// Create a fluidsynth object and load the current soundfont
|
||||
fluid_synth_t *create_synth(int &new_sfid);
|
||||
public:
|
||||
/// Constructor to initialize handles to NULL
|
||||
fluidsynth_audio_module();
|
||||
|
||||
void post_instantiate();
|
||||
void set_sample_rate(uint32_t sr) { srate = sr; }
|
||||
/// Handle MIDI Note On message (by sending it to fluidsynth)
|
||||
void note_on(int note, int vel);
|
||||
/// Handle MIDI Note Off message (by sending it to fluidsynth)
|
||||
void note_off(int note, int vel);
|
||||
/// Handle pitch bend message.
|
||||
inline void pitch_bend(int value)
|
||||
{
|
||||
fluid_synth_pitch_bend(synth, 0, value + 0x2000);
|
||||
}
|
||||
/// Handle control change messages.
|
||||
void control_change(int controller, int value);
|
||||
/// Handle program change messages.
|
||||
void program_change(int program);
|
||||
|
||||
/// Update variables from control ports.
|
||||
void params_changed() {
|
||||
}
|
||||
void activate();
|
||||
void deactivate();
|
||||
/// No CV inputs for now
|
||||
bool is_cv(int param_no) { return false; }
|
||||
/// Practically all the stuff here is noisy... for now
|
||||
bool is_noisy(int param_no) { return true; }
|
||||
/// Main processing function
|
||||
uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask);
|
||||
/// DSSI-style configure function for handling string port data
|
||||
char *configure(const char *key, const char *value);
|
||||
void send_configures(send_configure_iface *sci);
|
||||
int send_status_updates(send_updates_iface *sui, int last_serial);
|
||||
uint32_t message_run(const void *valid_inputs, void *output_ports) {
|
||||
// silence a default printf (which is kind of a warning about unhandled message_run)
|
||||
return 0;
|
||||
}
|
||||
~fluidsynth_audio_module();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
202
plugins/ladspa_effect/calf/calf/modules_small.h
Normal file
@@ -0,0 +1,202 @@
|
||||
/* Calf DSP Library
|
||||
* "Small" audio modules for modular synthesis
|
||||
*
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_MODULES_SMALL_H
|
||||
#define __CALF_MODULES_SMALL_H
|
||||
|
||||
#if USE_LV2
|
||||
|
||||
#include <lv2.h>
|
||||
#include "plugininfo.h"
|
||||
#include "lv2_polymorphic_port.h"
|
||||
#include "lv2helpers.h"
|
||||
|
||||
namespace calf_plugins {
|
||||
|
||||
/// Empty implementations for plugin functions. Note, that some functions aren't virtual, because they're called via the particular
|
||||
/// subclass via template wrappers (ladspa_small_wrapper<> etc), not via base class pointer/reference. On the other hand,
|
||||
/// other functions are virtual when overhead is acceptable (instantiation time functions etc.)
|
||||
class null_small_audio_module: public uri_map_access
|
||||
{
|
||||
public:
|
||||
uint32_t srate;
|
||||
double odsr;
|
||||
uint32_t poly_type_control, poly_type_audio;
|
||||
/// for polymorphic ports: "is audio" flags for first 32 ports (should be sufficient for most plugins)
|
||||
uint32_t poly_port_types;
|
||||
|
||||
null_small_audio_module()
|
||||
: srate((uint32_t)-1)
|
||||
, odsr(0.)
|
||||
, poly_type_control(0)
|
||||
, poly_type_audio(0)
|
||||
, poly_port_types(0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Called when host changes type of the polymorphic port
|
||||
inline void set_port_type(uint32_t port, uint32_t type, void *type_data) {
|
||||
if (port >= 32)
|
||||
return;
|
||||
uint32_t port_mask = 1 << port;
|
||||
if (type == poly_type_control)
|
||||
poly_port_types &= ~port_mask;
|
||||
else if (type == poly_type_audio)
|
||||
poly_port_types |= port_mask;
|
||||
on_port_types_changed();
|
||||
}
|
||||
|
||||
/// Returns 1 for audio ports and 0 for control ports
|
||||
inline unsigned int port_is_audio(unsigned int port) {
|
||||
return (poly_port_types >> port) & 1;
|
||||
}
|
||||
|
||||
/// Returns (unsigned)-1 for audio ports and 0 for control ports
|
||||
inline unsigned int port_audio_mask(unsigned int port) {
|
||||
return 0 - ((poly_port_types >> port) & 1);
|
||||
}
|
||||
|
||||
/// Returns (unsigned)-1 for audio ports and 0 for control ports
|
||||
static inline unsigned int port_audio_mask(unsigned int port, uint32_t poly_port_types) {
|
||||
return 0 - ((poly_port_types >> port) & 1);
|
||||
}
|
||||
|
||||
virtual void on_port_types_changed() {}
|
||||
inline void set_bundle_path(const char *path) {}
|
||||
/// Called to map all the necessary URIs
|
||||
virtual void map_uris()
|
||||
{
|
||||
poly_type_control = map_uri(LV2_POLYMORPHIC_PORT_URI, "http://lv2plug.in/ns/lv2core#ControlPort");
|
||||
poly_type_audio = map_uri(LV2_POLYMORPHIC_PORT_URI, "http://lv2plug.in/ns/lv2core#AudioPort");
|
||||
}
|
||||
/// Called on instantiation with the list of LV2 features called
|
||||
virtual void use_features(const LV2_Feature *const *features) {
|
||||
while(*features)
|
||||
{
|
||||
use_feature((*features)->URI, (*features)->data);
|
||||
features++;
|
||||
}
|
||||
}
|
||||
/// LADSPA-esque activate function, except it is called after ports are connected, not before
|
||||
inline void activate() {}
|
||||
/// LADSPA-esque deactivate function
|
||||
inline void deactivate() {}
|
||||
/// Set sample rate for the plugin
|
||||
inline void set_sample_rate(uint32_t sr) { srate = sr; odsr = 1.0 / sr; }
|
||||
static inline const void *ext_data(const char *URI) { return NULL; }
|
||||
};
|
||||
|
||||
/// Templatized version useful when the number of inputs and outputs is small
|
||||
template<unsigned int Inputs, unsigned int Outputs>
|
||||
class small_audio_module_base: public null_small_audio_module
|
||||
{
|
||||
public:
|
||||
enum { in_count = Inputs, out_count = Outputs };
|
||||
/// Input pointers
|
||||
float *ins[in_count];
|
||||
/// Output pointers
|
||||
float *outs[out_count];
|
||||
};
|
||||
|
||||
template<class Module>
|
||||
struct lv2_small_wrapper
|
||||
{
|
||||
typedef Module instance;
|
||||
static LV2_Descriptor descriptor;
|
||||
std::string uri;
|
||||
static uint32_t poly_port_types;
|
||||
|
||||
lv2_small_wrapper(const char *id)
|
||||
{
|
||||
uri = "http://calf.sourceforge.net/small_plugins/" + std::string(id);
|
||||
descriptor.URI = uri.c_str();
|
||||
descriptor.instantiate = cb_instantiate;
|
||||
descriptor.connect_port = cb_connect;
|
||||
descriptor.activate = cb_activate;
|
||||
descriptor.run = cb_run;
|
||||
descriptor.deactivate = cb_deactivate;
|
||||
descriptor.cleanup = cb_cleanup;
|
||||
descriptor.extension_data = cb_ext_data;
|
||||
|
||||
plugin_port_type_grabber ptg(poly_port_types);
|
||||
Module::plugin_info(&ptg);
|
||||
}
|
||||
|
||||
static void cb_connect(LV2_Handle Instance, uint32_t port, void *DataLocation) {
|
||||
unsigned long ins = Module::in_count;
|
||||
unsigned long outs = Module::out_count;
|
||||
instance *const mod = (instance *)Instance;
|
||||
if (port < ins)
|
||||
mod->ins[port] = (float *)DataLocation;
|
||||
else if (port < ins + outs)
|
||||
mod->outs[port - ins] = (float *)DataLocation;
|
||||
}
|
||||
|
||||
static void cb_activate(LV2_Handle Instance) {
|
||||
// Note the changed semantics (now more LV2-like)
|
||||
instance *const mod = (instance *)Instance;
|
||||
mod->activate();
|
||||
}
|
||||
|
||||
static void cb_deactivate(LV2_Handle Instance) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
mod->deactivate();
|
||||
}
|
||||
|
||||
static uint32_t cb_set_type(LV2_Handle Instance, uint32_t port, uint32_t type, void *type_data)
|
||||
{
|
||||
instance *const mod = (instance *)Instance;
|
||||
mod->set_port_type(port, type, type_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LV2_Handle cb_instantiate(const LV2_Descriptor * Descriptor, double sample_rate, const char *bundle_path, const LV2_Feature *const *features)
|
||||
{
|
||||
instance *mod = new instance();
|
||||
mod->poly_port_types = poly_port_types;
|
||||
// XXXKF some people use fractional sample rates; we respect them ;-)
|
||||
mod->set_bundle_path(bundle_path);
|
||||
mod->use_features(features);
|
||||
mod->set_sample_rate((uint32_t)sample_rate);
|
||||
return mod;
|
||||
}
|
||||
|
||||
static void cb_run(LV2_Handle Instance, uint32_t SampleCount) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
mod->process(SampleCount);
|
||||
}
|
||||
|
||||
static void cb_cleanup(LV2_Handle Instance) {
|
||||
instance *const mod = (instance *)Instance;
|
||||
delete mod;
|
||||
}
|
||||
|
||||
static const void *cb_ext_data(const char *URI) {
|
||||
return Module::ext_data(URI);
|
||||
}
|
||||
};
|
||||
|
||||
extern const LV2_Descriptor *lv2_small_descriptor(uint32_t index);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
264
plugins/ladspa_effect/calf/calf/modules_synths.h
Normal file
@@ -0,0 +1,264 @@
|
||||
/* Calf DSP Library
|
||||
* Audio modules - synthesizers
|
||||
*
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_MODULES_SYNTHS_H
|
||||
#define __CALF_MODULES_SYNTHS_H
|
||||
|
||||
#include <assert.h>
|
||||
#include "biquad.h"
|
||||
#include "onepole.h"
|
||||
#include "audio_fx.h"
|
||||
#include "inertia.h"
|
||||
#include "osc.h"
|
||||
#include "synth.h"
|
||||
#include "envelope.h"
|
||||
#include "organ.h"
|
||||
#include "modmatrix.h"
|
||||
|
||||
namespace calf_plugins {
|
||||
|
||||
#define MONOSYNTH_WAVE_BITS 12
|
||||
|
||||
/// Monosynth-in-making. Parameters may change at any point, so don't make songs with it!
|
||||
/// It lacks inertia for parameters, even for those that really need it.
|
||||
class monosynth_audio_module: public audio_module<monosynth_metadata>, public line_graph_iface, public mod_matrix
|
||||
{
|
||||
public:
|
||||
enum { mod_matrix_slots = 10 };
|
||||
float *ins[in_count];
|
||||
float *outs[out_count];
|
||||
float *params[param_count];
|
||||
uint32_t srate, crate;
|
||||
static dsp::waveform_family<MONOSYNTH_WAVE_BITS> *waves;
|
||||
dsp::waveform_oscillator<MONOSYNTH_WAVE_BITS> osc1, osc2;
|
||||
dsp::triangle_lfo lfo;
|
||||
bool running, stopping, gate, force_fadeout;
|
||||
int last_key;
|
||||
|
||||
float buffer[step_size], buffer2[step_size];
|
||||
uint32_t output_pos;
|
||||
dsp::onepole<float> phaseshifter;
|
||||
dsp::biquad_d1_lerp<float> filter;
|
||||
dsp::biquad_d1_lerp<float> filter2;
|
||||
/// Waveform number - OSC1
|
||||
int wave1;
|
||||
/// Waveform number - OSC2
|
||||
int wave2;
|
||||
/// Last used waveform number - OSC1
|
||||
int prev_wave1;
|
||||
/// Last used waveform number - OSC2
|
||||
int prev_wave2;
|
||||
int filter_type, last_filter_type;
|
||||
float freq, start_freq, target_freq, cutoff, decay_factor, fgain, fgain_delta, separation;
|
||||
float detune, xpose, xfade, ampctl, fltctl, queue_vel;
|
||||
float odcr, porta_time, lfo_bend, lfo_clock, last_lfov, modwheel_value;
|
||||
/// Last value of phase shift for pulse width emulation for OSC1
|
||||
int32_t last_pwshift1;
|
||||
/// Last value of phase shift for pulse width emulation for OSC2
|
||||
int32_t last_pwshift2;
|
||||
int queue_note_on, stop_count, modwheel_value_int;
|
||||
int legato;
|
||||
dsp::adsr envelope;
|
||||
dsp::keystack stack;
|
||||
dsp::gain_smoothing master;
|
||||
/// Smoothed cutoff value
|
||||
dsp::inertia<dsp::exponential_ramp> inertia_cutoff;
|
||||
/// Smoothed pitch bend value
|
||||
dsp::inertia<dsp::exponential_ramp> inertia_pitchbend;
|
||||
/// Smoothed channel pressure value
|
||||
dsp::inertia<dsp::linear_ramp> inertia_pressure;
|
||||
/// Rows of the modulation matrix
|
||||
dsp::modulation_entry mod_matrix_data[mod_matrix_slots];
|
||||
/// Currently used velocity
|
||||
float velocity;
|
||||
/// Last value of oscillator mix ratio
|
||||
float last_xfade;
|
||||
/// Current calculated mod matrix outputs
|
||||
float moddest[moddest_count];
|
||||
|
||||
monosynth_audio_module();
|
||||
static void precalculate_waves(progress_report_iface *reporter);
|
||||
void set_sample_rate(uint32_t sr);
|
||||
void delayed_note_on();
|
||||
/// Handle MIDI Note On message (does not immediately trigger a note, as it must start on
|
||||
/// boundary of step_size samples).
|
||||
void note_on(int note, int vel);
|
||||
/// Handle MIDI Note Off message
|
||||
void note_off(int note, int vel);
|
||||
/// Handle MIDI Channel Pressure
|
||||
void channel_pressure(int value);
|
||||
/// Handle pitch bend message.
|
||||
inline void pitch_bend(int value)
|
||||
{
|
||||
inertia_pitchbend.set_inertia(pow(2.0, (value * *params[par_pwhlrange]) / (1200.0 * 8192.0)));
|
||||
}
|
||||
/// Update oscillator frequency based on base frequency, detune amount, pitch bend scaling factor and sample rate.
|
||||
inline void set_frequency()
|
||||
{
|
||||
float detune_scaled = (detune - 1); // * log(freq / 440);
|
||||
if (*params[par_scaledetune] > 0)
|
||||
detune_scaled *= pow(20.0 / freq, *params[par_scaledetune]);
|
||||
float p1 = 1, p2 = 1;
|
||||
if (moddest[moddest_o1detune] != 0)
|
||||
p1 = pow(2.0, moddest[moddest_o1detune] * (1.0 / 1200.0));
|
||||
if (moddest[moddest_o2detune] != 0)
|
||||
p2 = pow(2.0, moddest[moddest_o2detune] * (1.0 / 1200.0));
|
||||
osc1.set_freq(freq * (1 - detune_scaled) * p1 * inertia_pitchbend.get_last() * lfo_bend, srate);
|
||||
osc2.set_freq(freq * (1 + detune_scaled) * p2 * inertia_pitchbend.get_last() * lfo_bend * xpose, srate);
|
||||
}
|
||||
/// Handle control change messages.
|
||||
void control_change(int controller, int value);
|
||||
/// Update variables from control ports.
|
||||
void params_changed() {
|
||||
float sf = 0.001f;
|
||||
envelope.set(*params[par_attack] * sf, *params[par_decay] * sf, std::min(0.999f, *params[par_sustain]), *params[par_release] * sf, srate / step_size, *params[par_fade] * sf);
|
||||
filter_type = dsp::fastf2i_drm(*params[par_filtertype]);
|
||||
decay_factor = odcr * 1000.0 / *params[par_decay];
|
||||
separation = pow(2.0, *params[par_cutoffsep] / 1200.0);
|
||||
wave1 = dsp::clip(dsp::fastf2i_drm(*params[par_wave1]), 0, (int)wave_count - 1);
|
||||
wave2 = dsp::clip(dsp::fastf2i_drm(*params[par_wave2]), 0, (int)wave_count - 1);
|
||||
detune = pow(2.0, *params[par_detune] / 1200.0);
|
||||
xpose = pow(2.0, *params[par_osc2xpose] / 12.0);
|
||||
xfade = *params[par_oscmix];
|
||||
legato = dsp::fastf2i_drm(*params[par_legato]);
|
||||
master.set_inertia(*params[par_master]);
|
||||
set_frequency();
|
||||
if (wave1 != prev_wave1 || wave2 != prev_wave2)
|
||||
lookup_waveforms();
|
||||
}
|
||||
void activate();
|
||||
void deactivate();
|
||||
void post_instantiate()
|
||||
{
|
||||
precalculate_waves(progress_report);
|
||||
}
|
||||
/// Set waveform addresses for oscillators
|
||||
void lookup_waveforms();
|
||||
/// Run oscillators
|
||||
void calculate_buffer_oscs(float lfo);
|
||||
/// Run two filters in series to produce mono output samples.
|
||||
void calculate_buffer_ser();
|
||||
/// Run one filter to produce mono output samples.
|
||||
void calculate_buffer_single();
|
||||
/// Run two filters (one per channel) to produce stereo output samples.
|
||||
void calculate_buffer_stereo();
|
||||
/// Retrieve filter graph (which is 'live' so it cannot be generated by get_static_graph), or fall back to get_static_graph.
|
||||
bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context);
|
||||
/// @retval true if the filter 1 is to be used for the left channel and filter 2 for the right channel
|
||||
/// @retval false if filters are to be connected in series and sent (mono) to both channels
|
||||
inline bool is_stereo_filter() const
|
||||
{
|
||||
return filter_type == flt_2lp12 || filter_type == flt_2bp6;
|
||||
}
|
||||
/// No CV inputs for now
|
||||
bool is_cv(int param_no) { return false; }
|
||||
/// Practically all the stuff here is noisy
|
||||
bool is_noisy(int param_no) { return param_no != par_cutoff; }
|
||||
/// Calculate control signals and produce step_size samples of output.
|
||||
void calculate_step();
|
||||
/// Main processing function
|
||||
uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask);
|
||||
};
|
||||
|
||||
struct organ_audio_module: public audio_module<organ_metadata>, public dsp::drawbar_organ, public line_graph_iface
|
||||
{
|
||||
public:
|
||||
using drawbar_organ::note_on;
|
||||
using drawbar_organ::note_off;
|
||||
using drawbar_organ::control_change;
|
||||
enum { param_count = drawbar_organ::param_count};
|
||||
float *ins[in_count];
|
||||
float *outs[out_count];
|
||||
float *params[param_count];
|
||||
dsp::organ_parameters par_values;
|
||||
uint32_t srate;
|
||||
bool panic_flag;
|
||||
/// Value for configure variable map_curve
|
||||
std::string var_map_curve;
|
||||
|
||||
organ_audio_module()
|
||||
: drawbar_organ(&par_values)
|
||||
{
|
||||
var_map_curve = "2\n0 1\n1 1\n"; // XXXKF hacky bugfix
|
||||
}
|
||||
|
||||
void post_instantiate()
|
||||
{
|
||||
dsp::organ_voice_base::precalculate_waves(progress_report);
|
||||
}
|
||||
|
||||
void set_sample_rate(uint32_t sr) {
|
||||
srate = sr;
|
||||
}
|
||||
void params_changed() {
|
||||
for (int i = 0; i < param_count - var_count; i++)
|
||||
((float *)&par_values)[i] = *params[i];
|
||||
|
||||
unsigned int old_poly = polyphony_limit;
|
||||
polyphony_limit = dsp::clip(dsp::fastf2i_drm(*params[par_polyphony]), 1, 32);
|
||||
if (polyphony_limit < old_poly)
|
||||
trim_voices();
|
||||
|
||||
update_params();
|
||||
}
|
||||
inline void pitch_bend(int amt)
|
||||
{
|
||||
drawbar_organ::pitch_bend(amt);
|
||||
}
|
||||
void activate() {
|
||||
setup(srate);
|
||||
panic_flag = false;
|
||||
}
|
||||
void deactivate();
|
||||
uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
|
||||
float *o[2] = { outs[0] + offset, outs[1] + offset };
|
||||
if (panic_flag)
|
||||
{
|
||||
control_change(120, 0); // stop all sounds
|
||||
control_change(121, 0); // reset all controllers
|
||||
panic_flag = false;
|
||||
}
|
||||
render_separate(o, nsamples);
|
||||
return 3;
|
||||
}
|
||||
/// No CV inputs for now
|
||||
bool is_cv(int param_no) { return false; }
|
||||
/// Practically all the stuff here is noisy
|
||||
bool is_noisy(int param_no) { return true; }
|
||||
void execute(int cmd_no);
|
||||
bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context);
|
||||
|
||||
char *configure(const char *key, const char *value);
|
||||
void send_configures(send_configure_iface *);
|
||||
uint32_t message_run(const void *valid_inputs, void *output_ports) {
|
||||
// silence a default printf (which is kind of a warning about unhandled message_run)
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#if ENABLE_EXPERIMENTAL
|
||||
|
||||
#include "wavetable.h"
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
213
plugins/ladspa_effect/calf/calf/multichorus.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/* Calf DSP Library
|
||||
* Multitap chorus class.
|
||||
*
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_MULTICHORUS_H
|
||||
#define __CALF_MULTICHORUS_H
|
||||
|
||||
#include "audio_fx.h"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
typedef fixed_point<unsigned int, 20> chorus_phase;
|
||||
|
||||
template<class T, uint32_t Voices>
|
||||
class sine_multi_lfo
|
||||
{
|
||||
protected:
|
||||
sine_table<int, 4096, 65535> sine;
|
||||
|
||||
public:
|
||||
/// Current LFO phase
|
||||
chorus_phase phase;
|
||||
/// LFO phase increment
|
||||
chorus_phase dphase;
|
||||
/// LFO phase per-voice increment
|
||||
chorus_phase vphase;
|
||||
/// Current number of voices
|
||||
uint32_t voices;
|
||||
/// Current scale (output multiplier)
|
||||
T scale;
|
||||
/// Per-voice offset unit (the value that says how much the voices are offset with respect to each other in non-100% 'overlap' mode), scaled so that full range = 131072
|
||||
int32_t voice_offset;
|
||||
/// LFO Range scaling for non-100% overlap
|
||||
uint32_t voice_depth;
|
||||
public:
|
||||
sine_multi_lfo()
|
||||
{
|
||||
phase = dphase = vphase = 0.0;
|
||||
voice_offset = 0;
|
||||
voice_depth = 1U << 31;
|
||||
|
||||
set_voices(Voices);
|
||||
}
|
||||
inline uint32_t get_voices() const
|
||||
{
|
||||
return voices;
|
||||
}
|
||||
inline void set_voices(uint32_t value)
|
||||
{
|
||||
voices = value;
|
||||
// use sqrt, because some phases will cancel each other - so 1 / N is usually too low
|
||||
scale = sqrt(1.0 / voices);
|
||||
}
|
||||
inline void set_overlap(float overlap)
|
||||
{
|
||||
// If we scale the delay amount so that full range of a single LFO is 0..1, all the overlapped LFOs will cover 0..range
|
||||
// How it's calculated:
|
||||
// 1. First voice is assumed to always cover the range of 0..1
|
||||
// 2. Each remaining voice contributes an interval of a width = 1 - overlap, starting from the end of the interval of the previous voice
|
||||
// Coverage = non-overlapped part of the LFO range in the 1st voice
|
||||
float range = 1.f + (1.f - overlap) * (voices - 1);
|
||||
float scaling = 1.f / range;
|
||||
voice_offset = (int)(131072 * (1 - overlap) / range);
|
||||
voice_depth = (unsigned int)((1U << 30) * 1.0 * scaling);
|
||||
}
|
||||
/// Get LFO value for given voice, returns a values in range of [-65536, 65535] (or close)
|
||||
inline int get_value(uint32_t voice) {
|
||||
// find this voice's phase (= phase + voice * 360 degrees / number of voices)
|
||||
chorus_phase voice_phase = phase + vphase * (int)voice;
|
||||
// find table offset
|
||||
unsigned int ipart = voice_phase.ipart();
|
||||
// interpolate (use 14 bits of precision - because the table itself uses 17 bits and the result of multiplication must fit in int32_t)
|
||||
// note, the result is still -65535 .. 65535, it's just interpolated
|
||||
// it is never reaching -65536 - but that's acceptable
|
||||
int intval = voice_phase.lerp_by_fract_int<int, 14, int>(sine.data[ipart], sine.data[ipart+1]);
|
||||
// apply the voice offset/depth (rescale from -65535..65535 to appropriate voice's "band")
|
||||
return -65535 + voice * voice_offset + ((voice_depth >> (30-13)) * (65536 + intval) >> 13);
|
||||
}
|
||||
inline void step() {
|
||||
phase += dphase;
|
||||
}
|
||||
inline T get_scale() const {
|
||||
return scale;
|
||||
}
|
||||
void reset() {
|
||||
phase = 0.f;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Multi-tap chorus without feedback.
|
||||
* Perhaps MaxDelay should be a bit longer!
|
||||
*/
|
||||
template<class T, class MultiLfo, class Postprocessor, int MaxDelay=4096>
|
||||
class multichorus: public chorus_base
|
||||
{
|
||||
protected:
|
||||
simple_delay<MaxDelay,T> delay;
|
||||
public:
|
||||
MultiLfo lfo;
|
||||
Postprocessor post;
|
||||
public:
|
||||
multichorus() {
|
||||
rate = 0.63f;
|
||||
dry = 0.5f;
|
||||
wet = 0.5f;
|
||||
min_delay = 0.005f;
|
||||
mod_depth = 0.0025f;
|
||||
setup(44100);
|
||||
}
|
||||
void reset() {
|
||||
delay.reset();
|
||||
lfo.reset();
|
||||
}
|
||||
void set_rate(float rate) {
|
||||
chorus_base::set_rate(rate);
|
||||
lfo.dphase = dphase;
|
||||
}
|
||||
virtual void setup(int sample_rate) {
|
||||
modulation_effect::setup(sample_rate);
|
||||
delay.reset();
|
||||
lfo.reset();
|
||||
set_min_delay(get_min_delay());
|
||||
set_mod_depth(get_mod_depth());
|
||||
}
|
||||
template<class OutIter, class InIter>
|
||||
void process(OutIter buf_out, InIter buf_in, int nsamples) {
|
||||
int mds = min_delay_samples + mod_depth_samples * 1024 + 2*65536;
|
||||
int mdepth = mod_depth_samples;
|
||||
// 1 sample peak-to-peak = mod_depth_samples of 32 (this scaling stuff is tricky and may - but shouldn't - be wrong)
|
||||
// with 192 kHz sample rate, 1 ms = 192 samples, and the maximum 20 ms = 3840 samples (so, 4096 will be used)
|
||||
// 3840 samples of mod depth = mdepth of 122880 (which multiplied by 65536 doesn't fit in int32_t)
|
||||
// so, it will be right-shifted by 2, which gives it a safe range of 30720
|
||||
// NB: calculation of mod_depth_samples (and multiply-by-32) is in chorus_base::set_mod_depth
|
||||
mdepth = mdepth >> 2;
|
||||
T scale = lfo.get_scale();
|
||||
for (int i=0; i<nsamples; i++) {
|
||||
phase += dphase;
|
||||
|
||||
float in = *buf_in++;
|
||||
|
||||
delay.put(in);
|
||||
unsigned int nvoices = lfo.get_voices();
|
||||
T out = 0.f;
|
||||
// add up values from all voices, each voice tell its LFO phase and the buffer value is picked at that location
|
||||
for (unsigned int v = 0; v < nvoices; v++)
|
||||
{
|
||||
int lfo_output = lfo.get_value(v);
|
||||
// 3 = log2(32 >> 2) + 1 because the LFO value is in range of [-65535, 65535] (17 bits)
|
||||
int dv = mds + (mdepth * lfo_output >> (3 + 1));
|
||||
int ifv = dv >> 16;
|
||||
T fd; // signal from delay's output
|
||||
delay.get_interp(fd, ifv, (dv & 0xFFFF)*(1.0/65536.0));
|
||||
out += fd;
|
||||
}
|
||||
// apply the post filter
|
||||
out = post.process(out);
|
||||
T sdry = in * gs_dry.get();
|
||||
T swet = out * gs_wet.get() * scale;
|
||||
*buf_out++ = sdry + swet;
|
||||
lfo.step();
|
||||
}
|
||||
post.sanitize();
|
||||
}
|
||||
float freq_gain(float freq, float sr)
|
||||
{
|
||||
typedef std::complex<double> cfloat;
|
||||
freq *= 2.0 * M_PI / sr;
|
||||
cfloat z = 1.0 / exp(cfloat(0.0, freq)); // z^-1
|
||||
cfloat h = 0.0;
|
||||
int mds = min_delay_samples + mod_depth_samples * 1024 + 2*65536;
|
||||
int mdepth = mod_depth_samples;
|
||||
mdepth = mdepth >> 2;
|
||||
T scale = lfo.get_scale();
|
||||
unsigned int nvoices = lfo.get_voices();
|
||||
for (unsigned int v = 0; v < nvoices; v++)
|
||||
{
|
||||
int lfo_output = lfo.get_value(v);
|
||||
// 3 = log2(32 >> 2) + 1 because the LFO value is in range of [-65535, 65535] (17 bits)
|
||||
int dv = mds + (mdepth * lfo_output >> (3 + 1));
|
||||
int fldp = dv >> 16;
|
||||
cfloat zn = std::pow(z, fldp); // z^-N
|
||||
h += zn + (zn * z - zn) * cfloat(dv / 65536.0 - fldp);
|
||||
}
|
||||
// apply the post filter
|
||||
h *= post.h_z(z);
|
||||
// mix with dry signal
|
||||
float v = std::abs(cfloat(gs_dry.get_last()) + cfloat(scale * gs_wet.get_last()) * h);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
192
plugins/ladspa_effect/calf/calf/onepole.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/* Calf DSP Library
|
||||
* Basic one-pole one-zero filters based on bilinear transform.
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_ONEPOLE_H
|
||||
#define __CALF_ONEPOLE_H
|
||||
|
||||
#include "primitives.h"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
/**
|
||||
* one-pole filter, for floating point values
|
||||
* coefficient calculation is based on bilinear transform, and the code itself is based on my very old OneSignal lib
|
||||
* lp and hp are *somewhat* tested, allpass is not tested at all
|
||||
* don't use this for integers because it won't work
|
||||
*/
|
||||
template<class T = float, class Coeff = float>
|
||||
class onepole
|
||||
{
|
||||
public:
|
||||
typedef std::complex<double> cfloat;
|
||||
|
||||
T x1, y1;
|
||||
Coeff a0, a1, b1;
|
||||
|
||||
onepole()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
/// Set coefficients for a lowpass filter
|
||||
void set_lp(float fc, float sr)
|
||||
{
|
||||
// x x
|
||||
// x+1 x-1
|
||||
Coeff x = tan (M_PI * fc / (2 * sr));
|
||||
Coeff q = 1/(1+x);
|
||||
a0 = a1 = x*q;
|
||||
b1 = (x-1)*q;
|
||||
}
|
||||
|
||||
/// Set coefficients for an allpass filter
|
||||
void set_ap(float fc, float sr)
|
||||
{
|
||||
// x-1 x+1
|
||||
// x+1 x-1
|
||||
Coeff x = tan (M_PI * fc / (2 * sr));
|
||||
Coeff q = 1/(1+x);
|
||||
b1 = a0 = (x-1)*q;
|
||||
a1 = 1;
|
||||
}
|
||||
|
||||
/// Set coefficients for an allpass filter, using omega instead of fc and sr
|
||||
/// omega = (PI / 2) * fc / sr
|
||||
void set_ap_w(float w)
|
||||
{
|
||||
// x-1 x+1
|
||||
// x+1 x-1
|
||||
Coeff x = tan (w);
|
||||
Coeff q = 1/(1+x);
|
||||
b1 = a0 = (x-1)*q;
|
||||
a1 = 1;
|
||||
}
|
||||
|
||||
/// Set coefficients for a highpass filter
|
||||
void set_hp(float fc, float sr)
|
||||
{
|
||||
// x -x
|
||||
// x+1 x-1
|
||||
Coeff x = tan (M_PI * fc / (2 * sr));
|
||||
Coeff q = 1/(1+x);
|
||||
a0 = q;
|
||||
a1 = -a0;
|
||||
b1 = (x-1)*q;
|
||||
}
|
||||
|
||||
/// Process one sample
|
||||
inline T process(T in)
|
||||
{
|
||||
T out = in * a0 + x1 * a1 - y1 * b1;
|
||||
x1 = in;
|
||||
y1 = out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Process one sample, assuming it's a lowpass filter (optimized special case)
|
||||
inline T process_lp(T in)
|
||||
{
|
||||
T out = (in + x1) * a0 - y1 * b1;
|
||||
x1 = in;
|
||||
y1 = out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Process one sample, assuming it's a highpass filter (optimized special case)
|
||||
inline T process_hp(T in)
|
||||
{
|
||||
T out = (in - x1) * a0 - y1 * b1;
|
||||
x1 = in;
|
||||
y1 = out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Process one sample, assuming it's an allpass filter (optimized special case)
|
||||
inline T process_ap(T in)
|
||||
{
|
||||
T out = (in - y1) * a0 + x1;
|
||||
x1 = in;
|
||||
y1 = out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Process one sample using external state variables
|
||||
inline T process_ap(T in, float &x1, float &y1)
|
||||
{
|
||||
T out = (in - y1) * a0 + x1;
|
||||
x1 = in;
|
||||
y1 = out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Process one sample using external state variables, including filter coeff
|
||||
inline T process_ap(T in, float &x1, float &y1, float a0)
|
||||
{
|
||||
T out = (in - y1) * a0 + x1;
|
||||
x1 = in;
|
||||
y1 = out;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline bool empty() {
|
||||
return y1 == 0;
|
||||
}
|
||||
|
||||
inline void sanitize()
|
||||
{
|
||||
dsp::sanitize(x1);
|
||||
dsp::sanitize(y1);
|
||||
}
|
||||
|
||||
inline void reset()
|
||||
{
|
||||
dsp::zero(x1);
|
||||
dsp::zero(y1);
|
||||
}
|
||||
|
||||
template<class U>
|
||||
inline void copy_coeffs(const onepole<U> &src)
|
||||
{
|
||||
a0 = src.a0;
|
||||
a1 = src.a1;
|
||||
b1 = src.b1;
|
||||
}
|
||||
|
||||
/// Return the filter's gain at frequency freq
|
||||
/// @param freq Frequency to look up
|
||||
/// @param sr Filter sample rate (used to convert frequency to angular frequency)
|
||||
float freq_gain(float freq, float sr)
|
||||
{
|
||||
freq *= 2.0 * M_PI / sr;
|
||||
cfloat z = 1.0 / exp(cfloat(0.0, freq));
|
||||
|
||||
return std::abs(h_z(z));
|
||||
}
|
||||
|
||||
/// Return H(z) the filter's gain at frequency freq
|
||||
/// @param z Z variable (e^jw)
|
||||
cfloat h_z(const cfloat &z)
|
||||
{
|
||||
return (cfloat(a0) + double(a1) * z) / (cfloat(1.0) + double(b1) * z);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
374
plugins/ladspa_effect/calf/calf/organ.h
Normal file
@@ -0,0 +1,374 @@
|
||||
/* Calf DSP Library
|
||||
* Drawbar organ emulator.
|
||||
*
|
||||
* Copyright (C) 2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CALF_ORGAN_H
|
||||
#define __CALF_ORGAN_H
|
||||
|
||||
#include "synth.h"
|
||||
#include "envelope.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#define ORGAN_KEYTRACK_POINTS 4
|
||||
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
struct organ_parameters {
|
||||
enum { FilterCount = 2, EnvCount = 3 };
|
||||
struct organ_filter_parameters
|
||||
{
|
||||
float cutoff;
|
||||
float resonance;
|
||||
float envmod[organ_parameters::EnvCount];
|
||||
float keyf;
|
||||
};
|
||||
|
||||
struct organ_env_parameters
|
||||
{
|
||||
float attack, decay, sustain, release, velscale, ampctl;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// these parameters are binary-copied from control ports (order is important!)
|
||||
|
||||
float drawbars[9];
|
||||
float harmonics[9];
|
||||
float waveforms[9];
|
||||
float detune[9];
|
||||
float phase[9];
|
||||
float pan[9];
|
||||
float routing[9];
|
||||
float foldover;
|
||||
float percussion_time;
|
||||
float percussion_level;
|
||||
float percussion_wave;
|
||||
float percussion_harmonic;
|
||||
float percussion_vel2amp;
|
||||
float percussion_fm_time;
|
||||
float percussion_fm_depth;
|
||||
float percussion_fm_wave;
|
||||
float percussion_fm_harmonic;
|
||||
float percussion_vel2fm;
|
||||
float percussion_trigger;
|
||||
float percussion_stereo;
|
||||
float filter_chain;
|
||||
float filter1_type;
|
||||
float master;
|
||||
|
||||
organ_filter_parameters filters[organ_parameters::FilterCount];
|
||||
organ_env_parameters envs[organ_parameters::EnvCount];
|
||||
float lfo_rate;
|
||||
float lfo_amt;
|
||||
float lfo_wet;
|
||||
float lfo_phase;
|
||||
float lfo_mode;
|
||||
|
||||
float global_transpose;
|
||||
float global_detune;
|
||||
|
||||
float polyphony;
|
||||
|
||||
float quad_env;
|
||||
|
||||
float pitch_bend_range;
|
||||
|
||||
float bass_freq;
|
||||
float bass_gain;
|
||||
float treble_freq;
|
||||
float treble_gain;
|
||||
|
||||
float dummy_mapcurve;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// these parameters are calculated
|
||||
|
||||
double perc_decay_const, perc_fm_decay_const;
|
||||
float multiplier[9];
|
||||
int phaseshift[9];
|
||||
float cutoff;
|
||||
unsigned int foldvalue;
|
||||
float pitch_bend;
|
||||
|
||||
float percussion_keytrack[ORGAN_KEYTRACK_POINTS][2];
|
||||
|
||||
organ_parameters() : pitch_bend(1.0f) {}
|
||||
|
||||
inline int get_percussion_wave() { return dsp::fastf2i_drm(percussion_wave); }
|
||||
inline int get_percussion_fm_wave() { return dsp::fastf2i_drm(percussion_fm_wave); }
|
||||
};
|
||||
|
||||
#define ORGAN_WAVE_BITS 12
|
||||
#define ORGAN_WAVE_SIZE 4096
|
||||
#define ORGAN_BIG_WAVE_BITS 17
|
||||
#define ORGAN_BIG_WAVE_SIZE 131072
|
||||
/// 2^ORGAN_BIG_WAVE_SHIFT = how many (quasi)periods per sample
|
||||
#define ORGAN_BIG_WAVE_SHIFT 5
|
||||
|
||||
class organ_voice_base: public calf_plugins::organ_enums
|
||||
{
|
||||
public:
|
||||
typedef waveform_family<ORGAN_WAVE_BITS> small_wave_family;
|
||||
typedef waveform_family<ORGAN_BIG_WAVE_BITS> big_wave_family;
|
||||
public:
|
||||
organ_parameters *parameters;
|
||||
protected:
|
||||
static small_wave_family (*waves)[wave_count_small];
|
||||
static big_wave_family (*big_waves)[wave_count_big];
|
||||
|
||||
// dsp::sine_table<float, ORGAN_WAVE_SIZE, 1> sine_wave;
|
||||
int note;
|
||||
dsp::decay amp;
|
||||
/// percussion FM carrier amplitude envelope
|
||||
dsp::decay pamp;
|
||||
/// percussion FM modulator amplitude envelope
|
||||
dsp::decay fm_amp;
|
||||
dsp::fixed_point<int64_t, 20> pphase, dpphase;
|
||||
dsp::fixed_point<int64_t, 20> modphase, moddphase;
|
||||
float fm_keytrack;
|
||||
int &sample_rate_ref;
|
||||
bool &released_ref;
|
||||
/// pamp per-sample (linear) step during release stage (calculated on release so that it will take 30ms for it to go from "current value at release point" to 0)
|
||||
float rel_age_const;
|
||||
|
||||
organ_voice_base(organ_parameters *_parameters, int &_sample_rate_ref, bool &_released_ref);
|
||||
|
||||
inline float wave(float *data, dsp::fixed_point<int, 20> ph) {
|
||||
return ph.lerp_table_lookup_float(data);
|
||||
}
|
||||
inline float big_wave(float *data, dsp::fixed_point<int64_t, 20> &ph) {
|
||||
// wrap to fit within the wave
|
||||
return ph.lerp_table_lookup_float_mask(data, ORGAN_BIG_WAVE_SIZE - 1);
|
||||
}
|
||||
public:
|
||||
static inline small_wave_family &get_wave(int wave) {
|
||||
return (*waves)[wave];
|
||||
}
|
||||
static inline big_wave_family &get_big_wave(int wave) {
|
||||
return (*big_waves)[wave];
|
||||
}
|
||||
static void precalculate_waves(calf_plugins::progress_report_iface *reporter);
|
||||
void update_pitch()
|
||||
{
|
||||
float phase = dsp::midi_note_to_phase(note, 100 * parameters->global_transpose + parameters->global_detune, sample_rate_ref);
|
||||
dpphase.set((long int) (phase * parameters->percussion_harmonic * parameters->pitch_bend));
|
||||
moddphase.set((long int) (phase * parameters->percussion_fm_harmonic * parameters->pitch_bend));
|
||||
}
|
||||
// this doesn't really have a voice interface
|
||||
void render_percussion_to(float (*buf)[2], int nsamples);
|
||||
void perc_note_on(int note, int vel);
|
||||
void perc_note_off(int note, int vel);
|
||||
void perc_reset()
|
||||
{
|
||||
pphase = 0;
|
||||
modphase = 0;
|
||||
dpphase = 0;
|
||||
moddphase = 0;
|
||||
note = -1;
|
||||
}
|
||||
};
|
||||
|
||||
class organ_vibrato
|
||||
{
|
||||
protected:
|
||||
enum { VibratoSize = 6 };
|
||||
float vibrato_x1[VibratoSize][2], vibrato_y1[VibratoSize][2];
|
||||
float lfo_phase;
|
||||
dsp::onepole<float> vibrato[2];
|
||||
public:
|
||||
void reset();
|
||||
void process(organ_parameters *parameters, float (*data)[2], unsigned int len, float sample_rate);
|
||||
};
|
||||
|
||||
class organ_voice: public dsp::voice, public organ_voice_base {
|
||||
protected:
|
||||
enum { Channels = 2, BlockSize = 64, EnvCount = organ_parameters::EnvCount, FilterCount = organ_parameters::FilterCount };
|
||||
union {
|
||||
float output_buffer[BlockSize][Channels];
|
||||
float aux_buffers[3][BlockSize][Channels];
|
||||
};
|
||||
dsp::fixed_point<int64_t, 52> phase, dphase;
|
||||
dsp::biquad_d1<float> filterL[2], filterR[2];
|
||||
adsr envs[EnvCount];
|
||||
dsp::inertia<dsp::linear_ramp> expression;
|
||||
organ_vibrato vibrato;
|
||||
float velocity;
|
||||
bool perc_released;
|
||||
/// The envelopes have ended and the voice is in final fadeout stage
|
||||
bool finishing;
|
||||
dsp::inertia<dsp::exponential_ramp> inertia_pitchbend;
|
||||
|
||||
public:
|
||||
organ_voice()
|
||||
: organ_voice_base(NULL, sample_rate, perc_released)
|
||||
, expression(dsp::linear_ramp(16))
|
||||
, inertia_pitchbend(dsp::exponential_ramp(1))
|
||||
{
|
||||
inertia_pitchbend.set_now(1);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
inertia_pitchbend.ramp.set_length(sample_rate / (BlockSize * 30)); // 1/30s
|
||||
vibrato.reset();
|
||||
phase = 0;
|
||||
for (int i = 0; i < FilterCount; i++)
|
||||
{
|
||||
filterL[i].reset();
|
||||
filterR[i].reset();
|
||||
}
|
||||
}
|
||||
|
||||
void note_on(int note, int vel) {
|
||||
stolen = false;
|
||||
finishing = false;
|
||||
perc_released = false;
|
||||
released = false;
|
||||
reset();
|
||||
this->note = note;
|
||||
const float sf = 0.001f;
|
||||
for (int i = 0; i < EnvCount; i++)
|
||||
{
|
||||
organ_parameters::organ_env_parameters &p = parameters->envs[i];
|
||||
envs[i].set(sf * p.attack, sf * p.decay, p.sustain, sf * p.release, sample_rate / BlockSize);
|
||||
envs[i].note_on();
|
||||
}
|
||||
update_pitch();
|
||||
velocity = vel * 1.0 / 127.0;
|
||||
amp.set(1.0f);
|
||||
perc_note_on(note, vel);
|
||||
}
|
||||
|
||||
void note_off(int /* vel */) {
|
||||
// reset age to 0 (because decay will turn from exponential to linear, necessary because of error cumulation prevention)
|
||||
perc_released = true;
|
||||
if (pamp.get_active())
|
||||
{
|
||||
pamp.reinit();
|
||||
}
|
||||
rel_age_const = pamp.get() * ((1.0/44100.0)/0.03);
|
||||
for (int i = 0; i < EnvCount; i++)
|
||||
envs[i].note_off();
|
||||
}
|
||||
|
||||
virtual float get_priority() { return stolen ? 20000 : (perc_released ? 1 : (sostenuto ? 200 : 100)); }
|
||||
|
||||
virtual void steal() {
|
||||
perc_released = true;
|
||||
finishing = true;
|
||||
stolen = true;
|
||||
}
|
||||
|
||||
void render_block();
|
||||
|
||||
virtual int get_current_note() {
|
||||
return note;
|
||||
}
|
||||
virtual bool get_active() {
|
||||
// printf("note %d getactive %d use_percussion %d pamp active %d\n", note, amp.get_active(), use_percussion(), pamp.get_active());
|
||||
return (note != -1) && (amp.get_active() || (use_percussion() && pamp.get_active()));
|
||||
}
|
||||
void update_pitch();
|
||||
inline bool use_percussion()
|
||||
{
|
||||
return dsp::fastf2i_drm(parameters->percussion_trigger) == perctrig_polyphonic && parameters->percussion_level > 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// Not a true voice, just something with similar-ish interface.
|
||||
class percussion_voice: public organ_voice_base {
|
||||
public:
|
||||
int sample_rate;
|
||||
bool released;
|
||||
|
||||
percussion_voice(organ_parameters *_parameters)
|
||||
: organ_voice_base(_parameters, sample_rate, released)
|
||||
, released(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool get_active() {
|
||||
return (note != -1) && pamp.get_active();
|
||||
}
|
||||
bool get_noticable() {
|
||||
return (note != -1) && (pamp.get() > 0.2 * parameters->percussion_level);
|
||||
}
|
||||
void setup(int sr) {
|
||||
sample_rate = sr;
|
||||
}
|
||||
};
|
||||
|
||||
struct drawbar_organ: public dsp::basic_synth, public calf_plugins::organ_enums {
|
||||
organ_parameters *parameters;
|
||||
percussion_voice percussion;
|
||||
organ_vibrato global_vibrato;
|
||||
two_band_eq eq_l, eq_r;
|
||||
|
||||
drawbar_organ(organ_parameters *_parameters)
|
||||
: parameters(_parameters)
|
||||
, percussion(_parameters) {
|
||||
}
|
||||
void render_separate(float *output[], int nsamples);
|
||||
dsp::voice *alloc_voice() {
|
||||
block_voice<organ_voice> *v = new block_voice<organ_voice>();
|
||||
v->parameters = parameters;
|
||||
return v;
|
||||
}
|
||||
virtual void percussion_note_on(int note, int vel) {
|
||||
percussion.perc_note_on(note, vel);
|
||||
}
|
||||
virtual void params_changed() = 0;
|
||||
virtual void setup(int sr) {
|
||||
basic_synth::setup(sr);
|
||||
percussion.setup(sr);
|
||||
parameters->cutoff = 0;
|
||||
params_changed();
|
||||
global_vibrato.reset();
|
||||
}
|
||||
void update_params();
|
||||
void control_change(int controller, int value)
|
||||
{
|
||||
#if 0
|
||||
if (controller == 11)
|
||||
{
|
||||
parameters->cutoff = value / 64.0 - 1;
|
||||
}
|
||||
#endif
|
||||
dsp::basic_synth::control_change(controller, value);
|
||||
}
|
||||
void pitch_bend(int amt);
|
||||
virtual bool check_percussion() {
|
||||
switch(dsp::fastf2i_drm(parameters->percussion_trigger))
|
||||
{
|
||||
case organ_voice_base::perctrig_first:
|
||||
return active_voices.empty();
|
||||
case organ_voice_base::perctrig_each:
|
||||
default:
|
||||
return true;
|
||||
case organ_voice_base::perctrig_eachplus:
|
||||
return !percussion.get_noticable();
|
||||
case organ_voice_base::perctrig_polyphonic:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
306
plugins/ladspa_effect/calf/calf/osc.h
Normal file
@@ -0,0 +1,306 @@
|
||||
/* Calf DSP Library
|
||||
* Oscillators
|
||||
*
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CALF_OSC_H
|
||||
#define __CALF_OSC_H
|
||||
|
||||
#include "fft.h"
|
||||
#include <map>
|
||||
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/** Very simple, non-bandlimited saw oscillator. Should not be used for anything
|
||||
* else than testing/prototyping. Unless get() function is replaced with something
|
||||
* with "proper" oscillator code, as the frequency setting function is fine.
|
||||
*/
|
||||
struct simple_oscillator
|
||||
{
|
||||
/// Phase (from 0 to 0xFFFFFFFF)
|
||||
uint32_t phase;
|
||||
/// Per-sample phase delta (phase increment), equal to 2^32*freq/sr.
|
||||
uint32_t phasedelta;
|
||||
/// Reset oscillator phase to zero.
|
||||
void reset()
|
||||
{
|
||||
phase = 0;
|
||||
}
|
||||
/// Set phase delta based on oscillator frequency and sample rate.
|
||||
void set_freq(float freq, float sr)
|
||||
{
|
||||
phasedelta = (int)(freq * 65536.0 * 256.0 * 16.0 / sr) << 4;
|
||||
}
|
||||
/// Set phase delta based on oscillator frequency and inverse of sample rate.
|
||||
void set_freq_odsr(float freq, double odsr)
|
||||
{
|
||||
phasedelta = (int)(freq * 65536.0 * 256.0 * 16.0 * odsr) << 4;
|
||||
}
|
||||
inline float get()
|
||||
{
|
||||
float value = (phase >> 16 ) / 65535.0 - 0.5;
|
||||
phase += phasedelta;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* FFT-based bandlimiting helper class. Allows conversion between time and frequency domains and generating brickwall filtered
|
||||
* versions of a waveform given a pre-computed spectrum.
|
||||
* Waveform size must be a power of two, and template argument SIZE_BITS is log2 of waveform size.
|
||||
*/
|
||||
template<int SIZE_BITS>
|
||||
struct bandlimiter
|
||||
{
|
||||
enum { SIZE = 1 << SIZE_BITS };
|
||||
static dsp::fft<float, SIZE_BITS> &get_fft()
|
||||
{
|
||||
static dsp::fft<float, SIZE_BITS> fft;
|
||||
return fft;
|
||||
}
|
||||
|
||||
std::complex<float> spectrum[SIZE];
|
||||
|
||||
/// Import time domain waveform and calculate spectrum from it
|
||||
void compute_spectrum(float input[SIZE])
|
||||
{
|
||||
dsp::fft<float, SIZE_BITS> &fft = get_fft();
|
||||
std::complex<float> *data = new std::complex<float>[SIZE];
|
||||
for (int i = 0; i < SIZE; i++)
|
||||
data[i] = input[i];
|
||||
fft.calculate(data, spectrum, false);
|
||||
delete []data;
|
||||
}
|
||||
|
||||
/// Generate the waveform from the contained spectrum.
|
||||
void compute_waveform(float output[SIZE])
|
||||
{
|
||||
dsp::fft<float, SIZE_BITS> &fft = get_fft();
|
||||
std::complex<float> *data = new std::complex<float>[SIZE];
|
||||
fft.calculate(spectrum, data, true);
|
||||
for (int i = 0; i < SIZE; i++)
|
||||
output[i] = data[i].real();
|
||||
delete []data;
|
||||
}
|
||||
|
||||
/// remove DC offset of the spectrum (it usually does more harm than good!)
|
||||
void remove_dc()
|
||||
{
|
||||
spectrum[0] = 0.f;
|
||||
}
|
||||
|
||||
/// Very basic bandlimiting (brickwall filter)
|
||||
/// might need to be improved much in future!
|
||||
void make_waveform(float output[SIZE], int cutoff, bool foldover = false)
|
||||
{
|
||||
dsp::fft<float, SIZE_BITS> &fft = get_fft();
|
||||
std::vector<std::complex<float> > new_spec, iffted;
|
||||
new_spec.resize(SIZE);
|
||||
iffted.resize(SIZE);
|
||||
// Copy original harmonics up to cutoff point
|
||||
new_spec[0] = spectrum[0];
|
||||
for (int i = 1; i < cutoff; i++)
|
||||
new_spec[i] = spectrum[i],
|
||||
new_spec[SIZE - i] = spectrum[SIZE - i];
|
||||
// Fill the rest with zeros, optionally folding over harmonics over the
|
||||
// cutoff point into the lower octaves while halving the amplitude.
|
||||
// (I think it is almost nice for bell type waveforms when the original
|
||||
// waveform has few widely spread harmonics)
|
||||
if (foldover)
|
||||
{
|
||||
std::complex<float> fatt(0.5);
|
||||
cutoff /= 2;
|
||||
if (cutoff < 2)
|
||||
cutoff = 2;
|
||||
for (int i = SIZE / 2; i >= cutoff; i--)
|
||||
{
|
||||
new_spec[i / 2] += new_spec[i] * fatt;
|
||||
new_spec[SIZE - i / 2] += new_spec[SIZE - i] * fatt;
|
||||
new_spec[i] = 0.f,
|
||||
new_spec[SIZE - i] = 0.f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cutoff < 1)
|
||||
cutoff = 1;
|
||||
for (int i = cutoff; i < SIZE / 2; i++)
|
||||
new_spec[i] = 0.f,
|
||||
new_spec[SIZE - i] = 0.f;
|
||||
}
|
||||
// convert back to time domain (IFFT) and extract only real part
|
||||
fft.calculate(new_spec.data(), iffted.data(), true);
|
||||
for (int i = 0; i < SIZE; i++)
|
||||
output[i] = iffted[i].real();
|
||||
}
|
||||
};
|
||||
|
||||
/// Set of bandlimited wavetables
|
||||
template<int SIZE_BITS>
|
||||
struct waveform_family: public std::map<uint32_t, float *>
|
||||
{
|
||||
enum { SIZE = 1 << SIZE_BITS };
|
||||
using std::map<uint32_t, float *>::iterator;
|
||||
using std::map<uint32_t, float *>::end;
|
||||
using std::map<uint32_t, float *>::lower_bound;
|
||||
float original[SIZE];
|
||||
|
||||
/// Fill the family using specified bandlimiter and original waveform. Optionally apply foldover.
|
||||
/// Does not produce harmonics over specified limit (limit = (SIZE / 2) / min_number_of_harmonics)
|
||||
void make(bandlimiter<SIZE_BITS> &bl, float input[SIZE], bool foldover = false, uint32_t limit = SIZE / 2)
|
||||
{
|
||||
memcpy(original, input, sizeof(original));
|
||||
bl.compute_spectrum(input);
|
||||
make_from_spectrum(bl, foldover);
|
||||
}
|
||||
|
||||
/// Fill the family using specified bandlimiter and spectrum contained within. Optionally apply foldover.
|
||||
/// Does not produce harmonics over specified limit (limit = (SIZE / 2) / min_number_of_harmonics)
|
||||
void make_from_spectrum(bandlimiter<SIZE_BITS> &bl, bool foldover = false, uint32_t limit = SIZE / 2)
|
||||
{
|
||||
bl.remove_dc();
|
||||
|
||||
uint32_t base = 1 << (32 - SIZE_BITS);
|
||||
uint32_t cutoff = SIZE / 2, top = SIZE / 2;
|
||||
float vmax = 0;
|
||||
for (unsigned int i = 0; i < cutoff; i++)
|
||||
vmax = std::max(vmax, abs(bl.spectrum[i]));
|
||||
float vthres = vmax / 1024.0; // -60dB
|
||||
float cumul = 0.f;
|
||||
while(cutoff > (SIZE / limit)) {
|
||||
if (!foldover)
|
||||
{
|
||||
// skip harmonics too quiet to be heard, but measure their loudness cumulatively,
|
||||
// because even if a single harmonic is too quiet, a whole bunch of them may add up
|
||||
// to considerable amount of space
|
||||
cumul = 0.f;
|
||||
while(cutoff > 1 && cumul + abs(bl.spectrum[cutoff - 1]) < vthres)
|
||||
{
|
||||
cumul += abs(bl.spectrum[cutoff - 1]);
|
||||
cutoff--;
|
||||
}
|
||||
}
|
||||
float *wf = new float[SIZE+1];
|
||||
bl.make_waveform(wf, cutoff, foldover);
|
||||
wf[SIZE] = wf[0];
|
||||
(*this)[base * (top / cutoff)] = wf;
|
||||
cutoff = (int)(0.75 * cutoff);
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve waveform pointer suitable for specified phase_delta
|
||||
inline float *get_level(uint32_t phase_delta)
|
||||
{
|
||||
iterator i = upper_bound(phase_delta);
|
||||
if (i == end())
|
||||
return NULL;
|
||||
// printf("Level = %08x\n", i->first);
|
||||
return i->second;
|
||||
}
|
||||
/// Destructor, deletes the waveforms and removes them from the map.
|
||||
~waveform_family()
|
||||
{
|
||||
for (iterator i = begin(); i != end(); i++)
|
||||
delete []i->second;
|
||||
clear();
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
// cubic interpolation
|
||||
static inline float cerp(float pm1, float p0, float p1, float p2, float t)
|
||||
{
|
||||
return (-t*(t-1)*(t-2) * pm1 + 3*(t+1)*(t-1)*(t-2) * p0 - 3*(t+1)*t*(t-2) * p1 + (t+1)*t*(t-1) * p2) * (1.0 / 6.0);
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Simple table-based lerping oscillator. Uses waveform of size 2^SIZE_BITS.
|
||||
* Combine with waveform_family if bandlimited waveforms are needed. Because
|
||||
* of linear interpolation, it's usually a good idea to use large tables
|
||||
* (2048-4096 points), otherwise aliasing may be produced.
|
||||
*/
|
||||
template<int SIZE_BITS>
|
||||
struct waveform_oscillator: public simple_oscillator
|
||||
{
|
||||
enum { SIZE = 1 << SIZE_BITS, MASK = SIZE - 1, SCALE = 1 << (32 - SIZE_BITS) };
|
||||
float *waveform;
|
||||
inline float get()
|
||||
{
|
||||
uint32_t wpos = phase >> (32 - SIZE_BITS);
|
||||
float value = dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], (phase & (SCALE - 1)) * (1.0f / SCALE));
|
||||
phase += phasedelta;
|
||||
return value;
|
||||
}
|
||||
/// Add/substract two phase-shifted values
|
||||
inline float get_phaseshifted(uint32_t shift, float mix)
|
||||
{
|
||||
uint32_t wpos = phase >> (32 - SIZE_BITS);
|
||||
float value1 = dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], (phase & (SCALE - 1)) * (1.0f / SCALE));
|
||||
wpos = (phase + shift) >> (32 - SIZE_BITS);
|
||||
float value2 = dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], ((phase + shift) & (SCALE - 1)) * (1.0f / SCALE));
|
||||
float value = value1 + mix * value2;
|
||||
phase += phasedelta;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple triangle LFO without any smoothing or anything of this sort.
|
||||
*/
|
||||
struct triangle_lfo: public simple_oscillator
|
||||
{
|
||||
inline float get()
|
||||
{
|
||||
uint32_t phase2 = phase;
|
||||
// start at 90 degrees point of the "/\" wave (-1 to +1)
|
||||
phase2 += 1<<30;
|
||||
// if in second half, invert the wave (so it falls back into 0..0x7FFFFFFF)
|
||||
phase2 ^= ((int32_t)phase2)>>31;
|
||||
|
||||
float value = (phase2 >> 6) / 16777216.0 - 1.0;
|
||||
phase += phasedelta;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
/// Simple stupid inline function to normalize a waveform (by removing DC offset and ensuring max absolute value of 1).
|
||||
static inline void normalize_waveform(float *table, unsigned int size)
|
||||
{
|
||||
float dc = 0;
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
dc += table[i];
|
||||
dc /= size;
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
table[i] -= dc;
|
||||
float thismax = 0;
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
thismax = std::max(thismax, fabsf(table[i]));
|
||||
if (thismax < 0.000001f)
|
||||
return;
|
||||
double divv = 1.0 / thismax;
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
table[i] *= divv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
502
plugins/ladspa_effect/calf/calf/osctl.h
Normal file
@@ -0,0 +1,502 @@
|
||||
/* Calf DSP Library
|
||||
* Open Sound Control primitives
|
||||
*
|
||||
* Copyright (C) 2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CALF_OSCTL_H
|
||||
#define __CALF_OSCTL_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace osctl
|
||||
{
|
||||
|
||||
enum osc_type
|
||||
{
|
||||
osc_i32 = 'i',
|
||||
osc_f32 = 'f',
|
||||
osc_string = 's',
|
||||
osc_blob = 'b',
|
||||
|
||||
// unsupported
|
||||
osc_i64 = 'h',
|
||||
osc_ts = 't',
|
||||
osc_f64 = 'd',
|
||||
osc_string_alt = 'S',
|
||||
osc_char = 'c',
|
||||
osc_rgba = 'r',
|
||||
osc_midi = 'm',
|
||||
osc_true = 'T',
|
||||
osc_false = 'F',
|
||||
osc_nil = 'N',
|
||||
osc_inf = 'I',
|
||||
osc_start_array = '[',
|
||||
osc_end_array = ']'
|
||||
};
|
||||
|
||||
extern const char *osc_type_name(osc_type type);
|
||||
|
||||
struct osc_exception: public std::exception
|
||||
{
|
||||
virtual const char *what() const throw() { return "OSC parsing error"; }
|
||||
};
|
||||
|
||||
struct osc_read_exception: public std::exception
|
||||
{
|
||||
virtual const char *what() const throw() { return "OSC buffer underflow"; }
|
||||
};
|
||||
|
||||
struct osc_write_exception: public std::exception
|
||||
{
|
||||
virtual const char *what() const throw() { return "OSC buffer overflow"; }
|
||||
};
|
||||
|
||||
struct null_buffer
|
||||
{
|
||||
static bool read(uint8_t *dest, uint32_t bytes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static bool write(uint8_t *dest, uint32_t bytes)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
static void clear()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct raw_buffer
|
||||
{
|
||||
uint8_t *ptr;
|
||||
uint32_t pos, count, size;
|
||||
|
||||
raw_buffer()
|
||||
{
|
||||
ptr = NULL;
|
||||
pos = count = size = 0;
|
||||
}
|
||||
raw_buffer(uint8_t *_ptr, uint32_t _count, uint32_t _size)
|
||||
{
|
||||
set(_ptr, _count, _size);
|
||||
}
|
||||
inline void set(uint8_t *_ptr, uint32_t _count, uint32_t _size)
|
||||
{
|
||||
ptr = _ptr;
|
||||
pos = 0;
|
||||
count = _count;
|
||||
size = _size;
|
||||
}
|
||||
bool read(uint8_t *dest, uint32_t bytes)
|
||||
{
|
||||
if (pos + bytes > count)
|
||||
return false;
|
||||
memcpy(dest, ptr + pos, bytes);
|
||||
pos += bytes;
|
||||
return true;
|
||||
}
|
||||
bool write(const uint8_t *src, uint32_t bytes)
|
||||
{
|
||||
if (count + bytes > size)
|
||||
return false;
|
||||
memcpy(ptr + count, src, bytes);
|
||||
count += bytes;
|
||||
return true;
|
||||
}
|
||||
int read_left()
|
||||
{
|
||||
return count - pos;
|
||||
}
|
||||
int write_left()
|
||||
{
|
||||
return size - count;
|
||||
}
|
||||
inline int write_misalignment()
|
||||
{
|
||||
return 4 - (count & 3);
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
pos = 0;
|
||||
count = 0;
|
||||
}
|
||||
int tell()
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
void seek(int _pos)
|
||||
{
|
||||
pos = _pos;
|
||||
}
|
||||
};
|
||||
|
||||
struct string_buffer
|
||||
{
|
||||
std::string data;
|
||||
uint32_t pos, size;
|
||||
|
||||
string_buffer()
|
||||
{
|
||||
pos = 0;
|
||||
size = 1048576;
|
||||
}
|
||||
string_buffer(std::string _data, int _size = 1048576)
|
||||
{
|
||||
data = _data;
|
||||
pos = 0;
|
||||
size = _size;
|
||||
}
|
||||
bool read(uint8_t *dest, uint32_t bytes)
|
||||
{
|
||||
if (pos + bytes > data.length())
|
||||
return false;
|
||||
memcpy(dest, &data[pos], bytes);
|
||||
pos += bytes;
|
||||
return true;
|
||||
}
|
||||
bool write(const uint8_t *src, uint32_t bytes)
|
||||
{
|
||||
if (data.length() + bytes > size)
|
||||
return false;
|
||||
uint32_t wpos = data.length();
|
||||
data.resize(wpos + bytes);
|
||||
memcpy(&data[wpos], src, bytes);
|
||||
return true;
|
||||
}
|
||||
inline int read_left()
|
||||
{
|
||||
return data.length() - pos;
|
||||
}
|
||||
inline int write_left()
|
||||
{
|
||||
return size - data.length();
|
||||
}
|
||||
inline int write_misalignment()
|
||||
{
|
||||
return 4 - (data.length() & 3);
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
data.clear();
|
||||
pos = 0;
|
||||
}
|
||||
int tell()
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
void seek(int _pos)
|
||||
{
|
||||
pos = _pos;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffer, class TypeBuffer = null_buffer, bool Throw = true>
|
||||
struct osc_stream
|
||||
{
|
||||
Buffer &buffer;
|
||||
TypeBuffer *type_buffer;
|
||||
bool error;
|
||||
|
||||
osc_stream(Buffer &_buffer) : buffer(_buffer), type_buffer(NULL), error(false) {}
|
||||
osc_stream(Buffer &_buffer, TypeBuffer &_type_buffer) : buffer(_buffer), type_buffer(&_type_buffer), error(false) {}
|
||||
inline void pad()
|
||||
{
|
||||
uint32_t zero = 0;
|
||||
write(&zero, buffer.write_misalignment());
|
||||
}
|
||||
inline void read(void *dest, uint32_t bytes)
|
||||
{
|
||||
if (!buffer.read((uint8_t *)dest, bytes))
|
||||
{
|
||||
#if 0
|
||||
if (Throw)
|
||||
throw osc_read_exception();
|
||||
else
|
||||
#endif
|
||||
{
|
||||
error = true;
|
||||
memset(dest, 0, bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
inline void write(const void *src, uint32_t bytes)
|
||||
{
|
||||
if (!buffer.write((const uint8_t *)src, bytes))
|
||||
{
|
||||
#if 0
|
||||
if (Throw)
|
||||
throw osc_write_exception();
|
||||
else
|
||||
#endif
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
inline void clear()
|
||||
{
|
||||
buffer.clear();
|
||||
if (type_buffer)
|
||||
type_buffer->clear();
|
||||
}
|
||||
inline void write_type(char ch)
|
||||
{
|
||||
if (type_buffer)
|
||||
type_buffer->write((uint8_t *)&ch, 1);
|
||||
}
|
||||
};
|
||||
|
||||
typedef osc_stream<string_buffer> osc_strstream;
|
||||
typedef osc_stream<string_buffer, string_buffer> osc_typed_strstream;
|
||||
|
||||
struct osc_inline_strstream: public string_buffer, public osc_strstream
|
||||
{
|
||||
osc_inline_strstream()
|
||||
: string_buffer(), osc_strstream(static_cast<string_buffer &>(*this))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct osc_str_typed_buffer_pair
|
||||
{
|
||||
string_buffer buf_data, buf_types;
|
||||
};
|
||||
|
||||
struct osc_inline_typed_strstream: public osc_str_typed_buffer_pair, public osc_typed_strstream
|
||||
{
|
||||
osc_inline_typed_strstream()
|
||||
: osc_str_typed_buffer_pair(), osc_typed_strstream(buf_data, buf_types)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator <<(osc_stream<Buffer, TypeBuffer> &s, uint32_t val)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator >>(osc_stream<Buffer, TypeBuffer> &s, uint32_t &val)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator >>(osc_stream<Buffer, TypeBuffer> &s, int32_t &val)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator <<(osc_stream<Buffer, TypeBuffer> &s, float val)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator >>(osc_stream<Buffer, TypeBuffer> &s, float &val)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator <<(osc_stream<Buffer, TypeBuffer> &s, const std::string &str)
|
||||
{
|
||||
s.write(&str[0], str.length());
|
||||
s.pad();
|
||||
s.write_type(osc_string);
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator >>(osc_stream<Buffer, TypeBuffer> &s, std::string &str)
|
||||
{
|
||||
// inefficient...
|
||||
char five[5];
|
||||
five[4] = '\0';
|
||||
str.resize(0);
|
||||
while(1)
|
||||
{
|
||||
s.read(five, 4);
|
||||
if (five[0] == '\0')
|
||||
break;
|
||||
str += five;
|
||||
if (!five[1] || !five[2] || !five[3])
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer, class DestBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
read_buffer_from_osc_stream(osc_stream<Buffer, TypeBuffer> &s, DestBuffer &buf)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer, class SrcBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
write_buffer_to_osc_stream(osc_stream<Buffer, TypeBuffer> &s, SrcBuffer &buf)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator >>(osc_stream<Buffer, TypeBuffer> &s, raw_buffer &str)
|
||||
{
|
||||
return read_buffer_from_osc_stream(s, str);
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator >>(osc_stream<Buffer, TypeBuffer> &s, string_buffer &str)
|
||||
{
|
||||
return read_buffer_from_osc_stream(s, str);
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator <<(osc_stream<Buffer, TypeBuffer> &s, raw_buffer &str)
|
||||
{
|
||||
return write_buffer_to_osc_stream(s, str);
|
||||
}
|
||||
|
||||
template<class Buffer, class TypeBuffer>
|
||||
inline osc_stream<Buffer, TypeBuffer> &
|
||||
operator <<(osc_stream<Buffer, TypeBuffer> &s, string_buffer &str)
|
||||
{
|
||||
return write_buffer_to_osc_stream(s, str);
|
||||
}
|
||||
|
||||
// XXXKF: I don't support reading binary blobs yet
|
||||
#if 0
|
||||
struct osc_net_bad_address: public std::exception
|
||||
{
|
||||
std::string addr, error_msg;
|
||||
osc_net_bad_address(const char *_addr)
|
||||
{
|
||||
addr = _addr;
|
||||
error_msg = "Incorrect OSC URI: " + addr;
|
||||
}
|
||||
virtual const char *what() const throw() { return error_msg.c_str(); }
|
||||
virtual ~osc_net_bad_address() throw () {}
|
||||
};
|
||||
|
||||
struct osc_net_exception: public std::exception
|
||||
{
|
||||
int net_errno;
|
||||
std::string command, error_msg;
|
||||
osc_net_exception(const char *cmd, int _errno = errno)
|
||||
{
|
||||
command = cmd;
|
||||
net_errno = _errno;
|
||||
error_msg = "OSC error in "+command+": "+strerror(_errno);
|
||||
}
|
||||
virtual const char *what() const throw() { return error_msg.c_str(); }
|
||||
virtual ~osc_net_exception() throw () {}
|
||||
};
|
||||
|
||||
struct osc_net_dns_exception: public std::exception
|
||||
{
|
||||
int net_errno;
|
||||
std::string command, error_msg;
|
||||
virtual const char *what() const throw() { return error_msg.c_str(); }
|
||||
virtual ~osc_net_dns_exception() throw () {}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class OscStream>
|
||||
struct osc_message_sink
|
||||
{
|
||||
virtual void receive_osc_message(std::string address, std::string type_tag, OscStream &buffer)=0;
|
||||
virtual ~osc_message_sink() {}
|
||||
};
|
||||
|
||||
template<class OscStream, class DumpStream>
|
||||
struct osc_message_dump: public osc_message_sink<OscStream>
|
||||
{
|
||||
DumpStream &stream;
|
||||
osc_message_dump(DumpStream &_stream) : stream(_stream) {}
|
||||
|
||||
virtual void receive_osc_message(std::string address, std::string type_tag, OscStream &buffer)
|
||||
{
|
||||
int pos = buffer.buffer.tell();
|
||||
stream << "address: " << address << ", type tag: " << type_tag << std::endl;
|
||||
for (unsigned int i = 0; i < type_tag.size(); i++)
|
||||
{
|
||||
stream << "Argument " << i << " is ";
|
||||
switch(type_tag[i])
|
||||
{
|
||||
case 'i':
|
||||
{
|
||||
uint32_t val;
|
||||
buffer >> val;
|
||||
stream << val;
|
||||
break;
|
||||
}
|
||||
case 'f':
|
||||
{
|
||||
float val;
|
||||
buffer >> val;
|
||||
stream << val;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
{
|
||||
std::string val;
|
||||
buffer >> val;
|
||||
stream << val;
|
||||
break;
|
||||
}
|
||||
case 'b':
|
||||
{
|
||||
osctl::string_buffer val;
|
||||
buffer >> val;
|
||||
stream << "blob (" << val.data.length() << " bytes)";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
stream << "unknown - cannot parse more arguments" << std::endl;
|
||||
i = type_tag.size();
|
||||
break;
|
||||
}
|
||||
}
|
||||
stream << std::endl;
|
||||
}
|
||||
stream << std::flush;
|
||||
buffer.buffer.seek(pos);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
105
plugins/ladspa_effect/calf/calf/plugininfo.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/* Calf DSP Library
|
||||
* Plugin introspection interface
|
||||
*
|
||||
* Copyright (C) 2008 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CALF_PLUGININFO_H
|
||||
#define __CALF_PLUGININFO_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace calf_plugins {
|
||||
|
||||
/// A sink to send information about an audio port
|
||||
struct plain_port_info_iface
|
||||
{
|
||||
/// Called if it's an input port
|
||||
virtual plain_port_info_iface& input() { return *this; }
|
||||
/// Called if it's an output port
|
||||
virtual plain_port_info_iface& output() { return *this; }
|
||||
virtual plain_port_info_iface& lv2_ttl(const std::string &text) { return *this; }
|
||||
virtual ~plain_port_info_iface() {}
|
||||
};
|
||||
|
||||
/// A sink to send information about a control port (very incomplete, missing stuff: units, integer, boolean, toggled, notAutomatic, notGUI...)
|
||||
struct control_port_info_iface
|
||||
{
|
||||
/// Called if it's an input port
|
||||
virtual control_port_info_iface& input() { return *this; }
|
||||
/// Called if it's an output port
|
||||
virtual control_port_info_iface& output() { return *this; }
|
||||
/// Called to mark the port as using linear range [from, to]
|
||||
virtual control_port_info_iface& lin_range(double from, double to) { return *this; }
|
||||
/// Called to mark the port as using log range [from, to]
|
||||
virtual control_port_info_iface& log_range(double from, double to) { return *this; }
|
||||
virtual control_port_info_iface& toggle() { return *this; }
|
||||
virtual control_port_info_iface& trigger() { return *this; }
|
||||
virtual control_port_info_iface& integer() { return *this; }
|
||||
virtual control_port_info_iface& lv2_ttl(const std::string &text) { return *this; }
|
||||
virtual control_port_info_iface& polymorphic() { return lv2_ttl("a poly:PolymorphicPort ;"); }
|
||||
virtual control_port_info_iface& poly_audio() { return lv2_ttl("poly:supportsType lv2:AudioPort ;"); }
|
||||
virtual ~control_port_info_iface() {}
|
||||
};
|
||||
|
||||
/// A sink to send information about a plugin
|
||||
struct plugin_info_iface
|
||||
{
|
||||
/// Set plugin names (ID, name and label)
|
||||
virtual void names(const std::string &name, const std::string &label, const std::string &category, const std::string µname = std::string()) {}
|
||||
/// Add an audio port (returns a sink which accepts further description)
|
||||
virtual plain_port_info_iface &audio_port(const std::string &id, const std::string &name, const std::string µname = std::string("N/A"))=0;
|
||||
/// Add an event port (returns a sink which accepts further description)
|
||||
virtual plain_port_info_iface &event_port(const std::string &id, const std::string &name, const std::string µname = std::string("N/A"))=0;
|
||||
/// Add a control port (returns a sink which accepts further description)
|
||||
virtual control_port_info_iface &control_port(const std::string &id, const std::string &name, double def_value, const std::string µname = "N/A")=0;
|
||||
/// Add arbitrary TTL clauses
|
||||
virtual void lv2_ttl(const std::string &text) {}
|
||||
/// Add small plugin GUI
|
||||
virtual void has_gui() { lv2_ttl("uiext:ui <http://calf.sourceforge.net/small_plugins/gui/gtk2-gui> ;"); }
|
||||
/// Called after plugin has reported all the information
|
||||
virtual void finalize() {}
|
||||
virtual ~plugin_info_iface() {}
|
||||
};
|
||||
|
||||
struct plugin_port_type_grabber: public plugin_info_iface, public control_port_info_iface
|
||||
{
|
||||
uint32_t ⌖
|
||||
uint32_t index;
|
||||
|
||||
plain_port_info_iface pp;
|
||||
control_port_info_iface cp;
|
||||
|
||||
plugin_port_type_grabber(uint32_t &_target) : target(_target), index(0) { target = 0; }
|
||||
|
||||
virtual plain_port_info_iface &audio_port(const std::string &id, const std::string &name, const std::string µname = std::string("N/A")) { target |= (1 << index); index++; return pp; }
|
||||
virtual plain_port_info_iface &event_port(const std::string &id, const std::string &name, const std::string µname = std::string("N/A")) { index++; return pp; }
|
||||
virtual control_port_info_iface &control_port(const std::string &id, const std::string &name, double def_value, const std::string µname = "N/A") { index++; return cp; }
|
||||
};
|
||||
|
||||
/// A sink to send information about plugins
|
||||
struct plugin_list_info_iface
|
||||
{
|
||||
/// Add an empty plugin object and return the sink to be filled with information
|
||||
virtual plugin_info_iface &plugin(const std::string &id) = 0;
|
||||
virtual ~plugin_list_info_iface() {}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
142
plugins/ladspa_effect/calf/calf/preset.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* Calf DSP Library
|
||||
* Preset management
|
||||
*
|
||||
* Copyright (C) 2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_PRESET_H
|
||||
#define __CALF_PRESET_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <ostream>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
|
||||
namespace calf_plugins {
|
||||
|
||||
class plugin_ctl_iface;
|
||||
|
||||
/// Contents of single preset
|
||||
struct plugin_preset
|
||||
{
|
||||
/// Bank the preset belongs to (not used yet)
|
||||
int bank;
|
||||
/// Program number of the preset (not used yet)
|
||||
int program;
|
||||
/// Name of the preset
|
||||
std::string name;
|
||||
/// Name of the plugin the preset is for
|
||||
std::string plugin;
|
||||
/// Names of parameters in values array (for each item in param_names there should be a counterpart in values)
|
||||
std::vector<std::string> param_names;
|
||||
/// Values of parameters
|
||||
std::vector<float> values;
|
||||
/// DSSI configure-style variables
|
||||
std::map<std::string, std::string> variables;
|
||||
|
||||
plugin_preset() : bank(0), program(0) {}
|
||||
/// Export preset as XML
|
||||
std::string to_xml();
|
||||
/// "Upload" preset content to the plugin
|
||||
void activate(plugin_ctl_iface *plugin);
|
||||
/// "Download" preset content from the plugin
|
||||
void get_from(plugin_ctl_iface *plugin);
|
||||
|
||||
std::string get_safe_name();
|
||||
};
|
||||
|
||||
/// Exception thrown by preset system
|
||||
struct preset_exception
|
||||
{
|
||||
std::string message, param, fulltext;
|
||||
int error;
|
||||
preset_exception(const std::string &_message, const std::string &_param, int _error)
|
||||
: message(_message), param(_param), error(_error)
|
||||
{
|
||||
}
|
||||
const char *what() {
|
||||
if (error)
|
||||
fulltext = message + " " + param + " (" + strerror(error) + ")";
|
||||
else
|
||||
fulltext = message + " " + param;
|
||||
return fulltext.c_str();
|
||||
}
|
||||
~preset_exception()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// A vector of presets
|
||||
typedef std::vector<plugin_preset> preset_vector;
|
||||
|
||||
/// A single list of presets (usually there are two - @see get_builtin_presets(), get_user_presets() )
|
||||
struct preset_list
|
||||
{
|
||||
/// Parser states
|
||||
enum parser_state
|
||||
{
|
||||
START, ///< Beginning of parsing process (before root element)
|
||||
LIST, ///< Inside root element
|
||||
PRESET, ///< Inside preset definition
|
||||
VALUE, ///< Inside (empty) param tag
|
||||
VAR, ///< Inside (non-empty) var tag
|
||||
} state;
|
||||
|
||||
/// Contained presets (usually for all plugins)
|
||||
preset_vector presets;
|
||||
/// Temporary preset used during parsing process
|
||||
plugin_preset parser_preset;
|
||||
/// Preset number counters for DSSI (currently broken)
|
||||
std::map<std::string, int> last_preset_ids;
|
||||
/// The key used in current <var name="key"> tag (for state == VAR)
|
||||
std::string current_key;
|
||||
|
||||
/// Return the name of the built-in or user-defined preset file
|
||||
static std::string get_preset_filename(bool builtin);
|
||||
/// Load default preset list (built-in or user-defined)
|
||||
bool load_defaults(bool builtin);
|
||||
void parse(const std::string &data);
|
||||
/// Load preset list from XML file
|
||||
void load(const char *filename);
|
||||
/// Save preset list as XML file
|
||||
void save(const char *filename);
|
||||
/// Append or replace a preset (replaces a preset with the same plugin and preset name)
|
||||
void add(const plugin_preset &sp);
|
||||
/// Get a sublist of presets for a given plugin (those with plugin_preset::plugin == plugin)
|
||||
void get_for_plugin(preset_vector &vec, const char *plugin);
|
||||
|
||||
protected:
|
||||
/// Internal function: start element handler for expat
|
||||
static void xml_start_element_handler(void *user_data, const char *name, const char *attrs[]);
|
||||
/// Internal function: end element handler for expat
|
||||
static void xml_end_element_handler(void *user_data, const char *name);
|
||||
/// Internal function: character data (tag text content) handler for expat
|
||||
static void xml_character_data_handler(void *user_data, const char *data, int len);
|
||||
};
|
||||
|
||||
/// Return the current list of built-in (factory) presets (these are loaded from system-wide file)
|
||||
extern preset_list &get_builtin_presets();
|
||||
|
||||
/// Return the current list of user-defined presets (these are loaded from ~/.calfpresets)
|
||||
extern preset_list &get_user_presets();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
516
plugins/ladspa_effect/calf/calf/primitives.h
Normal file
@@ -0,0 +1,516 @@
|
||||
/* Calf DSP Library
|
||||
* DSP primitives.
|
||||
*
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_PRIMITIVES_H
|
||||
#define __CALF_PRIMITIVES_H
|
||||
|
||||
#include <stack>
|
||||
#include <map>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace dsp {
|
||||
|
||||
/// Set a float to zero
|
||||
inline void zero(float &v) {
|
||||
v = 0;
|
||||
};
|
||||
|
||||
/// Set a double to zero
|
||||
inline void zero(double &v) {
|
||||
v = 0;
|
||||
};
|
||||
|
||||
/// Set 64-bit unsigned integer value to zero
|
||||
inline void zero(uint64_t &v) { v = 0; };
|
||||
/// Set 32-bit unsigned integer value to zero
|
||||
inline void zero(uint32_t &v) { v = 0; };
|
||||
/// Set 16-bit unsigned integer value to zero
|
||||
inline void zero(uint16_t &v) { v = 0; };
|
||||
/// Set 8-bit unsigned integer value to zero
|
||||
inline void zero(uint8_t &v) { v = 0; };
|
||||
/// Set 64-bit signed integer value to zero
|
||||
inline void zero(int64_t &v) { v = 0; };
|
||||
/// Set 32-bit signed integer value to zero
|
||||
inline void zero(int32_t &v) { v = 0; };
|
||||
/// Set 16-bit signed integer value to zero
|
||||
inline void zero(int16_t &v) { v = 0; };
|
||||
/// Set 8-bit signed integer value to zero
|
||||
inline void zero(int8_t &v) { v = 0; };
|
||||
|
||||
/// Set array (buffer or anything similar) to vector of zeroes
|
||||
template<class T>
|
||||
void zero(T *data, unsigned int size) {
|
||||
T value;
|
||||
dsp::zero(value);
|
||||
for (unsigned int i=0; i<size; i++)
|
||||
*data++ = value;
|
||||
}
|
||||
|
||||
template<class T = float>struct stereo_sample {
|
||||
T left;
|
||||
T right;
|
||||
/// default constructor - preserves T's semantics (ie. no implicit initialization to 0)
|
||||
inline stereo_sample() {
|
||||
}
|
||||
inline stereo_sample(T _left, T _right) {
|
||||
left = _left;
|
||||
right = _right;
|
||||
}
|
||||
inline stereo_sample(T _both) {
|
||||
left = right = _both;
|
||||
}
|
||||
template<typename U>
|
||||
inline stereo_sample(const stereo_sample<U> &value) {
|
||||
left = value.left;
|
||||
right = value.right;
|
||||
}
|
||||
inline stereo_sample& operator=(const T &value) {
|
||||
left = right = value;
|
||||
return *this;
|
||||
}
|
||||
template<typename U>
|
||||
inline stereo_sample& operator=(const stereo_sample<U> &value) {
|
||||
left = value.left;
|
||||
right = value.right;
|
||||
return *this;
|
||||
}
|
||||
/*
|
||||
inline operator T() const {
|
||||
return (left+right)/2;
|
||||
}
|
||||
*/
|
||||
inline stereo_sample& operator*=(const T &multiplier) {
|
||||
left *= multiplier;
|
||||
right *= multiplier;
|
||||
return *this;
|
||||
}
|
||||
inline stereo_sample& operator+=(const stereo_sample<T> &value) {
|
||||
left += value.left;
|
||||
right += value.right;
|
||||
return *this;
|
||||
}
|
||||
inline stereo_sample& operator-=(const stereo_sample<T> &value) {
|
||||
left -= value.left;
|
||||
right -= value.right;
|
||||
return *this;
|
||||
}
|
||||
template<typename U> inline stereo_sample<U> operator*(const U &value) const {
|
||||
return stereo_sample<U>(left*value, right*value);
|
||||
}
|
||||
/*inline stereo_sample<float> operator*(float value) const {
|
||||
return stereo_sample<float>(left*value, right*value);
|
||||
}
|
||||
inline stereo_sample<double> operator*(double value) const {
|
||||
return stereo_sample<double>(left*value, right*value);
|
||||
}*/
|
||||
inline stereo_sample<T> operator+(const stereo_sample<T> &value) {
|
||||
return stereo_sample(left+value.left, right+value.right);
|
||||
}
|
||||
inline stereo_sample<T> operator-(const stereo_sample<T> &value) {
|
||||
return stereo_sample(left-value.left, right-value.right);
|
||||
}
|
||||
inline stereo_sample<T> operator+(const T &value) {
|
||||
return stereo_sample(left+value, right+value);
|
||||
}
|
||||
inline stereo_sample<T> operator-(const T &value) {
|
||||
return stereo_sample(left-value, right-value);
|
||||
}
|
||||
inline stereo_sample<float> operator+(float value) {
|
||||
return stereo_sample<float>(left+value, right+value);
|
||||
}
|
||||
inline stereo_sample<float> operator-(float value) {
|
||||
return stereo_sample<float>(left-value, right-value);
|
||||
}
|
||||
inline stereo_sample<double> operator+(double value) {
|
||||
return stereo_sample<double>(left+value, right+value);
|
||||
}
|
||||
inline stereo_sample<double> operator-(double value) {
|
||||
return stereo_sample<double>(left-value, right-value);
|
||||
}
|
||||
};
|
||||
|
||||
/// Multiply constant by stereo_value
|
||||
template<class T>
|
||||
inline stereo_sample<T> operator*(const T &value, const stereo_sample<T> &value2) {
|
||||
return stereo_sample<T>(value2.left*value, value2.right*value);
|
||||
}
|
||||
|
||||
/// Add constant to stereo_value
|
||||
template<class T>
|
||||
inline stereo_sample<T> operator+(const T &value, const stereo_sample<T> &value2) {
|
||||
return stereo_sample<T>(value2.left+value, value2.right+value);
|
||||
}
|
||||
|
||||
/// Subtract stereo_value from constant (yields stereo_value of course)
|
||||
template<class T>
|
||||
inline stereo_sample<T> operator-(const T &value, const stereo_sample<T> &value2) {
|
||||
return stereo_sample<T>(value-value2.left, value-value2.right);
|
||||
}
|
||||
|
||||
/// Shift value right by 'bits' bits (multiply by 2^-bits)
|
||||
template<typename T>
|
||||
inline stereo_sample<T> shr(stereo_sample<T> v, int bits = 1) {
|
||||
v.left = shr(v.left, bits);
|
||||
v.right = shr(v.right, bits);
|
||||
return v;
|
||||
}
|
||||
|
||||
/// Set a stereo_sample<T> value to zero
|
||||
template<typename T>
|
||||
inline void zero(stereo_sample<T> &v) {
|
||||
dsp::zero(v.left);
|
||||
dsp::zero(v.right);
|
||||
}
|
||||
|
||||
/// 'Small value' for integer and other types
|
||||
template<typename T>
|
||||
inline T small_value() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// 'Small value' for floats (2^-24) - used for primitive underrun prevention. The value is pretty much arbitrary (allowing for 24-bit signals normalized to 1.0).
|
||||
template<>
|
||||
inline float small_value<float>() {
|
||||
return (1.0/16777216.0); // allows for 2^-24, should be enough for 24-bit DACs at least :)
|
||||
}
|
||||
|
||||
/// 'Small value' for doubles (2^-24) - used for primitive underrun prevention. The value is pretty much arbitrary.
|
||||
template<>
|
||||
inline double small_value<double>() {
|
||||
return (1.0/16777216.0);
|
||||
}
|
||||
|
||||
/// Convert a single value to single value = do nothing :) (but it's a generic with specialisation for stereo_sample)
|
||||
template<typename T>
|
||||
inline float mono(T v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
/// Convert a stereo_sample to single value by averaging two channels
|
||||
template<typename T>
|
||||
inline T mono(stereo_sample<T> v) {
|
||||
return shr(v.left+v.right);
|
||||
}
|
||||
|
||||
/// Clip a value to [min, max]
|
||||
template<typename T>
|
||||
inline T clip(T value, T min, T max) {
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// Clip a double to [-1.0, +1.0]
|
||||
inline double clip11(double value) {
|
||||
double a = fabs(value);
|
||||
if (a<=1) return value;
|
||||
return (a<0) ? -1.0 : 1.0;
|
||||
}
|
||||
|
||||
/// Clip a float to [-1.0f, +1.0f]
|
||||
inline float clip11(float value) {
|
||||
float a = fabsf(value);
|
||||
if (a<=1) return value;
|
||||
return (a<0) ? -1.0f : 1.0f;
|
||||
}
|
||||
|
||||
/// Clip a double to [0.0, +1.0]
|
||||
inline double clip01(double value) {
|
||||
double a = fabs(value-0.5);
|
||||
if (a<=0.5) return value;
|
||||
return (a<0) ? -0.0 : 1.0;
|
||||
}
|
||||
|
||||
/// Clip a float to [0.0f, +1.0f]
|
||||
inline float clip01(float value) {
|
||||
float a = fabsf(value-0.5f);
|
||||
if (a<=0.5f) return value;
|
||||
return (a<0) ? -0.0f : 1.0f;
|
||||
}
|
||||
|
||||
// Linear interpolation (mix-way between v1 and v2).
|
||||
template<typename T, typename U>
|
||||
inline T lerp(T v1, T v2, U mix) {
|
||||
return v1+(v2-v1)*mix;
|
||||
}
|
||||
|
||||
// Linear interpolation for stereo values (mix-way between v1 and v2).
|
||||
template<typename T>
|
||||
inline stereo_sample<T> lerp(stereo_sample<T> &v1, stereo_sample<T> &v2, float mix) {
|
||||
return stereo_sample<T>(v1.left+(v2.left-v1.left)*mix, v1.right+(v2.right-v1.right)*mix);
|
||||
}
|
||||
|
||||
/**
|
||||
* decay-only envelope (linear or exponential); deactivates itself when it goes below a set point (epsilon)
|
||||
*/
|
||||
class decay
|
||||
{
|
||||
double value, initial;
|
||||
unsigned int age, mask;
|
||||
bool active;
|
||||
public:
|
||||
decay() {
|
||||
active = false;
|
||||
mask = 127;
|
||||
initial = value = 0.0;
|
||||
}
|
||||
inline bool get_active() {
|
||||
return active;
|
||||
}
|
||||
inline double get() {
|
||||
return active ? value : 0.0;
|
||||
}
|
||||
inline void set(double v) {
|
||||
initial = value = v;
|
||||
active = true;
|
||||
age = 0;
|
||||
}
|
||||
/// reinitialise envelope (must be called if shape changes from linear to exponential or vice versa in the middle of envelope)
|
||||
inline void reinit()
|
||||
{
|
||||
initial = value;
|
||||
age = 1;
|
||||
}
|
||||
inline void add(double v) {
|
||||
if (active)
|
||||
value += v;
|
||||
else
|
||||
value = v;
|
||||
initial = value;
|
||||
age = 0;
|
||||
active = true;
|
||||
}
|
||||
static inline double calc_exp_constant(double times, double cycles)
|
||||
{
|
||||
if (cycles < 1.0)
|
||||
cycles = 1.0;
|
||||
return pow(times, 1.0 / cycles);
|
||||
}
|
||||
inline void age_exp(double constant, double epsilon) {
|
||||
if (active) {
|
||||
if (!(age & mask))
|
||||
value = initial * pow(constant, (double)age);
|
||||
else
|
||||
value *= constant;
|
||||
if (value < epsilon)
|
||||
active = false;
|
||||
age++;
|
||||
}
|
||||
}
|
||||
inline void age_lin(double constant, double epsilon) {
|
||||
if (active) {
|
||||
if (!(age & mask))
|
||||
value = initial - constant * age;
|
||||
else
|
||||
value -= constant;
|
||||
if (value < epsilon)
|
||||
active = false;
|
||||
age++;
|
||||
}
|
||||
}
|
||||
inline void deactivate() {
|
||||
active = false;
|
||||
value = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class scheduler;
|
||||
|
||||
class task {
|
||||
public:
|
||||
virtual void execute(scheduler *s)=0;
|
||||
virtual void dispose() { delete this; }
|
||||
virtual ~task() {}
|
||||
};
|
||||
|
||||
/// this scheduler is based on std::multimap, so it isn't very fast, I guess
|
||||
/// maybe some day it should be rewritten to use heapsort or something
|
||||
/// work in progress, don't use!
|
||||
class scheduler {
|
||||
std::multimap<unsigned int, task *> timeline;
|
||||
unsigned int time, next_task;
|
||||
bool eob;
|
||||
class end_buf_task: public task {
|
||||
public:
|
||||
scheduler *p;
|
||||
end_buf_task(scheduler *_p) : p(_p) {}
|
||||
virtual void execute(scheduler *s) { p->eob = true; }
|
||||
virtual void dispose() { }
|
||||
} eobt;
|
||||
public:
|
||||
|
||||
scheduler()
|
||||
: time(0)
|
||||
, next_task((unsigned)-1)
|
||||
, eob(true)
|
||||
, eobt (this)
|
||||
{
|
||||
time = 0;
|
||||
next_task = (unsigned)-1;
|
||||
eob = false;
|
||||
}
|
||||
inline bool is_next_tick() {
|
||||
if (time < next_task)
|
||||
return true;
|
||||
do_tasks();
|
||||
}
|
||||
inline void next_tick() {
|
||||
time++;
|
||||
}
|
||||
void set(int pos, task *t) {
|
||||
timeline.insert(std::pair<unsigned int, task *>(time+pos, t));
|
||||
next_task = timeline.begin()->first;
|
||||
}
|
||||
void do_tasks() {
|
||||
std::multimap<unsigned int, task *>::iterator i = timeline.begin();
|
||||
while(i != timeline.end() && i->first == time) {
|
||||
i->second->execute(this);
|
||||
i->second->dispose();
|
||||
timeline.erase(i);
|
||||
}
|
||||
}
|
||||
bool is_eob() {
|
||||
return eob;
|
||||
}
|
||||
void set_buffer_size(int count) {
|
||||
set(count, &eobt);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Force "small enough" float value to zero
|
||||
*/
|
||||
inline void sanitize(float &value)
|
||||
{
|
||||
if (std::abs(value) < small_value<float>())
|
||||
value = 0.f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force "small enough" double value to zero
|
||||
*/
|
||||
inline void sanitize(double &value)
|
||||
{
|
||||
if (std::abs(value) < small_value<double>())
|
||||
value = 0.f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force "small enough" stereo value to zero
|
||||
*/
|
||||
template<class T>
|
||||
inline void sanitize(stereo_sample<T> &value)
|
||||
{
|
||||
sanitize(value.left);
|
||||
sanitize(value.right);
|
||||
}
|
||||
|
||||
inline float fract16(unsigned int value)
|
||||
{
|
||||
return (value & 0xFFFF) * (1.0 / 65536.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* typical precalculated sine table
|
||||
*/
|
||||
template<class T, int N, int Multiplier>
|
||||
class sine_table
|
||||
{
|
||||
public:
|
||||
static bool initialized;
|
||||
static T data[N+1];
|
||||
sine_table() {
|
||||
if (initialized)
|
||||
return;
|
||||
initialized = true;
|
||||
for (int i=0; i<N+1; i++)
|
||||
data[i] = (T)(Multiplier*sin(i*2*M_PI*(1.0/N)));
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, int N, int Multiplier>
|
||||
bool sine_table<T,N,Multiplier>::initialized = false;
|
||||
|
||||
template<class T, int N, int Multiplier>
|
||||
T sine_table<T,N,Multiplier>::data[N+1];
|
||||
|
||||
/// fast float to int conversion using default rounding mode
|
||||
inline int fastf2i_drm(float f)
|
||||
{
|
||||
#ifdef __X86__
|
||||
volatile int v;
|
||||
__asm ( "flds %1; fistpl %0" : "=m"(v) : "m"(f));
|
||||
return v;
|
||||
#else
|
||||
return (int)nearbyintf(f);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Convert MIDI note to frequency in Hz.
|
||||
inline float note_to_hz(double note, double detune_cents = 0.0)
|
||||
{
|
||||
return 440 * pow(2.0, (note - 69 + detune_cents/100.0) / 12.0);
|
||||
}
|
||||
|
||||
/// Hermite interpolation between two points and slopes in normalized range (written after Wikipedia article)
|
||||
/// @arg t normalized x coordinate (0-1 over the interval in question)
|
||||
/// @arg p0 first point
|
||||
/// @arg p1 second point
|
||||
/// @arg m0 first slope (multiply by interval width when using over non-1-wide interval)
|
||||
/// @arg m1 second slope (multiply by interval width when using over non-1-wide interval)
|
||||
inline float normalized_hermite(float t, float p0, float p1, float m0, float m1)
|
||||
{
|
||||
float t2 = t*t;
|
||||
float t3 = t2*t;
|
||||
return (2*t3 - 3*t2 + 1) * p0 + (t3 - 2*t2 + t) * m0 + (-2*t3 + 3*t2) * p1 + (t3-t2) * m1;
|
||||
}
|
||||
|
||||
/// Hermite interpolation between two points and slopes
|
||||
/// @arg x point within interval (x0 <= x <= x1)
|
||||
/// @arg x0 interval start
|
||||
/// @arg x1 interval end
|
||||
/// @arg p0 value at x0
|
||||
/// @arg p1 value at x1
|
||||
/// @arg m0 slope (steepness, tangent) at x0
|
||||
/// @arg m1 slope at x1
|
||||
inline float hermite_interpolation(float x, float x0, float x1, float p0, float p1, float m0, float m1)
|
||||
{
|
||||
float width = x1 - x0;
|
||||
float t = (x - x0) / width;
|
||||
m0 *= width;
|
||||
m1 *= width;
|
||||
float t2 = t*t;
|
||||
float t3 = t2*t;
|
||||
|
||||
float ct0 = p0;
|
||||
float ct1 = m0;
|
||||
float ct2 = -3 * p0 - 2 * m0 + 3 * p1 - m1;
|
||||
float ct3 = 2 * p0 + m0 - 2 * p1 + m1;
|
||||
|
||||
return ct3 * t3 + ct2 * t2 + ct1 * t + ct0;
|
||||
//return (2*t3 - 3*t2 + 1) * p0 + (t3 - 2*t2 + t) * m0 + (-2*t3 + 3*t2) * p1 + (t3-t2) * m1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
228
plugins/ladspa_effect/calf/calf/synth.h
Normal file
@@ -0,0 +1,228 @@
|
||||
/* Calf DSP Library
|
||||
* Framework for synthesizer-like plugins. This is based
|
||||
* on my earlier work on Drawbar electric organ emulator.
|
||||
*
|
||||
* Copyright (C) 2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_SYNTH_H
|
||||
#define __CALF_SYNTH_H
|
||||
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <bitset>
|
||||
#include "primitives.h"
|
||||
#include "audio_fx.h"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
/**
|
||||
* A kind of set with fast non-ordered iteration, used for storing lists of pressed keys.
|
||||
*/
|
||||
class keystack {
|
||||
private:
|
||||
int dcount;
|
||||
uint8_t active[128];
|
||||
uint8_t states[128];
|
||||
public:
|
||||
keystack() {
|
||||
memset(states, 0xFF, sizeof(states));
|
||||
dcount = 0;
|
||||
}
|
||||
void clear() {
|
||||
for (int i=0; i<dcount; i++)
|
||||
states[active[i]] = 0xFF;
|
||||
dcount = 0;
|
||||
}
|
||||
bool push(int key) {
|
||||
assert(key >= 0 && key <= 127);
|
||||
if (states[key] != 0xFF) {
|
||||
return true;
|
||||
}
|
||||
states[key] = dcount;
|
||||
active[dcount++] = key;
|
||||
return false;
|
||||
}
|
||||
bool pop(int key) {
|
||||
if (states[key] == 0xFF)
|
||||
return false;
|
||||
int pos = states[key];
|
||||
if (pos != dcount-1) {
|
||||
// reuse the popped item's stack position for stack top
|
||||
int last = active[dcount-1];
|
||||
active[pos] = last;
|
||||
// mark that position's new place on stack
|
||||
states[last] = pos;
|
||||
}
|
||||
states[key] = 0xFF;
|
||||
dcount--;
|
||||
return true;
|
||||
}
|
||||
inline bool has(int key) {
|
||||
return states[key] != 0xFF;
|
||||
}
|
||||
inline int count() {
|
||||
return dcount;
|
||||
}
|
||||
inline bool empty() {
|
||||
return (dcount == 0);
|
||||
}
|
||||
inline int nth(int n) {
|
||||
return active[n];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert MIDI note number to normalized UINT phase (where 1<<32 is full cycle).
|
||||
* @param MIDI note number
|
||||
* @param cents detune in cents (1/100 of a semitone)
|
||||
* @param sr sample rate
|
||||
*/
|
||||
inline unsigned int midi_note_to_phase(int note, double cents, int sr) {
|
||||
double incphase = 440*pow(2.0, (note-69)/12.0 + cents/1200.0)/sr;
|
||||
if (incphase >= 1.0) incphase = fmod(incphase, 1.0);
|
||||
incphase *= 65536.0*65536.0;
|
||||
return (unsigned int)incphase;
|
||||
}
|
||||
|
||||
// Base class for all voice objects
|
||||
class voice {
|
||||
public:
|
||||
int sample_rate;
|
||||
bool released, sostenuto, stolen;
|
||||
|
||||
voice() : sample_rate(-1), released(false), sostenuto(false), stolen(false) {}
|
||||
|
||||
/// reset voice to default state (used when a voice is to be reused)
|
||||
virtual void setup(int sr) { sample_rate = sr; }
|
||||
/// reset voice to default state (used when a voice is to be reused)
|
||||
virtual void reset()=0;
|
||||
/// a note was pressed
|
||||
virtual void note_on(int note, int vel)=0;
|
||||
/// a note was released
|
||||
virtual void note_off(int vel)=0;
|
||||
/// check if voice can be removed from active voice list
|
||||
virtual bool get_active()=0;
|
||||
/// render voice data to buffer
|
||||
virtual void render_to(float (*buf)[2], int nsamples)=0;
|
||||
/// very fast note off
|
||||
virtual void steal()=0;
|
||||
/// return the note used by this voice
|
||||
virtual int get_current_note()=0;
|
||||
virtual float get_priority() { return stolen ? 20000 : (released ? 1 : (sostenuto ? 200 : 100)); }
|
||||
/// empty virtual destructor
|
||||
virtual ~voice() {}
|
||||
};
|
||||
|
||||
/// An "optimized" voice class using fixed-size processing units
|
||||
/// and fixed number of channels. The drawback is that voice
|
||||
/// control is not sample-accurate, and no modulation input
|
||||
/// is possible, but it should be good enough for most cases
|
||||
/// (like Calf Organ).
|
||||
template<class Base>
|
||||
class block_voice: public Base {
|
||||
public:
|
||||
// derived from Base
|
||||
// enum { Channels = 2 };
|
||||
using Base::Channels;
|
||||
// enum { BlockSize = 16 };
|
||||
using Base::BlockSize;
|
||||
// float output_buffer[BlockSize][Channels];
|
||||
using Base::output_buffer;
|
||||
// void render_block();
|
||||
using Base::render_block;
|
||||
unsigned int read_ptr;
|
||||
|
||||
block_voice()
|
||||
{
|
||||
read_ptr = BlockSize;
|
||||
}
|
||||
virtual void reset()
|
||||
{
|
||||
Base::reset();
|
||||
read_ptr = BlockSize;
|
||||
}
|
||||
virtual void render_to(float (*buf)[2], int nsamples)
|
||||
{
|
||||
int p = 0;
|
||||
while(p < nsamples)
|
||||
{
|
||||
if (read_ptr == BlockSize)
|
||||
{
|
||||
render_block();
|
||||
read_ptr = 0;
|
||||
}
|
||||
int ncopy = std::min<int>(BlockSize - read_ptr, nsamples - p);
|
||||
for (int i = 0; i < ncopy; i++)
|
||||
for (int c = 0; c < Channels; c++)
|
||||
buf[p + i][c] += output_buffer[read_ptr + i][c];
|
||||
p += ncopy;
|
||||
read_ptr += ncopy;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Base class for all kinds of polyphonic instruments, provides
|
||||
/// somewhat reasonable voice management, pedal support - and
|
||||
/// little else. It's implemented as a base class with virtual
|
||||
/// functions, so there's some performance loss, but it shouldn't
|
||||
/// be horrible.
|
||||
/// @todo it would make sense to support all notes off controller too
|
||||
struct basic_synth {
|
||||
protected:
|
||||
/// Current sample rate
|
||||
int sample_rate;
|
||||
/// Hold pedal state
|
||||
bool hold;
|
||||
/// Sostenuto pedal state
|
||||
bool sostenuto;
|
||||
/// Voices currently playing
|
||||
std::list<dsp::voice *> active_voices;
|
||||
/// Voices allocated, but not used
|
||||
std::stack<dsp::voice *> unused_voices;
|
||||
/// Gate values for all 128 MIDI notes
|
||||
std::bitset<128> gate;
|
||||
/// Maximum allocated number of channels
|
||||
unsigned int polyphony_limit;
|
||||
|
||||
void kill_note(int note, int vel, bool just_one);
|
||||
public:
|
||||
virtual void setup(int sr) {
|
||||
sample_rate = sr;
|
||||
hold = false;
|
||||
sostenuto = false;
|
||||
polyphony_limit = (unsigned)-1;
|
||||
}
|
||||
virtual void trim_voices();
|
||||
virtual dsp::voice *give_voice();
|
||||
virtual dsp::voice *alloc_voice()=0;
|
||||
virtual dsp::voice *steal_voice();
|
||||
virtual void render_to(float (*output)[2], int nsamples);
|
||||
virtual void note_on(int note, int vel);
|
||||
virtual void percussion_note_on(int note, int vel) {}
|
||||
virtual void control_change(int ctl, int val);
|
||||
virtual void note_off(int note, int vel);
|
||||
/// amt = -8192 to 8191
|
||||
virtual void pitch_bend(int amt) {}
|
||||
virtual void on_pedal_release();
|
||||
virtual bool check_percussion() { return active_voices.empty(); }
|
||||
virtual ~basic_synth();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
161
plugins/ladspa_effect/calf/calf/utils.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/* Calf DSP Library
|
||||
* Utilities
|
||||
*
|
||||
* Copyright (C) 2008 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __CALF_UTILS_H
|
||||
#define __CALF_UTILS_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace calf_utils
|
||||
{
|
||||
|
||||
/// Pthreads based mutex class
|
||||
class ptmutex
|
||||
{
|
||||
public:
|
||||
pthread_mutex_t pm;
|
||||
|
||||
ptmutex(int type = PTHREAD_MUTEX_RECURSIVE)
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, type);
|
||||
pthread_mutex_init(&pm, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
|
||||
bool lock()
|
||||
{
|
||||
return pthread_mutex_lock(&pm) == 0;
|
||||
}
|
||||
|
||||
bool trylock()
|
||||
{
|
||||
return pthread_mutex_trylock(&pm) == 0;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&pm);
|
||||
}
|
||||
|
||||
~ptmutex()
|
||||
{
|
||||
pthread_mutex_destroy(&pm);
|
||||
}
|
||||
};
|
||||
|
||||
/// Exception-safe mutex lock
|
||||
class ptlock
|
||||
{
|
||||
ptmutex &mutex;
|
||||
bool locked;
|
||||
|
||||
public:
|
||||
ptlock(ptmutex &_m) : mutex(_m), locked(true)
|
||||
{
|
||||
mutex.lock();
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
mutex.unlock();
|
||||
locked = false;
|
||||
}
|
||||
void unlocked()
|
||||
{
|
||||
locked = false;
|
||||
}
|
||||
~ptlock()
|
||||
{
|
||||
if (locked)
|
||||
mutex.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
/// Exception-safe temporary assignment
|
||||
template<class T>
|
||||
class scope_assign
|
||||
{
|
||||
T &data, old_value;
|
||||
public:
|
||||
scope_assign(T &_data, T new_value)
|
||||
: data(_data), old_value(_data)
|
||||
{
|
||||
data = new_value;
|
||||
}
|
||||
~scope_assign()
|
||||
{
|
||||
data = old_value;
|
||||
}
|
||||
};
|
||||
|
||||
struct text_exception: public std::exception
|
||||
{
|
||||
const char *text;
|
||||
std::string container;
|
||||
public:
|
||||
text_exception(const std::string &t) : container(t) { text = container.c_str(); }
|
||||
virtual const char *what() const throw () { return text; }
|
||||
virtual ~text_exception() throw () {}
|
||||
};
|
||||
|
||||
struct file_exception: public std::exception
|
||||
{
|
||||
const char *text;
|
||||
std::string message, filename, container;
|
||||
public:
|
||||
file_exception(const std::string &f) : message(strerror(errno)), filename(f), container(filename + ":" + message) { text = container.c_str(); }
|
||||
file_exception(const std::string &f, const std::string &t) : message(t), filename(f), container(filename + ":" + message) { text = container.c_str(); }
|
||||
virtual const char *what() const throw () { return text; }
|
||||
virtual ~file_exception() throw () {}
|
||||
};
|
||||
|
||||
/// String-to-string mapping
|
||||
typedef std::map<std::string, std::string> dictionary;
|
||||
|
||||
/// Serialize a dictonary to a string
|
||||
extern std::string encode_map(const dictionary &data);
|
||||
/// Deserialize a dictonary from a string
|
||||
extern void decode_map(dictionary &data, const std::string &src);
|
||||
|
||||
/// int-to-string
|
||||
extern std::string i2s(int value);
|
||||
|
||||
/// float-to-string
|
||||
extern std::string f2s(double value);
|
||||
|
||||
/// float-to-string-that-doesn't-resemble-an-int
|
||||
extern std::string ff2s(double value);
|
||||
|
||||
/// Escape a string to be used in XML file
|
||||
std::string xml_escape(const std::string &src);
|
||||
|
||||
/// Load file from disk into a std::string blob, or throw file_exception
|
||||
std::string load_file(const std::string &src);
|
||||
|
||||
/// Indent a string by another string (prefix each line)
|
||||
std::string indent(const std::string &src, const std::string &indent);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
325
plugins/ladspa_effect/calf/giface.cpp
Normal file
@@ -0,0 +1,325 @@
|
||||
/* Calf DSP Library
|
||||
* Module wrapper methods.
|
||||
*
|
||||
* Copyright (C) 2001-2007 Krzysztof Foltman
|
||||
*
|
||||
* This program 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 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <memory.h>
|
||||
#include <calf/giface.h>
|
||||
#include <stdio.h>
|
||||
using namespace std;
|
||||
using namespace calf_utils;
|
||||
using namespace calf_plugins;
|
||||
|
||||
float parameter_properties::from_01(double value01) const
|
||||
{
|
||||
double value = dsp::clip(value01, 0., 1.);
|
||||
switch(flags & PF_SCALEMASK)
|
||||
{
|
||||
case PF_SCALE_DEFAULT:
|
||||
case PF_SCALE_LINEAR:
|
||||
case PF_SCALE_PERC:
|
||||
default:
|
||||
value = min + (max - min) * value01;
|
||||
break;
|
||||
case PF_SCALE_QUAD:
|
||||
value = min + (max - min) * value01 * value01;
|
||||
break;
|
||||
case PF_SCALE_LOG:
|
||||
value = min * pow(double(max / min), value01);
|
||||
break;
|
||||
case PF_SCALE_GAIN:
|
||||
if (value01 < 0.00001)
|
||||
value = min;
|
||||
else {
|
||||
float rmin = std::max(1.0f / 1024.0f, min);
|
||||
value = rmin * pow(double(max / rmin), value01);
|
||||
}
|
||||
break;
|
||||
case PF_SCALE_LOG_INF:
|
||||
assert(step);
|
||||
if (value01 > (step - 1.0) / step)
|
||||
value = FAKE_INFINITY;
|
||||
else
|
||||
value = min * pow(double(max / min), value01 * step / (step - 1.0));
|
||||
break;
|
||||
}
|
||||
switch(flags & PF_TYPEMASK)
|
||||
{
|
||||
case PF_INT:
|
||||
case PF_BOOL:
|
||||
case PF_ENUM:
|
||||
case PF_ENUM_MULTI:
|
||||
if (value > 0)
|
||||
value = (int)(value + 0.5);
|
||||
else
|
||||
value = (int)(value - 0.5);
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
double parameter_properties::to_01(float value) const
|
||||
{
|
||||
switch(flags & PF_SCALEMASK)
|
||||
{
|
||||
case PF_SCALE_DEFAULT:
|
||||
case PF_SCALE_LINEAR:
|
||||
case PF_SCALE_PERC:
|
||||
default:
|
||||
return double(value - min) / (max - min);
|
||||
case PF_SCALE_QUAD:
|
||||
return sqrt(double(value - min) / (max - min));
|
||||
case PF_SCALE_LOG:
|
||||
value /= min;
|
||||
return log((double)value) / log((double)max / min);
|
||||
case PF_SCALE_LOG_INF:
|
||||
if (IS_FAKE_INFINITY(value))
|
||||
return max;
|
||||
value /= min;
|
||||
assert(step);
|
||||
return (step - 1.0) * log((double)value) / (step * log((double)max / min));
|
||||
case PF_SCALE_GAIN:
|
||||
if (value < 1.0 / 1024.0) // new bottom limit - 60 dB
|
||||
return 0;
|
||||
double rmin = std::max(1.0f / 1024.0f, min);
|
||||
value /= rmin;
|
||||
return log((double)value) / log(max / rmin);
|
||||
}
|
||||
}
|
||||
|
||||
float parameter_properties::get_increment() const
|
||||
{
|
||||
float increment = 0.01;
|
||||
if (step > 1)
|
||||
increment = 1.0 / (step - 1);
|
||||
else
|
||||
if (step > 0 && step < 1)
|
||||
increment = step;
|
||||
else
|
||||
if ((flags & PF_TYPEMASK) != PF_FLOAT)
|
||||
increment = 1.0 / (max - min);
|
||||
return increment;
|
||||
}
|
||||
|
||||
int parameter_properties::get_char_count() const
|
||||
{
|
||||
if ((flags & PF_SCALEMASK) == PF_SCALE_PERC)
|
||||
return 6;
|
||||
if ((flags & PF_SCALEMASK) == PF_SCALE_GAIN) {
|
||||
char buf[256];
|
||||
size_t len = 0;
|
||||
sprintf(buf, "%0.0f dB", 6.0 * log(min) / log(2));
|
||||
len = strlen(buf);
|
||||
sprintf(buf, "%0.0f dB", 6.0 * log(max) / log(2));
|
||||
len = std::max(len, strlen(buf)) + 2;
|
||||
return (int)len;
|
||||
}
|
||||
return std::max(to_string(min).length(), std::max(to_string(max).length(), to_string(min + (max-min) * 0.987654).length()));
|
||||
}
|
||||
|
||||
std::string parameter_properties::to_string(float value) const
|
||||
{
|
||||
char buf[32];
|
||||
if ((flags & PF_SCALEMASK) == PF_SCALE_PERC) {
|
||||
sprintf(buf, "%0.f%%", 100.0 * value);
|
||||
return string(buf);
|
||||
}
|
||||
if ((flags & PF_SCALEMASK) == PF_SCALE_GAIN) {
|
||||
if (value < 1.0 / 1024.0) // new bottom limit - 60 dB
|
||||
return "-inf dB"; // XXXKF change to utf-8 infinity
|
||||
sprintf(buf, "%0.1f dB", 6.0 * log(value) / log(2));
|
||||
return string(buf);
|
||||
}
|
||||
switch(flags & PF_TYPEMASK)
|
||||
{
|
||||
case PF_STRING:
|
||||
return "N/A";
|
||||
case PF_INT:
|
||||
case PF_BOOL:
|
||||
case PF_ENUM:
|
||||
case PF_ENUM_MULTI:
|
||||
value = (int)value;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((flags & PF_SCALEMASK) == PF_SCALE_LOG_INF && IS_FAKE_INFINITY(value))
|
||||
sprintf(buf, "+inf"); // XXXKF change to utf-8 infinity
|
||||
else
|
||||
sprintf(buf, "%g", value);
|
||||
|
||||
switch(flags & PF_UNITMASK) {
|
||||
case PF_UNIT_DB: return string(buf) + " dB";
|
||||
case PF_UNIT_HZ: return string(buf) + " Hz";
|
||||
case PF_UNIT_SEC: return string(buf) + " s";
|
||||
case PF_UNIT_MSEC: return string(buf) + " ms";
|
||||
case PF_UNIT_CENTS: return string(buf) + " ct";
|
||||
case PF_UNIT_SEMITONES: return string(buf) + "#";
|
||||
case PF_UNIT_BPM: return string(buf) + " bpm";
|
||||
case PF_UNIT_RPM: return string(buf) + " rpm";
|
||||
case PF_UNIT_DEG: return string(buf) + " deg";
|
||||
case PF_UNIT_NOTE:
|
||||
{
|
||||
static const char *notes = "C C#D D#E F F#G G#A A#B ";
|
||||
int note = (int)value;
|
||||
if (note < 0 || note > 127)
|
||||
return "---";
|
||||
return string(notes + 2 * (note % 12), 2) + i2s(note / 12 - 2);
|
||||
}
|
||||
}
|
||||
|
||||
return string(buf);
|
||||
}
|
||||
|
||||
void calf_plugins::plugin_ctl_iface::clear_preset() {
|
||||
int param_count = get_param_count();
|
||||
for (int i=0; i < param_count; i++)
|
||||
{
|
||||
parameter_properties &pp = *get_param_props(i);
|
||||
if ((pp.flags & PF_TYPEMASK) == PF_STRING)
|
||||
{
|
||||
configure(pp.short_name, pp.choices ? pp.choices[0] : "");
|
||||
}
|
||||
else
|
||||
set_param_value(i, pp.def_value);
|
||||
}
|
||||
}
|
||||
|
||||
const char *calf_plugins::load_gui_xml(const std::string &plugin_id)
|
||||
{
|
||||
#if 0
|
||||
try {
|
||||
return strdup(calf_utils::load_file((std::string(PKGLIBDIR) + "/gui-" + plugin_id + ".xml").c_str()).c_str());
|
||||
}
|
||||
catch(file_exception e)
|
||||
#endif
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool calf_plugins::check_for_message_context_ports(parameter_properties *parameters, int count)
|
||||
{
|
||||
for (int i = count - 1; i >= 0; i--)
|
||||
{
|
||||
if (parameters[i].flags & PF_PROP_MSGCONTEXT)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool calf_plugins::check_for_string_ports(parameter_properties *parameters, int count)
|
||||
{
|
||||
for (int i = count - 1; i >= 0; i--)
|
||||
{
|
||||
if ((parameters[i].flags & PF_TYPEMASK) == PF_STRING)
|
||||
return true;
|
||||
if ((parameters[i].flags & PF_TYPEMASK) < PF_STRING)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if USE_DSSI
|
||||
struct osc_cairo_control: public cairo_iface
|
||||
{
|
||||
osctl::osc_inline_typed_strstream &os;
|
||||
|
||||
osc_cairo_control(osctl::osc_inline_typed_strstream &_os) : os(_os) {}
|
||||
virtual void set_source_rgba(float r, float g, float b, float a = 1.f)
|
||||
{
|
||||
os << (uint32_t)LGI_SET_RGBA << r << g << b << a;
|
||||
}
|
||||
virtual void set_line_width(float width)
|
||||
{
|
||||
os << (uint32_t)LGI_SET_WIDTH << width;
|
||||
}
|
||||
};
|
||||
|
||||
static void send_graph_via_osc(osctl::osc_client &client, const std::string &address, line_graph_iface *graph, std::vector<int> ¶ms)
|
||||
{
|
||||
osctl::osc_inline_typed_strstream os;
|
||||
osc_cairo_control cairoctl(os);
|
||||
for (size_t i = 0; i < params.size(); i++)
|
||||
{
|
||||
int index = params[i];
|
||||
os << (uint32_t)LGI_GRAPH;
|
||||
os << (uint32_t)index;
|
||||
for (int j = 0; ; j++)
|
||||
{
|
||||
float data[128];
|
||||
if (graph->get_graph(index, j, data, 128, &cairoctl))
|
||||
{
|
||||
os << (uint32_t)LGI_SUBGRAPH;
|
||||
os << (uint32_t)128;
|
||||
for (int p = 0; p < 128; p++)
|
||||
os << data[p];
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
for (int j = 0; ; j++)
|
||||
{
|
||||
float x, y;
|
||||
int size = 3;
|
||||
if (graph->get_dot(index, j, x, y, size, &cairoctl))
|
||||
os << (uint32_t)LGI_DOT << x << y << (uint32_t)size;
|
||||
else
|
||||
break;
|
||||
}
|
||||
for (int j = 0; ; j++)
|
||||
{
|
||||
float pos = 0;
|
||||
bool vertical = false;
|
||||
string legend;
|
||||
if (graph->get_gridline(index, j, pos, vertical, legend, &cairoctl))
|
||||
os << (uint32_t)LGI_LEGEND << pos << (uint32_t)(vertical ? 1 : 0) << legend;
|
||||
else
|
||||
break;
|
||||
}
|
||||
os << (uint32_t)LGI_END_ITEM;
|
||||
}
|
||||
os << (uint32_t)LGI_END;
|
||||
client.send(address, os);
|
||||
}
|
||||
|
||||
calf_plugins::dssi_feedback_sender::dssi_feedback_sender(const char *URI, line_graph_iface *_graph, calf_plugins::parameter_properties *props, int num_params)
|
||||
{
|
||||
graph = _graph;
|
||||
client = new osctl::osc_client;
|
||||
client->bind("0.0.0.0", 0);
|
||||
client->set_url(URI);
|
||||
for (int i = 0; i < num_params; i++)
|
||||
{
|
||||
if (props[i].flags & PF_PROP_GRAPH)
|
||||
indices.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
void calf_plugins::dssi_feedback_sender::update()
|
||||
{
|
||||
send_graph_via_osc(*client, "/lineGraph", graph, indices);
|
||||
}
|
||||
|
||||
calf_plugins::dssi_feedback_sender::~dssi_feedback_sender()
|
||||
{
|
||||
// this would not be received by GUI's main loop because it's already been terminated
|
||||
// client->send("/iQuit");
|
||||
delete client;
|
||||
}
|
||||
#endif
|
||||