commit 5bd39c2e1d41ad2ddea93e3296eb0b838143cce0
parent 81c307a3e56b2cf285d545fd46c0c1ab3e6b3d60
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Sun, 2 May 2010 13:59:59 -0400
Merge branch 'nio' into niox
Conflicts:
src/CMakeLists.txt
src/Nio/InMgr.cpp
src/Nio/OutMgr.cpp
Diffstat:
60 files changed, 1888 insertions(+), 593 deletions(-)
diff --git a/AUTHORS.txt b/AUTHORS.txt
@@ -16,4 +16,6 @@ Contributors:
Tobias Doerffel (static-instance variables fix, missing include fix)
James Morris (Memory leaks in FLTK GUI)
Alan Calvert (Portions of New IO)
+ Stephen Parry (DSSI rebuild)
+ Ryan Billing (APhaser)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -5,3 +5,7 @@ project(zynaddsubfx)
enable_testing()
#Currently the only directory that uses cmake
add_subdirectory(src)
+
+install(FILES AUTHORS.txt COPYING FAQ.txt HISTORY.txt README.txt
+ DESTINATION share/doc/zynaddsubfx
+ )
diff --git a/ChangeLog b/ChangeLog
@@ -982,3 +982,17 @@
- General Code Cleanup
- Adding OpenGL linking for proper compiles
+14 Jan 2010 (Mark McCurry)
+ - Fixed No UI Flag "-U" as it was previously partially initializing
+ the gui
+
+14 Feb 2010 (Stephen Parry)
+ - DSSI Support Repaired
+
+14 Feb 2010 (Mark McCurry)
+ - Made the Echo attempt to adjust the delay instead of erasing it
+ when length is changed
+
+02 May 2010 (Mark McCurry)
+ - Merging in cleanup from effects and adding APhaser by Ryan Billing
+
diff --git a/HISTORY.txt b/HISTORY.txt
@@ -1,3 +1,13 @@
+2.4.1 (In Beta)
+ - Azerty layout
+ - XML bug fixes
+ - Vibrato/Unison additions
+ - Reverb rewrite
+ - DSSI support enabled
+ - Adding APhaser
+ - other bugfixes
+ - code cleanup
+
2.4.0 (21 Jun 2009)
- extended mono functionality
- legato mode
diff --git a/doc/build.txt b/doc/build.txt
@@ -1,5 +1,5 @@
-Building ZynAddSubFX
-====================
+Appendix B: Building ZynAddSubFX
+================================
Introduction to CMake
---------------------
@@ -33,6 +33,11 @@ Quick start guide
For the impatient ones, here is a quick guide on how to immediately
build ZynAddSubFX from source.
+
+**************************************************************
+Note: This assumes that you already have a copy of the source.
+**************************************************************
+
---------------------------------
#enter the source directory
cd zynaddsubfx
@@ -46,13 +51,9 @@ cd build
cmake ..
#OPTIONAL: Adjust compile variables in the Cache file:
-$EDITOR CMakeCache.txt
+ccmake .
#And finally, build as usual using make
make
---------------------------------
-Customizing the build
----------------------
-
-
diff --git a/doc/getting.txt b/doc/getting.txt
@@ -0,0 +1,61 @@
+Appendix C: Getting ZynAddSubFX
+===============================
+
+Usually there are several methods to obtain a copy of ZynAddSubFX.
+
+SourceForge::
+ http://sourceforge.net/projects/zynaddsubfx/files/
+Distribuition::
+ apt/yum/others
+Git::
+ git://zynaddsubfx.git.sourceforge.net/gitroot/zynaddsubfx/zynaddsubfx
+
+Introduction to Git
+-------------------
+
+For those who want to live on the bleeding edge or who want to assist with
+making sure that the next release has fewer bugs, you will want to get aquanted
+with git.
+Git is used to manage the source code for this project and can be used to
+quickly and easily get an up-to-date copy of the source code.
+
+Getting the Source Code
+~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to get a copy of the ZynAddSubFX source code, all that needs to be done is:
+
+---------------------------------------------
+git clone git://zynaddsubfx.git.sourceforge.net/gitroot/zynaddsubfx/zynaddsubfx
+
+cd zynaddsubfx
+---------------------------------------------
+
+You should now be in the directory of the source code.
+
+For simple steps on building, please see Appendix B of the manual.
+
+Checking out a branch
+~~~~~~~~~~~~~~~~~~~~~
+
+Lets say that development has extended into the creation of a new feature that
+you want to preview.
+For the sake of this guide, lets assume that the name of the branch that the
+feature is on is foo.
+
+-----------------------------------------
+#checkout the foo branch from sourceforge
+git checkout --track -b foo origin/foo
+
+#lets checkout the primary branch again
+git checkout master
+
+#hop back to the other branch
+git checkout foo
+----------------------------------------
+
+Now one should be able to change branches and go into the build directory (as
+described in Appendix B) and recompile ZynAddSubFX.
+
+NOTE: When using branches other than the master be aware that stability may
+ suffer
+
diff --git a/doc/zynaddsubfx.txt b/doc/zynaddsubfx.txt
@@ -18,3 +18,7 @@ include::./controller.txt[]
include::./nrpn.txt[]
include::./mididefaults.txt[]
+
+include::./build.txt[]
+
+include::./getting.txt[]
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
@@ -6,6 +6,7 @@ message(STATUS "Checking Library Path" $ENV{CMAKE_LIBRARY_PATH} ${CMAKE_LIBRARY_
find_package(zlib REQUIRED)
find_package(fftw REQUIRED)
find_package(MXML REQUIRED)
+find_package(PkgConfig REQUIRED)
#find_package(pthread REQUIRED)
#find_package(OSS)
find_package(Alsa)
@@ -33,6 +34,7 @@ SET (OssEnable ${ALSA_FOUND} CACHE BOOL #TODO perhaps check for /dev/dsp
SET (PaEnable ${PORTAUDIO_FOUND} CACHE BOOL
"Enable support for Port Audio System")
+
# Now, handle the incoming settings and set define flags/variables based
# on this
@@ -48,6 +50,13 @@ else ()
message(STATUS "GUI module defaulting to off")
endif()
+if(NOT PKG_CONFIG_FOUND)
+ message(FATAL_ERROR "pkg-config not found")
+endif(NOT PKG_CONFIG_FOUND)
+
+# lash
+pkg_search_module(LASH lash-1.0)
+mark_as_advanced(LASH_LIBRARIES)
########### Settings dependant code ###########
# From here on, the setting variables have been prepared so concentrate
@@ -79,6 +88,13 @@ if (CompileTests)
ENABLE_TESTING()
endif()
+if(LASH_FOUND)
+ include_directories(${LASH_INCLUDE_DIRS})
+ add_definitions(-DUSE_LASH)
+ set(AUDIO_LIBRARIES ${AUDIO_LIBRARIES} ${LASH_LIBRARIES})
+ message(STATUS "Compiling with lash")
+endif()
+
add_definitions(-DFFTW_VERSION_${FFTW_VERSION}
-DASM_F2I_YES
-g #TODO #todo put in a better location
@@ -124,7 +140,7 @@ if(FltkGui)
message(STATUS ${MYFLTK_LDFLAGS})
- set(GUI_LIBRARIES ${MYFLTK_LIBRARIES} ${FLTK_LIBRARIES} ${OPENGL_LIBRARIES} zynaddsubfx_gui)
+ set(GUI_LIBRARIES ${FLTK_LIBRARIES} ${MYFLTK_LIBRARIES} ${OPENGL_LIBRARIES} zynaddsubfx_gui)
add_definitions(-DFLTK_GUI)
@@ -224,3 +240,6 @@ target_link_libraries(zynaddsubfx
${OS_LIBRARIES}
)
+install(TARGETS zynaddsubfx
+ RUNTIME DESTINATION bin
+ )
diff --git a/src/Effects/APhaser.cpp b/src/Effects/APhaser.cpp
@@ -0,0 +1,450 @@
+/*
+
+ APhaser.C - Approximate digital model of an analog JFET phaser.
+ Analog modeling implemented by Ryan Billing aka Transmogrifox.
+ November, 2009
+
+ Credit to:
+ ///////////////////
+ ZynAddSubFX - a software synthesizer
+
+ Phaser.C - Phaser effect
+ Copyright (C) 2002-2005 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ Modified for rakarrack by Josep Andreu
+
+ DSP analog modeling theory & practice largely influenced by various CCRMA publications, particularly works by Julius O. Smith.
+ ////////////////////
+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ 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 (version 2) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include <cmath>
+#include "APhaser.h"
+#include <cstdio>
+#include <iostream>
+using namespace std;
+#define PHASER_LFO_SHAPE 2
+#define ONE_ 0.99999f // To prevent LFO ever reaching 1.0 for filter stability purposes
+#define ZERO_ 0.00001f // Same idea as above.
+
+Analog_Phaser::Analog_Phaser(const int & insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_)
+ :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0)
+{
+ lxn1 = NULL;
+ lyn1 = NULL;
+ rxn1 = NULL;
+ ryn1 = NULL;
+
+ offset = new REALTYPE[12]; //model mismatch between JFET devices
+ offset[0] = -0.2509303f;
+ offset[1] = 0.9408924f;
+ offset[2] = 0.998f;
+ offset[3] = -0.3486182f;
+ offset[4] = -0.2762545f;
+ offset[5] = -0.5215785f;
+ offset[6] = 0.2509303f;
+ offset[7] = -0.9408924f;
+ offset[8] = -0.998f;
+ offset[9] = 0.3486182f;
+ offset[10] = 0.2762545f;
+ offset[11] = 0.5215785f;
+
+ barber = 0; //Deactivate barber pole phasing by default
+
+ mis = 1.0f;
+ Rmin = 625.0f; // 2N5457 typical on resistance at Vgs = 0
+ Rmax = 22000.0f; // Resistor parallel to FET
+ Rmx = Rmin/Rmax;
+ Rconst = 1.0f + Rmx; // Handle parallel resistor relationship
+ C = 0.00000005f; // 50 nF
+ CFs = (float) 2.0f*(float)SAMPLE_RATE*C;
+ invperiod = 1.0f / ((float) SOUND_BUFFER_SIZE);
+
+
+ Ppreset = 0;
+ setpreset (Ppreset);
+ cleanup ();
+};
+
+Analog_Phaser::~Analog_Phaser()
+{
+
+ if(lxn1 != NULL)
+ delete[]lxn1;
+
+ if(lyn1 != NULL)
+ delete[]lyn1;
+
+ if(rxn1 != NULL)
+ delete[]rxn1;
+
+ if(ryn1 != NULL)
+ delete[]ryn1;
+
+ if(offset != NULL)
+ delete[]offset;
+};
+
+
+/*
+ * Effect output
+ */
+void Analog_Phaser::out(const Stereo<REALTYPE *> &input)
+{
+ int i, j;
+ float lfol, lfor, lgain, rgain, bl, br, gl, gr, rmod, lmod, d, hpfr, hpfl;
+ lgain = 0.0;
+ rgain = 0.0;
+
+ //initialize hpf
+ hpfl = 0.0;
+ hpfr = 0.0;
+
+ lfo.effectlfoout (&lfol, &lfor);
+ lmod = lfol*width + depth;
+ rmod = lfor*width + depth;
+
+ if(lmod > ONE_)
+ lmod = ONE_;
+ else if(lmod < ZERO_)
+ lmod = ZERO_;
+ if(rmod > ONE_)
+ rmod = ONE_;
+ else if(rmod < ZERO_)
+ rmod = ZERO_;
+
+ if(Phyper != 0)
+ {
+ lmod *= lmod; //Triangle wave squared is approximately sin on bottom, tri on top
+ rmod *= rmod; //Result is exponential sweep more akin to filter in synth with exponential generator circuitry.
+ };
+
+ lmod = sqrtf(1.0f - lmod); //gl,gr is Vp - Vgs. Typical FET drain-source resistance follows constant/[1-sqrt(Vp - Vgs)]
+ rmod = sqrtf(1.0f - rmod);
+
+ rdiff = (rmod - oldrgain) * invperiod;
+ ldiff = (lmod - oldlgain) * invperiod;
+
+ gl = oldlgain;
+ gr = oldrgain;
+
+ oldlgain = lmod;
+ oldrgain = rmod;
+
+ for (i = 0; i < SOUND_BUFFER_SIZE; i++)
+ {
+
+ gl += ldiff; // Linear interpolation between LFO samples
+ gr += rdiff;
+
+ float lxn = input.l()[i];
+ float rxn = input.r()[i];
+
+
+ if (barber) {
+ gl = fmodf((gl + 0.25f) , ONE_);
+ gr = fmodf((gr + 0.25f) , ONE_);
+ };
+
+
+ //cout << lxn << " vs ";
+ //Left channel
+ for (j = 0; j < Pstages; j++)
+ { //Phasing routine
+ mis = 1.0f + offsetpct*offset[j];
+ d = (1.0f + 2.0f*(0.25f + gl)*hpfl*hpfl*distortion) * mis; //This is symmetrical. FET is not, so this deviates slightly, however sym dist. is better sounding than a real FET.
+ Rconst = 1.0f + mis*Rmx;
+ bl = (Rconst - gl )/ (d*Rmin); // This is 1/R. R is being modulated to control filter fc.
+ lgain = (CFs - bl)/(CFs + bl);
+
+ lyn1[j] = lgain * (lxn + lyn1[j]) - lxn1[j];
+ //lyn1[j] += DENORMAL_GUARD;
+ hpfl = lyn1[j] + (1.0f-lgain)*lxn1[j]; //high pass filter -- Distortion depends on the high-pass part of the AP stage.
+
+ lxn1[j] = lxn;
+ lxn = lyn1[j];
+ if (j==1) lxn += fbl; //Insert feedback after first phase stage
+ };
+ //cout << lxn << endl;
+
+ //Right channel
+ for (j = 0; j < Pstages; j++)
+ { //Phasing routine
+ mis = 1.0f + offsetpct*offset[j];
+ d = (1.0f + 2.0f*(0.25f + gr)*hpfr*hpfr*distortion) * mis; // distortion
+ Rconst = 1.0f + mis*Rmx;
+ br = (Rconst - gr )/ (d*Rmin);
+ rgain = (CFs - br)/(CFs + br);
+
+ ryn1[j] = rgain * (rxn + ryn1[j]) - rxn1[j];
+ //ryn1[j] += DENORMAL_GUARD;
+ hpfr = ryn1[j] + (1.0f-rgain)*rxn1[j]; //high pass filter
+
+ rxn1[j] = rxn;
+ rxn = ryn1[j];
+ if (j==1) rxn += fbr; //Insert feedback after first phase stage
+ }
+
+ //cout << fb << ' ' << input.l()[i] - lxn << endl;
+ //cout << "input" << input.l()[i] << "output:" << lxn << endl;
+
+ fbl = lxn * fb;
+ fbr = rxn * fb;
+ efxoutl[i] = lxn;
+ efxoutr[i] = rxn;
+
+ }
+
+ if(Poutsub != 0)
+ for(i = 0; i < SOUND_BUFFER_SIZE; i++)
+ {
+ efxoutl[i] *= -1.0f;
+ efxoutr[i] *= -1.0f;
+ };
+};
+
+/*
+ * Cleanup the effect
+ */
+void Analog_Phaser::cleanup()
+{
+ fbl = 0.0;
+ fbr = 0.0;
+ oldlgain = 0.0;
+ oldrgain = 0.0;
+ for(int i = 0; i < Pstages; i++)
+ {
+ lxn1[i] = 0.0;
+
+ lyn1[i] = 0.0;
+
+ rxn1[i] = 0.0;
+
+ ryn1[i] = 0.0;
+
+ };
+};
+
+/*
+ * Parameter control
+ */
+void Analog_Phaser::setwidth(unsigned char Pwidth)
+{
+ this->Pwidth = Pwidth;
+ width = ((float)Pwidth / 127.0f);
+};
+
+
+void Analog_Phaser::setfb(unsigned char Pfb)
+{
+ this->Pfb = Pfb;
+ fb = (float) (Pfb - 64) / 64.2f;
+};
+
+void Analog_Phaser::setvolume(unsigned char Pvolume)
+{
+ cout << "setting volume" << (int) Pvolume << endl;
+ this->Pvolume = Pvolume;
+ // outvolume is needed in calling program
+ if(insertion == 0) {
+ outvolume = pow(0.01, (1.0 - Pvolume / 127.0)) * 4.0;
+ volume = 1.0;
+ }
+ else
+ volume = outvolume = Pvolume / 127.0;
+};
+
+void Analog_Phaser::setdistortion(unsigned char Pdistortion)
+{
+ this->Pdistortion = Pdistortion;
+ distortion = (float)Pdistortion / 127.0f;
+};
+
+void Analog_Phaser::setoffset(unsigned char Poffset)
+{
+ this->Poffset = Poffset;
+ offsetpct = (float)Poffset / 127.0f;
+};
+
+void Analog_Phaser::setstages(unsigned char Pstages)
+{
+
+ if(lxn1 != NULL)
+ delete[]lxn1;
+
+ if(lyn1 != NULL)
+ delete[]lyn1;
+
+ if(rxn1 != NULL)
+ delete[]rxn1;
+
+ if(ryn1 != NULL)
+ delete[]ryn1;
+
+
+ if(Pstages >= MAX_PHASER_STAGES)
+ Pstages = MAX_PHASER_STAGES ;
+ this->Pstages = Pstages;
+
+
+ lxn1 = new REALTYPE[Pstages];
+ lyn1 = new REALTYPE[Pstages];
+
+ rxn1 = new REALTYPE[Pstages];
+ ryn1 = new REALTYPE[Pstages];
+
+ cleanup();
+};
+
+void Analog_Phaser::setdepth(unsigned char Pdepth)
+{
+ this->Pdepth = Pdepth;
+ depth = (float)(Pdepth - 64) / 127.0f; //Pdepth input should be 0-127. depth shall range 0-0.5 since we don't need to shift the full spectrum.
+};
+
+
+void Analog_Phaser::setpreset(unsigned char npreset)
+{
+ const int PRESET_SIZE = 13;
+ const int NUM_PRESETS = 6;
+ unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
+ //Phaser1
+ {64, 20, 14, 0, 1, 64, 110, 40, 4, 10, 0, 64, 1},
+ //Phaser2
+ {64, 20, 14, 5, 1, 64, 110, 40, 6, 10, 0, 70, 1},
+ //Phaser3
+ {64, 20, 9, 0, 0, 64, 40, 40, 8, 10, 0, 60, 0},
+ //Phaser4
+ {64, 20, 14, 10, 0, 64, 110, 80, 7, 10, 1, 45, 1},
+ //Phaser5
+ {25, 20, 240, 10, 0, 64, 25, 16, 8, 100, 0, 25, 0},
+ //Phaser6
+ {64, 20, 1, 10, 1, 64, 110, 40, 12, 10, 0, 70, 1}
+ };
+ if(npreset >= NUM_PRESETS)
+ npreset = NUM_PRESETS - 1;
+ for(int n = 0; n < PRESET_SIZE; n++)
+ changepar(n, presets[npreset][n]);
+ Ppreset = npreset;
+};
+
+
+void Analog_Phaser::changepar(int npar, unsigned char value)
+{
+ switch(npar)
+ {
+ case 0:
+ setvolume(value);
+ break;
+ case 1:
+ setdistortion(value);
+ break;
+ case 2:
+ lfo.Pfreq = value;
+ lfo.updateparams();
+ break;
+ case 3:
+ lfo.Prandomness = value;
+ lfo.updateparams ();
+ break;
+ case 4:
+ lfo.PLFOtype = value;
+ lfo.updateparams();
+ barber = 0;
+ if (value == 2) barber = 1;
+ break;
+ case 5:
+ lfo.Pstereo = value;
+ lfo.updateparams();
+ break;
+ case 6:
+ setwidth(value);
+ break;
+ case 7:
+ setfb(value);
+ break;
+ case 8:
+ setstages(value);
+ break;
+ case 9:
+ setoffset(value);
+ break;
+ case 10:
+ if (value > 1)
+ value = 1;
+ Poutsub = value;
+ break;
+ case 11:
+ setdepth(value);
+ break;
+ case 12:
+ if (value > 1)
+ value = 1;
+ Phyper = value;
+ break;
+ };
+};
+
+unsigned char Analog_Phaser::getpar(int npar) const
+{
+ switch(npar)
+ {
+ case 0:
+ return(Pvolume);
+ break;
+ case 1:
+ return(Pdistortion);
+ break;
+ case 2:
+ return(lfo.Pfreq);
+ break;
+ case 3:
+ return(lfo.Prandomness);
+ break;
+ case 4:
+ return(lfo.PLFOtype);
+ break;
+ case 5:
+ return(lfo.Pstereo);
+ break;
+ case 6:
+ return(Pwidth);
+ break;
+ case 7:
+ return(Pfb);
+ break;
+ case 8:
+ return(Pstages);
+ break;
+ case 9:
+ return(Poffset);
+ break;
+ case 10:
+ return(Poutsub);
+ break;
+ case 11:
+ return(Pdepth);
+ break;
+ case 12:
+ return(Phyper);
+ break;
+
+ default:
+ return(0);
+ }
+}
diff --git a/src/Effects/APhaser.h b/src/Effects/APhaser.h
@@ -0,0 +1,86 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Phaser.h - Phaser effect
+ Copyright (C) 2002-2005 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ Modified for rakarrack by Josep Andreu
+
+ Further modified for rakarrack by Ryan Billing (Transmogrifox) to model Analog Phaser behavior 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ 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 (version 2) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef APHASER_H
+#define APHASER_H
+#include "../globals.h"
+#include "Effect.h"
+#include "EffectLFO.h"
+
+#define MAX_PHASER_STAGES 12
+
+class Analog_Phaser:public Effect
+{
+ public:
+ Analog_Phaser(const int & insertion_, REALTYPE * efxoutl_, REALTYPE * efxoutr_);
+ ~Analog_Phaser();
+ void out(const Stereo<REALTYPE *> &input);
+ void setpreset(unsigned char npreset);
+ void changepar(int npar, unsigned char value);
+ unsigned char getpar(int npar) const;
+ void cleanup();
+ //unsigned char Ppreset;
+
+ private:
+ //Phaser parameters
+ EffectLFO lfo; //Phaser modulator
+ unsigned char Pvolume; //Used in Process.C to set wet/dry mix
+ unsigned char Pdistortion; //Model distortion added by FET element
+ unsigned char Pwidth; //Phaser width (LFO amplitude)
+ unsigned char Pfb; //feedback
+ unsigned char Poffset; //Model mismatch between variable resistors
+ unsigned char Pstages; //Number of first-order All-Pass stages
+ unsigned char Poutsub; //if I wish to subtract the output instead of the adding it
+ unsigned char Phyper; //lfo^2 -- converts tri into hyper-sine
+ unsigned char Pdepth; //Depth of phaser sweep
+ unsigned char Pbarber; //Enable parber pole phasing
+
+
+ //Control parameters
+ void setvolume(unsigned char Pvolume);
+ void setdistortion(unsigned char Pdistortion);
+ void setwidth(unsigned char Pwidth);
+ void setfb(unsigned char Pfb);
+ void setoffset(unsigned char Poffset);
+ void setstages(unsigned char Pstages);
+ void setdepth(unsigned char Pdepth);
+
+ //Internal Variables
+ bool barber; //Barber pole phasing flag
+ REALTYPE distortion, fb, width, offsetpct, fbl, fbr, depth;
+ REALTYPE *lxn1, *lyn1,*rxn1, *ryn1, *offset;
+ REALTYPE oldlgain, oldrgain, rdiff, ldiff, invperiod;
+
+ float mis;
+ float Rmin; // 2N5457 typical on resistance at Vgs = 0
+ float Rmax; // Resistor parallel to FET
+ float Rmx; // Rmin/Rmax to avoid division in loop
+ float Rconst; // Handle parallel resistor relationship
+ float C; // Capacitor
+ float CFs; // A constant derived from capacitor and resistor relationships
+};
+
+#endif
diff --git a/src/Effects/Alienwah.cpp b/src/Effects/Alienwah.cpp
@@ -46,7 +46,7 @@ Alienwah::~Alienwah()
/*
* Apply the effect
*/
-void Alienwah::out(REALTYPE *smpsl, REALTYPE *smpsr)
+void Alienwah::out(const Stereo<float *> &smp)
{
REALTYPE lfol, lfor; //Left/Right LFOs
complex<REALTYPE> clfol, clfor, out, tmp;
@@ -67,7 +67,7 @@ void Alienwah::out(REALTYPE *smpsl, REALTYPE *smpsr)
tmp = clfol * x + oldclfol * x1;
out = tmp * oldl[oldk];
- out.real() += (1 - fabs(fb)) * smpsr[i] * (1.0 - panning);
+ out.real() += (1 - fabs(fb)) * smp.l()[i] * (1.0 - panning);
oldl[oldk] = out;
REALTYPE l = out.real() * 10.0 * (fb + 0.1);
@@ -76,7 +76,7 @@ void Alienwah::out(REALTYPE *smpsl, REALTYPE *smpsr)
tmp = clfor * x + oldclfor * x1;
out = tmp * oldr[oldk];
- out.real() += (1 - fabs(fb)) * smpsr[i] * (1.0 - panning);
+ out.real() += (1 - fabs(fb)) * smp.r()[i] * (1.0 - panning);
oldr[oldk] = out;
REALTYPE r = out.real() * 10.0 * (fb + 0.1);
@@ -110,13 +110,13 @@ void Alienwah::cleanup()
* Parameter control
*/
-void Alienwah::setdepth(const unsigned char &Pdepth)
+void Alienwah::setdepth(unsigned char Pdepth)
{
this->Pdepth = Pdepth;
depth = (Pdepth / 127.0);
}
-void Alienwah::setfb(const unsigned char &Pfb)
+void Alienwah::setfb(unsigned char Pfb)
{
this->Pfb = Pfb;
fb = fabs((Pfb - 64.0) / 64.1);
@@ -127,7 +127,7 @@ void Alienwah::setfb(const unsigned char &Pfb)
fb = -fb;
}
-void Alienwah::setvolume(const unsigned char &Pvolume)
+void Alienwah::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
@@ -137,25 +137,25 @@ void Alienwah::setvolume(const unsigned char &Pvolume)
volume = outvolume;
}
-void Alienwah::setpanning(const unsigned char &Ppanning)
+void Alienwah::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
-void Alienwah::setlrcross(const unsigned char &Plrcross)
+void Alienwah::setlrcross(unsigned char Plrcross)
{
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0;
}
-void Alienwah::setphase(const unsigned char &Pphase)
+void Alienwah::setphase(unsigned char Pphase)
{
this->Pphase = Pphase;
phase = (Pphase - 64.0) / 64.0 * PI;
}
-void Alienwah::setdelay(const unsigned char &Pdelay)
+void Alienwah::setdelay(unsigned char Pdelay)
{
if(oldl != NULL)
delete [] oldl;
@@ -190,12 +190,12 @@ void Alienwah::setpreset(unsigned char npreset)
for(int n = 0; n < PRESET_SIZE; n++)
changepar(n, presets[npreset][n]);
if(insertion == 0)
- changepar(0, presets[npreset][0] / 2); //lower the volume if this is system effect
+ changepar(0, presets[npreset][0] / 2); //lower the volume if this is system effect
Ppreset = npreset;
}
-void Alienwah::changepar(const int &npar, const unsigned char &value)
+void Alienwah::changepar(int npar, unsigned char value)
{
switch(npar) {
case 0:
@@ -238,7 +238,7 @@ void Alienwah::changepar(const int &npar, const unsigned char &value)
}
}
-unsigned char Alienwah::getpar(const int &npar) const
+unsigned char Alienwah::getpar(int npar) const
{
switch(npar) {
case 0:
diff --git a/src/Effects/Alienwah.h b/src/Effects/Alienwah.h
@@ -46,11 +46,11 @@ class Alienwah:public Effect
REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_);
~Alienwah();
- void out(REALTYPE *const smpsl, REALTYPE *const smpsr);
+ void out(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);
- void changepar(const int &npar, const unsigned char &value);
- unsigned char getpar(const int &npar) const;
+ void changepar(int npar, unsigned char value);
+ unsigned char getpar(int npar) const;
void cleanup();
private:
@@ -66,13 +66,13 @@ class Alienwah:public Effect
//Control Parameters
- void setvolume(const unsigned char &Pvolume);
- void setpanning(const unsigned char &Ppanning);
- void setdepth(const unsigned char &Pdepth);
- void setfb(const unsigned char &Pfb);
- void setlrcross(const unsigned char &Plrcross);
- void setdelay(const unsigned char &Pdelay);
- void setphase(const unsigned char &Pphase);
+ void setvolume(unsigned char Pvolume);
+ void setpanning(unsigned char Ppanning);
+ void setdepth(unsigned char Pdepth);
+ void setfb(unsigned char Pfb);
+ void setlrcross(unsigned char Plrcross);
+ void setdelay(unsigned char Pdelay);
+ void setphase(unsigned char Pphase);
//Internal Values
REALTYPE panning, fb, depth, lrcross, phase;
diff --git a/src/Effects/CMakeLists.txt b/src/Effects/CMakeLists.txt
@@ -10,6 +10,7 @@ set(zynaddsubfx_effect_SRCS
EQ.cpp
Phaser.cpp
Reverb.cpp
+ APhaser.cpp
)
add_library(zynaddsubfx_effect STATIC
diff --git a/src/Effects/Chorus.cpp b/src/Effects/Chorus.cpp
@@ -35,9 +35,6 @@ Chorus::Chorus(const int &insertion_,
{
dlk = 0;
drk = 0;
- //maxdelay=(int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE);
- //delayl=new REALTYPE[maxdelay];
- //delayr=new REALTYPE[maxdelay];
setpreset(Ppreset);
@@ -71,18 +68,7 @@ REALTYPE Chorus::getdelay(REALTYPE xlfo)
return result;
}
-/*
- * Apply the effect
- */
-void Chorus::out(REALTYPE *smpsl, REALTYPE *smpsr)
-{
- const Stereo<AuSample> input(AuSample(SOUND_BUFFER_SIZE, smpsl), AuSample(
- SOUND_BUFFER_SIZE,
- smpsr));
- out(input);
-}
-
-void Chorus::out(const Stereo<AuSample> &input)
+void Chorus::out(const Stereo<float *> &input)
{
const REALTYPE one = 1.0;
dl1 = dl2;
@@ -92,7 +78,7 @@ void Chorus::out(const Stereo<AuSample> &input)
dl2 = getdelay(lfol);
dr2 = getdelay(lfor);
- for(int i = 0; i < input.l().size(); i++) {
+ for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
REALTYPE inl = input.l()[i];
REALTYPE inr = input.r()[i];
//LRcross
@@ -137,14 +123,14 @@ void Chorus::out(const Stereo<AuSample> &input)
}
if(Poutsub != 0)
- for(int i = 0; i < input.l().size(); i++) {
+ for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] *= -1.0;
efxoutr[i] *= -1.0;
}
;
- for(int i = 0; i < input.l().size(); i++) {
+ for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
efxoutl[i] *= panning;
efxoutr[i] *= (1.0 - panning);
}
@@ -162,24 +148,24 @@ void Chorus::cleanup()
/*
* Parameter control
*/
-void Chorus::setdepth(const unsigned char &Pdepth)
+void Chorus::setdepth(unsigned char Pdepth)
{
this->Pdepth = Pdepth;
depth = (pow(8.0, (Pdepth / 127.0) * 2.0) - 1.0) / 1000.0; //seconds
}
-void Chorus::setdelay(const unsigned char &Pdelay)
+void Chorus::setdelay(unsigned char Pdelay)
{
this->Pdelay = Pdelay;
delay = (pow(10.0, (Pdelay / 127.0) * 2.0) - 1.0) / 1000.0; //seconds
}
-void Chorus::setfb(const unsigned char &Pfb)
+void Chorus::setfb(unsigned char Pfb)
{
this->Pfb = Pfb;
fb = (Pfb - 64.0) / 64.1;
}
-void Chorus::setvolume(const unsigned char &Pvolume)
+void Chorus::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
@@ -189,13 +175,13 @@ void Chorus::setvolume(const unsigned char &Pvolume)
volume = outvolume;
}
-void Chorus::setpanning(const unsigned char &Ppanning)
+void Chorus::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
-void Chorus::setlrcross(const unsigned char &Plrcross)
+void Chorus::setlrcross(unsigned char Plrcross)
{
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0;
@@ -236,7 +222,7 @@ void Chorus::setpreset(unsigned char npreset)
}
-void Chorus::changepar(const int &npar, const unsigned char &value)
+void Chorus::changepar(int npar, unsigned char value)
{
switch(npar) {
case 0:
@@ -288,7 +274,7 @@ void Chorus::changepar(const int &npar, const unsigned char &value)
}
}
-unsigned char Chorus::getpar(const int &npar) const
+unsigned char Chorus::getpar(int npar) const
{
switch(npar) {
case 0:
diff --git a/src/Effects/Chorus.h b/src/Effects/Chorus.h
@@ -25,7 +25,7 @@
#include "../globals.h"
#include "Effect.h"
#include "EffectLFO.h"
-#include "../Samples/AuSample.h"
+#include "../Samples/Sample.h"
#include "../Misc/Stereo.h"
#define MAX_CHORUS_DELAY 250.0 //ms
@@ -37,8 +37,7 @@ class Chorus:public Effect
Chorus(const int &insetion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
/**Destructor*/
~Chorus();
- void out(REALTYPE *smpsl, REALTYPE *smpsr);
- void out(const Stereo<AuSample> &input);
+ void out(const Stereo<float *> &input);
void setpreset(unsigned char npreset);
/**
* Sets the value of the chosen variable
@@ -58,7 +57,7 @@ class Chorus:public Effect
* @param npar number of chosen parameter
* @param value the new value
*/
- void changepar(const int &npar, const unsigned char &value);
+ void changepar(int npar, unsigned char value);
/**
* Gets the value of the chosen variable
*
@@ -77,7 +76,7 @@ class Chorus:public Effect
* @param npar number of chosen parameter
* @return the value of the parameter
*/
- unsigned char getpar(const int &npar) const;
+ unsigned char getpar(int npar) const;
void cleanup();
private:
@@ -94,19 +93,18 @@ class Chorus:public Effect
//Parameter Controls
- void setvolume(const unsigned char &Pvolume);
- void setpanning(const unsigned char &Ppanning);
- void setdepth(const unsigned char &Pdepth);
- void setdelay(const unsigned char &Pdelay);
- void setfb(const unsigned char &Pfb);
- void setlrcross(const unsigned char &Plrcross);
+ void setvolume(unsigned char Pvolume);
+ void setpanning(unsigned char Ppanning);
+ void setdepth(unsigned char Pdepth);
+ void setdelay(unsigned char Pdelay);
+ void setfb(unsigned char Pfb);
+ void setlrcross(unsigned char Plrcross);
//Internal Values
REALTYPE depth, delay, fb, lrcross, panning;
REALTYPE dl1, dl2, dr1, dr2, lfol, lfor;
int maxdelay;
- Stereo<AuSample> delaySample;
- //REALTYPE *delayl,*delayr;
+ Stereo<Sample> delaySample;
int dlk, drk, dlhi, dlhi2;
REALTYPE getdelay(REALTYPE xlfo);
REALTYPE dllo, mdel;
diff --git a/src/Effects/Distorsion.cpp b/src/Effects/Distorsion.cpp
@@ -260,7 +260,7 @@ void Distorsion::applyfilters(REALTYPE *efxoutl, REALTYPE *efxoutr)
/*
* Effect output
*/
-void Distorsion::out(REALTYPE *smpsl, REALTYPE *smpsr)
+void Distorsion::out(const Stereo<float *> &smp)
{
int i;
REALTYPE l, r, lout, rout;
@@ -271,14 +271,14 @@ void Distorsion::out(REALTYPE *smpsl, REALTYPE *smpsr)
if(Pstereo != 0) { //Stereo
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
- efxoutl[i] = smpsl[i] * inputvol * panning;
- efxoutr[i] = smpsr[i] * inputvol * (1.0 - panning);
+ efxoutl[i] = smp.l()[i] * inputvol * panning;
+ efxoutr[i] = smp.r()[i] * inputvol * (1.0 - panning);
}
}
else {
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
efxoutl[i] =
- (smpsl[i] * panning + smpsr[i] * (1.0 - panning)) * inputvol;
+ (smp.l()[i] * panning + smp.r()[i] * (1.0 - panning)) * inputvol;
;
}
@@ -315,7 +315,7 @@ void Distorsion::out(REALTYPE *smpsl, REALTYPE *smpsr)
/*
* Parameter control
*/
-void Distorsion::setvolume(const unsigned char &Pvolume)
+void Distorsion::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
@@ -330,20 +330,20 @@ void Distorsion::setvolume(const unsigned char &Pvolume)
cleanup();
}
-void Distorsion::setpanning(const unsigned char &Ppanning)
+void Distorsion::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = (Ppanning + 0.5) / 127.0;
}
-void Distorsion::setlrcross(const unsigned char &Plrcross)
+void Distorsion::setlrcross(unsigned char Plrcross)
{
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0 * 1.0;
}
-void Distorsion::setlpf(const unsigned char &Plpf)
+void Distorsion::setlpf(unsigned char Plpf)
{
this->Plpf = Plpf;
REALTYPE fr = exp(pow(Plpf / 127.0, 0.5) * log(25000.0)) + 40;
@@ -351,7 +351,7 @@ void Distorsion::setlpf(const unsigned char &Plpf)
lpfr->setfreq(fr);
}
-void Distorsion::sethpf(const unsigned char &Phpf)
+void Distorsion::sethpf(unsigned char Phpf)
{
this->Phpf = Phpf;
REALTYPE fr = exp(pow(Phpf / 127.0, 0.5) * log(25000.0)) + 20.0;
@@ -391,7 +391,7 @@ void Distorsion::setpreset(unsigned char npreset)
}
-void Distorsion::changepar(const int &npar, const unsigned char &value)
+void Distorsion::changepar(int npar, unsigned char value)
{
switch(npar) {
case 0:
@@ -439,7 +439,7 @@ void Distorsion::changepar(const int &npar, const unsigned char &value)
}
}
-unsigned char Distorsion::getpar(const int &npar) const
+unsigned char Distorsion::getpar(int npar) const
{
switch(npar) {
case 0:
diff --git a/src/Effects/Distorsion.h b/src/Effects/Distorsion.h
@@ -38,32 +38,32 @@ class Distorsion:public Effect
public:
Distorsion(const int &insertion, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~Distorsion();
- void out(REALTYPE *smpsl, REALTYPE *smpr);
+ void out(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);
- void changepar(const int &npar, const unsigned char &value);
- unsigned char getpar(const int &npar) const;
+ void changepar(int npar, unsigned char value);
+ unsigned char getpar(int npar) const;
void cleanup();
void applyfilters(REALTYPE *efxoutl, REALTYPE *efxoutr);
private:
//Parametrii
- unsigned char Pvolume; //Volumul or E/R
- unsigned char Ppanning; //Panning
- unsigned char Plrcross; // L/R Mixing
- unsigned char Pdrive; //the input amplification
- unsigned char Plevel; //the output amplification
- unsigned char Ptype; //Distorsion type
- unsigned char Pnegate; //if the input is negated
- unsigned char Plpf; //lowpass filter
- unsigned char Phpf; //highpass filter
- unsigned char Pstereo; //0=mono,1=stereo
+ unsigned char Pvolume; //Volume or E/R
+ unsigned char Ppanning; //Panning
+ unsigned char Plrcross; // L/R Mixing
+ unsigned char Pdrive; //the input amplification
+ unsigned char Plevel; //the output amplification
+ unsigned char Ptype; //Distorsion type
+ unsigned char Pnegate; //if the input is negated
+ unsigned char Plpf; //lowpass filter
+ unsigned char Phpf; //highpass filter
+ unsigned char Pstereo; //0=mono,1=stereo
unsigned char Pprefiltering; //if you want to do the filtering before the distorsion
- void setvolume(const unsigned char &Pvolume);
- void setpanning(const unsigned char &Ppanning);
- void setlrcross(const unsigned char &Plrcross);
- void setlpf(const unsigned char &Plpf);
- void sethpf(const unsigned char &Phpf);
+ void setvolume(unsigned char Pvolume);
+ void setpanning(unsigned char Ppanning);
+ void setlrcross(unsigned char Plrcross);
+ void setlpf(unsigned char Plpf);
+ void sethpf(unsigned char Phpf);
//Real Parameters
REALTYPE panning, lrcross;
diff --git a/src/Effects/DynamicFilter.cpp b/src/Effects/DynamicFilter.cpp
@@ -46,7 +46,7 @@ DynamicFilter::~DynamicFilter()
/*
* Apply the effect
*/
-void DynamicFilter::out(REALTYPE *smpsl, REALTYPE *smpsr)
+void DynamicFilter::out(const Stereo<float *> &smp)
{
int i;
if(filterpars->changed) {
@@ -62,10 +62,10 @@ void DynamicFilter::out(REALTYPE *smpsl, REALTYPE *smpsr)
REALTYPE q = filterpars->getq();
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
- efxoutl[i] = smpsl[i];
- efxoutr[i] = smpsr[i];
+ efxoutl[i] = smp.l()[i];
+ efxoutr[i] = smp.r()[i];
- REALTYPE x = (fabs(smpsl[i]) + fabs(smpsr[i])) * 0.5;
+ REALTYPE x = (fabs(smp.l()[i]) + fabs(smp.l()[i])) * 0.5;
ms1 = ms1 * (1.0 - ampsmooth) + x * ampsmooth + 1e-10;
}
@@ -110,14 +110,14 @@ void DynamicFilter::cleanup()
* Parameter control
*/
-void DynamicFilter::setdepth(const unsigned char &Pdepth)
+void DynamicFilter::setdepth(unsigned char Pdepth)
{
this->Pdepth = Pdepth;
depth = pow((Pdepth / 127.0), 2.0);
}
-void DynamicFilter::setvolume(const unsigned char &Pvolume)
+void DynamicFilter::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
@@ -127,14 +127,14 @@ void DynamicFilter::setvolume(const unsigned char &Pvolume)
volume = outvolume;
}
-void DynamicFilter::setpanning(const unsigned char &Ppanning)
+void DynamicFilter::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
-void DynamicFilter::setampsns(const unsigned char &Pampsns)
+void DynamicFilter::setampsns(unsigned char Pampsns)
{
ampsns = pow(Pampsns / 127.0, 2.5) * 10.0;
if(Pampsnsinv != 0)
@@ -270,7 +270,7 @@ void DynamicFilter::setpreset(unsigned char npreset)
}
-void DynamicFilter::changepar(const int &npar, const unsigned char &value)
+void DynamicFilter::changepar(int npar, unsigned char value)
{
switch(npar) {
case 0:
@@ -312,7 +312,7 @@ void DynamicFilter::changepar(const int &npar, const unsigned char &value)
}
}
-unsigned char DynamicFilter::getpar(const int &npar) const
+unsigned char DynamicFilter::getpar(int npar) const
{
switch(npar) {
case 0:
diff --git a/src/Effects/DynamicFilter.h b/src/Effects/DynamicFilter.h
@@ -33,11 +33,11 @@ class DynamicFilter:public Effect
public:
DynamicFilter(int insetion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~DynamicFilter();
- void out(REALTYPE *smpsl, REALTYPE *smpsr);
+ void out(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);
- void changepar(const int &npar, const unsigned char &value);
- unsigned char getpar(const int &npar) const;
+ void changepar(int npar, unsigned char value);
+ unsigned char getpar(int npar) const;
void cleanup();
// void setdryonly();
@@ -53,10 +53,10 @@ class DynamicFilter:public Effect
unsigned char Pampsmooth; //how smooth the input amplitude changes the filter
//Parameter Control
- void setvolume(const unsigned char &Pvolume);
- void setpanning(const unsigned char &Ppanning);
- void setdepth(const unsigned char &Pdepth);
- void setampsns(const unsigned char &Pampsns);
+ void setvolume(unsigned char Pvolume);
+ void setpanning(unsigned char Ppanning);
+ void setdepth(unsigned char Pdepth);
+ void setampsns(unsigned char Pampsns);
void reinitfilter();
diff --git a/src/Effects/EQ.cpp b/src/Effects/EQ.cpp
@@ -45,9 +45,6 @@ EQ::EQ(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_)
EQ::~EQ()
{}
-/*
- * Cleanup the effect
- */
void EQ::cleanup()
{
for(int i = 0; i < MAX_EQ_BANDS; i++) {
@@ -56,17 +53,12 @@ void EQ::cleanup()
}
}
-
-
-/*
- * Effect output
- */
-void EQ::out(REALTYPE *smpsl, REALTYPE *smpsr)
+void EQ::out(const Stereo<float *> &smp)
{
int i;
for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
- efxoutl[i] = smpsl[i] * volume;
- efxoutr[i] = smpsr[i] * volume;
+ efxoutl[i] = smp.l()[i] * volume;
+ efxoutr[i] = smp.r()[i] * volume;
}
for(i = 0; i < MAX_EQ_BANDS; i++) {
@@ -81,7 +73,7 @@ void EQ::out(REALTYPE *smpsl, REALTYPE *smpsr)
/*
* Parameter control
*/
-void EQ::setvolume(const unsigned char &Pvolume)
+void EQ::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
@@ -113,7 +105,7 @@ void EQ::setpreset(unsigned char npreset)
}
-void EQ::changepar(const int &npar, const unsigned char &value)
+void EQ::changepar(int npar, unsigned char value)
{
switch(npar) {
case 0:
@@ -167,7 +159,7 @@ void EQ::changepar(const int &npar, const unsigned char &value)
}
}
-unsigned char EQ::getpar(const int &npar) const
+unsigned char EQ::getpar(int npar) const
{
switch(npar) {
case 0:
diff --git a/src/Effects/EQ.h b/src/Effects/EQ.h
@@ -33,17 +33,17 @@ class EQ:public Effect
public:
EQ(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~EQ();
- void out(REALTYPE *smpsl, REALTYPE *smpr);
+ void out(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);
- void changepar(const int &npar, const unsigned char &value);
- unsigned char getpar(const int &npar) const;
+ void changepar(int npar, unsigned char value);
+ unsigned char getpar(int npar) const;
void cleanup();
REALTYPE getfreqresponse(REALTYPE freq);
private:
//Parameters
unsigned char Pvolume; /**<Volume*/
- void setvolume(const unsigned char &Pvolume);
+ void setvolume(unsigned char Pvolume);
struct {
//parameters
diff --git a/src/Effects/Echo.cpp b/src/Effects/Echo.cpp
@@ -3,7 +3,9 @@
Echo.C - Echo effect
Copyright (C) 2002-2005 Nasca Octavian Paul
+ Copyright (C) 2009-2010 Mark McCurry
Author: Nasca Octavian Paul
+ Mark McCurry
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License
@@ -21,95 +23,93 @@
*/
#include <cmath>
-#include <iostream>
#include "Echo.h"
+#define MAX_DELAY 2
+
Echo::Echo(const int &insertion_,
REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_)
:Effect(insertion_, efxoutl_, efxoutr_, NULL, 0),
Pvolume(50), Ppanning(64), //Pdelay(60),
Plrdelay(100), Plrcross(100), Pfb(40), Phidamp(60),
- lrdelay(0), delaySample(1), old(0.0)
+ delayTime(1), lrdelay(0),
+ delay(new REALTYPE[(int)(MAX_DELAY * SAMPLE_RATE)],
+ new REALTYPE[(int)(MAX_DELAY * SAMPLE_RATE)]),
+ old(0.0), pos(0), delta(1), ndelta(1)
{
+ initdelays();
setpreset(Ppreset);
}
-Echo::~Echo() {}
+Echo::~Echo()
+{
+ delete[] delay.l();
+ delete[] delay.r();
+}
/*
* Cleanup the effect
*/
void Echo::cleanup()
{
- delaySample.l().clear();
- delaySample.r().clear();
+ memset(delay.l(),0,MAX_DELAY*SAMPLE_RATE*sizeof(REALTYPE));
+ memset(delay.r(),0,MAX_DELAY*SAMPLE_RATE*sizeof(REALTYPE));
old = Stereo<REALTYPE>(0.0);
}
+inline int max(int a, int b)
+{
+ return a > b ? a : b;
+}
/*
* Initialize the delays
*/
void Echo::initdelays()
{
- /**\todo make this adjust insted of destroy old delays*/
- kl = 0;
- kr = 0;
- dl = (int)(1 + delay.getiVal() * SAMPLE_RATE - lrdelay);
- if(dl < 1)
- dl = 1;
- dr = (int)(1 + delay.getiVal() * SAMPLE_RATE + lrdelay);
- if(dr < 1)
- dr = 1;
-
- delaySample.l() = AuSample(dl);
- delaySample.r() = AuSample(dr);
+ cleanup();
+ //number of seconds to delay left chan
+ float dl = delayCtl.getiVal() - lrdelay;
- old = Stereo<REALTYPE>(0.0);
-}
+ //number of seconds to delay right chan
+ float dr = delayCtl.getiVal() + lrdelay;
-/*
- * Effect output
- */
-void Echo::out(REALTYPE *const smpsl, REALTYPE *const smpsr)
-{
- Stereo<AuSample> input(AuSample(SOUND_BUFFER_SIZE, smpsl), AuSample(
- SOUND_BUFFER_SIZE,
- smpsr));
- out(input);
+ ndelta.l() = max(1,(int) (dl * SAMPLE_RATE));
+ ndelta.r() = max(1,(int) (dr * SAMPLE_RATE));
}
-void Echo::out(const Stereo<AuSample> &input)
+void Echo::out(const Stereo<float *> &input)
{
-//void Echo::out(const Stereo<AuSample> & input){ //ideal
- REALTYPE l, r, ldl, rdl; /**\todo move l+r->? ldl+rdl->?*/
+ REALTYPE ldl, rdl;
- for(int i = 0; i < input.l().size(); i++) {
- ldl = delaySample.l()[kl];
- rdl = delaySample.r()[kr];
- l = ldl * (1.0 - lrcross) + rdl * lrcross;
- r = rdl * (1.0 - lrcross) + ldl * lrcross;
- ldl = l;
- rdl = r;
+ for(int i = 0; i < SOUND_BUFFER_SIZE; ++i) {
+ ldl = delay.l()[pos.l()];
+ rdl = delay.r()[pos.r()];
+ ldl = ldl * (1.0 - lrcross) + rdl * lrcross;
+ rdl = rdl * (1.0 - lrcross) + ldl * lrcross;
efxoutl[i] = ldl * 2.0;
efxoutr[i] = rdl * 2.0;
-
ldl = input.l()[i] * panning - ldl * fb;
rdl = input.r()[i] * (1.0 - panning) - rdl * fb;
//LowPass Filter
- delaySample.l()[kl] = ldl = ldl * hidamp + old.l() * (1.0 - hidamp);
- delaySample.r()[kr] = rdl = rdl * hidamp + old.r() * (1.0 - hidamp);
- old.l() = ldl;
- old.r() = rdl;
-
- if(++kl >= dl)
- kl = 0;
- if(++kr >= dr)
- kr = 0;
+ old.l() = delay.l()[(pos.l()+delta.l())%(MAX_DELAY * SAMPLE_RATE)] = ldl * hidamp + old.l() * (1.0 - hidamp);
+ old.r() = delay.r()[(pos.r()+delta.r())%(MAX_DELAY * SAMPLE_RATE)] = rdl * hidamp + old.r() * (1.0 - hidamp);
+
+ //increment
+ ++pos.l();// += delta.l();
+ ++pos.r();// += delta.r();
+
+ //ensure that pos is still in bounds
+ pos.l() %= MAX_DELAY * SAMPLE_RATE;
+ pos.r() %= MAX_DELAY * SAMPLE_RATE;
+
+ //adjust delay if needed
+ delta.l() = (15*delta.l() + ndelta.l())/16;
+ delta.r() = (15*delta.r() + ndelta.r())/16;
}
}
@@ -117,7 +117,7 @@ void Echo::out(const Stereo<AuSample> &input)
/*
* Parameter control
*/
-void Echo::setvolume(const unsigned char &Pvolume)
+void Echo::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
@@ -132,45 +132,45 @@ void Echo::setvolume(const unsigned char &Pvolume)
cleanup();
}
-void Echo::setpanning(const unsigned char &Ppanning)
+void Echo::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = (Ppanning + 0.5) / 127.0;
}
-void Echo::setdelay(const unsigned char &Pdelay)
+void Echo::setdelay(unsigned char Pdelay)
{
- delay.setmVal(Pdelay);
+ delayCtl.setmVal(Pdelay);
//this->Pdelay=Pdelay;
//delay=1+(int)(Pdelay/127.0*SAMPLE_RATE*1.5);//0 .. 1.5 sec
initdelays();
}
-void Echo::setlrdelay(const unsigned char &Plrdelay)
+void Echo::setlrdelay(unsigned char Plrdelay)
{
REALTYPE tmp;
this->Plrdelay = Plrdelay;
tmp =
- (pow(2, fabs(Plrdelay - 64.0) / 64.0 * 9) - 1.0) / 1000.0 * SAMPLE_RATE;
+ (pow(2, fabs(Plrdelay - 64.0) / 64.0 * 9) - 1.0) / 1000.0;
if(Plrdelay < 64.0)
tmp = -tmp;
- lrdelay = (int) tmp;
+ lrdelay = tmp;
initdelays();
}
-void Echo::setlrcross(const unsigned char &Plrcross)
+void Echo::setlrcross(unsigned char Plrcross)
{
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0 * 1.0;
}
-void Echo::setfb(const unsigned char &Pfb)
+void Echo::setfb(unsigned char Pfb)
{
this->Pfb = Pfb;
fb = Pfb / 128.0;
}
-void Echo::sethidamp(const unsigned char &Phidamp)
+void Echo::sethidamp(unsigned char Phidamp)
{
this->Phidamp = Phidamp;
hidamp = 1.0 - Phidamp / 127.0;
@@ -213,7 +213,7 @@ void Echo::setpreset(unsigned char npreset)
}
-void Echo::changepar(const int &npar, const unsigned char &value)
+void Echo::changepar(int npar, unsigned char value)
{
switch(npar) {
case 0:
@@ -240,7 +240,7 @@ void Echo::changepar(const int &npar, const unsigned char &value)
}
}
-unsigned char Echo::getpar(const int &npar) const
+unsigned char Echo::getpar(int npar) const
{
switch(npar) {
case 0:
@@ -250,7 +250,7 @@ unsigned char Echo::getpar(const int &npar) const
return Ppanning;
break;
case 2:
- return delay.getmVal();
+ return delayCtl.getmVal();
break;
case 3:
return Plrdelay;
diff --git a/src/Effects/Echo.h b/src/Effects/Echo.h
@@ -25,8 +25,8 @@
#include "../globals.h"
#include "Effect.h"
-#include "../Samples/AuSample.h"
#include "../Misc/Stereo.h"
+#include "../Samples/Sample.h"
#include "../Controls/DelayCtl.h"
/**Echo Effect*/
@@ -51,15 +51,7 @@ class Echo:public Effect
*/
~Echo();
- /**
- * Outputs the echo to efxoutl and efxoutr
- * @param smpsl Sample from Left channel
- * @param smpsr Sample from Right channel
- * \todo try to figure out if smpsl should be const *const
- * or not (It should be)
- */
- void out(REALTYPE *const smpsl, REALTYPE *const smpr);
- void out(const Stereo<AuSample> &input);
+ void out(const Stereo<float *> &input);
/**
* Sets the state of Echo to the specified preset
@@ -81,7 +73,7 @@ class Echo:public Effect
* @param npar number of chosen parameter
* @param value the new value
*/
- void changepar(const int &npar, const unsigned char &value);
+ void changepar(int npar, unsigned char value);
/**
* Gets the specified parameter
@@ -97,7 +89,7 @@ class Echo:public Effect
* @param npar number of chosen parameter
* @return value of parameter
*/
- unsigned char getpar(const int &npar) const;
+ unsigned char getpar(int npar) const;
int getnumparams();
@@ -108,31 +100,38 @@ class Echo:public Effect
void setdryonly();
private:
//Parameters
- char Pvolume; /**<#1 Volume or Dry/Wetness*/
+ char Pvolume; /**<#1 Volume or Dry/Wetness*/
char Ppanning; /**<#2 Panning*/
- DelayCtl delay; /**<#3 Delay of the Echo*/
+ DelayCtl delayCtl; /**<#3 Delay of the Echo*/
char Plrdelay; /**<#4 L/R delay difference*/
char Plrcross; /**<#5 L/R Mixing*/
- char Pfb; /**<#6Feedback*/
- char Phidamp; /**<#7Dampening of the Echo*/
+ char Pfb; /**<#6Feedback*/
+ char Phidamp; /**<#7Dampening of the Echo*/
- void setvolume(const unsigned char &Pvolume);
- void setpanning(const unsigned char &Ppanning);
- void setdelay(const unsigned char &Pdelay);
- void setlrdelay(const unsigned char &Plrdelay);
- void setlrcross(const unsigned char &Plrcross);
- void setfb(const unsigned char &Pfb);
- void sethidamp(const unsigned char &Phidamp);
+ void setvolume(unsigned char Pvolume);
+ void setpanning(unsigned char Ppanning);
+ void setdelay(unsigned char Pdelay);
+ void setlrdelay(unsigned char Plrdelay);
+ void setlrcross(unsigned char Plrcross);
+ void setfb(unsigned char Pfb);
+ void sethidamp(unsigned char Phidamp);
//Real Parameters
- REALTYPE panning, lrcross, fb, hidamp; //needs better names
- int dl, dr, lrdelay; //needs better names
+ REALTYPE panning, lrcross, fb, hidamp;
+ //Left/Right delay lengths
+ Stereo<int> delayTime;
+ float lrdelay;
void initdelays();
- Stereo<AuSample> delaySample;
+ //2 channel ring buffer
+ Stereo<REALTYPE *> delay;
Stereo<REALTYPE> old;
- int kl, kr;
+ //position of reading/writing from delaysample
+ Stereo<int> pos;
+ //step size for delay buffer
+ Stereo<int> delta;
+ Stereo<int> ndelta;
};
#endif
diff --git a/src/Effects/Effect.cpp b/src/Effects/Effect.cpp
@@ -23,10 +23,15 @@
#include "Effect.h"
#include "../Params/FilterParams.h"
-
Effect::Effect(bool insertion_, REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_, FilterParams *filterpars_,
const unsigned char &Ppreset_)
:Ppreset(Ppreset_), efxoutl(efxoutl_), efxoutr(efxoutr_),
- filterpars(filterpars_), insertion(insertion_) {}
+ filterpars(filterpars_), insertion(insertion_)
+{}
+
+void Effect::out(REALTYPE *const smpsl, REALTYPE *const smpsr)
+{
+ out(Stereo<float *>(smpsl,smpsr));
+};
diff --git a/src/Effects/Effect.h b/src/Effects/Effect.h
@@ -25,6 +25,8 @@
#include "../Misc/Util.h"
#include "../globals.h"
+#include "../Params/FilterParams.h"
+#include "../Misc/Stereo.h"
class FilterParams;
@@ -56,12 +58,12 @@ class Effect
/**Change parameter npar to value
* @param npar chosen parameter
* @param value chosen new value*/
- virtual void changepar(const int &npar, const unsigned char &value) = 0;
+ virtual void changepar(int npar, unsigned char value) = 0;
/**Get the value of parameter npar
* @param npar chosen parameter
* @return the value of the parameter in an unsigned char or 0 if it
* does not exist*/
- virtual unsigned char getpar(const int &npar) const = 0;
+ virtual unsigned char getpar(int npar) const = 0;
/**Output result of effect based on the given buffers
*
* This method should result in the effect generating its results
@@ -71,7 +73,8 @@ class Effect
* @param smpsl Input buffer for the Left channel
* @param smpsr Input buffer for the Right channel
*/
- virtual void out(REALTYPE *const smpsl, REALTYPE *const smpsr) = 0;
+ void out(REALTYPE *const smpsl, REALTYPE *const smpsr);
+ virtual void out(const Stereo<float *> &smp) = 0;
/**Reset the state of the effect*/
virtual void cleanup() {}
/**This is only used for EQ (for user interface)*/
@@ -82,7 +85,7 @@ class Effect
unsigned char Ppreset; /**<Currently used preset*/
REALTYPE *const efxoutl; /**<Effect out Left Channel*/
REALTYPE *const efxoutr; /**<Effect out Right Channel*/
- /**\todo make efxoutl and efxoutr private and replace them with a StereoSample*/
+ /**\todo make efxoutl and efxoutr private and replace them with a Stereo<float*>*/
REALTYPE outvolume;/**<This is the volume of effect and is public because
* it is needed in system effects.
@@ -96,7 +99,7 @@ class Effect
protected:
const bool insertion;/**<If Effect is an insertion effect, insertion=1
- *otherwise, it should be insertion=0*/
+ *otherwise, it should be insertion=0*/
};
#endif
diff --git a/src/Effects/EffectMgr.cpp b/src/Effects/EffectMgr.cpp
@@ -31,6 +31,9 @@
#include "../Misc/XMLwrapper.h"
#include "../Params/FilterParams.h"
+#include <iostream>
+using namespace std;
+>>>>>>> master:src/Effects/EffectMgr.cpp
EffectMgr::EffectMgr(int insertion_, pthread_mutex_t *mutex_)
:insertion(insertion_),
@@ -111,6 +114,9 @@ void EffectMgr::changeeffect(int nefx_)
case 8:
efx = new DynamicFilter(insertion, efxoutl, efxoutr);
break;
+ case 9:
+ efx = new Analog_Phaser(insertion, efxoutl, efxoutr);
+ break;
//put more effect here
default:
efx = NULL;
diff --git a/src/Effects/EffectMgr.h b/src/Effects/EffectMgr.h
@@ -32,6 +32,14 @@ class Effect;
class FilterParams;
class XMLwrapper;
+#include "Distorsion.h"
+#include "EQ.h"
+#include "DynamicFilter.h"
+#include "APhaser.h"
+#include "../Misc/XMLwrapper.h"
+#include "../Params/FilterParams.h"
+#include "../Params/Presets.h"
+
/**Effect manager, an interface betwen the program and effects*/
class EffectMgr:public Presets
{
diff --git a/src/Effects/Makefile b/src/Effects/Makefile
@@ -2,7 +2,7 @@ include ../Makefile.inc
objects=Alienwah.o Chorus.o Echo.o Effect.o \
EffectLFO.o EffectMgr.o Phaser.o Reverb.o \
- Distorsion.o EQ.o DynamicFilter.o
+ Distorsion.o EQ.o DynamicFilter.o APhaser.o
all: $(objects)
diff --git a/src/Effects/Phaser.cpp b/src/Effects/Phaser.cpp
@@ -38,7 +38,7 @@ Phaser::~Phaser()
/*
* Effect output
*/
-void Phaser::out(REALTYPE *smpsl, REALTYPE *smpsr)
+void Phaser::out(const Stereo<float *> &smp)
{
int i, j;
REALTYPE lfol, lfor, lgain, rgain, tmp;
@@ -69,8 +69,8 @@ void Phaser::out(REALTYPE *smpsl, REALTYPE *smpsr)
REALTYPE x1 = 1.0 - x;
REALTYPE gl = lgain * x + oldgain.left() * x1;
REALTYPE gr = rgain * x + oldgain.right() * x1;
- REALTYPE inl = smpsl[i] * panning + fbl;
- REALTYPE inr = smpsr[i] * (1.0 - panning) + fbr;
+ REALTYPE inl = smp.l()[i] * panning + fbl;
+ REALTYPE inr = smp.r()[i] * (1.0 - panning) + fbr;
//Left channel
for(j = 0; j < Pstages * 2; j++) { //Phasing routine
@@ -121,20 +121,20 @@ void Phaser::cleanup()
/*
* Parameter control
*/
-void Phaser::setdepth(const unsigned char &Pdepth)
+void Phaser::setdepth(unsigned char Pdepth)
{
this->Pdepth = Pdepth;
depth = (Pdepth / 127.0);
}
-void Phaser::setfb(const unsigned char &Pfb)
+void Phaser::setfb(unsigned char Pfb)
{
this->Pfb = Pfb;
fb = (Pfb - 64.0) / 64.1;
}
-void Phaser::setvolume(const unsigned char &Pvolume)
+void Phaser::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
outvolume = Pvolume / 127.0;
@@ -144,29 +144,29 @@ void Phaser::setvolume(const unsigned char &Pvolume)
volume = outvolume;
}
-void Phaser::setpanning(const unsigned char &Ppanning)
+void Phaser::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
panning = Ppanning / 127.0;
}
-void Phaser::setlrcross(const unsigned char &Plrcross)
+void Phaser::setlrcross(unsigned char Plrcross)
{
this->Plrcross = Plrcross;
lrcross = Plrcross / 127.0;
}
-void Phaser::setstages(const unsigned char &Pstages)
+void Phaser::setstages(unsigned char Pstages)
{
if(Pstages >= MAX_PHASER_STAGES)
this->Pstages = MAX_PHASER_STAGES - 1;
else
this->Pstages = Pstages;
- old = Stereo<AuSample>(Pstages * 2);
+ old = Stereo<Sample>(Pstages * 2);
cleanup();
}
-void Phaser::setphase(const unsigned char &Pphase)
+void Phaser::setphase(unsigned char Pphase)
{
this->Pphase = Pphase;
phase = (Pphase / 127.0);
@@ -199,7 +199,7 @@ void Phaser::setpreset(unsigned char npreset)
}
-void Phaser::changepar(const int &npar, const unsigned char &value)
+void Phaser::changepar(int npar, unsigned char value)
{
switch(npar) {
case 0:
@@ -248,7 +248,7 @@ void Phaser::changepar(const int &npar, const unsigned char &value)
}
}
-unsigned char Phaser::getpar(const int &npar) const
+unsigned char Phaser::getpar(int npar) const
{
switch(npar) {
case 0:
diff --git a/src/Effects/Phaser.h b/src/Effects/Phaser.h
@@ -24,7 +24,7 @@
#define PHASER_H
#include "../globals.h"
#include "../Misc/Stereo.h"
-#include "../Samples/AuSample.h"
+#include "../Samples/Sample.h"
#include "Effect.h"
#include "EffectLFO.h"
@@ -35,10 +35,10 @@ class Phaser:public Effect
public:
Phaser(const int &insetion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~Phaser();
- void out(REALTYPE *smpsl, REALTYPE *smpsr);
+ void out(const Stereo<float *> &smp);
void setpreset(unsigned char npreset);
- void changepar(const int &npar, const unsigned char &value);
- unsigned char getpar(const int &npar) const;
+ void changepar(int npar, unsigned char value);
+ unsigned char getpar(int npar) const;
void cleanup();
void setdryonly();
@@ -49,26 +49,23 @@ class Phaser:public Effect
unsigned char Ppanning;
unsigned char Pdepth; /**<the depth of the Phaser*/
unsigned char Pfb; /**<feedback*/
- unsigned char Plrcross; /**<feedback*/
+ unsigned char Plrcross; /**<crossover*/
unsigned char Pstages;
unsigned char Poutsub; /**<if I wish to substract the output instead of the adding it*/
unsigned char Pphase;
- //Control Parametrii
- void setvolume(const unsigned char &Pvolume);
- void setpanning(const unsigned char &Ppanning);
- void setdepth(const unsigned char &Pdepth);
- void setfb(const unsigned char &Pfb);
- void setlrcross(const unsigned char &Plrcross);
- void setstages(const unsigned char &Pstages);
- void setphase(const unsigned char &Pphase);
+ //Control Parameters
+ void setvolume(unsigned char Pvolume);
+ void setpanning(unsigned char Ppanning);
+ void setdepth(unsigned char Pdepth);
+ void setfb(unsigned char Pfb);
+ void setlrcross(unsigned char Plrcross);
+ void setstages(unsigned char Pstages);
+ void setphase(unsigned char Pphase);
//Internal Values
- //int insertion; //inherited from Effect
REALTYPE panning, fb, depth, lrcross, fbl, fbr, phase;
- //REALTYPE *oldl,*oldr;
- Stereo<AuSample> old;
- //REALTYPE oldlgain,oldrgain;
+ Stereo<Sample> old;
Stereo<REALTYPE> oldgain;
};
diff --git a/src/Effects/Reverb.cpp b/src/Effects/Reverb.cpp
@@ -165,14 +165,14 @@ void Reverb::processmono(int ch, REALTYPE *output)
/*
* Effect output
*/
-void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r)
+void Reverb::out(const Stereo<float *> &smp)
{
int i;
if((Pvolume == 0) && (insertion != 0))
return;
for(i = 0; i < SOUND_BUFFER_SIZE; i++)
- inputbuf[i] = (smps_l[i] + smps_r[i]) / 2.0;
+ inputbuf[i] = (smp.l()[i] + smp.r()[i]) / 2.0;
;
if(idelay != NULL) {
@@ -215,7 +215,7 @@ void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r)
/*
* Parameter control
*/
-void Reverb::setvolume(const unsigned char &Pvolume)
+void Reverb::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
if(insertion == 0) {
@@ -229,13 +229,13 @@ void Reverb::setvolume(const unsigned char &Pvolume)
}
}
-void Reverb::setpan(const unsigned char &Ppan)
+void Reverb::setpan(unsigned char Ppan)
{
this->Ppan = Ppan;
pan = (REALTYPE)Ppan / 127.0;
}
-void Reverb::settime(const unsigned char &Ptime)
+void Reverb::settime(unsigned char Ptime)
{
int i;
REALTYPE t;
@@ -271,7 +271,7 @@ void Reverb::setlohidamp(unsigned char Plohidamp)
}
}
-void Reverb::setidelay(const unsigned char &Pidelay)
+void Reverb::setidelay(unsigned char Pidelay)
{
REALTYPE delay;
this->Pidelay = Pidelay;
@@ -290,13 +290,13 @@ void Reverb::setidelay(const unsigned char &Pidelay)
}
}
-void Reverb::setidelayfb(const unsigned char &Pidelayfb)
+void Reverb::setidelayfb(unsigned char Pidelayfb)
{
this->Pidelayfb = Pidelayfb;
idelayfb = Pidelayfb / 128.0;
}
-void Reverb::sethpf(const unsigned char &Phpf)
+void Reverb::sethpf(unsigned char Phpf)
{
this->Phpf = Phpf;
if(Phpf == 0) { //No HighPass
@@ -313,7 +313,7 @@ void Reverb::sethpf(const unsigned char &Phpf)
}
}
-void Reverb::setlpf(const unsigned char &Plpf)
+void Reverb::setlpf(unsigned char Plpf)
{
this->Plpf = Plpf;
if(Plpf == 127) { //No LowPass
@@ -405,7 +405,7 @@ void Reverb::settype(unsigned char Ptype)
}
}
-void Reverb::setroomsize(const unsigned char &Proomsize)
+void Reverb::setroomsize(unsigned char Proomsize)
{
this->Proomsize = Proomsize;
if(Proomsize == 0)
@@ -418,7 +418,7 @@ void Reverb::setroomsize(const unsigned char &Proomsize)
settype(Ptype);
}
-void Reverb::setbandwidth(const unsigned char &Pbandwidth) {
+void Reverb::setbandwidth(unsigned char Pbandwidth) {
this->Pbandwidth = Pbandwidth;
REALTYPE v = Pbandwidth / 127.0;
if(bandwidth)
@@ -468,7 +468,7 @@ void Reverb::setpreset(unsigned char npreset)
}
-void Reverb::changepar(const int &npar, const unsigned char &value)
+void Reverb::changepar(int npar, unsigned char value)
{
switch(npar) {
case 0:
@@ -511,7 +511,7 @@ void Reverb::changepar(const int &npar, const unsigned char &value)
}
}
-unsigned char Reverb::getpar(const int &npar) const
+unsigned char Reverb::getpar(int npar) const
{
switch(npar) {
case 0:
diff --git a/src/Effects/Reverb.h b/src/Effects/Reverb.h
@@ -40,12 +40,12 @@ class Reverb:public Effect
public:
Reverb(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~Reverb();
- void out(REALTYPE *smps_l, REALTYPE *smps_r);
+ void out(const Stereo<float *> &smp);
void cleanup();
void setpreset(unsigned char npreset);
- void changepar(const int &npar, const unsigned char &value);
- unsigned char getpar(const int &npar) const;
+ void changepar(int npar, unsigned char value);
+ unsigned char getpar(int npar) const;
private:
//Parametrii
@@ -90,17 +90,17 @@ class Reverb:public Effect
unsigned char Pbandwidth;
//parameter control
- void setvolume(const unsigned char &Pvolume);
- void setpan(const unsigned char &Ppan);
- void settime(const unsigned char &Ptime);
+ void setvolume(unsigned char Pvolume);
+ void setpan(unsigned char Ppan);
+ void settime(unsigned char Ptime);
void setlohidamp(unsigned char Plohidamp);
- void setidelay(const unsigned char &Pidelay);
- void setidelayfb(const unsigned char &Pidelayfb);
- void sethpf(const unsigned char &Phpf);
- void setlpf(const unsigned char &Plpf);
+ void setidelay(unsigned char Pidelay);
+ void setidelayfb(unsigned char Pidelayfb);
+ void sethpf(unsigned char Phpf);
+ void setlpf(unsigned char Plpf);
void settype(unsigned char Ptype);
- void setroomsize(const unsigned char &Proomsize);
- void setbandwidth(const unsigned char &Pbandwidth);
+ void setroomsize(unsigned char Proomsize);
+ void setbandwidth(unsigned char Pbandwidth);
REALTYPE pan, erbalance;
//Parameters
diff --git a/src/Makefile b/src/Makefile
@@ -1,9 +1,9 @@
include Makefile.inc
ifneq ($(MAKECMDGOALS),debug)
- CXXFLAGS= -O2 -Wall -g
+ CXXFLAGS= -O2 -Wall -g -fPIC
else
- CXXFLAGS= -O2 -Wall -Wpointer-arith
+ CXXFLAGS= -O2 -Wall -Wpointer-arith -fPIC
endif
CXXFLAGS += -DOS_$(OS_PORT) -D$(MIDIIN)MIDIIN -DFFTW_VERSION_$(FFTW_VERSION) -DASM_F2I_$(ASM_F2I) -ggdb
diff --git a/src/Makefile.inc b/src/Makefile.inc
@@ -68,6 +68,7 @@ ifeq ($(OS_PORT),LINUX)
AUDIOOUT=$(LINUX_AUDIOOUT)
WINDOWS_VST=NO
ifeq ($(LINUX_DSSI),YES)
+ DISABLE_GUI=YES
MIDIIN=DSSI
AUDIOOUT=DSSI
endif
diff --git a/src/Misc/Bank.cpp b/src/Misc/Bank.cpp
@@ -26,7 +26,9 @@
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
+#include <algorithm>
+#include <pthread.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
@@ -34,6 +36,8 @@
#include "Config.h"
+using namespace std;
+
#define INSTRUMENT_EXTENSION ".xiz"
//if this file exists into a directory, this make the directory to be considered as a bank, even if it not contains a instrument file
@@ -237,16 +241,21 @@ void Bank::savetoslot(unsigned int ninstrument, Part *part)
/*
* Loads the instrument from the bank
*/
-void Bank::loadfromslot(unsigned int ninstrument, Part *part)
+void Bank::loadfromslot(unsigned int ninstrument, Part *&part)
{
if(emptyslot(ninstrument))
return;
- part->defaultsinstrument();
-
-// printf("load: %s\n",ins[ninstrument].filename);
+ Part *p = new Part(part->getMicrotonal(), part->getFFT(), part->mutex);
+ p->loadXMLinstrument(ins[ninstrument].filename);
+ p->Penabled = true;
+ p->applyparameters();
- part->loadXMLinstrument(ins[ninstrument].filename);
+ //swap pointers to greatly reduce locked time
+ pthread_mutex_lock(part->mutex);
+ swap(part,p);
+ delete p;
+ pthread_mutex_unlock(part->mutex);
}
diff --git a/src/Misc/Bank.h b/src/Misc/Bank.h
@@ -57,7 +57,7 @@ class Bank
/**Saves the given Part to slot*/
void savetoslot(unsigned int ninstrument, Part *part);
/**Loads the given slot into a Part*/
- void loadfromslot(unsigned int ninstrument, Part *part);
+ void loadfromslot(unsigned int ninstrument, Part *&part);
/**Swaps Slots*/
void swapslot(unsigned int n1, unsigned int n2);
diff --git a/src/Misc/CMakeLists.txt b/src/Misc/CMakeLists.txt
@@ -13,6 +13,10 @@ set(zynaddsubfx_misc_SRCS
WavFile.cpp
)
+if (LASH_FOUND)
+ set(zynaddsubfx_misc_SRCS ${zynaddsubfx_misc_SRCS} LASHClient.cpp)
+endif()
+
add_library(zynaddsubfx_misc STATIC
${zynaddsubfx_misc_SRCS}
)
diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp
@@ -21,6 +21,8 @@
*/
+#warning TODO move Sequencer out of master
+
#include "Master.h"
#include "../Params/LFOParams.h"
diff --git a/src/Misc/Master.h b/src/Misc/Master.h
@@ -148,7 +148,6 @@ class Master
int swaplr; //1 if L and R are swapped
//Sequencer
-#warning TODO move Sequencer out of master
Sequencer seq;
//other objects
diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp
@@ -178,7 +178,11 @@ void Part::cleanup()
Part::~Part()
{
- cleanup();
+ for(int k = 0; k < POLIPHONY; k++)
+ KillNotePos(k);
+ for(int nefx = 0; nefx < NUM_PART_EFX; nefx++)
+ partefx[nefx]->cleanup();
+
for(int n = 0; n < NUM_KIT_ITEMS; n++) {
if(kit[n].adpars != NULL)
delete (kit[n].adpars);
diff --git a/src/Misc/Part.h b/src/Misc/Part.h
@@ -106,6 +106,9 @@ class Part
void setkeylimit(unsigned char Pkeylimit);
void setkititemstatus(int kititem, int Penabled_);
+ Microtonal *getMicrotonal(){return microtonal;};
+ FFTwrapper *getFFT(){return fft;};
+
unsigned char Penabled; /**<if the part is enabled*/
unsigned char Pvolume; /**<part volume*/
unsigned char Pminkey; /**<the minimum key that the part receives noteon messages*/
diff --git a/src/Nio/AlsaEngine.cpp b/src/Nio/AlsaEngine.cpp
@@ -287,10 +287,14 @@ bool AlsaEngine::openAudio()
snd_pcm_hw_params_set_rate_near(audio.handle, audio.params,
&audio.sampleRate, NULL);
- audio.frames = 32;
+ audio.frames = 512;
snd_pcm_hw_params_set_period_size_near(audio.handle,
audio.params, &audio.frames, NULL);
+ audio.periods = 4;
+ snd_pcm_hw_params_set_periods_near(audio.handle,
+ audio.params, &audio.periods, NULL);
+
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(audio.handle, audio.params);
if (rc < 0) {
diff --git a/src/Nio/AlsaEngine.h b/src/Nio/AlsaEngine.h
@@ -71,6 +71,7 @@ class AlsaEngine : public AudioOut, MidiIn
snd_pcm_hw_params_t *params;
unsigned int sampleRate;
snd_pcm_uframes_t frames;
+ unsigned int periods;
const short *buffer;
pthread_t pThread;
} audio;
diff --git a/src/Nio/JackEngine.cpp b/src/Nio/JackEngine.cpp
@@ -268,7 +268,7 @@ bool JackEngine::processAudio(jack_nframes_t nframes)
}
-int JackEngine::_xrunCallback(void *arg)
+int JackEngine::_xrunCallback(void * /*/arg*/)
{
cerr << "Jack reports xrun" << endl;
return 0;
@@ -304,7 +304,7 @@ void JackEngine::handleMidi(unsigned long frames)
jack_midi_event_t jack_midi_event;
jack_nframes_t event_index = 0;
unsigned char *midi_data;
- unsigned char type, chan;
+ unsigned char type;
while(jack_midi_event_get(&jack_midi_event, midi_buf,
event_index++) == 0) {
diff --git a/src/Nio/OssEngine.cpp b/src/Nio/OssEngine.cpp
@@ -98,7 +98,7 @@ void OssEngine::stopAudio()
return;
audio.handle = -1;
- if(!getMidiEn())
+ if(!getMidiEn() && engThread)
pthread_join(*engThread, NULL);
delete engThread;
engThread = NULL;
@@ -187,7 +187,7 @@ void OssEngine::stopMidi()
midi.handle = -1;
- if(!getAudioEn()) {
+ if(!getAudioEn() && engThread) {
pthread_join(*engThread, NULL);
delete engThread;
engThread = NULL;
diff --git a/src/Nio/OutMgr.cpp b/src/Nio/OutMgr.cpp
@@ -143,6 +143,7 @@ string OutMgr::getSink() const
cerr << "BUG: No current output in OutMgr " << __LINE__ << endl;
return "ERROR";
}
+ return "ERROR";
}
void OutMgr::addSmps(REALTYPE *l, REALTYPE *r)
diff --git a/src/Nio/WavEngine.h b/src/Nio/WavEngine.h
@@ -38,8 +38,8 @@ class WavEngine: public AudioOut
bool Start();
void Stop();
- void setAudioEn(bool nval){};
- bool getAudioEn() const{};
+ void setAudioEn(bool /*nval*/){};
+ bool getAudioEn() const{return true;};
protected:
void *AudioThread();
diff --git a/src/Output/DSSIaudiooutput.cpp b/src/Output/DSSIaudiooutput.cpp
@@ -20,268 +20,666 @@
*/
+/*
+ * Inital working DSSI output code contributed by Stephen G. Parry
+ */
+
//this file contains code used from trivial_synth.c from
-//the DSSI (published by Steve Harris under public domain) as a template
-//the code is incomplete
+//the DSSI (published by Steve Harris under public domain) as a template.
+
#include <string.h>
#include "DSSIaudiooutput.h"
+#include "../Misc/Config.h"
+#include "../Misc/Bank.h"
+#include <limits.h>
+
+//
+// Static stubs for LADSPA member functions
+//
+// LADSPA is essentially a C handle based API; This plug-in implementation is
+// a C++ OO one so we need stub functions to map from C API calls to C++ object
+// method calls.
+void DSSIaudiooutput::stub_connectPort(LADSPA_Handle instance, unsigned long port, LADSPA_Data * data)
+{
+ getInstance(instance)->connectPort(port, data);
+}
-static LADSPA_Descriptor *tsLDescriptor = NULL;
-static DSSI_Descriptor *tsDDescriptor = NULL;
-
-typedef struct {
- LADSPA_Data *outl;
- LADSPA_Data *outr;
-// note_data data[MIDI_NOTES];
-// float omega[MIDI_NOTES];
-} TS;
+void DSSIaudiooutput::stub_activate(LADSPA_Handle instance)
+{
+ getInstance(instance)->activate();
+}
+void DSSIaudiooutput::stub_run(LADSPA_Handle instance, unsigned long sample_count)
+{
+ getInstance(instance)->run(sample_count);
+}
-static void cleanupTS(LADSPA_Handle instance)
+void DSSIaudiooutput::stub_deactivate(LADSPA_Handle instance)
{
- free(instance);
+ getInstance(instance)->deactivate();
}
-static void connectPortTS(LADSPA_Handle instance, unsigned long port,
- LADSPA_Data *data)
+
+
+void DSSIaudiooutput::stub_cleanup(LADSPA_Handle instance)
{
- TS *plugin;
- plugin = (TS *) instance;
- switch(port) {
- case 0:
- plugin->outl = data;
- break;
- case 1:
- plugin->outr = data;
- break;
- }
+ DSSIaudiooutput* plugin_instance = getInstance(instance);
+ plugin_instance->cleanup();
+ delete plugin_instance;
}
+
const LADSPA_Descriptor *ladspa_descriptor(unsigned long index)
{
- switch(index) {
- case 0:
- return tsLDescriptor;
- default:
+ return DSSIaudiooutput::getLadspaDescriptor(index);
+}
+
+//
+// Static stubs for DSSI member functions
+//
+// DSSI is essentially a C handle based API; This plug-in implementation is
+// a C++ OO one so we need stub functions to map from C API calls to C++ object
+// method calls.
+const DSSI_Program_Descriptor* DSSIaudiooutput::stub_getProgram (LADSPA_Handle instance, unsigned long index)
+{
+ return getInstance(instance)->getProgram(index);
+}
+
+void DSSIaudiooutput::stub_selectProgram(LADSPA_Handle instance, unsigned long bank, unsigned long program)
+{
+ getInstance(instance)->selectProgram(bank, program);
+}
+
+int DSSIaudiooutput::stub_getMidiControllerForPort(LADSPA_Handle instance, unsigned long port)
+{
+ return getInstance(instance)->getMidiControllerForPort(port);
+}
+
+void DSSIaudiooutput::stub_runSynth(LADSPA_Handle instance, unsigned long sample_count,
+ snd_seq_event_t *events, unsigned long event_count)
+{
+ getInstance(instance)->runSynth(sample_count, events, event_count);
+}
+
+const DSSI_Descriptor *dssi_descriptor(unsigned long index)
+{
+ return DSSIaudiooutput::getDssiDescriptor(index);
+}
+
+//
+// LADSPA member functions
+//
+
+/**
+ * Instantiates a plug-in.
+ *
+ * This LADSPA member function instantiates a plug-in.
+ * Note that instance initialisation should generally occur in
+ * activate() rather than here.
+ *
+ * Zyn Implementation
+ * ------------------
+ * This implementation creates a C++ class object and hides its pointer
+ * in the handle by type casting.
+ *
+ * @param descriptor [in] the descriptor for this plug-in
+ * @param s_rate [in] the sample rate
+ * @return the plug-in instance handle if successful else NULL
+ */
+LADSPA_Handle DSSIaudiooutput::instantiate(const LADSPA_Descriptor * descriptor, unsigned long s_rate)
+{
+ if(descriptor->UniqueID == dssiDescriptor->LADSPA_Plugin->UniqueID)
+ {
+ return (LADSPA_Handle)(new DSSIaudiooutput(s_rate));
+ }
+ else
+ {
return NULL;
}
}
-const DSSI_Descriptor *dssi_descriptor(unsigned long index)
+/**
+ * Connects a port on an instantiated plug-in.
+ *
+ * This LADSPA member function connects a port on an instantiated plug-in to a
+ * memory location at which a block of data for the port will be read/written.
+ * The data location is expected to be an array of LADSPA_Data for audio ports
+ * or a single LADSPA_Data value for control ports. Memory issues will be
+ * managed by the host. The plug-in must read/write the data at these locations
+ * every time run() or run_adding() is called and the data present at the time
+ * of this connection call should not be considered meaningful.
+ *
+ * Zyn Implementation
+ * ------------------
+ * The buffer pointers are stored as member variables
+ *
+ * @param port [in] the port to be connected
+ * @param data [in] the data buffer to write to / read from
+ */
+void DSSIaudiooutput::connectPort(unsigned long port, LADSPA_Data * data)
{
-// FILE *a=fopen("/tmp/zzzzz11z","w");
-// fprintf(a,"aaaaaaaaaaa TEST\n");
-// fclose(a);
- switch(index) {
+ switch (port) {
case 0:
- return tsDDescriptor;
- default:
- return NULL;
+ outl = data;
+ break;
+ case 1:
+ outr = data;
+ break;
}
}
-static LADSPA_Handle instantiateTS(const LADSPA_Descriptor *descriptor,
- unsigned long s_rate)
+/**
+ * Initialises a plug-in instance and activates it for use.
+ *
+ * This LADSPA member function initialises a plug-in instance and activates it
+ * for use. This is separated from instantiate() to aid real-time support and
+ * so that hosts can reinitialise a plug-in instance by calling deactivate() and
+ * then activate(). In this case the plug-in instance must reset all state
+ * information dependent on the history of the plug-in instance except for any
+ * data locations provided by connect_port() and any gain set by
+ * set_run_adding_gain().
+ *
+ * Zyn Implementation
+ * ------------------
+ * Currently this does nothing; Care must be taken as to code placed here as
+ * too much code here seems to cause time-out problems in jack-dssi-host.
+*/
+void DSSIaudiooutput::activate()
{
- TS *plugin_data = (TS *) malloc(sizeof(TS));
- /* for (i=0; i<MIDI_NOTES; i++) {
- plugin_data->omega[i] = M_PI * 2.0 / (double)s_rate *
- pow(2.0, (i-69.0) / 12.0);
- }
- */
- return (LADSPA_Handle) plugin_data;
}
-static void activateTS(LADSPA_Handle instance)
+/**
+ * Runs an instance of a plug-in for a block.
+ *
+ * This LADSPA member function runs an instance of a plug-in for a block.
+ * Note that if an activate() function exists then it must be called before
+ * run() or run_adding(). If deactivate() is called for a plug-in instance then
+ * the plug-in instance may not be reused until activate() has been called again.
+ *
+ * Zyn Implementation
+ * ------------------
+ * This is a LADSPA function that does not process any MIDI events; it is hence
+ * implemented by simply calling runSynth() with an empty event list.
+ *
+ * @param sample_count [in] the block size (in samples) for which the plug-in instance may run
+ */
+void DSSIaudiooutput::run(unsigned long sample_count)
+{
+ runSynth(sample_count,NULL,(unsigned long)0);
+}
+
+/**
+ * Counterpart to activate().
+ *
+ * This LADSPA member function is the counterpart to activate() (see above).
+ * Deactivation is not similar to pausing as the plug-in instance will be
+ * reinitialised when activate() is called to reuse it.
+ *
+ * Zyn Implementation
+ * ------------------
+ * Currently this function does nothing.
+ */
+void DSSIaudiooutput::deactivate()
{
- TS *plugin_data = (TS *) instance;
-// for (i=0; i<MIDI_NOTES; i++) {
-// plugin_data->data[i].active = 0;
-// }
}
+/**
+ * Deletes a plug-in instance that is no longer required.
+ *
+ * LADSPA member function; once an instance of a plug-in has been finished with
+ * it can be deleted using this function. The instance handle ceases to be
+ * valid after this call.
+ *
+ * If activate() was called for a plug-in instance then a corresponding call to
+ * deactivate() must be made before cleanup() is called.
+ *
+ * Zyn Implementation
+ * ------------------
+ * Currently cleanup is deferred to the destructor that is invoked after cleanup()
+ */
+void DSSIaudiooutput::cleanup()
+{
+}
+
+/**
+ * Initial entry point for the LADSPA plug-in library.
+ *
+ * This LADSPA function is the initial entry point for the plug-in library.
+ * The LADSPA host looks for this entry point in each shared library object it
+ * finds and then calls the function to enumerate the plug-ins within the
+ * library.
+ *
+ * Zyn Implementation
+ * ------------------
+ * As the Zyn plug-in is a DSSI plug-in, the LADSPA descriptor is embedded inside
+ * the DSSI descriptor, which is created by DSSIaudiooutput::initDssiDescriptor()
+ * statically when the library is loaded. This function then merely returns a pointer
+ * to that embedded descriptor.
+ *
+ * @param index [in] the index number of the plug-in within the library.
+ * @return if index is in range, a pointer to the plug-in descriptor is returned, else NULL
+ */
+const LADSPA_Descriptor* DSSIaudiooutput::getLadspaDescriptor(unsigned long index)
+{
+ if(index > 0 || dssiDescriptor == NULL)
+ return NULL;
+ else
+ return dssiDescriptor->LADSPA_Plugin;
+}
-static void runTS(LADSPA_Handle instance, unsigned long sample_count,
- snd_seq_event_t *events, unsigned long event_count)
+//
+// DSSI member functions
+//
+
+/**
+ * Provides a description of a program available on this synth.
+ *
+ * This DSSI member function pointer provides a description of a program (named
+ * preset sound) available on this synth.
+ *
+ * Zyn Implementation
+ * ------------------
+ * The instruments in all Zyn's bank directories, as shown by the `instrument
+ * -> show instrument bank` command, are enumerated to the host by this
+ * function, allowing access to all those instruments.
+ * The first time an instrument is requested, the bank it is in and any
+ * unmapped ones preceding that are mapped; all the instruments names and
+ * filenames from those banks are stored in the programMap member variable for
+ * later use. This is done on demand in this way, rather than up front in one
+ * go because loading all the instrument names in one go can lead to timeouts
+ * and zombies.
+ *
+ * @param index [in] index into the plug-in's list of
+ * programs, not a program number as represented by the Program
+ * field of the DSSI_Program_Descriptor. (This distinction is
+ * needed to support synths that use non-contiguous program or
+ * bank numbers.)
+ * @return a DSSI_Program_Descriptor pointer that is
+ * guaranteed to be valid only until the next call to get_program,
+ * deactivate, or configure, on the same plug-in instance, or NULL if index is out of range.
+ */
+const DSSI_Program_Descriptor* DSSIaudiooutput::getProgram (unsigned long index)
{
- TS *plugin_data = (TS *) instance;
-// LADSPA_Data *const output = plugin_data->output;
-// LADSPA_Data freq = *(plugin_data->freq);
-// LADSPA_Data vol = *(plugin_data->vol);
-// note_data *data = plugin_data->data;
- unsigned long pos;
- unsigned long event_pos;
- unsigned long note;
-
- /* if (freq < 1.0) {
- freq = 440.0f;
- }
- if (vol < 0.000001) {
- vol = 1.0f;
- }
+ static DSSI_Program_Descriptor retVal;
- if (event_count > 0) {
- printf("trivial_synth: have %ld events\n", event_count);
- }
+ /* Make sure we have the list of banks loaded */
+ initBanks();
+
+ /* Make sure that the bank containing the instrument has been mapped */
+ while (index >= programMap.size() && mapNextBank())
+ /* DO NOTHING MORE */;
- for (pos = 0, event_pos = 0; pos < sample_count; pos++) {
+ if(index >= programMap.size())
+ {
+ /* No more instruments */
+ return NULL;
+ }
+ else
+ {
+ /* OK, return the instrument */
+ retVal.Name = programMap[index].name.c_str();
+ retVal.Program = programMap[index].program;
+ retVal.Bank = programMap[index].bank;
+ return &retVal;
+ }
+}
- while (event_pos < event_count
- && pos == events[event_pos].time.tick) {
+/**
+ * Selects a new program for this synth.
+ *
+ * This DSSI member function selects a new program for this synth. The program
+ * change will take effect immediately at the start of the next run_synth()
+ * call. An invalid bank / instrument combination is ignored.
+ *
+ * Zyn Implementation
+ * ------------------
+ * the banks and instruments are as shown in the `instrument -> show instrument
+ * bank` command in Zyn. The bank no is a 1-based index into the list of banks
+ * Zyn loads and shows in the drop down and the program number is the
+ * instrument within that bank.
+ *
+ * @param bank [in] the bank number to select
+ * @param program [in] the program number within the bank to select
+ */
+void DSSIaudiooutput::selectProgram(unsigned long bank, unsigned long program)
+{
+ initBanks();
+// cerr << "selectProgram(" << (bank & 0x7F) << ':' << ((bank >> 7) & 0x7F) << "," << program << ")" << '\n';
+ if(bank < MAX_NUM_BANKS && program < BANK_SIZE)
+ {
+ char* bankdir = master->bank.banks[ bank ].dir;
+ if(bankdir != NULL)
+ {
+ pthread_mutex_lock(&master->mutex);
+
+ /* We have to turn off the CheckPADsynth functionality, else
+ * the program change takes way too long and we get timeouts
+ * and hence zombies (!) */
+ int save = config.cfg.CheckPADsynth;
+ config.cfg.CheckPADsynth = 0;
+
+ /* Load the bank... */
+ master->bank.loadbank(bankdir);
+
+ /* restore the CheckPADsynth flag */
+ config.cfg.CheckPADsynth = save;
+
+ /* Now load the instrument... */
+ master->bank.loadfromslot((unsigned int)program, master->part[0]);
+
+ pthread_mutex_unlock(&master->mutex);
+ }
+ }
+}
- printf("trivial_synth: event type %d\n", events[event_pos].type);
+/**
+ * Returns the MIDI controller number or NRPN for a input control port
+ *
+ * This DSSI member function returns the MIDI controller number or NRPN that
+ * should be mapped to the given input control port. If the given port should
+ * not have any MIDI controller mapped to it, the function will return DSSI_NONE.
+ * The behaviour of this function is undefined if the given port
+ * number does not correspond to an input control port.
+ *
+ * Zyn Implementation
+ * ------------------
+ * Currently Zyn does not define any controller ports, but may do in the future.
+ *
+ * @param port [in] the input controller port
+ * @return the CC and NRPN values shifted and ORed together.
+ */
+int DSSIaudiooutput::getMidiControllerForPort(unsigned long port)
+{
+ return DSSI_NONE;
+}
- if (events[event_pos].type == SND_SEQ_EVENT_NOTEON) {
- data[events[event_pos].data.note.note].amp =
- events[event_pos].data.note.velocity / 512.0f;
- data[events[event_pos].data.note.note].
- active = events[event_pos].data.note.velocity > 0;
- data[events[event_pos].data.note.note].
- phase = 0.0;
- } else if (events[event_pos].type == SND_SEQ_EVENT_NOTEOFF) {
- data[events[event_pos].data.note.note].
- active = 0;
- }
- event_pos++;
+/**
+ * Runs the synth for a block.
+ *
+ * This DSSI member function runs the synth for a block. This is identical in
+ * function to the LADSPA run() function, except that it also supplies events
+ * to the synth.
+ *
+ * Zyn Implementation
+ * ------------------
+ * Zyn implements synthesis in Master::GetAudioOutSamples; runSynth calls this
+ * function in chunks delimited by the sample_count and the frame indexes in
+ * the events block, calling the appropriate NoteOn, NoteOff and SetController
+ * members of Master to process the events supplied between each chunk.
+ *
+ * @param sample_count [in] the block size (in samples) for which the synth
+ * instance may run.
+ * @param events [in] The Events pointer points to a block of ALSA
+ * sequencer events, used to communicate MIDI and related events to the synth.
+ * Each event must be timestamped relative to the start of the block,
+ * (mis)using the ALSA "tick time" field as a frame count. The host is
+ * responsible for ensuring that events with differing timestamps are already
+ * ordered by time. Must not include NOTE (only NOTE_ON / NOTE_OFF), LSB or MSB
+ * events.
+ * @param event_count [in] the number of entries in the `events` block
+ */
+void DSSIaudiooutput::runSynth(unsigned long sample_count, snd_seq_event_t *events, unsigned long event_count)
+{
+ unsigned long from_frame = 0;
+ unsigned long event_index = 0;
+ unsigned long next_event_frame = 0;
+ unsigned long to_frame = 0;
+ pthread_mutex_lock(&master->mutex);
+
+ do {
+ /* Find the time of the next event, if any */
+ if(events == NULL || event_index >= event_count)
+ next_event_frame = ULONG_MAX;
+ else
+ next_event_frame = events[event_index].time.tick;
+
+ /* find the end of the sub-sample to be processed this time round... */
+ /* if the next event falls within the desired sample interval... */
+ if(next_event_frame < sample_count && next_event_frame >= to_frame)
+ /* set the end to be at that event */
+ to_frame = next_event_frame;
+ else
+ /* ...else go for the whole remaining sample */
+ to_frame = sample_count;
+ if(from_frame<to_frame)
+ {
+ // call master to fill from `from_frame` to `to_frame`:
+ master->GetAudioOutSamples(to_frame - from_frame, (int)sampleRate, &(outl[from_frame]), &(outr[from_frame]));
+ // next sub-sample please...
+ from_frame = to_frame;
}
- output[pos] = 0.0f;
- for (note = 0; note < MIDI_NOTES; note++) {
- if (data[note].active) {
- output[pos] += sin(data[note].phase) * data[note].amp * vol;
- data[note].phase += plugin_data->omega[note] * freq;
- if (data[note].phase > M_PI * 2.0) {
- data[note].phase -= M_PI * 2.0;
+ // Now process any event(s) at the current timing point
+ while(events != NULL && event_index < event_count && events[event_index].time.tick == to_frame)
+ {
+ if(events[event_index].type == SND_SEQ_EVENT_NOTEON)
+ {
+ master->NoteOn(events[event_index].data.note.channel, events[event_index].data.note.note, events[event_index].data.note.velocity);
}
+ else if(events[event_index].type == SND_SEQ_EVENT_NOTEOFF)
+ {
+ master->NoteOff(events[event_index].data.note.channel, events[event_index].data.note.note);
}
+ else if(events[event_index].type == SND_SEQ_EVENT_CONTROLLER)
+ {
+ master->SetController(events[event_index].data.control.channel, events[event_index].data.control.param, events[event_index].data.control.value);
+ }
+ else
+ {
+ }
+ event_index++;
}
- }
- */
-}
+ // Keep going until we have the desired total length of sample...
+ } while(to_frame < sample_count);
-static void runTSWrapper(LADSPA_Handle instance,
- unsigned long sample_count)
-{
- runTS(instance, sample_count, NULL, 0);
+ pthread_mutex_unlock(&master->mutex);
}
-int getControllerTS(LADSPA_Handle instance, unsigned long port)
+/**
+ * Initial entry point for the DSSI plug-in library.
+ *
+ * This DSSI function is the initial entry point for the plug-in library.
+ * The DSSI host looks for this entry point in each shared library object it
+ * finds and then calls the function to enumerate the plug-ins within the
+ * library.
+ *
+ * Zyn Implementation
+ * ------------------
+ * The descriptor is created statically by DSSIaudiooutput::initDssiDescriptor()
+ * when the plug-in library is loaded. This function merely returns a pointer to
+ * that descriptor.
+ *
+ * @param index [in] the index number of the plug-in within the library.
+ * @return if index is in range, a pointer to the plug-in descriptor is returned, else NULL
+ */
+const DSSI_Descriptor* DSSIaudiooutput::getDssiDescriptor(unsigned long index)
{
- return -1;
+ if(index > 0 || dssiDescriptor == NULL)
+ return NULL;
+ else
+ return dssiDescriptor;
}
-void _init()
+//
+// Internal member functions
+//
+
+// Initialise the DSSI descriptor, statically:
+DSSI_Descriptor* DSSIaudiooutput::dssiDescriptor = DSSIaudiooutput::initDssiDescriptor();
+
+/**
+ * Initializes the DSSI (and LADSPA) descriptor, returning it is an object.
+ */
+DSSI_Descriptor* DSSIaudiooutput::initDssiDescriptor()
{
- char **port_names;
- LADSPA_PortDescriptor *port_descriptors;
- LADSPA_PortRangeHint *port_range_hints;
-
- FILE *a = fopen("/tmp/zzzzzz", "w");
- fprintf(a, "aaaaaaaaaaa TEST\n");
- fclose(a);
-
-
- tsLDescriptor = (LADSPA_Descriptor *) malloc(sizeof(LADSPA_Descriptor));
- if(tsLDescriptor) {
- tsLDescriptor->UniqueID = 100;
- tsLDescriptor->Label = "ZASF";
- tsLDescriptor->Properties = 0;
- tsLDescriptor->Name = "ZynAddSubFX";
- tsLDescriptor->Maker =
- "Nasca Octavian Paul <zynaddsubfx@yahoo.com>";
- tsLDescriptor->Copyright = "GNU General Public License v.2";
- tsLDescriptor->PortCount = 2;
-
- port_descriptors = (LADSPA_PortDescriptor *)
- calloc(tsLDescriptor->PortCount, sizeof
- (LADSPA_PortDescriptor));
- tsLDescriptor->PortDescriptors =
- (const LADSPA_PortDescriptor *) port_descriptors;
-
- port_range_hints = (LADSPA_PortRangeHint *)
- calloc(tsLDescriptor->PortCount, sizeof
- (LADSPA_PortRangeHint));
- tsLDescriptor->PortRangeHints =
- (const LADSPA_PortRangeHint *) port_range_hints;
-
- port_names = (char **) calloc(tsLDescriptor->PortCount, sizeof(char *));
- tsLDescriptor->PortNames = (const char **) port_names;
-
- port_descriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
- port_names[0] = "Output L";
- port_range_hints[0].HintDescriptor = 0;
- port_descriptors[1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
- port_names[1] = "Output R";
- port_range_hints[1].HintDescriptor = 0;
-
- tsLDescriptor->activate = activateTS;
- tsLDescriptor->cleanup = cleanupTS;
- tsLDescriptor->connect_port = connectPortTS;
- tsLDescriptor->deactivate = NULL;
- tsLDescriptor->instantiate = instantiateTS;
- tsLDescriptor->run = runTSWrapper;
- tsLDescriptor->run_adding = NULL;
- tsLDescriptor->set_run_adding_gain = NULL;
+ DSSI_Descriptor* newDssiDescriptor = new DSSI_Descriptor;
+
+ LADSPA_PortDescriptor* newPortDescriptors;
+ char** newPortNames;
+ LADSPA_PortRangeHint* newPortRangeHints;
+
+ if (newDssiDescriptor)
+ {
+ LADSPA_Descriptor* newLadspaDescriptor = new LADSPA_Descriptor;
+ if (newLadspaDescriptor)
+ {
+ newLadspaDescriptor->UniqueID = 100;
+ newLadspaDescriptor->Label = "ZASF";
+ newLadspaDescriptor->Properties = 0;
+ newLadspaDescriptor->Name = "ZynAddSubFX";
+ newLadspaDescriptor->Maker = "Nasca Octavian Paul <zynaddsubfx@yahoo.com>";
+ newLadspaDescriptor->Copyright = "GNU General Public License v.2";
+ newLadspaDescriptor->PortCount = 2;
+
+ newPortNames = new char *[newLadspaDescriptor->PortCount];
+ newPortNames[0] = "Output L";
+ newPortNames[1] = "Output R";
+ newLadspaDescriptor->PortNames = newPortNames;
+
+ newPortDescriptors = new LADSPA_PortDescriptor[newLadspaDescriptor->PortCount];
+ newPortDescriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+ newPortDescriptors[1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+ newLadspaDescriptor->PortDescriptors = newPortDescriptors;
+
+ newPortRangeHints = new LADSPA_PortRangeHint[newLadspaDescriptor->PortCount];
+ newPortRangeHints[0].HintDescriptor = 0;
+ newPortRangeHints[1].HintDescriptor = 0;
+ newLadspaDescriptor->PortRangeHints = newPortRangeHints;
+
+ newLadspaDescriptor->activate = stub_activate;
+ newLadspaDescriptor->cleanup = stub_cleanup;
+ newLadspaDescriptor->connect_port = stub_connectPort;
+ newLadspaDescriptor->deactivate = stub_deactivate;
+ newLadspaDescriptor->instantiate = instantiate;
+ newLadspaDescriptor->run = stub_run;
+ newLadspaDescriptor->run_adding = NULL;
+ newLadspaDescriptor->set_run_adding_gain = NULL;
+ }
+ newDssiDescriptor->LADSPA_Plugin = newLadspaDescriptor;
+ newDssiDescriptor->DSSI_API_Version = 1;
+ newDssiDescriptor->configure = NULL;
+ newDssiDescriptor->get_program = stub_getProgram;
+ newDssiDescriptor->get_midi_controller_for_port = stub_getMidiControllerForPort;
+ newDssiDescriptor->select_program = stub_selectProgram;
+ newDssiDescriptor->run_synth = stub_runSynth;
+ newDssiDescriptor->run_synth_adding = NULL;
+ newDssiDescriptor->run_multiple_synths = NULL;
+ newDssiDescriptor->run_multiple_synths_adding = NULL;
}
- tsDDescriptor = (DSSI_Descriptor *) malloc(sizeof(DSSI_Descriptor));
- if(tsDDescriptor) {
- tsDDescriptor->DSSI_API_Version = 1;
- tsDDescriptor->LADSPA_Plugin = tsLDescriptor;
- tsDDescriptor->configure = NULL;
- tsDDescriptor->get_program = NULL;
- tsDDescriptor->get_midi_controller_for_port = getControllerTS;
- tsDDescriptor->select_program = NULL;
- tsDDescriptor->run_synth = runTS;
- tsDDescriptor->run_synth_adding = NULL;
- tsDDescriptor->run_multiple_synths = NULL;
- tsDDescriptor->run_multiple_synths_adding = NULL;
- }
-}
+ dssiDescriptor = newDssiDescriptor;
-void _fini()
-{}
+ return dssiDescriptor;
+}
+/**
+ * Converts a LADSPA / DSSI handle into a DSSIaudiooutput instance.
+ *
+ * @param instance [in]
+ * @return the instance
+ */
+DSSIaudiooutput* DSSIaudiooutput::getInstance(LADSPA_Handle instance)
+{
+ return (DSSIaudiooutput*)(instance);
+}
+/**
+ * The private sole constructor for the DSSIaudiooutput class.
+ *
+ * Only ever called via instantiate().
+ * @param sampleRate [in] the sample rate to be used by the synth.
+ * @return
+ */
+DSSIaudiooutput::DSSIaudiooutput(unsigned long sampleRate)
+{
+ this->sampleRate = sampleRate;
+ this->banksInited = false;
+ config.init();
+ srand(time(NULL));
+ denormalkillbuf=new REALTYPE [SOUND_BUFFER_SIZE];
+ for (int i=0;i<SOUND_BUFFER_SIZE;i++) denormalkillbuf[i]=(RND-0.5)*1e-16;
+ this->master = new Master();
+}
+/**
+ * The destructor for the DSSIaudiooutput class
+ * @return
+ */
+DSSIaudiooutput::~DSSIaudiooutput()
+{
+}
-//the constructor and the destructor are defined in main.C
-/*
-void VSTSynth::process (float **inputs, float **outputs, long sampleframes){
- float *outl=outputs[0];
- float *outr=outputs[1];
- pthread_mutex_lock(&vmaster->mutex);
- vmaster->GetAudioOutSamples(sampleframes,(int) getSampleRate(),outl,outr);
- pthread_mutex_unlock(&vmaster->mutex);
-};
-
-void VSTSynth::processReplacing (float **inputs, float **outputs, long sampleframes){
- process(inputs,outputs,sampleframes);
-};
-
-long int VSTSynth::canDo(char *txt){
- if (strcmp(txt,"receiveVstEvents")==0) return (1);
- if (strcmp(txt,"receiveVstMidiEvent")==0) return (1);
- return(-1);
-};
-
-bool VSTSynth::getVendorString(char *txt){
- strcpy(txt,"Nasca O. Paul");
- return(true);
-};
-
-bool VSTSynth::getProductString(char *txt){
- strcpy(txt,"ZynAddSubFX");
- return(true);
-};
-
-void VSTSynth::resume(){
- wantEvents();
-};
+/**
+ * Ensures the list of bank (directories) has been initialised.
+ */
+void DSSIaudiooutput::initBanks(void)
+{
+ if(!banksInited)
+ {
+ pthread_mutex_lock(&master->mutex);
+ master->bank.rescanforbanks();
+ banksInited = true;
+ pthread_mutex_unlock(&master->mutex);
+ }
+}
-*/
+/**
+ * constructor for the internally used ProgramDescriptor class
+ *
+ * @param _bank [in] bank number
+ * @param _program [in] program number
+ * @param _name [in] instrument / sample name
+ * @return
+ */
+DSSIaudiooutput::ProgramDescriptor::ProgramDescriptor(unsigned long _bank, unsigned long _program, char* _name) :
+ bank(_bank), program(_program), name(_name)
+{
+}
+/**
+ * The map of programs available; held as a single shared statically allocated object.
+ */
+vector <DSSIaudiooutput::ProgramDescriptor> DSSIaudiooutput::programMap = vector<DSSIaudiooutput::ProgramDescriptor>();
+
+/**
+ * Index controlling the map of banks
+ */
+long DSSIaudiooutput::bankNoToMap = 1;
+
+/**
+ * Queries and maps the next available bank of instruments.
+ *
+ * If the program index requested to getProgram() lies beyond the banks mapped to date,
+ * this member function is called to map the next one.
+ * @return true if a new bank has been found and mapped, else false.
+ */
+bool DSSIaudiooutput::mapNextBank()
+{
+ pthread_mutex_lock(&master->mutex);
+ Bank& bank = master->bank;
+ bool retval;
+ if(bankNoToMap >= MAX_NUM_BANKS || bank.banks[bankNoToMap].dir == NULL)
+ {
+ retval = false;
+ }
+ else
+ {
+ bank.loadbank(bank.banks[bankNoToMap].dir);
+ for(unsigned long instrument = 0; instrument < BANK_SIZE; instrument++)
+ {
+ char* insName = bank.getname(instrument);
+ if(insName != NULL && insName[0] != '\0' && insName[0] != ' ')
+ {
+ programMap.push_back(ProgramDescriptor(bankNoToMap,instrument,insName));
+ }
+ }
+ bankNoToMap ++;
+ retval = true;
+ }
+ pthread_mutex_unlock(&master->mutex);
+ return retval;
+}
diff --git a/src/Output/DSSIaudiooutput.h b/src/Output/DSSIaudiooutput.h
@@ -26,34 +26,86 @@
#include "../globals.h"
#include "../Misc/Master.h"
-#include "../UI/MasterUI.h"
#include <dssi.h>
#include <ladspa.h>
+#include <vector>
-/*
-class VSTSynth:public AudioEffectX{
- public:
- VSTSynth (audioMasterCallback audioMaster);
- ~VSTSynth();
-
- virtual void process (float **inputs, float **outputs, long sampleframes);
- virtual void processReplacing (float **inputs, float **outputs, long sampleframes);
- virtual long processEvents(VstEvents *events);//this is used for Midi input
- virtual long int canDo(char *txt);
- virtual bool getVendorString(char *txt);
- virtual bool getProductString(char *txt);
- virtual void resume();
-
- virtual long getChunk(void** data,bool isPreset=false);
- virtual void setChunk(void *data,long size,bool isPreset=false);
-
- MasterUI *ui;
- int Pexitprogram;
-
- Master *vmaster;
- pthread_t thr;
+class DSSIaudiooutput
+{
+public:
+ //
+ // Static stubs for LADSPA member functions
+ //
+ static void stub_connectPort(LADSPA_Handle instance, unsigned long port, LADSPA_Data * data);
+ static void stub_activate(LADSPA_Handle instance);
+ static void stub_run(LADSPA_Handle instance, unsigned long sample_count);
+ static void stub_deactivate(LADSPA_Handle Instance);
+ static void stub_cleanup(LADSPA_Handle instance);
+
+ //
+ // Static stubs for DSSI member functions
+ //
+ static const DSSI_Program_Descriptor* stub_getProgram (LADSPA_Handle instance, unsigned long Index);
+ static void stub_selectProgram(LADSPA_Handle instance, unsigned long bank, unsigned long program);
+ static int stub_getMidiControllerForPort(LADSPA_Handle instance, unsigned long port);
+ static void stub_runSynth(LADSPA_Handle instance, unsigned long sample_count,
+ snd_seq_event_t *events, unsigned long event_count);
+
+ /*
+ * LADSPA member functions
+ */
+ static LADSPA_Handle instantiate(const LADSPA_Descriptor * descriptor, unsigned long s_rate);
+ void connectPort(unsigned long port, LADSPA_Data * data);
+ void activate();
+ void run(unsigned long sample_count);
+ void deactivate();
+ void cleanup();
+ static const LADSPA_Descriptor* getLadspaDescriptor(unsigned long index);
+
+ /*
+ * DSSI member functions
+ */
+ const DSSI_Program_Descriptor* getProgram (unsigned long Index);
+ void selectProgram(unsigned long bank, unsigned long program);
+ int getMidiControllerForPort(unsigned long port);
+ void runSynth(unsigned long sample_count, snd_seq_event_t *events, unsigned long event_count);
+ static const DSSI_Descriptor* getDssiDescriptor(unsigned long index);
+
+ struct ProgramDescriptor
+ {
+ unsigned long bank;
+ unsigned long program;
+ string name;
+ ProgramDescriptor(unsigned long _bank, unsigned long _program, char* _name);
+ };
+
+private:
+
+ DSSIaudiooutput(unsigned long sampleRate);
+ ~DSSIaudiooutput();
+ static DSSI_Descriptor* initDssiDescriptor();
+ static DSSIaudiooutput* getInstance(LADSPA_Handle instance);
+ void initBanks();
+ bool mapNextBank();
+
+ LADSPA_Data *outl;
+ LADSPA_Data *outr;
+ long sampleRate;
+ Master* master;
+ static DSSI_Descriptor* dssiDescriptor;
+ static string bankDirNames[];
+ static
+ vector <ProgramDescriptor> programMap;
+
+ /**
+ * Flag controlling the list of bank directories
+ */
+ bool banksInited;
+
+ static
+ long bankNoToMap;
};
-*/
+
#endif
diff --git a/src/Params/LFOParams.cpp b/src/Params/LFOParams.cpp
@@ -25,7 +25,7 @@
#include "../globals.h"
#include "LFOParams.h"
-int LFOParams::time;
+int LFOParams::time=0;
LFOParams::LFOParams(char Pfreq_,
char Pintensity_,
@@ -55,7 +55,6 @@ LFOParams::LFOParams(char Pfreq_,
Ddelay = Pdelay_;
Dcontinous = Pcontinous_;
fel = fel_;
- time = 0;
defaults();
}
diff --git a/src/Samples/CMakeLists.txt b/src/Samples/CMakeLists.txt
@@ -1,6 +1,4 @@
set(zynaddsubfx_samples_SRCS
- AuSample.cpp
- FqSample.cpp
Sample.cpp
)
diff --git a/src/Samples/Makefile b/src/Samples/Makefile
@@ -1,6 +1,6 @@
include ../Makefile.inc
-objects=Sample.o AuSample.o FqSample.o
+objects=Sample.o
all: $(objects)
diff --git a/src/Samples/Sample.cpp b/src/Samples/Sample.cpp
@@ -20,8 +20,12 @@
*/
#include <cmath>
#include <cstring>//for memcpy/memset
+
+#include <iostream>
#include "Sample.h"
+using namespace std;
+
#warning TODO Think about renaming Sample to Frame
/**\TODO start using pointer math here as these will be Frequency called
* functions throughout the code*/
@@ -163,6 +167,10 @@ Sample &Sample::append(const Sample &smp)
Sample Sample::subSample(int a, int b) const
{
return Sample(b-a, buffer+a);
+ delete buffer;
+
+ buffer = nbuffer;
+ bufferSize = nbufferSize;
}
REALTYPE Sample::max() const
diff --git a/src/Tests/CMakeLists.txt b/src/Tests/CMakeLists.txt
@@ -1,6 +1,6 @@
unit_test(ControllerTest ControllerTest.h ../Params/Controller.h)
unit_test(EchoTest EchoTest.h ../Effects/Echo.h)
-unit_test(SampleTest SampleTest.h ../Samples/AuSample.h)
+unit_test(SampleTest SampleTest.h ../Samples/Sample.h)
unit_test(MicrotonalTest MicrotonalTest.h ../Misc/Microtonal.h)
unit_test(XMLwrapperTest XMLwrapperTest.h ../Misc/XMLwrapper.h)
unit_test(ADnoteTest AdNoteTest.h ../Synth/ADnote.h)
diff --git a/src/Tests/EchoTest.h b/src/Tests/EchoTest.h
@@ -22,24 +22,31 @@
#include <cxxtest/TestSuite.h>
#include <cmath>
#include <cstdlib>
+#include <iostream>
#include "../Effects/Echo.h"
#include "../globals.h"
-//int SOUND_BUFFER_SIZE=256;
+
+using namespace std;
+
class EchoTest:public CxxTest::TestSuite
{
public:
void setUp() {
outL = new float[SOUND_BUFFER_SIZE];
for(int i = 0; i < SOUND_BUFFER_SIZE; ++i)
- *(outL + i) = 0;
+ outL[i] = 0.0;
outR = new float[SOUND_BUFFER_SIZE];
for(int i = 0; i < SOUND_BUFFER_SIZE; ++i)
- *(outR + i) = 0;
- input = new Stereo<AuSample>(SOUND_BUFFER_SIZE);
+ outR[i] = 0.0;
+ input = new Stereo<REALTYPE *>(new REALTYPE[SOUND_BUFFER_SIZE],new REALTYPE[SOUND_BUFFER_SIZE]);
+ for(int i = 0; i < SOUND_BUFFER_SIZE; ++i)
+ input->l()[i] = input->r()[i] = 0.0f;
testFX = new Echo(true, outL, outR);
}
void tearDown() {
+ delete[] input->r();
+ delete[] input->l();
delete input;
delete[] outL;
delete[] outR;
@@ -60,7 +67,11 @@ class EchoTest:public CxxTest::TestSuite
void testClear() {
char DELAY = 2;
testFX->changepar(DELAY, 127);
- *input = Stereo<AuSample>(AuSample(SOUND_BUFFER_SIZE, 1.0));
+
+ //flood with high input
+ for(int i = 0; i < SOUND_BUFFER_SIZE; ++i)
+ input->r()[i] = input->l()[i] = 1.0;
+
for(int i = 0; i < 500; ++i)
testFX->out(*input);
for(int i = 0; i < SOUND_BUFFER_SIZE; ++i) {
@@ -80,7 +91,10 @@ class EchoTest:public CxxTest::TestSuite
}
//Insures that the proper decay occurs with high feedback
void testDecaywFb() {
- *input = Stereo<AuSample>(AuSample(SOUND_BUFFER_SIZE, 1.0));
+
+ //flood with high input
+ for(int i = 0; i < SOUND_BUFFER_SIZE; ++i)
+ input->r()[i] = input->l()[i] = 1.0;
char FEEDBACK = 5;
testFX->changepar(FEEDBACK, 127);
for(int i = 0; i < 100; ++i)
@@ -91,19 +105,18 @@ class EchoTest:public CxxTest::TestSuite
}
float amp = abs(outL[0] + outR[0]) / 2;
//reset input to zero
- *input = Stereo<AuSample>(SOUND_BUFFER_SIZE);
+ for(int i = 0; i < SOUND_BUFFER_SIZE; ++i)
+ input->r()[i] = input->l()[i] = 0.0;
+
//give the echo time to fade based upon zero input and high feedback
for(int i = 0; i < 50; ++i)
testFX->out(*input);
- TS_ASSERT_LESS_THAN(abs(outL[0] + outR[0]) / 2, amp);
+ TS_ASSERT_LESS_THAN_EQUALS(abs(outL[0] + outR[0]) / 2, amp);
}
-
-
-
private:
- Stereo<AuSample> *input;
+ Stereo<REALTYPE *> *input;
float *outR, *outL;
Echo *testFX;
};
diff --git a/src/Tests/SampleTest.h b/src/Tests/SampleTest.h
@@ -20,34 +20,34 @@
*/
#include <cxxtest/TestSuite.h>
-#include "../Samples/AuSample.h"
+#include "../Samples/Sample.h"
class SampleTest:public CxxTest::TestSuite
{
public:
void testInit() {
- AuSample smp(10);
+ Sample smp(10);
TS_ASSERT_EQUALS(smp.size(), 10);
for(int i = 0; i < 20; ++i)
TS_ASSERT_EQUALS(smp[i], 0.0);
- AuSample nsmp(5, 15.0);
+ Sample nsmp(5, 15.0);
TS_ASSERT_EQUALS(nsmp.size(), 5);
TS_ASSERT_EQUALS(nsmp[4], 15.0);
}
void testAssign() {
- AuSample smp(3);
+ Sample smp(3);
smp[0] = 0;
smp[1] = 1;
smp[2] = 2;
- AuSample nsmp(40);
+ Sample nsmp(40);
nsmp = smp;
TS_ASSERT_EQUALS(smp.size(), nsmp.size());
for(int i = 0; i < 29; ++i)
TS_ASSERT_EQUALS(smp[i], nsmp[i]);
}
void testBounds() {
- AuSample smp(0);
+ Sample smp(0);
TS_ASSERT(smp.size() != 0);
}
@@ -55,16 +55,16 @@ class SampleTest:public CxxTest::TestSuite
float *fl = new float[50];
for(int i = 0; i < 50; ++i)
*(fl + i) = i;
- AuSample smp(2);
- smp = AuSample(50, fl);
+ Sample smp(2);
+ smp = Sample(50, fl);
delete [] fl;
for(int i = 0; i < 50; ++i)
TS_ASSERT_DELTA(smp[i], i, 0.001);
- smp = AuSample(3);
+ smp = Sample(3);
}
void testClear() {
- AuSample smp(50);
+ Sample smp(50);
for(int i = 0; i < 50; ++i)
smp[i] = 10;
smp.clear();
diff --git a/src/UI/BankUI.fl b/src/UI/BankUI.fl
@@ -1,5 +1,5 @@
# data file for the Fltk User Interface Designer (fluid)
-version 1.0107
+version 1.0300
header_name {.h}
code_name {.cc}
decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {}
@@ -31,13 +31,13 @@ decl {\#include "../Misc/Config.h"} {public
}
class BankProcess_ {} {
- Function {process()} {open return_type {virtual void}
+ Function {process()} {return_type {virtual void}
} {}
decl {Bank *bank;} {public
}
}
-class BankSlot {open : {public Fl_Button,BankProcess_}
+class BankSlot {: {public Fl_Button,BankProcess_}
} {
Function {BankSlot(int x,int y, int w, int h, const char *label=0):Fl_Button(x,y,w,h,label)} {} {
code {what=NULL;
@@ -59,8 +59,7 @@ int tmp=Fl_Button::handle(event);
if ((*what!=0) && Fl::event_inside(this)) (bp->*fnc)();
return(tmp);} {}
}
- Function {init(int nslot_, int *what_, int *whatslot_,void (BankProcess_:: *fnc_)(void),BankProcess_ *bp_,Bank *bank_,int *nselected_)} {open
- } {
+ Function {init(int nslot_, int *what_, int *whatslot_,void (BankProcess_:: *fnc_)(void),BankProcess_ *bp_,Bank *bank_,int *nselected_)} {} {
code {nslot=nslot_;
what=what_;
whatslot=whatslot_;
@@ -74,8 +73,7 @@ labelsize(13);
align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
highlight=0;
-refresh();} {selected
- }
+refresh();} {}
}
Function {refresh()} {} {
code {if (bank->emptyslot(nslot)) {
@@ -254,9 +252,7 @@ if ((what==2)&&(bank->emptyslot(slot)==0)&&(mode!=4)) {//Rename slot
};
if ((what==1)&&(mode==1)&&(!bank->emptyslot(slot))){//Reads from slot
- pthread_mutex_lock(&master->mutex);
bank->loadfromslot(slot,master->part[*npart]);
- pthread_mutex_unlock(&master->mutex);
master->part[*npart]->applyparameters();
snprintf((char *)master->part[*npart]->Pname,PART_MAX_NAME_LEN,"%s",bank->getname(slot));
cbwig->do_callback();
@@ -305,7 +301,8 @@ if (mode==4){//swap
bs[slot]->refresh();
};
};
-if (mode!=4) refreshmainwindow();} {}
+if (mode!=4) refreshmainwindow();} {selected
+ }
}
Function {refreshmainwindow()} {} {
code {bankuiwindow->label(bank->bankfiletitle);
diff --git a/src/UI/EffUI.fl b/src/UI/EffUI.fl
@@ -1,5 +1,5 @@
# data file for the Fltk User Interface Designer (fluid)
-version 1.0109
+version 1.0300
header_name {.h}
code_name {.cc}
decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {}
@@ -155,7 +155,7 @@ return(log(freq/20.0)/log(1000.0));} {}
decl {int maxdB;} {}
}
-class EffUI {open : {public Fl_Group,public PresetsUI_}
+class EffUI {: {public Fl_Group,public PresetsUI_}
} {
Function {EffUI(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} {
code {eff=NULL;
@@ -167,6 +167,7 @@ effreverbwindow->hide();//delete (effreverbwindow);
effechowindow->hide();//delete (effechowindow);
effchoruswindow->hide();//delete (effchoruswindow);
effphaserwindow->hide();//delete (effphaserwindow);
+effaphaserwindow->hide();//delete (effaphaserwindow);
effalienwahwindow->hide();//delete (effalienwahwindow);
effdistorsionwindow->hide();//delete (effdistorsionwindow);
effeqwindow->hide();//delete (effeqwindow);
@@ -179,7 +180,7 @@ if (filterwindow!=NULL){
}
Function {make_null_window()} {} {
Fl_Window effnullwindow {
- xywh {287 379 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide
+ xywh {216 539 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide
class Fl_Group
} {
Fl_Text_Display {} {
@@ -188,11 +189,10 @@ if (filterwindow!=NULL){
}
}
}
- Function {make_reverb_window()} {open
- } {
- Fl_Window effreverbwindow {open
- xywh {343 337 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1
- class Fl_Group visible
+ Function {make_reverb_window()} {} {
+ Fl_Window effreverbwindow {
+ xywh {343 337 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide
+ class Fl_Group
} {
Fl_Text_Display {} {
label {Reverb }
@@ -344,7 +344,7 @@ if (eff->geteffectpar(10)==2) revp12->activate();
callback {int x=64;
if (Fl::event_button1()) x=(int)o->value();
else o->value(x);
-eff->seteffectpar(11,x);} selected
+eff->seteffectpar(11,x);}
tooltip RoomSize xywh {200 10 25 25} box ROUND_UP_BOX labelfont 1 labelsize 8 align 8 minimum 1 maximum 127 step 1
class WidgetPDial
}
@@ -704,6 +704,134 @@ refresh(eff);}
}
}
}
+ Function {make_analog_phaser_window()} {selected
+ } {
+ Fl_Window effaphaserwindow {
+ xywh {292 251 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide
+ code0 {putchar('a'); putchar('b'); putchar('c');}
+ class Fl_Group
+ } {
+ Fl_Choice aphaserp {
+ label Preset
+ callback {eff->changepreset((int)o->value());
+refresh(eff);}
+ xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7
+ } {
+ MenuItem {} {
+ label {Phaser 1}
+ xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7
+ }
+ MenuItem {} {
+ label {Phaser 2}
+ xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7
+ }
+ MenuItem {} {
+ label {Phaser 3}
+ xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7
+ }
+ MenuItem {} {
+ label {Phaser 4}
+ xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7
+ }
+ MenuItem {} {
+ label {Phaser 5}
+ xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7
+ }
+ MenuItem {} {
+ label {Phaser 6}
+ xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7
+ }
+ }
+ Fl_Text_Display {} {
+ label APhaser
+ xywh {260 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8
+ }
+ Fl_Dial aphaser0 {
+ label Vol
+ callback {eff->seteffectpar(0,(int) o->value());}
+ tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
+ class WidgetPDial
+ }
+ Fl_Dial aphaser1 {
+ label dist
+ callback {eff->seteffectpar(1,(int) o->value());}
+ tooltip Distortion xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
+ class WidgetPDial
+ }
+ Fl_Dial aphaser2 {
+ label Freq
+ callback {eff->seteffectpar(2,(int) o->value());}
+ tooltip {LFO frequency} xywh {85 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
+ class WidgetPDial
+ }
+ Fl_Dial aphaser3 {
+ label rnd
+ callback {eff->seteffectpar(3,(int) o->value());}
+ tooltip Randomness xywh {120 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127
+ class WidgetPDial
+ }
+ Fl_Choice aphaser4 {
+ label {LFO type}
+ callback {eff->seteffectpar(4,(int) o->value());}
+ tooltip {LFO function} xywh {155 50 40 15} down_box BORDER_BOX labelfont 1 labelsize 10 align 130 textsize 8
+ } {
+ MenuItem {} {
+ label SINE
+ xywh {15 15 100 20} labelfont 1 labelsize 10
+ }
+ MenuItem {} {
+ label TRI
+ xywh {25 25 100 20} labelfont 1 labelsize 10
+ }
+ }
+ Fl_Dial aphaser5 {
+ label {St.df}
+ callback {eff->seteffectpar(5,(int) o->value());}
+ tooltip {Left/Right Channel Phase Shift} xywh {200 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
+ class WidgetPDial
+ }
+ Fl_Dial aphaser6 {
+ label Dpth
+ callback {eff->seteffectpar(6,(int) o->value());}
+ tooltip {LFO Depth} xywh {235 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
+ class WidgetPDial
+ }
+ Fl_Dial aphaser7 {
+ label Fb
+ callback {eff->seteffectpar(7,(int) o->value());}
+ tooltip Feedback xywh {270 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
+ class WidgetPDial
+ }
+ Fl_Counter aphaser8 {
+ label Stages
+ callback {eff->seteffectpar(8,(int) o->value());}
+ xywh {305 55 35 15} type Simple labelfont 1 labelsize 11 minimum 0 maximum 127 step 1
+ code0 {o->range(1,MAX_PHASER_STAGES);}
+ }
+ Fl_Dial aphaser9 {
+ label offset
+ callback {eff->seteffectpar(9,(int) o->value());}
+ tooltip offset xywh {345 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
+ class WidgetPDial
+ }
+ Fl_Check_Button aphaser10 {
+ label Substract
+ callback {eff->seteffectpar(10,(int) o->value());}
+ tooltip {inverts output} xywh {185 10 74 20} box THIN_UP_BOX down_box DOWN_BOX color 230 labelfont 1 labelsize 10
+ }
+ Fl_Dial aphaser11 {
+ label Depth
+ callback {eff->seteffectpar(11,(int) o->value());}
+ xywh {155 10 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 maximum 127
+ class WidgetPDial
+ }
+ Fl_Check_Button aphaser12 {
+ label {hyp.}
+ callback {eff->seteffectpar(12,(int) o->value());}
+ tooltip hyper xywh {100 10 55 15} down_box DOWN_BOX
+ }
+ }
+ }
Function {make_alienwah_window()} {} {
Fl_Window effalienwahwindow {
xywh {538 250 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide
@@ -1251,6 +1379,7 @@ make_reverb_window();
make_echo_window();
make_chorus_window();
make_phaser_window();
+make_analog_phaser_window();
make_alienwah_window();
make_distorsion_window();
make_eq_window();
@@ -1264,6 +1393,7 @@ effreverbwindow->position(px,py);
effechowindow->position(px,py);
effchoruswindow->position(px,py);
effphaserwindow->position(px,py);
+effaphaserwindow->position(px,py);
effalienwahwindow->position(px,py);
effdistorsionwindow->position(px,py);
effeqwindow->position(px,py);
@@ -1271,8 +1401,7 @@ effdynamicfilterwindow->position(px,py);
refresh(eff);} {}
}
- Function {refresh(EffectMgr *eff_)} {open
- } {
+ Function {refresh(EffectMgr *eff_)} {} {
code {eff=eff_;
this->hide();
@@ -1281,6 +1410,7 @@ effreverbwindow->hide();
effechowindow->hide();
effchoruswindow->hide();
effphaserwindow->hide();
+effaphaserwindow->hide();
effalienwahwindow->hide();
effdistorsionwindow->hide();
effeqwindow->hide();
@@ -1416,6 +1546,24 @@ switch(eff->geteffect()){
effdynamicfilterwindow->show();
break;
+ case 9://make_analog_phaser_window();
+ aphaserp->value(eff->getpreset());
+ aphaser0->value(eff->geteffectpar(0));
+ aphaser1->value(eff->geteffectpar(1));
+ aphaser2->value(eff->geteffectpar(2));
+ aphaser3->value(eff->geteffectpar(3));
+ aphaser4->value(eff->geteffectpar(4));
+ aphaser5->value(eff->geteffectpar(5));
+ aphaser6->value(eff->geteffectpar(6));
+ aphaser7->value(eff->geteffectpar(7));
+ aphaser8->value(eff->geteffectpar(8));
+ aphaser9->value(eff->geteffectpar(9));
+ aphaser10->value(eff->geteffectpar(10));
+ aphaser11->value(eff->geteffectpar(11));
+ aphaser12->value(eff->geteffectpar(12));
+ putchar('?');
+ effaphaserwindow->show();
+ break;
default:effnullwindow->show();
break;
};
diff --git a/src/UI/MasterUI.fl b/src/UI/MasterUI.fl
@@ -699,8 +699,8 @@ pthread_mutex_unlock(&master->mutex);}
xywh {0 80 390 160}
} {
Fl_Group {} {
- label {System Effects} open
- xywh {0 100 390 140} box ENGRAVED_FRAME labeltype EMBOSSED_LABEL labelsize 15 align 25
+ label {System Effects}
+ xywh {0 100 390 140} box ENGRAVED_FRAME labeltype EMBOSSED_LABEL labelsize 15 align 25 hide
} {
Fl_Counter syseffnocounter {
label {Sys.Effect No.}
@@ -756,6 +756,10 @@ syseffectui->refresh(master->sysefx[nsyseff]);}
label DynFilter
xywh {90 90 100 20} labelfont 1 labelsize 10
}
+ MenuItem {} {
+ label APhaser
+ xywh {0 0 36 21}
+ }
}
Fl_Group syseffectuigroup {
xywh {5 140 380 95} box FLAT_BOX color 48
@@ -786,7 +790,7 @@ pthread_mutex_unlock(&master->mutex);}
}
Fl_Group {} {
label {Insertion Effects}
- xywh {0 100 390 140} box ENGRAVED_FRAME labeltype EMBOSSED_LABEL labelsize 15 align 25 hide
+ xywh {0 100 390 140} box ENGRAVED_FRAME labeltype EMBOSSED_LABEL labelsize 15 align 25
} {
Fl_Counter inseffnocounter {
label {Ins.Effect No.}
@@ -855,6 +859,10 @@ inseffectui->show();}
label DynFilter
xywh {100 100 100 20} labelfont 1 labelsize 10
}
+ MenuItem {} {
+ label APhaser selected
+ xywh {0 0 36 21} labelfont 1 labelsize 10
+ }
}
Fl_Group inseffectuigroup {
xywh {5 140 380 95} box FLAT_BOX color 48
diff --git a/src/main.cpp b/src/main.cpp
@@ -466,7 +466,7 @@ int main(int argc, char *argv[])
<< endl;
#endif
#endif
-#if OS == WINDOWS
+#if OS_WINDOWS
cout
<<
"\nWARNING: On Windows systems, only short comandline parameters works."
@@ -503,10 +503,6 @@ int main(int argc, char *argv[])
}
else {
master->applyparameters();
-#ifndef DISABLE_GUI
- if(noui == 0)
- ui->refresh_master_ui();
-#endif
cout << "Master file loaded." << endl;
}
}
@@ -521,17 +517,17 @@ int main(int argc, char *argv[])
}
else {
master->part[loadtopart]->applyparameters();
-#ifndef DISABLE_GUI
- if(noui == 0)
- ui->refresh_master_ui();
-#endif
cout << "Instrument file loaded." << endl;
}
}
- if(noui == 0)
+#ifndef DISABLE_GUI
+ if(noui == 0) {
+ ui = new MasterUI(master, &Pexitprogram);
pthread_create(&thr3, NULL, thread3, NULL);
+ }
+#endif
// pthread_create(&thr4, NULL, thread4, NULL);
#ifdef WINMIDIIN
@@ -539,7 +535,11 @@ int main(int argc, char *argv[])
#endif
while(Pexitprogram == 0) {
- os_sleep(100000);
+#ifdef OS_LINUX
+ usleep(100000);
+#elif OS_WINDOWS
+ Sleep(100);
+#endif
}
#ifdef WINMIDIIN