ZynAddSubFX: resynced with their Git repo
ZynAddSubFX has gained some new developer power so development has been
going on well for quite a while now in their Git repo. It's time for
the first big resync so future changes can be integrated easily.
(cherry picked from commit 3c18e436cd)
This commit is contained in:
@@ -2,55 +2,6 @@ IF(LMMS_HAVE_FFTW3F)
|
||||
|
||||
INCLUDE(BuildPlugin)
|
||||
|
||||
SET(ZYN_SRC_CORE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/DSP/AnalogFilter.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/DSP/Filter.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/DSP/SVFilter.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/DSP/FFTwrapper.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/DSP/FormantFilter.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Input/NULLMidiIn.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Input/MidiIn.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Output/Recorder.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Output/WAVaudiooutput.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/EffectMgr.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Effect.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Phaser.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Echo.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/EffectLFO.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Chorus.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/DynamicFilter.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Reverb.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/EQ.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Distorsion.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Alienwah.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Params/LFOParams.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Params/EnvelopeParams.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Params/SUBnoteParameters.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Params/ADnoteParameters.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Params/Presets.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Params/FilterParams.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Params/PADnoteParameters.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Params/Controller.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Params/PresetsStore.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Seq/MIDIFile.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Seq/MIDIEvents.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Seq/Sequencer.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/PADnote.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/SUBnote.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/LFO.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/Resonance.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/ADnote.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/Envelope.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/OscilGen.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Dump.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Bank.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Config.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/XMLwrapper.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Util.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Master.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Microtonal.C
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Part.C)
|
||||
|
||||
SET(ZYN_SRC_GUI
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/UI/MasterUI.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/UI/VirKeyboard.cc
|
||||
@@ -72,6 +23,7 @@ SET(ZYN_SRC_GUI
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/UI/BankUI.cc
|
||||
)
|
||||
|
||||
|
||||
SET(MXML_SRC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mxml/mxml-attr.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mxml/mxml-entity.c
|
||||
@@ -108,10 +60,37 @@ IF(LMMS_BUILD_WIN32)
|
||||
ADD_DEFINITIONS(-DPTW32_STATIC_LIB)
|
||||
ENDIF(LMMS_BUILD_WIN32)
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/fltk/ ${CMAKE_CURRENT_SOURCE_DIR} ${FFTW3F_INCLUDE_DIRS})
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/fltk/ ${CMAKE_CURRENT_SOURCE_DIR}/mxml ${CMAKE_CURRENT_SOURCE_DIR} ${FFTW3F_INCLUDE_DIRS})
|
||||
|
||||
ADD_LIBRARY(ZynAddSubFxCore SHARED LocalZynAddSubFx.cpp ${ZYN_SRC_CORE} ${MXML_SRC})
|
||||
TARGET_LINK_LIBRARIES(ZynAddSubFxCore ${FFTW3F_LIBRARIES} -lz -lpthread)
|
||||
set(ZASF_CORE_LIBS
|
||||
zynaddsubfx_input
|
||||
zynaddsubfx_output
|
||||
zynaddsubfx_misc
|
||||
zynaddsubfx_synth
|
||||
zynaddsubfx_seq
|
||||
zynaddsubfx_effect
|
||||
zynaddsubfx_params
|
||||
zynaddsubfx_dsp
|
||||
zynaddsubfx_samples
|
||||
zynaddsubfx_controls
|
||||
)
|
||||
|
||||
macro(unit_test NAME CXX_FILE FILES)
|
||||
endmacro(unit_test)
|
||||
|
||||
add_subdirectory(src/Misc)
|
||||
add_subdirectory(src/Input)
|
||||
add_subdirectory(src/Controls)
|
||||
add_subdirectory(src/Synth)
|
||||
add_subdirectory(src/Output)
|
||||
add_subdirectory(src/Seq)
|
||||
add_subdirectory(src/Effects)
|
||||
add_subdirectory(src/Params)
|
||||
add_subdirectory(src/DSP)
|
||||
add_subdirectory(src/Samples)
|
||||
|
||||
ADD_LIBRARY(ZynAddSubFxCore SHARED LocalZynAddSubFx.cpp ${MXML_SRC})
|
||||
TARGET_LINK_LIBRARIES(ZynAddSubFxCore ${FFTW3F_LIBRARIES} ${ZASF_CORE_LIBS} -lz -lpthread)
|
||||
IF(LMMS_BUILD_WIN32)
|
||||
TARGET_LINK_LIBRARIES(ZynAddSubFxCore -lwsock32)
|
||||
INSTALL(TARGETS ZynAddSubFxCore DESTINATION ${PLUGIN_DIR})
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include "LocalZynAddSubFx.h"
|
||||
|
||||
#include "src/Input/MidiIn.h"
|
||||
#include "src/Input/NULLMidiIn.h"
|
||||
#include "src/Misc/Master.h"
|
||||
#include "src/Misc/Dump.h"
|
||||
|
||||
@@ -169,7 +169,7 @@ void LocalZynAddSubFx::setPresetDir( const std::string & _dir )
|
||||
void LocalZynAddSubFx::processMidiEvent( const midiEvent & _e )
|
||||
{
|
||||
// all functions are called while m_master->mutex is held
|
||||
static MidiIn midiIn;
|
||||
static NULLMidiIn midiIn;
|
||||
|
||||
switch( _e.m_type )
|
||||
{
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
Main author:
|
||||
Nasca Octavian Paul
|
||||
Nasca Octavian Paul
|
||||
|
||||
Developers:
|
||||
Mark McCurry
|
||||
Mark McCurry
|
||||
Harald Hvaal
|
||||
|
||||
Contributors:
|
||||
Gerald Folcher (legato, mono notes memory)
|
||||
Lars Luthman (zombie fix,jack midi, LASH support)
|
||||
Daniel Clemente (with a workaround of X11 repeated key bug)
|
||||
Gerald Folcher (legato, mono notes memory)
|
||||
Lars Luthman (zombie fix,jack midi, LASH support)
|
||||
Daniel Clemente (with a workaround of X11 repeated key bug)
|
||||
Emmanuel Saracco (fix for JACK output)
|
||||
Achim Settelmeier (QUERTZ keyboard layout for virtual keyboard)
|
||||
J<>r<EFBFBD>mie Andr<64>i (AZERTY keyboard layout, Array index fix)
|
||||
Alexis Ballier (const char* <-> string mismatch, NULLMidi prototype fix)
|
||||
|
||||
|
||||
@@ -840,7 +840,7 @@
|
||||
hovers over them
|
||||
- Created tooltips for the effects knobs
|
||||
- Standardized the code, so it could compile with pedantic without
|
||||
errors [it looks like some errors may have ben missed]
|
||||
errors [it looks like some errors may have been missed]
|
||||
|
||||
22 Feb 2009 (Mark McCurry)
|
||||
- Fix improper deallocation in PresetsStore
|
||||
@@ -861,3 +861,34 @@
|
||||
- Almost all changes contained in Effects until further
|
||||
discussion on the style, so consistancy can be reached
|
||||
|
||||
28 May 2009 (Mark McCurry)
|
||||
- Added some more Doxygen comments
|
||||
- Added Audio Samples classes
|
||||
- Added Stereo template
|
||||
- Added Control class
|
||||
- Added DelayCtl class
|
||||
|
||||
20 Iun 2009 (Paul Nasca)
|
||||
- Bugfix: WAV export of PADsynth
|
||||
|
||||
10 Iul 2009 (Paul Nasca)
|
||||
- Update copyright info
|
||||
|
||||
11 Jul 2009 (Mark McCurry)
|
||||
- Added Proportinal Portamento
|
||||
- Replaced Docbook with AsciiDoc
|
||||
|
||||
18 Jul 2009 (Mark McCurry)
|
||||
- Enabled volume controller by default
|
||||
|
||||
20 Jul 2009 (Mark McCurry)
|
||||
- Incorperated AZERTY layout by sourceforge user jimee
|
||||
|
||||
02 Sep 2009 (Mark McCurry)
|
||||
- Incorperated const char* <-> string mismatch by Alexis Ballier
|
||||
|
||||
04 Sep 2009 (Mark McCurry)
|
||||
- Incorperated NULLMidiIn function prototype fix by Alexis Ballier
|
||||
|
||||
07 Sep 2009 (Mark McCurry)
|
||||
- Fixed glitch in XMLwrapper, which would prevent file loading
|
||||
|
||||
8
plugins/zynaddsubfx/src/Controls/CMakeLists.txt
Normal file
8
plugins/zynaddsubfx/src/Controls/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(zynaddsubfx_controls_SRCS
|
||||
Control.cpp
|
||||
DelayCtl.cpp
|
||||
)
|
||||
|
||||
add_library(zynaddsubfx_controls STATIC
|
||||
${zynaddsubfx_controls_SRCS}
|
||||
)
|
||||
40
plugins/zynaddsubfx/src/Controls/Control.cpp
Normal file
40
plugins/zynaddsubfx/src/Controls/Control.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Control.C - Control base class
|
||||
Copyright (C) 2009-2009 Mark McCurry
|
||||
Author: 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
|
||||
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 or later) 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 "Control.h"
|
||||
|
||||
Control::Control(char ndefaultval)
|
||||
:defaultval(ndefaultval),lockqueue(-1),locked(false)
|
||||
{}
|
||||
|
||||
void Control::lock()
|
||||
{
|
||||
locked=true;
|
||||
lockqueue=-1;
|
||||
}
|
||||
|
||||
void Control::ulock()
|
||||
{
|
||||
if (locked&&lockqueue>=0)
|
||||
setmVal(lockqueue);
|
||||
locked=false;
|
||||
}
|
||||
|
||||
58
plugins/zynaddsubfx/src/Controls/Control.h
Normal file
58
plugins/zynaddsubfx/src/Controls/Control.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Control.h - Control base class
|
||||
Copyright (C) 2009-2009 Mark McCurry
|
||||
Author: 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
|
||||
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 or later) 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 CONTROL_H
|
||||
#define CONTROL_H
|
||||
#include <string>
|
||||
/**A control for a parameter within the program*/
|
||||
class Control
|
||||
{
|
||||
public:
|
||||
Control(char ndefaultval);/**\todo create proper initialization list*/
|
||||
~Control() {};
|
||||
/**Return the string, which represents the internal value
|
||||
* @return a string representation of the current value*/
|
||||
virtual std::string getString()const=0;
|
||||
/**Set the Control to the given value
|
||||
* @param nval A number 0-127*/
|
||||
virtual void setmVal(char nval)=0;
|
||||
/**Return the midi value (aka the char)
|
||||
* @return the current value*/
|
||||
virtual char getmVal()const=0;
|
||||
/** Will lock the Control until it is ulocked
|
||||
*
|
||||
* Locking a Control will Stop it from having
|
||||
* its internal data altered*/
|
||||
void lock();
|
||||
/** Will unlock the Control
|
||||
*
|
||||
* This will also update the Control
|
||||
* if something attempted to update it while it was locked*/
|
||||
void ulock();
|
||||
private:
|
||||
char defaultval;/**<Default value of the Control*/
|
||||
char lockqueue; /**<The value is that is stored, while the Control is locked
|
||||
* and something attempts to update it*/
|
||||
bool locked;//upgrade this to a integer lock level if problems occur
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
50
plugins/zynaddsubfx/src/Controls/DelayCtl.cpp
Normal file
50
plugins/zynaddsubfx/src/Controls/DelayCtl.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
DelayCtl.C - Control For Delays
|
||||
Copyright (C) 2009-2009 Mark McCurry
|
||||
Author: 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
|
||||
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 or later) 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 "DelayCtl.h"
|
||||
#include <sstream>
|
||||
|
||||
DelayCtl::DelayCtl()
|
||||
:Control(64),value(64/127.0*1.5) {} /**\todo finishme*/
|
||||
|
||||
std::string DelayCtl::getString() const
|
||||
{
|
||||
std::ostringstream buf;
|
||||
buf<<value;
|
||||
return (buf.str() + " Seconds");
|
||||
}
|
||||
|
||||
void DelayCtl::setmVal(char nval)
|
||||
{
|
||||
/**\todo add locking code*/
|
||||
//value=1+(int)(nval/127.0*SAMPLE_RATE*1.5);//0 .. 1.5 sec
|
||||
value=(nval/127.0*1.5);//0 .. 1.5 sec
|
||||
}
|
||||
|
||||
char DelayCtl::getmVal() const
|
||||
{
|
||||
return((char)(value/1.5*127.0));
|
||||
}
|
||||
|
||||
float DelayCtl::getiVal() const
|
||||
{
|
||||
return(value);
|
||||
}
|
||||
43
plugins/zynaddsubfx/src/Controls/DelayCtl.h
Normal file
43
plugins/zynaddsubfx/src/Controls/DelayCtl.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
DelayCtl.h - Control For Delays
|
||||
Copyright (C) 2009-2009 Mark McCurry
|
||||
Author: 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
|
||||
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 or later) 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 "Control.h"
|
||||
|
||||
#ifndef DELAYCTL_H
|
||||
#define DELAYCTL_H
|
||||
/**A Control for Delays
|
||||
*
|
||||
* Will vary from 0 seconds to 1.5 seconds*/
|
||||
class DelayCtl:public Control
|
||||
{
|
||||
public:
|
||||
DelayCtl();
|
||||
~DelayCtl() {};
|
||||
std::string getString() const;
|
||||
void setmVal(char nval);
|
||||
char getmVal() const;
|
||||
float getiVal() const;
|
||||
private:
|
||||
float value;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,358 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
AnalogFilter.C - Several analog filters (lowpass, highpass...)
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <math.h>
|
||||
#include <stdio.h>
|
||||
#include "AnalogFilter.h"
|
||||
|
||||
AnalogFilter::AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages){
|
||||
stages=Fstages;
|
||||
for (int i=0;i<3;i++){
|
||||
oldc[i]=0.0;oldd[i]=0.0;
|
||||
c[i]=0.0;d[i]=0.0;
|
||||
};
|
||||
type=Ftype;
|
||||
freq=Ffreq;
|
||||
q=Fq;
|
||||
gain=1.0;
|
||||
if (stages>=MAX_FILTER_STAGES) stages=MAX_FILTER_STAGES;
|
||||
cleanup();
|
||||
firsttime=0;
|
||||
abovenq=0;oldabovenq=0;
|
||||
setfreq_and_q(Ffreq,Fq);
|
||||
firsttime=1;
|
||||
d[0]=0;//this is not used
|
||||
outgain=1.0;
|
||||
};
|
||||
|
||||
AnalogFilter::~AnalogFilter(){
|
||||
};
|
||||
|
||||
void AnalogFilter::cleanup(){
|
||||
for (int i=0;i<MAX_FILTER_STAGES+1;i++){
|
||||
x[i].c1=0.0;x[i].c2=0.0;
|
||||
y[i].c1=0.0;y[i].c2=0.0;
|
||||
oldx[i]=x[i];
|
||||
oldy[i]=y[i];
|
||||
};
|
||||
needsinterpolation=0;
|
||||
};
|
||||
|
||||
void AnalogFilter::computefiltercoefs(){
|
||||
REALTYPE tmp;
|
||||
REALTYPE omega,sn,cs,alpha,beta;
|
||||
int zerocoefs=0;//this is used if the freq is too high
|
||||
|
||||
//do not allow frequencies bigger than samplerate/2
|
||||
REALTYPE freq=this->freq;
|
||||
if (freq>(SAMPLE_RATE/2-500.0)) {
|
||||
freq=SAMPLE_RATE/2-500.0;
|
||||
zerocoefs=1;
|
||||
};
|
||||
if (freq<0.1) freq=0.1;
|
||||
//do not allow bogus Q
|
||||
if (q<0.0) q=0.0;
|
||||
REALTYPE tmpq,tmpgain;
|
||||
if (stages==0) {
|
||||
tmpq=q;
|
||||
tmpgain=gain;
|
||||
} else {
|
||||
tmpq=(q>1.0 ? pow(q,1.0/(stages+1)) : q);
|
||||
tmpgain=pow(gain,1.0/(stages+1));
|
||||
};
|
||||
|
||||
//most of theese are implementations of
|
||||
//the "Cookbook formulae for audio EQ" by Robert Bristow-Johnson
|
||||
//The original location of the Cookbook is:
|
||||
//http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
|
||||
switch(type){
|
||||
case 0://LPF 1 pole
|
||||
if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE);
|
||||
else tmp=0.0;
|
||||
c[0]=1.0-tmp;c[1]=0.0;c[2]=0.0;
|
||||
d[1]=tmp;d[2]=0.0;
|
||||
order=1;
|
||||
break;
|
||||
case 1://HPF 1 pole
|
||||
if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE);
|
||||
else tmp=0.0;
|
||||
c[0]=(1.0+tmp)/2.0;c[1]=-(1.0+tmp)/2.0;c[2]=0.0;
|
||||
d[1]=tmp;d[2]=0.0;
|
||||
order=1;
|
||||
break;
|
||||
case 2://LPF 2 poles
|
||||
if (zerocoefs==0){
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
alpha=sn/(2*tmpq);
|
||||
tmp=1+alpha;
|
||||
c[0]=(1.0-cs)/2.0/tmp;
|
||||
c[1]=(1.0-cs)/tmp;
|
||||
c[2]=(1.0-cs)/2.0/tmp;
|
||||
d[1]=-2*cs/tmp*(-1);
|
||||
d[2]=(1-alpha)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=1.0;c[1]=0.0;c[2]=0.0;
|
||||
d[1]=0.0;d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 3://HPF 2 poles
|
||||
if (zerocoefs==0){
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
alpha=sn/(2*tmpq);
|
||||
tmp=1+alpha;
|
||||
c[0]=(1.0+cs)/2.0/tmp;
|
||||
c[1]=-(1.0+cs)/tmp;
|
||||
c[2]=(1.0+cs)/2.0/tmp;
|
||||
d[1]=-2*cs/tmp*(-1);
|
||||
d[2]=(1-alpha)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=0.0;c[1]=0.0;c[2]=0.0;
|
||||
d[1]=0.0;d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 4://BPF 2 poles
|
||||
if (zerocoefs==0){
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
alpha=sn/(2*tmpq);
|
||||
tmp=1+alpha;
|
||||
c[0]=alpha/tmp*sqrt(tmpq+1);
|
||||
c[1]=0;
|
||||
c[2]=-alpha/tmp*sqrt(tmpq+1);
|
||||
d[1]=-2*cs/tmp*(-1);
|
||||
d[2]=(1-alpha)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=0.0;c[1]=0.0;c[2]=0.0;
|
||||
d[1]=0.0;d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 5://NOTCH 2 poles
|
||||
if (zerocoefs==0){
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
alpha=sn/(2*sqrt(tmpq));
|
||||
tmp=1+alpha;
|
||||
c[0]=1/tmp;
|
||||
c[1]=-2*cs/tmp;
|
||||
c[2]=1/tmp;
|
||||
d[1]=-2*cs/tmp*(-1);
|
||||
d[2]=(1-alpha)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=1.0;c[1]=0.0;c[2]=0.0;
|
||||
d[1]=0.0;d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 6://PEAK (2 poles)
|
||||
if (zerocoefs==0){
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
tmpq*=3.0;
|
||||
alpha=sn/(2*tmpq);
|
||||
tmp=1+alpha/tmpgain;
|
||||
c[0]=(1.0+alpha*tmpgain)/tmp;
|
||||
c[1]=(-2.0*cs)/tmp;
|
||||
c[2]=(1.0-alpha*tmpgain)/tmp;
|
||||
d[1]=-2*cs/tmp*(-1);
|
||||
d[2]=(1-alpha/tmpgain)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=1.0;c[1]=0.0;c[2]=0.0;
|
||||
d[1]=0.0;d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 7://Low Shelf - 2 poles
|
||||
if (zerocoefs==0){
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
tmpq=sqrt(tmpq);
|
||||
alpha=sn/(2*tmpq);
|
||||
beta=sqrt(tmpgain)/tmpq;
|
||||
tmp=(tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn;
|
||||
|
||||
c[0]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn)/tmp;
|
||||
c[1]=2.0*tmpgain*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp;
|
||||
c[2]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp;
|
||||
d[1]=-2.0*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp*(-1);
|
||||
d[2]=((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=tmpgain;c[1]=0.0;c[2]=0.0;
|
||||
d[1]=0.0;d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 8://High Shelf - 2 poles
|
||||
if (zerocoefs==0){
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
tmpq=sqrt(tmpq);
|
||||
alpha=sn/(2*tmpq);
|
||||
beta=sqrt(tmpgain)/tmpq;
|
||||
tmp=(tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn;
|
||||
|
||||
c[0]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn)/tmp;
|
||||
c[1]=-2.0*tmpgain*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp;
|
||||
c[2]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp;
|
||||
d[1]=2.0*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp*(-1);
|
||||
d[2]=((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=1.0;c[1]=0.0;c[2]=0.0;
|
||||
d[1]=0.0;d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
default://wrong type
|
||||
type=0;
|
||||
computefiltercoefs();
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
void AnalogFilter::setfreq(REALTYPE frequency){
|
||||
if (frequency<0.1) frequency=0.1;
|
||||
REALTYPE rap=freq/frequency;if (rap<1.0) rap=1.0/rap;
|
||||
|
||||
oldabovenq=abovenq;abovenq=frequency>(SAMPLE_RATE/2-500.0);
|
||||
|
||||
int nyquistthresh=(abovenq^oldabovenq);
|
||||
|
||||
|
||||
if ((rap>3.0)||(nyquistthresh!=0)){//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup)
|
||||
for (int i=0;i<3;i++){
|
||||
oldc[i]=c[i];oldd[i]=d[i];
|
||||
};
|
||||
for (int i=0;i<MAX_FILTER_STAGES+1;i++){
|
||||
oldx[i]=x[i];
|
||||
oldy[i]=y[i];
|
||||
};
|
||||
if (firsttime==0) needsinterpolation=1;
|
||||
};
|
||||
freq=frequency;
|
||||
computefiltercoefs();
|
||||
firsttime=0;
|
||||
|
||||
};
|
||||
|
||||
void AnalogFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){
|
||||
q=q_;
|
||||
setfreq(frequency);
|
||||
};
|
||||
|
||||
void AnalogFilter::setq(REALTYPE q_){
|
||||
q=q_;
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void AnalogFilter::settype(int type_){
|
||||
type=type_;
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void AnalogFilter::setgain(REALTYPE dBgain){
|
||||
gain=dB2rap(dBgain);
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void AnalogFilter::setstages(int stages_){
|
||||
if (stages_>=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1;
|
||||
stages=stages_;
|
||||
cleanup();
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void AnalogFilter::singlefilterout(REALTYPE *smp,fstage &x,fstage &y,REALTYPE *c,REALTYPE *d){
|
||||
int i;
|
||||
REALTYPE y0;
|
||||
if (order==1) {//First order filter
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
y0=smp[i]*c[0]+x.c1*c[1]+y.c1*d[1];
|
||||
y.c1=y0;
|
||||
x.c1=smp[i];
|
||||
//output
|
||||
smp[i]=y0;
|
||||
};
|
||||
};
|
||||
if (order==2) {//Second order filter
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
y0=smp[i]*c[0]+x.c1*c[1]+x.c2*c[2]+y.c1*d[1]+y.c2*d[2];
|
||||
y.c2=y.c1;
|
||||
y.c1=y0;
|
||||
x.c2=x.c1;
|
||||
x.c1=smp[i];
|
||||
//output
|
||||
smp[i]=y0;
|
||||
};
|
||||
};
|
||||
};
|
||||
void AnalogFilter::filterout(REALTYPE *smp){
|
||||
REALTYPE *ismp=NULL;//used if it needs interpolation
|
||||
int i;
|
||||
if (needsinterpolation!=0){
|
||||
ismp=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) ismp[i]=smp[i];
|
||||
for (i=0;i<stages+1;i++) singlefilterout(ismp,oldx[i],oldy[i],oldc,oldd);
|
||||
};
|
||||
|
||||
for (i=0;i<stages+1;i++) singlefilterout(smp,x[i],y[i],c,d);
|
||||
|
||||
if (needsinterpolation!=0){
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE x=i/(REALTYPE) SOUND_BUFFER_SIZE;
|
||||
smp[i]=ismp[i]*(1.0-x)+smp[i]*x;
|
||||
};
|
||||
delete [] ismp;
|
||||
needsinterpolation=0;
|
||||
};
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]*=outgain;
|
||||
};
|
||||
|
||||
REALTYPE AnalogFilter::H(REALTYPE freq){
|
||||
REALTYPE fr=freq/SAMPLE_RATE*PI*2.0;
|
||||
REALTYPE x=c[0],y=0.0;
|
||||
for (int n=1;n<3;n++){
|
||||
x+=cos(n*fr)*c[n];
|
||||
y-=sin(n*fr)*c[n];
|
||||
};
|
||||
REALTYPE h=x*x+y*y;
|
||||
x=1.0;y=0.0;
|
||||
for (int n=1;n<3;n++){
|
||||
x-=cos(n*fr)*d[n];
|
||||
y+=sin(n*fr)*d[n];
|
||||
};
|
||||
h=h/(x*x+y*y);
|
||||
return(pow(h,(stages+1.0)/2.0));
|
||||
};
|
||||
|
||||
407
plugins/zynaddsubfx/src/DSP/AnalogFilter.cpp
Normal file
407
plugins/zynaddsubfx/src/DSP/AnalogFilter.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
AnalogFilter.C - Several analog filters (lowpass, highpass...)
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <math.h>
|
||||
#include <stdio.h>
|
||||
#include "AnalogFilter.h"
|
||||
|
||||
AnalogFilter::AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages)
|
||||
{
|
||||
stages=Fstages;
|
||||
for (int i=0;i<3;i++) {
|
||||
oldc[i]=0.0;
|
||||
oldd[i]=0.0;
|
||||
c[i]=0.0;
|
||||
d[i]=0.0;
|
||||
};
|
||||
type=Ftype;
|
||||
freq=Ffreq;
|
||||
q=Fq;
|
||||
gain=1.0;
|
||||
if (stages>=MAX_FILTER_STAGES) stages=MAX_FILTER_STAGES;
|
||||
cleanup();
|
||||
firsttime=0;
|
||||
abovenq=0;
|
||||
oldabovenq=0;
|
||||
setfreq_and_q(Ffreq,Fq);
|
||||
firsttime=1;
|
||||
d[0]=0;//this is not used
|
||||
outgain=1.0;
|
||||
};
|
||||
|
||||
AnalogFilter::~AnalogFilter()
|
||||
{
|
||||
};
|
||||
|
||||
void AnalogFilter::cleanup()
|
||||
{
|
||||
for (int i=0;i<MAX_FILTER_STAGES+1;i++) {
|
||||
x[i].c1=0.0;
|
||||
x[i].c2=0.0;
|
||||
y[i].c1=0.0;
|
||||
y[i].c2=0.0;
|
||||
oldx[i]=x[i];
|
||||
oldy[i]=y[i];
|
||||
};
|
||||
needsinterpolation=0;
|
||||
};
|
||||
|
||||
void AnalogFilter::computefiltercoefs()
|
||||
{
|
||||
REALTYPE tmp;
|
||||
REALTYPE omega,sn,cs,alpha,beta;
|
||||
int zerocoefs=0;//this is used if the freq is too high
|
||||
|
||||
//do not allow frequencies bigger than samplerate/2
|
||||
REALTYPE freq=this->freq;
|
||||
if (freq>(SAMPLE_RATE/2-500.0)) {
|
||||
freq=SAMPLE_RATE/2-500.0;
|
||||
zerocoefs=1;
|
||||
};
|
||||
if (freq<0.1) freq=0.1;
|
||||
//do not allow bogus Q
|
||||
if (q<0.0) q=0.0;
|
||||
REALTYPE tmpq,tmpgain;
|
||||
if (stages==0) {
|
||||
tmpq=q;
|
||||
tmpgain=gain;
|
||||
} else {
|
||||
tmpq=(q>1.0 ? pow(q,1.0/(stages+1)) : q);
|
||||
tmpgain=pow(gain,1.0/(stages+1));
|
||||
};
|
||||
|
||||
//most of theese are implementations of
|
||||
//the "Cookbook formulae for audio EQ" by Robert Bristow-Johnson
|
||||
//The original location of the Cookbook is:
|
||||
//http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
|
||||
switch (type) {
|
||||
case 0://LPF 1 pole
|
||||
if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE);
|
||||
else tmp=0.0;
|
||||
c[0]=1.0-tmp;
|
||||
c[1]=0.0;
|
||||
c[2]=0.0;
|
||||
d[1]=tmp;
|
||||
d[2]=0.0;
|
||||
order=1;
|
||||
break;
|
||||
case 1://HPF 1 pole
|
||||
if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE);
|
||||
else tmp=0.0;
|
||||
c[0]=(1.0+tmp)/2.0;
|
||||
c[1]=-(1.0+tmp)/2.0;
|
||||
c[2]=0.0;
|
||||
d[1]=tmp;
|
||||
d[2]=0.0;
|
||||
order=1;
|
||||
break;
|
||||
case 2://LPF 2 poles
|
||||
if (zerocoefs==0) {
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
alpha=sn/(2*tmpq);
|
||||
tmp=1+alpha;
|
||||
c[0]=(1.0-cs)/2.0/tmp;
|
||||
c[1]=(1.0-cs)/tmp;
|
||||
c[2]=(1.0-cs)/2.0/tmp;
|
||||
d[1]=-2*cs/tmp*(-1);
|
||||
d[2]=(1-alpha)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=1.0;
|
||||
c[1]=0.0;
|
||||
c[2]=0.0;
|
||||
d[1]=0.0;
|
||||
d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 3://HPF 2 poles
|
||||
if (zerocoefs==0) {
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
alpha=sn/(2*tmpq);
|
||||
tmp=1+alpha;
|
||||
c[0]=(1.0+cs)/2.0/tmp;
|
||||
c[1]=-(1.0+cs)/tmp;
|
||||
c[2]=(1.0+cs)/2.0/tmp;
|
||||
d[1]=-2*cs/tmp*(-1);
|
||||
d[2]=(1-alpha)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=0.0;
|
||||
c[1]=0.0;
|
||||
c[2]=0.0;
|
||||
d[1]=0.0;
|
||||
d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 4://BPF 2 poles
|
||||
if (zerocoefs==0) {
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
alpha=sn/(2*tmpq);
|
||||
tmp=1+alpha;
|
||||
c[0]=alpha/tmp*sqrt(tmpq+1);
|
||||
c[1]=0;
|
||||
c[2]=-alpha/tmp*sqrt(tmpq+1);
|
||||
d[1]=-2*cs/tmp*(-1);
|
||||
d[2]=(1-alpha)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=0.0;
|
||||
c[1]=0.0;
|
||||
c[2]=0.0;
|
||||
d[1]=0.0;
|
||||
d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 5://NOTCH 2 poles
|
||||
if (zerocoefs==0) {
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
alpha=sn/(2*sqrt(tmpq));
|
||||
tmp=1+alpha;
|
||||
c[0]=1/tmp;
|
||||
c[1]=-2*cs/tmp;
|
||||
c[2]=1/tmp;
|
||||
d[1]=-2*cs/tmp*(-1);
|
||||
d[2]=(1-alpha)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=1.0;
|
||||
c[1]=0.0;
|
||||
c[2]=0.0;
|
||||
d[1]=0.0;
|
||||
d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 6://PEAK (2 poles)
|
||||
if (zerocoefs==0) {
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
tmpq*=3.0;
|
||||
alpha=sn/(2*tmpq);
|
||||
tmp=1+alpha/tmpgain;
|
||||
c[0]=(1.0+alpha*tmpgain)/tmp;
|
||||
c[1]=(-2.0*cs)/tmp;
|
||||
c[2]=(1.0-alpha*tmpgain)/tmp;
|
||||
d[1]=-2*cs/tmp*(-1);
|
||||
d[2]=(1-alpha/tmpgain)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=1.0;
|
||||
c[1]=0.0;
|
||||
c[2]=0.0;
|
||||
d[1]=0.0;
|
||||
d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 7://Low Shelf - 2 poles
|
||||
if (zerocoefs==0) {
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
tmpq=sqrt(tmpq);
|
||||
alpha=sn/(2*tmpq);
|
||||
beta=sqrt(tmpgain)/tmpq;
|
||||
tmp=(tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn;
|
||||
|
||||
c[0]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn)/tmp;
|
||||
c[1]=2.0*tmpgain*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp;
|
||||
c[2]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp;
|
||||
d[1]=-2.0*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp*(-1);
|
||||
d[2]=((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=tmpgain;
|
||||
c[1]=0.0;
|
||||
c[2]=0.0;
|
||||
d[1]=0.0;
|
||||
d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
case 8://High Shelf - 2 poles
|
||||
if (zerocoefs==0) {
|
||||
omega=2*PI*freq/SAMPLE_RATE;
|
||||
sn=sin(omega);
|
||||
cs=cos(omega);
|
||||
tmpq=sqrt(tmpq);
|
||||
alpha=sn/(2*tmpq);
|
||||
beta=sqrt(tmpgain)/tmpq;
|
||||
tmp=(tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn;
|
||||
|
||||
c[0]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn)/tmp;
|
||||
c[1]=-2.0*tmpgain*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp;
|
||||
c[2]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp;
|
||||
d[1]=2.0*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp*(-1);
|
||||
d[2]=((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp*(-1);
|
||||
} else {
|
||||
c[0]=1.0;
|
||||
c[1]=0.0;
|
||||
c[2]=0.0;
|
||||
d[1]=0.0;
|
||||
d[2]=0.0;
|
||||
};
|
||||
order=2;
|
||||
break;
|
||||
default://wrong type
|
||||
type=0;
|
||||
computefiltercoefs();
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
void AnalogFilter::setfreq(REALTYPE frequency)
|
||||
{
|
||||
if (frequency<0.1) frequency=0.1;
|
||||
REALTYPE rap=freq/frequency;
|
||||
if (rap<1.0) rap=1.0/rap;
|
||||
|
||||
oldabovenq=abovenq;
|
||||
abovenq=frequency>(SAMPLE_RATE/2-500.0);
|
||||
|
||||
int nyquistthresh=(abovenq^oldabovenq);
|
||||
|
||||
|
||||
if ((rap>3.0)||(nyquistthresh!=0)) {//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup)
|
||||
for (int i=0;i<3;i++) {
|
||||
oldc[i]=c[i];
|
||||
oldd[i]=d[i];
|
||||
};
|
||||
for (int i=0;i<MAX_FILTER_STAGES+1;i++) {
|
||||
oldx[i]=x[i];
|
||||
oldy[i]=y[i];
|
||||
};
|
||||
if (firsttime==0) needsinterpolation=1;
|
||||
};
|
||||
freq=frequency;
|
||||
computefiltercoefs();
|
||||
firsttime=0;
|
||||
|
||||
};
|
||||
|
||||
void AnalogFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_)
|
||||
{
|
||||
q=q_;
|
||||
setfreq(frequency);
|
||||
};
|
||||
|
||||
void AnalogFilter::setq(REALTYPE q_)
|
||||
{
|
||||
q=q_;
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void AnalogFilter::settype(int type_)
|
||||
{
|
||||
type=type_;
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void AnalogFilter::setgain(REALTYPE dBgain)
|
||||
{
|
||||
gain=dB2rap(dBgain);
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void AnalogFilter::setstages(int stages_)
|
||||
{
|
||||
if (stages_>=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1;
|
||||
stages=stages_;
|
||||
cleanup();
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void AnalogFilter::singlefilterout(REALTYPE *smp,fstage &x,fstage &y,REALTYPE *c,REALTYPE *d)
|
||||
{
|
||||
int i;
|
||||
REALTYPE y0;
|
||||
if (order==1) {//First order filter
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
y0=smp[i]*c[0]+x.c1*c[1]+y.c1*d[1];
|
||||
y.c1=y0;
|
||||
x.c1=smp[i];
|
||||
//output
|
||||
smp[i]=y0;
|
||||
};
|
||||
};
|
||||
if (order==2) {//Second order filter
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
y0=smp[i]*c[0]+x.c1*c[1]+x.c2*c[2]+y.c1*d[1]+y.c2*d[2];
|
||||
y.c2=y.c1;
|
||||
y.c1=y0;
|
||||
x.c2=x.c1;
|
||||
x.c1=smp[i];
|
||||
//output
|
||||
smp[i]=y0;
|
||||
};
|
||||
};
|
||||
};
|
||||
void AnalogFilter::filterout(REALTYPE *smp)
|
||||
{
|
||||
REALTYPE *ismp=NULL;//used if it needs interpolation
|
||||
int i;
|
||||
if (needsinterpolation!=0) {
|
||||
ismp=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) ismp[i]=smp[i];
|
||||
for (i=0;i<stages+1;i++) singlefilterout(ismp,oldx[i],oldy[i],oldc,oldd);
|
||||
};
|
||||
|
||||
for (i=0;i<stages+1;i++) singlefilterout(smp,x[i],y[i],c,d);
|
||||
|
||||
if (needsinterpolation!=0) {
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE x=i/(REALTYPE) SOUND_BUFFER_SIZE;
|
||||
smp[i]=ismp[i]*(1.0-x)+smp[i]*x;
|
||||
};
|
||||
delete [] ismp;
|
||||
needsinterpolation=0;
|
||||
};
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]*=outgain;
|
||||
};
|
||||
|
||||
REALTYPE AnalogFilter::H(REALTYPE freq)
|
||||
{
|
||||
REALTYPE fr=freq/SAMPLE_RATE*PI*2.0;
|
||||
REALTYPE x=c[0],y=0.0;
|
||||
for (int n=1;n<3;n++) {
|
||||
x+=cos(n*fr)*c[n];
|
||||
y-=sin(n*fr)*c[n];
|
||||
};
|
||||
REALTYPE h=x*x+y*y;
|
||||
x=1.0;
|
||||
y=0.0;
|
||||
for (int n=1;n<3;n++) {
|
||||
x-=cos(n*fr)*d[n];
|
||||
y+=sin(n*fr)*d[n];
|
||||
};
|
||||
h=h/(x*x+y*y);
|
||||
return(pow(h,(stages+1.0)/2.0));
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Analog Filter.h - Several analog filters (lowpass, highpass...)
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -25,10 +25,13 @@
|
||||
|
||||
#include "../globals.h"
|
||||
#include "Filter_.h"
|
||||
class AnalogFilter:public Filter_{
|
||||
public:
|
||||
|
||||
/**Implementation of Several analog filters (lowpass, highpass...)*/
|
||||
class AnalogFilter:public Filter_
|
||||
{
|
||||
public:
|
||||
AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages);
|
||||
~AnalogFilter();
|
||||
~AnalogFilter();
|
||||
void filterout(REALTYPE *smp);
|
||||
void setfreq(REALTYPE frequency);
|
||||
void setfreq_and_q(REALTYPE frequency,REALTYPE q_);
|
||||
@@ -38,14 +41,14 @@ class AnalogFilter:public Filter_{
|
||||
void setgain(REALTYPE dBgain);
|
||||
void setstages(int stages_);
|
||||
void cleanup();
|
||||
|
||||
|
||||
REALTYPE H(REALTYPE freq);//Obtains the response for a given frequency
|
||||
|
||||
private:
|
||||
struct fstage{
|
||||
REALTYPE c1,c2;
|
||||
|
||||
private:
|
||||
struct fstage {
|
||||
REALTYPE c1,c2;
|
||||
} x[MAX_FILTER_STAGES+1],y[MAX_FILTER_STAGES+1],
|
||||
oldx[MAX_FILTER_STAGES+1],oldy[MAX_FILTER_STAGES+1];
|
||||
oldx[MAX_FILTER_STAGES+1],oldy[MAX_FILTER_STAGES+1];
|
||||
|
||||
void singlefilterout(REALTYPE *smp,fstage &x,fstage &y,REALTYPE *c,REALTYPE *d);
|
||||
void computefiltercoefs();
|
||||
@@ -54,7 +57,7 @@ class AnalogFilter:public Filter_{
|
||||
REALTYPE freq;//Frequency given in Hz
|
||||
REALTYPE q; //Q factor (resonance or Q factor)
|
||||
REALTYPE gain;//the gain of the filter (if are shelf/peak) filters
|
||||
|
||||
|
||||
int order;//the order of the filter (number of poles)
|
||||
|
||||
REALTYPE c[3],d[3];//coefficients
|
||||
@@ -62,7 +65,7 @@ class AnalogFilter:public Filter_{
|
||||
REALTYPE oldc[3],oldd[3];//old coefficients(used only if some filter paremeters changes very fast, and it needs interpolation)
|
||||
|
||||
REALTYPE xd[3],yd[3];//used if the filter is applied more times
|
||||
int needsinterpolation,firsttime;
|
||||
int needsinterpolation,firsttime;/**\todo see if bool works for these*/
|
||||
int abovenq;//this is 1 if the frequency is above the nyquist
|
||||
int oldabovenq;//if the last time was above nyquist (used to see if it needs interpolation)
|
||||
};
|
||||
|
||||
13
plugins/zynaddsubfx/src/DSP/CMakeLists.txt
Normal file
13
plugins/zynaddsubfx/src/DSP/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
set(zynaddsubfx_dsp_SRCS
|
||||
AnalogFilter.cpp
|
||||
FFTwrapper.cpp
|
||||
Filter.cpp
|
||||
FormantFilter.cpp
|
||||
SVFilter.cpp
|
||||
)
|
||||
|
||||
add_library(zynaddsubfx_dsp STATIC
|
||||
${zynaddsubfx_dsp_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries(zynaddsubfx_dsp)
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
FFTwrapper.c - A wrapper for Fast Fourier Transforms
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -23,24 +23,26 @@
|
||||
#include <math.h>
|
||||
#include "FFTwrapper.h"
|
||||
|
||||
FFTwrapper::FFTwrapper(int fftsize_){
|
||||
FFTwrapper::FFTwrapper(int fftsize_)
|
||||
{
|
||||
fftsize=fftsize_;
|
||||
tmpfftdata1=new fftw_real[fftsize];
|
||||
tmpfftdata2=new fftw_real[fftsize];
|
||||
#ifdef FFTW_VERSION_2
|
||||
planfftw=rfftwf_create_plan(fftsize,FFTW_REAL_TO_COMPLEX,FFTW_ESTIMATE|FFTW_IN_PLACE);
|
||||
planfftwf_inv=rfftwf_create_plan(fftsize,FFTW_COMPLEX_TO_REAL,FFTW_ESTIMATE|FFTW_IN_PLACE);
|
||||
planfftw=rfftw_create_plan(fftsize,FFTW_REAL_TO_COMPLEX,FFTW_ESTIMATE|FFTW_IN_PLACE);
|
||||
planfftw_inv=rfftw_create_plan(fftsize,FFTW_COMPLEX_TO_REAL,FFTW_ESTIMATE|FFTW_IN_PLACE);
|
||||
#else
|
||||
planfftw=fftwf_plan_r2r_1d(fftsize,tmpfftdata1,tmpfftdata1,FFTW_R2HC,FFTW_ESTIMATE);
|
||||
planfftw_inv=fftwf_plan_r2r_1d(fftsize,tmpfftdata2,tmpfftdata2,FFTW_HC2R,FFTW_ESTIMATE);
|
||||
#endif
|
||||
};
|
||||
|
||||
FFTwrapper::~FFTwrapper(){
|
||||
FFTwrapper::~FFTwrapper()
|
||||
{
|
||||
#ifdef FFTW_VERSION_2
|
||||
rfftwf_destroy_plan(planfftw);
|
||||
rfftwf_destroy_plan(planfftwf_inv);
|
||||
#else
|
||||
rfftw_destroy_plan(planfftw);
|
||||
rfftw_destroy_plan(planfftw_inv);
|
||||
#else
|
||||
fftwf_destroy_plan(planfftw);
|
||||
fftwf_destroy_plan(planfftw_inv);
|
||||
#endif
|
||||
@@ -52,20 +54,21 @@ FFTwrapper::~FFTwrapper(){
|
||||
/*
|
||||
* do the Fast Fourier Transform
|
||||
*/
|
||||
void FFTwrapper::smps2freqs(REALTYPE *smps,FFTFREQS freqs){
|
||||
void FFTwrapper::smps2freqs(REALTYPE *smps,FFTFREQS freqs)
|
||||
{
|
||||
#ifdef FFTW_VERSION_2
|
||||
for (int i=0;i<fftsize;i++) tmpfftdata1[i]=smps[i];
|
||||
rfftwf_one(planfftw,tmpfftdata1,tmpfftdata2);
|
||||
rfftw_one(planfftw,tmpfftdata1,tmpfftdata2);
|
||||
for (int i=0;i<fftsize/2;i++) {
|
||||
freqs.c[i]=tmpfftdata2[i];
|
||||
if (i!=0) freqs.s[i]=tmpfftdata2[fftsize-i];
|
||||
freqs.c[i]=tmpfftdata2[i];
|
||||
if (i!=0) freqs.s[i]=tmpfftdata2[fftsize-i];
|
||||
};
|
||||
#else
|
||||
for (int i=0;i<fftsize;i++) tmpfftdata1[i]=smps[i];
|
||||
fftwf_execute(planfftw);
|
||||
for (int i=0;i<fftsize/2;i++) {
|
||||
freqs.c[i]=tmpfftdata1[i];
|
||||
if (i!=0) freqs.s[i]=tmpfftdata1[fftsize-i];
|
||||
freqs.c[i]=tmpfftdata1[i];
|
||||
if (i!=0) freqs.s[i]=tmpfftdata1[fftsize-i];
|
||||
};
|
||||
#endif
|
||||
tmpfftdata2[fftsize/2]=0.0;
|
||||
@@ -74,19 +77,20 @@ void FFTwrapper::smps2freqs(REALTYPE *smps,FFTFREQS freqs){
|
||||
/*
|
||||
* do the Inverse Fast Fourier Transform
|
||||
*/
|
||||
void FFTwrapper::freqs2smps(FFTFREQS freqs,REALTYPE *smps){
|
||||
void FFTwrapper::freqs2smps(FFTFREQS freqs,REALTYPE *smps)
|
||||
{
|
||||
tmpfftdata2[fftsize/2]=0.0;
|
||||
#ifdef FFTW_VERSION_2
|
||||
for (int i=0;i<fftsize/2;i++) {
|
||||
tmpfftdata1[i]=freqs.c[i];
|
||||
if (i!=0) tmpfftdata1[fftsize-i]=freqs.s[i];
|
||||
tmpfftdata1[i]=freqs.c[i];
|
||||
if (i!=0) tmpfftdata1[fftsize-i]=freqs.s[i];
|
||||
};
|
||||
rfftwf_one(planfftwf_inv,tmpfftdata1,tmpfftdata2);
|
||||
rfftw_one(planfftw_inv,tmpfftdata1,tmpfftdata2);
|
||||
for (int i=0;i<fftsize;i++) smps[i]=tmpfftdata2[i];
|
||||
#else
|
||||
for (int i=0;i<fftsize/2;i++) {
|
||||
tmpfftdata2[i]=freqs.c[i];
|
||||
if (i!=0) tmpfftdata2[fftsize-i]=freqs.s[i];
|
||||
tmpfftdata2[i]=freqs.c[i];
|
||||
if (i!=0) tmpfftdata2[fftsize-i]=freqs.s[i];
|
||||
};
|
||||
fftwf_execute(planfftw_inv);
|
||||
for (int i=0;i<fftsize;i++) smps[i]=tmpfftdata2[i];
|
||||
@@ -94,6 +98,3 @@ void FFTwrapper::freqs2smps(FFTFREQS freqs,REALTYPE *smps){
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
FFTwrapper.h - A wrapper for Fast Fourier Transforms
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -25,20 +25,43 @@
|
||||
|
||||
#include "../globals.h"
|
||||
|
||||
#ifdef FFTW_VERSION_2
|
||||
|
||||
#include <fftw.h>
|
||||
|
||||
/* If you got error messages about rfftw.h, replace the next include line with "#include <srfftw.h>"
|
||||
or with "#include <drfftw.h> (if one doesn't work try the other). It may be necessary to replace
|
||||
the <fftw.h> with <dfftw.h> or <sfftw.h>. If the neither one doesn't work,
|
||||
please install latest version of fftw(recomanded from the sources) from www.fftw.org.
|
||||
If you'll install fftw3 you need to change the Makefile.inc
|
||||
Hope all goes right." */
|
||||
#include <rfftw.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <fftw3.h>
|
||||
#define fftw_real float
|
||||
#define rfftw_plan fftwf_plan
|
||||
#endif
|
||||
|
||||
class FFTwrapper{
|
||||
public:
|
||||
FFTwrapper(int fftsize_);
|
||||
~FFTwrapper();
|
||||
void smps2freqs(REALTYPE *smps,FFTFREQS freqs);
|
||||
void freqs2smps(FFTFREQS freqs,REALTYPE *smps);
|
||||
private:
|
||||
int fftsize;
|
||||
fftw_real *tmpfftdata1,*tmpfftdata2;
|
||||
rfftw_plan planfftw,planfftw_inv;
|
||||
/**A wrapper for the FFTW library (Fast Fourier Transforms)*/
|
||||
class FFTwrapper
|
||||
{
|
||||
public:
|
||||
/**Constructor
|
||||
* @param fftsize The size of samples to be fed to fftw*/
|
||||
FFTwrapper(int fftsize_);
|
||||
/**Destructor*/
|
||||
~FFTwrapper();
|
||||
/**Convert Samples to Frequencies using Fourier Transform
|
||||
* @param smps Pointer to Samples to be converted; has length fftsize_
|
||||
* @param freqs Structure FFTFREQS which stores the frequencies*/
|
||||
void smps2freqs(REALTYPE *smps,FFTFREQS freqs);
|
||||
void freqs2smps(FFTFREQS freqs,REALTYPE *smps);
|
||||
private:
|
||||
int fftsize;
|
||||
fftw_real *tmpfftdata1,*tmpfftdata2;
|
||||
rfftw_plan planfftw,planfftw_inv;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Filter.C - Filters, uses analog,formant,etc. filters
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -25,48 +25,58 @@
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
Filter::Filter(FilterParams *pars){
|
||||
Filter::Filter(FilterParams *pars)
|
||||
{
|
||||
unsigned char Ftype=pars->Ptype;
|
||||
unsigned char Fstages=pars->Pstages;
|
||||
|
||||
|
||||
category=pars->Pcategory;
|
||||
|
||||
|
||||
switch (category) {
|
||||
case 1:filter=new FormantFilter(pars);
|
||||
break;
|
||||
case 2:filter=new SVFilter(Ftype,1000.0,pars->getq(),Fstages);
|
||||
filter->outgain=dB2rap(pars->getgain());
|
||||
if (filter->outgain>1.0) filter->outgain=sqrt(filter->outgain);
|
||||
break;
|
||||
default:filter=new AnalogFilter(Ftype,1000.0,pars->getq(),Fstages);
|
||||
if ((Ftype>=6)&&(Ftype<=8)) filter->setgain(pars->getgain());
|
||||
else filter->outgain=dB2rap(pars->getgain());
|
||||
break;
|
||||
case 1:
|
||||
filter=new FormantFilter(pars);
|
||||
break;
|
||||
case 2:
|
||||
filter=new SVFilter(Ftype,1000.0,pars->getq(),Fstages);
|
||||
filter->outgain=dB2rap(pars->getgain());
|
||||
if (filter->outgain>1.0) filter->outgain=sqrt(filter->outgain);
|
||||
break;
|
||||
default:
|
||||
filter=new AnalogFilter(Ftype,1000.0,pars->getq(),Fstages);
|
||||
if ((Ftype>=6)&&(Ftype<=8)) filter->setgain(pars->getgain());
|
||||
else filter->outgain=dB2rap(pars->getgain());
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
Filter::~Filter(){
|
||||
Filter::~Filter()
|
||||
{
|
||||
delete (filter);
|
||||
};
|
||||
|
||||
void Filter::filterout(REALTYPE *smp){
|
||||
void Filter::filterout(REALTYPE *smp)
|
||||
{
|
||||
filter->filterout(smp);
|
||||
};
|
||||
|
||||
void Filter::setfreq(REALTYPE frequency){
|
||||
void Filter::setfreq(REALTYPE frequency)
|
||||
{
|
||||
filter->setfreq(frequency);
|
||||
};
|
||||
|
||||
void Filter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){
|
||||
void Filter::setfreq_and_q(REALTYPE frequency,REALTYPE q_)
|
||||
{
|
||||
filter->setfreq_and_q(frequency,q_);
|
||||
};
|
||||
|
||||
void Filter::setq(REALTYPE q_){
|
||||
void Filter::setq(REALTYPE q_)
|
||||
{
|
||||
filter->setq(q_);
|
||||
};
|
||||
|
||||
REALTYPE Filter::getrealfreq(REALTYPE freqpitch){
|
||||
REALTYPE Filter::getrealfreq(REALTYPE freqpitch)
|
||||
{
|
||||
if ((category==0)||(category==2)) return(pow(2.0,freqpitch+9.96578428));//log2(1000)=9.95748
|
||||
else return(freqpitch);
|
||||
else return(freqpitch);
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Filter.h - Filters, uses analog,formant,etc. filters
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -31,17 +31,18 @@
|
||||
#include "SVFilter.h"
|
||||
#include "../Params/FilterParams.h"
|
||||
|
||||
class Filter{
|
||||
public:
|
||||
class Filter
|
||||
{
|
||||
public:
|
||||
Filter(FilterParams *pars);
|
||||
~Filter();
|
||||
~Filter();
|
||||
void filterout(REALTYPE *smp);
|
||||
void setfreq(REALTYPE frequency);
|
||||
void setfreq_and_q(REALTYPE frequency,REALTYPE q_);
|
||||
void setq(REALTYPE q_);
|
||||
|
||||
REALTYPE getrealfreq(REALTYPE freqpitch);
|
||||
private:
|
||||
private:
|
||||
Filter_ *filter;
|
||||
unsigned char category;
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Filter_.h - This class is inherited by filter classes
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -25,16 +25,17 @@
|
||||
|
||||
#include "../globals.h"
|
||||
|
||||
class Filter_{
|
||||
public:
|
||||
virtual ~Filter_(){};
|
||||
virtual void filterout(REALTYPE *smp){};
|
||||
virtual void setfreq(REALTYPE frequency){};
|
||||
virtual void setfreq_and_q(REALTYPE frequency,REALTYPE q_){};
|
||||
virtual void setq(REALTYPE q_){};
|
||||
virtual void setgain(REALTYPE dBgain){};
|
||||
class Filter_
|
||||
{
|
||||
public:
|
||||
virtual ~Filter_() {};
|
||||
virtual void filterout(REALTYPE *smp)=0;
|
||||
virtual void setfreq(REALTYPE frequency)=0;
|
||||
virtual void setfreq_and_q(REALTYPE frequency,REALTYPE q_)=0;
|
||||
virtual void setq(REALTYPE q_)=0;
|
||||
virtual void setgain(REALTYPE dBgain) {};
|
||||
REALTYPE outgain;
|
||||
private:
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
FormantFilter.C - formant filters
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <math.h>
|
||||
#include <stdio.h>
|
||||
#include "FormantFilter.h"
|
||||
|
||||
FormantFilter::FormantFilter(FilterParams *pars){
|
||||
numformants=pars->Pnumformants;
|
||||
for (int i=0;i<numformants;i++) formant[i]=new AnalogFilter(4/*BPF*/,1000.0,10.0,pars->Pstages);
|
||||
cleanup();
|
||||
inbuffer=new REALTYPE [SOUND_BUFFER_SIZE];
|
||||
tmpbuf=new REALTYPE [SOUND_BUFFER_SIZE];
|
||||
|
||||
for (int j=0;j<FF_MAX_VOWELS;j++)
|
||||
for (int i=0;i<numformants;i++){
|
||||
formantpar[j][i].freq=pars->getformantfreq(pars->Pvowels[j].formants[i].freq);
|
||||
formantpar[j][i].amp=pars->getformantamp(pars->Pvowels[j].formants[i].amp);
|
||||
formantpar[j][i].q=pars->getformantq(pars->Pvowels[j].formants[i].q);
|
||||
};
|
||||
for (int i=0;i<FF_MAX_FORMANTS;i++) oldformantamp[i]=1.0;
|
||||
for (int i=0;i<numformants;i++){
|
||||
currentformants[i].freq=1000.0;
|
||||
currentformants[i].amp=1.0;
|
||||
currentformants[i].q=2.0;
|
||||
};
|
||||
|
||||
formantslowness=pow(1.0-(pars->Pformantslowness/128.0),3.0);
|
||||
|
||||
sequencesize=pars->Psequencesize;if (sequencesize==0) sequencesize=1;
|
||||
for (int k=0;k<sequencesize;k++) sequence[k].nvowel=pars->Psequence[k].nvowel;
|
||||
|
||||
vowelclearness=pow(10.0,(pars->Pvowelclearness-32.0)/48.0);
|
||||
|
||||
sequencestretch=pow(0.1,(pars->Psequencestretch-32.0)/48.0);
|
||||
if (pars->Psequencereversed) sequencestretch*= -1.0;
|
||||
|
||||
outgain=dB2rap(pars->getgain());
|
||||
|
||||
oldinput=-1.0;
|
||||
Qfactor=1.0;oldQfactor=Qfactor;
|
||||
firsttime=1;
|
||||
};
|
||||
|
||||
FormantFilter::~FormantFilter(){
|
||||
for (int i=0;i<numformants;i++) delete(formant[i]);
|
||||
delete (inbuffer);
|
||||
delete (tmpbuf);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void FormantFilter::cleanup(){
|
||||
for (int i=0;i<numformants;i++) formant[i]->cleanup();
|
||||
};
|
||||
|
||||
void FormantFilter::setpos(REALTYPE input){
|
||||
int p1,p2;
|
||||
|
||||
if (firsttime!=0) slowinput=input;
|
||||
else slowinput=slowinput*(1.0-formantslowness)+input*formantslowness;
|
||||
|
||||
if ((fabs(oldinput-input)<0.001)&&(fabs(slowinput-input)<0.001)&&
|
||||
(fabs(Qfactor-oldQfactor)<0.001)) {
|
||||
// oldinput=input; daca setez asta, o sa faca probleme la schimbari foarte lente
|
||||
firsttime=0;
|
||||
return;
|
||||
} else oldinput=input;
|
||||
|
||||
|
||||
REALTYPE pos=fmod(input*sequencestretch,1.0);if (pos<0.0) pos+=1.0;
|
||||
|
||||
F2I(pos*sequencesize,p2);
|
||||
p1=p2-1;if (p1<0) p1+=sequencesize;
|
||||
|
||||
pos=fmod(pos*sequencesize,1.0);
|
||||
if (pos<0.0) pos=0.0; else if (pos>1.0) pos=1.0;
|
||||
pos=(atan((pos*2.0-1.0)*vowelclearness)/atan(vowelclearness)+1.0)*0.5;
|
||||
|
||||
p1=sequence[p1].nvowel;
|
||||
p2=sequence[p2].nvowel;
|
||||
|
||||
if (firsttime!=0) {
|
||||
for (int i=0;i<numformants;i++){
|
||||
currentformants[i].freq=formantpar[p1][i].freq*(1.0-pos)+formantpar[p2][i].freq*pos;
|
||||
currentformants[i].amp=formantpar[p1][i].amp*(1.0-pos)+formantpar[p2][i].amp*pos;
|
||||
currentformants[i].q=formantpar[p1][i].q*(1.0-pos)+formantpar[p2][i].q*pos;
|
||||
formant[i]->setfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor);
|
||||
oldformantamp[i]=currentformants[i].amp;
|
||||
};
|
||||
firsttime=0;
|
||||
} else {
|
||||
for (int i=0;i<numformants;i++){
|
||||
currentformants[i].freq=currentformants[i].freq*(1.0-formantslowness)
|
||||
+(formantpar[p1][i].freq*(1.0-pos)+formantpar[p2][i].freq*pos)*formantslowness;
|
||||
|
||||
currentformants[i].amp=currentformants[i].amp*(1.0-formantslowness)
|
||||
+(formantpar[p1][i].amp*(1.0-pos)+formantpar[p2][i].amp*pos)*formantslowness;
|
||||
|
||||
currentformants[i].q=currentformants[i].q*(1.0-formantslowness)
|
||||
+(formantpar[p1][i].q*(1.0-pos)+formantpar[p2][i].q*pos)*formantslowness;
|
||||
|
||||
formant[i]->setfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor);
|
||||
};
|
||||
};
|
||||
|
||||
oldQfactor=Qfactor;
|
||||
};
|
||||
|
||||
void FormantFilter::setfreq(REALTYPE frequency){
|
||||
setpos(frequency);
|
||||
};
|
||||
|
||||
void FormantFilter::setq(REALTYPE q_){
|
||||
Qfactor=q_;
|
||||
for (int i=0;i<numformants;i++) formant[i]->setq(Qfactor*currentformants[i].q);
|
||||
};
|
||||
|
||||
void FormantFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){
|
||||
Qfactor=q_;
|
||||
setpos(frequency);
|
||||
};
|
||||
|
||||
|
||||
void FormantFilter::filterout(REALTYPE *smp){
|
||||
int i,j;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
inbuffer[i]=smp[i];
|
||||
smp[i]=0.0;
|
||||
};
|
||||
|
||||
for (j=0;j<numformants;j++) {
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpbuf[i]=inbuffer[i]*outgain;
|
||||
formant[j]->filterout(tmpbuf);
|
||||
|
||||
if (ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j],currentformants[j].amp))
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]+=tmpbuf[i]*
|
||||
INTERPOLATE_AMPLITUDE(oldformantamp[j],currentformants[j].amp,i,SOUND_BUFFER_SIZE);
|
||||
else for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]+=tmpbuf[i]*currentformants[j].amp;
|
||||
oldformantamp[j]=currentformants[j].amp;
|
||||
};
|
||||
};
|
||||
|
||||
176
plugins/zynaddsubfx/src/DSP/FormantFilter.cpp
Normal file
176
plugins/zynaddsubfx/src/DSP/FormantFilter.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
FormantFilter.C - formant filters
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <math.h>
|
||||
#include <stdio.h>
|
||||
#include "FormantFilter.h"
|
||||
|
||||
FormantFilter::FormantFilter(FilterParams *pars)
|
||||
{
|
||||
numformants=pars->Pnumformants;
|
||||
for (int i=0;i<numformants;i++) formant[i]=new AnalogFilter(4/*BPF*/,1000.0,10.0,pars->Pstages);
|
||||
cleanup();
|
||||
inbuffer=new REALTYPE [SOUND_BUFFER_SIZE];
|
||||
tmpbuf=new REALTYPE [SOUND_BUFFER_SIZE];
|
||||
|
||||
for (int j=0;j<FF_MAX_VOWELS;j++)
|
||||
for (int i=0;i<numformants;i++) {
|
||||
formantpar[j][i].freq=pars->getformantfreq(pars->Pvowels[j].formants[i].freq);
|
||||
formantpar[j][i].amp=pars->getformantamp(pars->Pvowels[j].formants[i].amp);
|
||||
formantpar[j][i].q=pars->getformantq(pars->Pvowels[j].formants[i].q);
|
||||
};
|
||||
for (int i=0;i<FF_MAX_FORMANTS;i++) oldformantamp[i]=1.0;
|
||||
for (int i=0;i<numformants;i++) {
|
||||
currentformants[i].freq=1000.0;
|
||||
currentformants[i].amp=1.0;
|
||||
currentformants[i].q=2.0;
|
||||
};
|
||||
|
||||
formantslowness=pow(1.0-(pars->Pformantslowness/128.0),3.0);
|
||||
|
||||
sequencesize=pars->Psequencesize;
|
||||
if (sequencesize==0) sequencesize=1;
|
||||
for (int k=0;k<sequencesize;k++) sequence[k].nvowel=pars->Psequence[k].nvowel;
|
||||
|
||||
vowelclearness=pow(10.0,(pars->Pvowelclearness-32.0)/48.0);
|
||||
|
||||
sequencestretch=pow(0.1,(pars->Psequencestretch-32.0)/48.0);
|
||||
if (pars->Psequencereversed) sequencestretch*= -1.0;
|
||||
|
||||
outgain=dB2rap(pars->getgain());
|
||||
|
||||
oldinput=-1.0;
|
||||
Qfactor=1.0;
|
||||
oldQfactor=Qfactor;
|
||||
firsttime=1;
|
||||
};
|
||||
|
||||
FormantFilter::~FormantFilter()
|
||||
{
|
||||
for (int i=0;i<numformants;i++) delete(formant[i]);
|
||||
delete[] inbuffer;
|
||||
delete[] tmpbuf;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void FormantFilter::cleanup()
|
||||
{
|
||||
for (int i=0;i<numformants;i++) formant[i]->cleanup();
|
||||
};
|
||||
|
||||
void FormantFilter::setpos(REALTYPE input)
|
||||
{
|
||||
int p1,p2;
|
||||
|
||||
if (firsttime!=0) slowinput=input;
|
||||
else slowinput=slowinput*(1.0-formantslowness)+input*formantslowness;
|
||||
|
||||
if ((fabs(oldinput-input)<0.001)&&(fabs(slowinput-input)<0.001)&&
|
||||
(fabs(Qfactor-oldQfactor)<0.001)) {
|
||||
// oldinput=input; daca setez asta, o sa faca probleme la schimbari foarte lente
|
||||
firsttime=0;
|
||||
return;
|
||||
} else oldinput=input;
|
||||
|
||||
|
||||
REALTYPE pos=fmod(input*sequencestretch,1.0);
|
||||
if (pos<0.0) pos+=1.0;
|
||||
|
||||
F2I(pos*sequencesize,p2);
|
||||
p1=p2-1;
|
||||
if (p1<0) p1+=sequencesize;
|
||||
|
||||
pos=fmod(pos*sequencesize,1.0);
|
||||
if (pos<0.0) pos=0.0;
|
||||
else if (pos>1.0) pos=1.0;
|
||||
pos=(atan((pos*2.0-1.0)*vowelclearness)/atan(vowelclearness)+1.0)*0.5;
|
||||
|
||||
p1=sequence[p1].nvowel;
|
||||
p2=sequence[p2].nvowel;
|
||||
|
||||
if (firsttime!=0) {
|
||||
for (int i=0;i<numformants;i++) {
|
||||
currentformants[i].freq=formantpar[p1][i].freq*(1.0-pos)+formantpar[p2][i].freq*pos;
|
||||
currentformants[i].amp=formantpar[p1][i].amp*(1.0-pos)+formantpar[p2][i].amp*pos;
|
||||
currentformants[i].q=formantpar[p1][i].q*(1.0-pos)+formantpar[p2][i].q*pos;
|
||||
formant[i]->setfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor);
|
||||
oldformantamp[i]=currentformants[i].amp;
|
||||
};
|
||||
firsttime=0;
|
||||
} else {
|
||||
for (int i=0;i<numformants;i++) {
|
||||
currentformants[i].freq=currentformants[i].freq*(1.0-formantslowness)
|
||||
+(formantpar[p1][i].freq*(1.0-pos)+formantpar[p2][i].freq*pos)*formantslowness;
|
||||
|
||||
currentformants[i].amp=currentformants[i].amp*(1.0-formantslowness)
|
||||
+(formantpar[p1][i].amp*(1.0-pos)+formantpar[p2][i].amp*pos)*formantslowness;
|
||||
|
||||
currentformants[i].q=currentformants[i].q*(1.0-formantslowness)
|
||||
+(formantpar[p1][i].q*(1.0-pos)+formantpar[p2][i].q*pos)*formantslowness;
|
||||
|
||||
formant[i]->setfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor);
|
||||
};
|
||||
};
|
||||
|
||||
oldQfactor=Qfactor;
|
||||
};
|
||||
|
||||
void FormantFilter::setfreq(REALTYPE frequency)
|
||||
{
|
||||
setpos(frequency);
|
||||
};
|
||||
|
||||
void FormantFilter::setq(REALTYPE q_)
|
||||
{
|
||||
Qfactor=q_;
|
||||
for (int i=0;i<numformants;i++) formant[i]->setq(Qfactor*currentformants[i].q);
|
||||
};
|
||||
|
||||
void FormantFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_)
|
||||
{
|
||||
Qfactor=q_;
|
||||
setpos(frequency);
|
||||
};
|
||||
|
||||
|
||||
void FormantFilter::filterout(REALTYPE *smp)
|
||||
{
|
||||
int i,j;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
inbuffer[i]=smp[i];
|
||||
smp[i]=0.0;
|
||||
};
|
||||
|
||||
for (j=0;j<numformants;j++) {
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpbuf[i]=inbuffer[i]*outgain;
|
||||
formant[j]->filterout(tmpbuf);
|
||||
|
||||
if (ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j],currentformants[j].amp))
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]+=tmpbuf[i]*
|
||||
INTERPOLATE_AMPLITUDE(oldformantamp[j],currentformants[j].amp,i,SOUND_BUFFER_SIZE);
|
||||
else for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]+=tmpbuf[i]*currentformants[j].amp;
|
||||
oldformantamp[j]=currentformants[j].amp;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
FormantFilter.h - formant filter
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -29,37 +29,38 @@
|
||||
#include "../Params/FilterParams.h"
|
||||
|
||||
|
||||
class FormantFilter:public Filter_{
|
||||
public:
|
||||
class FormantFilter:public Filter_
|
||||
{
|
||||
public:
|
||||
FormantFilter(FilterParams *pars);
|
||||
~FormantFilter();
|
||||
~FormantFilter();
|
||||
void filterout(REALTYPE *smp);
|
||||
void setfreq(REALTYPE frequency);
|
||||
void setfreq_and_q(REALTYPE frequency,REALTYPE q_);
|
||||
void setq(REALTYPE q_);
|
||||
|
||||
void cleanup();
|
||||
private:
|
||||
private:
|
||||
AnalogFilter *formant[FF_MAX_FORMANTS];
|
||||
REALTYPE *inbuffer,*tmpbuf;
|
||||
|
||||
struct {
|
||||
REALTYPE freq,amp,q;//frequency,amplitude,Q
|
||||
REALTYPE freq,amp,q;//frequency,amplitude,Q
|
||||
} formantpar[FF_MAX_VOWELS][FF_MAX_FORMANTS],currentformants[FF_MAX_FORMANTS];
|
||||
|
||||
struct {
|
||||
unsigned char nvowel;
|
||||
unsigned char nvowel;
|
||||
} sequence [FF_MAX_SEQUENCE];
|
||||
|
||||
|
||||
REALTYPE oldformantamp[FF_MAX_FORMANTS];
|
||||
|
||||
|
||||
int sequencesize,numformants,firsttime;
|
||||
REALTYPE oldinput,slowinput;
|
||||
REALTYPE Qfactor,formantslowness,oldQfactor;
|
||||
REALTYPE vowelclearness,sequencestretch;
|
||||
|
||||
|
||||
void setpos(REALTYPE input);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
SVFilter.C - Several state-variable filters
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -24,7 +24,8 @@
|
||||
#include <stdio.h>
|
||||
#include "SVFilter.h"
|
||||
|
||||
SVFilter::SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages){
|
||||
SVFilter::SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages)
|
||||
{
|
||||
stages=Fstages;
|
||||
type=Ftype;
|
||||
freq=Ffreq;
|
||||
@@ -38,19 +39,24 @@ SVFilter::SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char
|
||||
setfreq_and_q(Ffreq,Fq);
|
||||
};
|
||||
|
||||
SVFilter::~SVFilter(){
|
||||
SVFilter::~SVFilter()
|
||||
{
|
||||
};
|
||||
|
||||
void SVFilter::cleanup(){
|
||||
for (int i=0;i<MAX_FILTER_STAGES+1;i++){
|
||||
st[i].low=0.0;st[i].high=0.0;
|
||||
st[i].band=0.0;st[i].notch=0.0;
|
||||
void SVFilter::cleanup()
|
||||
{
|
||||
for (int i=0;i<MAX_FILTER_STAGES+1;i++) {
|
||||
st[i].low=0.0;
|
||||
st[i].high=0.0;
|
||||
st[i].band=0.0;
|
||||
st[i].notch=0.0;
|
||||
};
|
||||
oldabovenq=0;
|
||||
abovenq=0;
|
||||
};
|
||||
|
||||
void SVFilter::computefiltercoefs(){
|
||||
void SVFilter::computefiltercoefs()
|
||||
{
|
||||
par.f=freq / SAMPLE_RATE*4.0;
|
||||
if (par.f>0.99999) par.f=0.99999;
|
||||
par.q=1.0-atan(sqrt(q))*2.0/PI;
|
||||
@@ -59,18 +65,21 @@ void SVFilter::computefiltercoefs(){
|
||||
};
|
||||
|
||||
|
||||
void SVFilter::setfreq(REALTYPE frequency){
|
||||
void SVFilter::setfreq(REALTYPE frequency)
|
||||
{
|
||||
if (frequency<0.1) frequency=0.1;
|
||||
REALTYPE rap=freq/frequency;if (rap<1.0) rap=1.0/rap;
|
||||
|
||||
oldabovenq=abovenq;abovenq=frequency>(SAMPLE_RATE/2-500.0);
|
||||
|
||||
REALTYPE rap=freq/frequency;
|
||||
if (rap<1.0) rap=1.0/rap;
|
||||
|
||||
oldabovenq=abovenq;
|
||||
abovenq=frequency>(SAMPLE_RATE/2-500.0);
|
||||
|
||||
int nyquistthresh=(abovenq^oldabovenq);
|
||||
|
||||
|
||||
if ((rap>3.0)||(nyquistthresh!=0)){//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup)
|
||||
if (firsttime==0) needsinterpolation=1;
|
||||
ipar=par;
|
||||
if ((rap>3.0)||(nyquistthresh!=0)) {//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup)
|
||||
if (firsttime==0) needsinterpolation=1;
|
||||
ipar=par;
|
||||
};
|
||||
freq=frequency;
|
||||
computefiltercoefs();
|
||||
@@ -78,72 +87,87 @@ void SVFilter::setfreq(REALTYPE frequency){
|
||||
|
||||
};
|
||||
|
||||
void SVFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){
|
||||
void SVFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_)
|
||||
{
|
||||
q=q_;
|
||||
setfreq(frequency);
|
||||
};
|
||||
|
||||
void SVFilter::setq(REALTYPE q_){
|
||||
void SVFilter::setq(REALTYPE q_)
|
||||
{
|
||||
q=q_;
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void SVFilter::settype(int type_){
|
||||
void SVFilter::settype(int type_)
|
||||
{
|
||||
type=type_;
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void SVFilter::setgain(REALTYPE dBgain){
|
||||
void SVFilter::setgain(REALTYPE dBgain)
|
||||
{
|
||||
gain=dB2rap(dBgain);
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void SVFilter::setstages(int stages_){
|
||||
void SVFilter::setstages(int stages_)
|
||||
{
|
||||
if (stages_>=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1;
|
||||
stages=stages_;
|
||||
cleanup();
|
||||
computefiltercoefs();
|
||||
};
|
||||
|
||||
void SVFilter::singlefilterout(REALTYPE *smp,fstage &x,parameters &par){
|
||||
void SVFilter::singlefilterout(REALTYPE *smp,fstage &x,parameters &par)
|
||||
{
|
||||
int i;
|
||||
REALTYPE *out=NULL;
|
||||
switch(type){
|
||||
case 0: out=&x.low;break;
|
||||
case 1: out=&x.high;break;
|
||||
case 2: out=&x.band;break;
|
||||
case 3: out=&x.notch;break;
|
||||
switch (type) {
|
||||
case 0:
|
||||
out=&x.low;
|
||||
break;
|
||||
case 1:
|
||||
out=&x.high;
|
||||
break;
|
||||
case 2:
|
||||
out=&x.band;
|
||||
break;
|
||||
case 3:
|
||||
out=&x.notch;
|
||||
break;
|
||||
};
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
x.low = x.low + par.f * x.band;
|
||||
x.high = par.q_sqrt * smp[i] - x.low - par.q*x.band;
|
||||
x.band = par.f * x.high + x.band;
|
||||
x.notch = x.high + x.low;
|
||||
|
||||
smp[i]= *out;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
x.low = x.low + par.f * x.band;
|
||||
x.high = par.q_sqrt * smp[i] - x.low - par.q*x.band;
|
||||
x.band = par.f * x.high + x.band;
|
||||
x.notch = x.high + x.low;
|
||||
|
||||
smp[i]= *out;
|
||||
};
|
||||
};
|
||||
|
||||
void SVFilter::filterout(REALTYPE *smp){
|
||||
void SVFilter::filterout(REALTYPE *smp)
|
||||
{
|
||||
int i;
|
||||
REALTYPE *ismp=NULL;
|
||||
|
||||
if (needsinterpolation!=0){
|
||||
ismp=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) ismp[i]=smp[i];
|
||||
for (i=0;i<stages+1;i++) singlefilterout(ismp,st[i],ipar);
|
||||
|
||||
if (needsinterpolation!=0) {
|
||||
ismp=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) ismp[i]=smp[i];
|
||||
for (i=0;i<stages+1;i++) singlefilterout(ismp,st[i],ipar);
|
||||
};
|
||||
|
||||
for (i=0;i<stages+1;i++) singlefilterout(smp,st[i],par);
|
||||
|
||||
if (needsinterpolation!=0){
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE x=i/(REALTYPE) SOUND_BUFFER_SIZE;
|
||||
smp[i]=ismp[i]*(1.0-x)+smp[i]*x;
|
||||
};
|
||||
delete [] ismp;
|
||||
needsinterpolation=0;
|
||||
if (needsinterpolation!=0) {
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE x=i/(REALTYPE) SOUND_BUFFER_SIZE;
|
||||
smp[i]=ismp[i]*(1.0-x)+smp[i]*x;
|
||||
};
|
||||
delete [] ismp;
|
||||
needsinterpolation=0;
|
||||
};
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]*=outgain;
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
SV Filter.h - Several state-variable filters
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -25,10 +25,11 @@
|
||||
|
||||
#include "../globals.h"
|
||||
#include "Filter_.h"
|
||||
class SVFilter:public Filter_{
|
||||
public:
|
||||
class SVFilter:public Filter_
|
||||
{
|
||||
public:
|
||||
SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages);
|
||||
~SVFilter();
|
||||
~SVFilter();
|
||||
void filterout(REALTYPE *smp);
|
||||
void setfreq(REALTYPE frequency);
|
||||
void setfreq_and_q(REALTYPE frequency,REALTYPE q_);
|
||||
@@ -39,13 +40,13 @@ class SVFilter:public Filter_{
|
||||
void setstages(int stages_);
|
||||
void cleanup();
|
||||
|
||||
private:
|
||||
struct fstage{
|
||||
REALTYPE low,high,band,notch;
|
||||
private:
|
||||
struct fstage {
|
||||
REALTYPE low,high,band,notch;
|
||||
} st[MAX_FILTER_STAGES+1];
|
||||
|
||||
struct parameters{
|
||||
REALTYPE f,q,q_sqrt;
|
||||
struct parameters {
|
||||
REALTYPE f,q,q_sqrt;
|
||||
}par,ipar;
|
||||
|
||||
|
||||
@@ -56,7 +57,7 @@ class SVFilter:public Filter_{
|
||||
REALTYPE freq;//Frequency given in Hz
|
||||
REALTYPE q; //Q factor (resonance or Q factor)
|
||||
REALTYPE gain;//the gain of the filter (if are shelf/peak) filters
|
||||
|
||||
|
||||
int abovenq;//this is 1 if the frequency is above the nyquist
|
||||
int oldabovenq;
|
||||
int needsinterpolation,firsttime;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Alienwah.C - "AlienWah" effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "Alienwah.h"
|
||||
|
||||
Alienwah::Alienwah(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0),oldl(NULL),oldr(NULL)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0),oldl(NULL),oldr(NULL)
|
||||
{
|
||||
setpreset(Ppreset);
|
||||
cleanup();
|
||||
@@ -32,7 +32,8 @@ Alienwah::Alienwah(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *cons
|
||||
oldclfor=complex<REALTYPE>(fb,0.0);
|
||||
};
|
||||
|
||||
Alienwah::~Alienwah(){
|
||||
Alienwah::~Alienwah()
|
||||
{
|
||||
if (oldl!=NULL) delete [] oldl;
|
||||
if (oldr!=NULL) delete [] oldr ;
|
||||
};
|
||||
@@ -41,7 +42,8 @@ Alienwah::~Alienwah(){
|
||||
/*
|
||||
* Apply the effect
|
||||
*/
|
||||
void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){
|
||||
void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr)
|
||||
{
|
||||
REALTYPE lfol,lfor; //Left/Right LFOs
|
||||
complex<REALTYPE> clfol,clfor,out,tmp;
|
||||
/**\todo Rework, as optimization can be used when the new complex type is
|
||||
@@ -49,37 +51,37 @@ void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){
|
||||
* Before all calculations needed to be done with individual REALTYPE,
|
||||
* but now they can be done together*/
|
||||
lfo.effectlfoout(&lfol,&lfor);
|
||||
lfol*=depth*PI*2.0;lfor*=depth*PI*2.0;
|
||||
lfol*=depth*PI*2.0;
|
||||
lfor*=depth*PI*2.0;
|
||||
clfol=complex<REALTYPE>(cos(lfol+phase)*fb,sin(lfol+phase)*fb); //rework
|
||||
clfor=complex<REALTYPE>(cos(lfor+phase)*fb,sin(lfor+phase)*fb); //rework
|
||||
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++){/**\todo reduce significantly with
|
||||
* valarray*/
|
||||
REALTYPE x=((REALTYPE) i)/SOUND_BUFFER_SIZE;
|
||||
REALTYPE x1=1.0-x;
|
||||
//left
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE x=((REALTYPE) i)/SOUND_BUFFER_SIZE;
|
||||
REALTYPE x1=1.0-x;
|
||||
//left
|
||||
tmp=clfol*x+oldclfol*x1;
|
||||
|
||||
out=tmp*oldl[oldk];
|
||||
out.real()+=(1-fabs(fb))*smpsr[i]*(1.0-panning);
|
||||
|
||||
|
||||
oldl[oldk]=out;
|
||||
REALTYPE l=out.real()*10.0*(fb+0.1);
|
||||
|
||||
//right
|
||||
REALTYPE l=out.real()*10.0*(fb+0.1);
|
||||
|
||||
//right
|
||||
tmp=clfor*x+oldclfor*x1;
|
||||
|
||||
|
||||
out=tmp*oldr[oldk];
|
||||
out.real()+=(1-fabs(fb))*smpsr[i]*(1.0-panning);
|
||||
|
||||
|
||||
oldr[oldk]=out;
|
||||
REALTYPE r=out.real()*10.0*(fb+0.1);
|
||||
REALTYPE r=out.real()*10.0*(fb+0.1);
|
||||
|
||||
|
||||
if (++oldk>=Pdelay) oldk=0;
|
||||
//LRcross
|
||||
efxoutl[i]=l*(1.0-lrcross)+r*lrcross;
|
||||
efxoutr[i]=r*(1.0-lrcross)+l*lrcross;
|
||||
if (++oldk>=Pdelay) oldk=0;
|
||||
//LRcross
|
||||
efxoutl[i]=l*(1.0-lrcross)+r*lrcross;
|
||||
efxoutr[i]=r*(1.0-lrcross)+l*lrcross;
|
||||
};
|
||||
|
||||
oldclfol=clfol;
|
||||
@@ -90,10 +92,11 @@ void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Alienwah::cleanup(){
|
||||
for (int i=0;i<Pdelay;i++) { /**\todo reduce with valarray*/
|
||||
oldl[i]=complex<REALTYPE>(0.0,0.0);
|
||||
oldr[i]=complex<REALTYPE>(0.0,0.0);
|
||||
void Alienwah::cleanup()
|
||||
{
|
||||
for (int i=0;i<Pdelay;i++) {
|
||||
oldl[i]=complex<REALTYPE>(0.0,0.0);
|
||||
oldr[i]=complex<REALTYPE>(0.0,0.0);
|
||||
};
|
||||
oldk=0;
|
||||
};
|
||||
@@ -103,12 +106,14 @@ void Alienwah::cleanup(){
|
||||
* Parameter control
|
||||
*/
|
||||
|
||||
void Alienwah::setdepth(const unsigned char &Pdepth){
|
||||
void Alienwah::setdepth(const unsigned char &Pdepth)
|
||||
{
|
||||
this->Pdepth=Pdepth;
|
||||
depth=(Pdepth/127.0);
|
||||
};
|
||||
|
||||
void Alienwah::setfb(const unsigned char &Pfb){
|
||||
void Alienwah::setfb(const unsigned char &Pfb)
|
||||
{
|
||||
this->Pfb=Pfb;
|
||||
fb=fabs((Pfb-64.0)/64.1);
|
||||
fb=sqrt(fb);
|
||||
@@ -116,29 +121,34 @@ void Alienwah::setfb(const unsigned char &Pfb){
|
||||
if (Pfb<64) fb=-fb;
|
||||
};
|
||||
|
||||
void Alienwah::setvolume(const unsigned char &Pvolume){
|
||||
void Alienwah::setvolume(const unsigned char &Pvolume)
|
||||
{
|
||||
this->Pvolume=Pvolume;
|
||||
outvolume=Pvolume/127.0;
|
||||
if (insertion==0) volume=1.0;
|
||||
else volume=outvolume;
|
||||
else volume=outvolume;
|
||||
};
|
||||
|
||||
void Alienwah::setpanning(const unsigned char &Ppanning){
|
||||
void Alienwah::setpanning(const unsigned char &Ppanning)
|
||||
{
|
||||
this->Ppanning=Ppanning;
|
||||
panning=Ppanning/127.0;
|
||||
};
|
||||
|
||||
void Alienwah::setlrcross(const unsigned char &Plrcross){
|
||||
void Alienwah::setlrcross(const unsigned char &Plrcross)
|
||||
{
|
||||
this->Plrcross=Plrcross;
|
||||
lrcross=Plrcross/127.0;
|
||||
};
|
||||
|
||||
void Alienwah::setphase(const unsigned char &Pphase){
|
||||
void Alienwah::setphase(const unsigned char &Pphase)
|
||||
{
|
||||
this->Pphase=Pphase;
|
||||
phase=(Pphase-64.0)/64.0*PI;
|
||||
};
|
||||
|
||||
void Alienwah::setdelay(const unsigned char &Pdelay){
|
||||
void Alienwah::setdelay(const unsigned char &Pdelay)
|
||||
{
|
||||
if (oldl!=NULL) delete [] oldl;
|
||||
if (oldr!=NULL) delete [] oldr;
|
||||
if (Pdelay>=MAX_ALIENWAH_DELAY) this->Pdelay=MAX_ALIENWAH_DELAY;
|
||||
@@ -148,19 +158,21 @@ void Alienwah::setdelay(const unsigned char &Pdelay){
|
||||
cleanup();
|
||||
};
|
||||
|
||||
void Alienwah::setpreset(unsigned char npreset){
|
||||
void Alienwah::setpreset(unsigned char npreset)
|
||||
{
|
||||
const int PRESET_SIZE=11;
|
||||
const int NUM_PRESETS=4;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//AlienWah1
|
||||
{127,64,70,0,0,62,60,105,25,0,64},
|
||||
//AlienWah2
|
||||
{127,64,73,106,0,101,60,105,17,0,64},
|
||||
//AlienWah3
|
||||
{127,64,63,0,1,100,112,105,31,0,42},
|
||||
//AlienWah4
|
||||
{93,64,25,0,1,66,101,11,47,0,86}};
|
||||
|
||||
//AlienWah1
|
||||
{127,64,70,0,0,62,60,105,25,0,64},
|
||||
//AlienWah2
|
||||
{127,64,73,106,0,101,60,105,17,0,64},
|
||||
//AlienWah3
|
||||
{127,64,63,0,1,100,112,105,31,0,42},
|
||||
//AlienWah4
|
||||
{93,64,25,0,1,66,101,11,47,0,86}
|
||||
};
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
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
|
||||
@@ -168,63 +180,88 @@ void Alienwah::setpreset(unsigned char npreset){
|
||||
};
|
||||
|
||||
|
||||
void Alienwah::changepar(const int &npar,const unsigned char &value){
|
||||
switch(npar){
|
||||
case 0: setvolume(value);
|
||||
break;
|
||||
case 1: setpanning(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();
|
||||
break;
|
||||
case 5: lfo.Pstereo=value;
|
||||
lfo.updateparams();
|
||||
break;
|
||||
case 6: setdepth(value);
|
||||
break;
|
||||
case 7: setfb(value);
|
||||
break;
|
||||
case 8: setdelay(value);
|
||||
break;
|
||||
case 9: setlrcross(value);
|
||||
break;
|
||||
case 10:setphase(value);
|
||||
break;
|
||||
void Alienwah::changepar(const int &npar,const unsigned char &value)
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
setvolume(value);
|
||||
break;
|
||||
case 1:
|
||||
setpanning(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();
|
||||
break;
|
||||
case 5:
|
||||
lfo.Pstereo=value;
|
||||
lfo.updateparams();
|
||||
break;
|
||||
case 6:
|
||||
setdepth(value);
|
||||
break;
|
||||
case 7:
|
||||
setfb(value);
|
||||
break;
|
||||
case 8:
|
||||
setdelay(value);
|
||||
break;
|
||||
case 9:
|
||||
setlrcross(value);
|
||||
break;
|
||||
case 10:
|
||||
setphase(value);
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char Alienwah::getpar(const int &npar)const{
|
||||
switch (npar){
|
||||
case 0: return(Pvolume);
|
||||
break;
|
||||
case 1: return(Ppanning);
|
||||
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(Pdepth);
|
||||
break;
|
||||
case 7: return(Pfb);
|
||||
break;
|
||||
case 8: return(Pdelay);
|
||||
break;
|
||||
case 9: return(Plrcross);
|
||||
break;
|
||||
case 10:return(Pphase);
|
||||
break;
|
||||
default:return (0);
|
||||
unsigned char Alienwah::getpar(const int &npar)const
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
return(Pvolume);
|
||||
break;
|
||||
case 1:
|
||||
return(Ppanning);
|
||||
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(Pdepth);
|
||||
break;
|
||||
case 7:
|
||||
return(Pfb);
|
||||
break;
|
||||
case 8:
|
||||
return(Pdelay);
|
||||
break;
|
||||
case 9:
|
||||
return(Plrcross);
|
||||
break;
|
||||
case 10:
|
||||
return(Pphase);
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Alienwah.h - "AlienWah" effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -32,50 +32,51 @@ using namespace std;
|
||||
#define MAX_ALIENWAH_DELAY 100
|
||||
|
||||
/**"AlienWah" Effect*/
|
||||
class Alienwah:public Effect {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param insetion_ 1 for insertion Effect, 0 for others
|
||||
* @param efxoutl_ Pointer to Alienwah's left channel output buffer
|
||||
* @param efxoutr_ Pointer to Alienwah's left channel output buffer
|
||||
* @return Initialized Alienwah
|
||||
*/
|
||||
Alienwah(const int &insetion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_);
|
||||
~Alienwah();
|
||||
void out(REALTYPE *const smpsl,REALTYPE *const smpsr);
|
||||
class Alienwah:public Effect
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param insetion_ 1 for insertion Effect, 0 for others
|
||||
* @param efxoutl_ Pointer to Alienwah's left channel output buffer
|
||||
* @param efxoutr_ Pointer to Alienwah's left channel output buffer
|
||||
* @return Initialized Alienwah
|
||||
*/
|
||||
Alienwah(const int &insetion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_);
|
||||
~Alienwah();
|
||||
void out(REALTYPE *const smpsl,REALTYPE *const smpsr);
|
||||
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
|
||||
private:
|
||||
//Alienwah Parameters
|
||||
EffectLFO lfo;//lfo-ul Alienwah
|
||||
unsigned char Pvolume;
|
||||
unsigned char Ppanning;
|
||||
unsigned char Pdepth;//the depth of the Alienwah
|
||||
unsigned char Pfb;//feedback
|
||||
unsigned char Plrcross;//feedback
|
||||
unsigned char Pdelay;
|
||||
unsigned char Pphase;
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
|
||||
|
||||
//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);
|
||||
|
||||
//Internal Values
|
||||
REALTYPE panning,fb,depth,lrcross,phase;
|
||||
complex<REALTYPE> *oldl,*oldr;
|
||||
complex<REALTYPE> oldclfol,oldclfor;
|
||||
int oldk;
|
||||
private:
|
||||
//Alienwah Parameters
|
||||
EffectLFO lfo;//lfo-ul Alienwah
|
||||
unsigned char Pvolume;
|
||||
unsigned char Ppanning;
|
||||
unsigned char Pdepth;//the depth of the Alienwah
|
||||
unsigned char Pfb;//feedback
|
||||
unsigned char Plrcross;//feedback
|
||||
unsigned char Pdelay;
|
||||
unsigned char Pphase;
|
||||
|
||||
|
||||
//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);
|
||||
|
||||
//Internal Values
|
||||
REALTYPE panning,fb,depth,lrcross,phase;
|
||||
complex<REALTYPE> *oldl,*oldr;
|
||||
complex<REALTYPE> oldclfol,oldclfor;
|
||||
int oldk;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
19
plugins/zynaddsubfx/src/Effects/CMakeLists.txt
Normal file
19
plugins/zynaddsubfx/src/Effects/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
set(zynaddsubfx_effect_SRCS
|
||||
Alienwah.cpp
|
||||
Chorus.cpp
|
||||
Distorsion.cpp
|
||||
DynamicFilter.cpp
|
||||
Echo.cpp
|
||||
Effect.cpp
|
||||
EffectLFO.cpp
|
||||
EffectMgr.cpp
|
||||
EQ.cpp
|
||||
Phaser.cpp
|
||||
Reverb.cpp
|
||||
)
|
||||
|
||||
add_library(zynaddsubfx_effect STATIC
|
||||
${zynaddsubfx_effect_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries(zynaddsubfx_effect)
|
||||
@@ -1,275 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Chorus.C - Chorus and Flange effects
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Chorus.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Chorus::Chorus(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0)
|
||||
{
|
||||
dlk=0;drk=0;
|
||||
maxdelay=(int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE);
|
||||
delayl=new REALTYPE[maxdelay];
|
||||
delayr=new REALTYPE[maxdelay];
|
||||
|
||||
setpreset(Ppreset);
|
||||
|
||||
lfo.effectlfoout(&lfol,&lfor);
|
||||
dl2=getdelay(lfol);
|
||||
dr2=getdelay(lfor);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
Chorus::~Chorus(){
|
||||
delete [] delayl;
|
||||
delete [] delayr;
|
||||
};
|
||||
|
||||
/*
|
||||
* get the delay value in samples; xlfo is the current lfo value
|
||||
*/
|
||||
REALTYPE Chorus::getdelay(REALTYPE xlfo){
|
||||
REALTYPE result;
|
||||
if (Pflangemode==0){
|
||||
result=(delay+xlfo*depth)*SAMPLE_RATE;
|
||||
} else result=0;
|
||||
|
||||
//check if it is too big delay(caused bu errornous setdelay() and setdepth()
|
||||
/**\todo fix setdelay() and setdepth(), so this error cannot occur*/
|
||||
if ((result+0.5)>=maxdelay) {
|
||||
cerr << "WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n";
|
||||
result=maxdelay-1.0;
|
||||
};
|
||||
return(result);
|
||||
};
|
||||
|
||||
/*
|
||||
* Apply the effect
|
||||
*/
|
||||
void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr){
|
||||
int i;
|
||||
const REALTYPE one=1.0;
|
||||
dl1=dl2;dr1=dr2;
|
||||
lfo.effectlfoout(&lfol,&lfor);
|
||||
|
||||
dl2=getdelay(lfol);
|
||||
dr2=getdelay(lfor);
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
REALTYPE inl=smpsl[i];
|
||||
REALTYPE inr=smpsr[i];
|
||||
//LRcross
|
||||
REALTYPE l=inl;
|
||||
REALTYPE r=inr;
|
||||
inl=l*(1.0-lrcross)+r*lrcross;
|
||||
inr=r*(1.0-lrcross)+l*lrcross;
|
||||
|
||||
//Left channel
|
||||
|
||||
//compute the delay in samples using linear interpolation between the lfo delays
|
||||
mdel=(dl1*(SOUND_BUFFER_SIZE-i)+dl2*i)/SOUND_BUFFER_SIZE;
|
||||
if (++dlk>=maxdelay) dlk=0;
|
||||
REALTYPE tmp=dlk-mdel+maxdelay*2.0;//where should I get the sample from
|
||||
|
||||
F2I(tmp,dlhi);
|
||||
dlhi%=maxdelay;
|
||||
|
||||
dlhi2=(dlhi-1+maxdelay)%maxdelay;
|
||||
dllo=1.0-fmod(tmp,one);
|
||||
efxoutl[i]=delayl[dlhi2]*dllo+delayl[dlhi]*(1.0-dllo);
|
||||
delayl[dlk]=inl+efxoutl[i]*fb;
|
||||
|
||||
//Right channel
|
||||
|
||||
//compute the delay in samples using linear interpolation between the lfo delays
|
||||
mdel=(dr1*(SOUND_BUFFER_SIZE-i)+dr2*i)/SOUND_BUFFER_SIZE;
|
||||
if (++drk>=maxdelay) drk=0;
|
||||
tmp=drk*1.0-mdel+maxdelay*2.0;//where should I get the sample from
|
||||
|
||||
F2I(tmp,dlhi);
|
||||
dlhi%=maxdelay;
|
||||
|
||||
dlhi2=(dlhi-1+maxdelay)%maxdelay;
|
||||
dllo=1.0-fmod(tmp,one);
|
||||
efxoutr[i]=delayr[dlhi2]*dllo+delayr[dlhi]*(1.0-dllo);
|
||||
delayr[dlk]=inr+efxoutr[i]*fb;
|
||||
|
||||
};
|
||||
|
||||
if (Poutsub!=0)
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i] *= -1.0;
|
||||
efxoutr[i] *= -1.0;
|
||||
};
|
||||
|
||||
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i]*=panning;
|
||||
efxoutr[i]*=(1.0-panning);
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Chorus::cleanup(){
|
||||
for (int i=0;i<maxdelay;i++){
|
||||
delayl[i]=0.0;
|
||||
delayr[i]=0.0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Chorus::setdepth(const 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){
|
||||
this->Pdelay=Pdelay;
|
||||
delay=(pow(10.0,(Pdelay/127.0)*2.0)-1.0)/1000.0;//seconds
|
||||
};
|
||||
|
||||
void Chorus::setfb(const unsigned char &Pfb){
|
||||
this->Pfb=Pfb;
|
||||
fb=(Pfb-64.0)/64.1;
|
||||
};
|
||||
void Chorus::setvolume(const unsigned char &Pvolume){
|
||||
this->Pvolume=Pvolume;
|
||||
outvolume=Pvolume/127.0;
|
||||
if (insertion==0) volume=1.0;
|
||||
else volume=outvolume;
|
||||
};
|
||||
|
||||
void Chorus::setpanning(const unsigned char &Ppanning){
|
||||
this->Ppanning=Ppanning;
|
||||
panning=Ppanning/127.0;
|
||||
};
|
||||
|
||||
void Chorus::setlrcross(const unsigned char &Plrcross){
|
||||
this->Plrcross=Plrcross;
|
||||
lrcross=Plrcross/127.0;
|
||||
};
|
||||
|
||||
void Chorus::setpreset(unsigned char npreset){
|
||||
const int PRESET_SIZE=12;
|
||||
const int NUM_PRESETS=10;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//Chorus1
|
||||
{64,64,50,0,0,90,40,85,64,119,0,0},
|
||||
//Chorus2
|
||||
{64,64,45,0,0,98,56,90,64,19,0,0},
|
||||
//Chorus3
|
||||
{64,64,29,0,1,42,97,95,90,127,0,0},
|
||||
//Celeste1
|
||||
{64,64,26,0,0,42,115,18,90,127,0,0},
|
||||
//Celeste2
|
||||
{64,64,29,117,0,50,115,9,31,127,0,1},
|
||||
//Flange1
|
||||
{64,64,57,0,0,60,23,3,62,0,0,0},
|
||||
//Flange2
|
||||
{64,64,33,34,1,40,35,3,109,0,0,0},
|
||||
//Flange3
|
||||
{64,64,53,34,1,94,35,3,54,0,0,1},
|
||||
//Flange4
|
||||
{64,64,40,0,1,62,12,19,97,0,0,0},
|
||||
//Flange5
|
||||
{64,64,55,105,0,24,39,19,17,0,0,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 Chorus::changepar(const int &npar,const unsigned char &value){
|
||||
switch(npar){
|
||||
case 0: setvolume(value);
|
||||
break;
|
||||
case 1: setpanning(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();
|
||||
break;
|
||||
case 5: lfo.Pstereo=value;
|
||||
lfo.updateparams();
|
||||
break;
|
||||
case 6: setdepth(value);
|
||||
break;
|
||||
case 7: setdelay(value);
|
||||
break;
|
||||
case 8: setfb(value);
|
||||
break;
|
||||
case 9: setlrcross(value);
|
||||
break;
|
||||
case 10:if (value>1) Pflangemode=1;
|
||||
else Pflangemode=value;
|
||||
break;
|
||||
case 11:if (value>1) Poutsub=1;
|
||||
else Poutsub=value;
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char Chorus::getpar(const int &npar)const{
|
||||
switch (npar){
|
||||
case 0: return(Pvolume);
|
||||
break;
|
||||
case 1: return(Ppanning);
|
||||
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(Pdepth);
|
||||
break;
|
||||
case 7: return(Pdelay);
|
||||
break;
|
||||
case 8: return(Pfb);
|
||||
break;
|
||||
case 9: return(Plrcross);
|
||||
break;
|
||||
case 10:return(Pflangemode);
|
||||
break;
|
||||
case 11:return(Poutsub);
|
||||
break;
|
||||
default:return (0);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
316
plugins/zynaddsubfx/src/Effects/Chorus.cpp
Normal file
316
plugins/zynaddsubfx/src/Effects/Chorus.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Chorus.C - Chorus and Flange effects
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Chorus.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Chorus::Chorus(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0),
|
||||
maxdelay((int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE)),
|
||||
delaySample(maxdelay)
|
||||
{
|
||||
dlk=0;
|
||||
drk=0;
|
||||
//maxdelay=(int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE);
|
||||
//delayl=new REALTYPE[maxdelay];
|
||||
//delayr=new REALTYPE[maxdelay];
|
||||
|
||||
setpreset(Ppreset);
|
||||
|
||||
lfo.effectlfoout(&lfol,&lfor);
|
||||
dl2=getdelay(lfol);
|
||||
dr2=getdelay(lfor);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
Chorus::~Chorus() {};
|
||||
|
||||
/*
|
||||
* get the delay value in samples; xlfo is the current lfo value
|
||||
*/
|
||||
REALTYPE Chorus::getdelay(REALTYPE xlfo)
|
||||
{
|
||||
REALTYPE result;
|
||||
if (Pflangemode==0) {
|
||||
result=(delay+xlfo*depth)*SAMPLE_RATE;
|
||||
} else result=0;
|
||||
|
||||
//check if it is too big delay(caused bu errornous setdelay() and setdepth()
|
||||
/**\todo fix setdelay() and setdepth(), so this error cannot occur*/
|
||||
if ((result+0.5)>=maxdelay) {
|
||||
cerr << "WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n";
|
||||
result=maxdelay-1.0;
|
||||
};
|
||||
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)
|
||||
{
|
||||
const REALTYPE one=1.0;
|
||||
dl1=dl2;
|
||||
dr1=dr2;
|
||||
lfo.effectlfoout(&lfol,&lfor);
|
||||
|
||||
dl2=getdelay(lfol);
|
||||
dr2=getdelay(lfor);
|
||||
|
||||
for (int i=0;i<input.l().size();i++) {
|
||||
REALTYPE inl=input.l()[i];
|
||||
REALTYPE inr=input.r()[i];
|
||||
//LRcross
|
||||
Stereo<REALTYPE> tmpc(inl,inr);
|
||||
//REALTYPE r=inr;
|
||||
inl=tmpc.l()*(1.0-lrcross)+tmpc.r()*lrcross;
|
||||
inr=tmpc.r()*(1.0-lrcross)+tmpc.l()*lrcross;
|
||||
|
||||
//Left channel
|
||||
|
||||
//compute the delay in samples using linear interpolation between the lfo delays
|
||||
mdel=(dl1*(SOUND_BUFFER_SIZE-i)+dl2*i)/SOUND_BUFFER_SIZE;
|
||||
if (++dlk>=maxdelay) dlk=0;
|
||||
REALTYPE tmp=dlk-mdel+maxdelay*2.0;//where should I get the sample from
|
||||
|
||||
F2I(tmp,dlhi);
|
||||
dlhi%=maxdelay;
|
||||
|
||||
dlhi2=(dlhi-1+maxdelay)%maxdelay;
|
||||
dllo=1.0-fmod(tmp,one);
|
||||
efxoutl[i]=delaySample.l()[dlhi2]*dllo+delaySample.l()[dlhi]*(1.0-dllo);
|
||||
delaySample.l()[dlk]=inl+efxoutl[i]*fb;
|
||||
|
||||
//Right channel
|
||||
|
||||
//compute the delay in samples using linear interpolation between the lfo delays
|
||||
mdel=(dr1*(SOUND_BUFFER_SIZE-i)+dr2*i)/SOUND_BUFFER_SIZE;
|
||||
if (++drk>=maxdelay) drk=0;
|
||||
tmp=drk*1.0-mdel+maxdelay*2.0;//where should I get the sample from
|
||||
|
||||
F2I(tmp,dlhi);
|
||||
dlhi%=maxdelay;
|
||||
|
||||
dlhi2=(dlhi-1+maxdelay)%maxdelay;
|
||||
dllo=1.0-fmod(tmp,one);
|
||||
efxoutr[i]=delaySample.r()[dlhi2]*dllo+delaySample.r()[dlhi]*(1.0-dllo);
|
||||
delaySample.r()[dlk]=inr+efxoutr[i]*fb;
|
||||
|
||||
};
|
||||
|
||||
if (Poutsub!=0)
|
||||
for (int i=0;i<input.l().size();i++) {
|
||||
efxoutl[i] *= -1.0;
|
||||
efxoutr[i] *= -1.0;
|
||||
};
|
||||
|
||||
|
||||
for (int i=0;i<input.l().size();i++) {
|
||||
efxoutl[i]*=panning;
|
||||
efxoutr[i]*=(1.0-panning);
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Chorus::cleanup()
|
||||
{
|
||||
delaySample.l().clear();
|
||||
delaySample.r().clear();
|
||||
};
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Chorus::setdepth(const 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)
|
||||
{
|
||||
this->Pdelay=Pdelay;
|
||||
delay=(pow(10.0,(Pdelay/127.0)*2.0)-1.0)/1000.0;//seconds
|
||||
};
|
||||
|
||||
void Chorus::setfb(const unsigned char &Pfb)
|
||||
{
|
||||
this->Pfb=Pfb;
|
||||
fb=(Pfb-64.0)/64.1;
|
||||
};
|
||||
void Chorus::setvolume(const unsigned char &Pvolume)
|
||||
{
|
||||
this->Pvolume=Pvolume;
|
||||
outvolume=Pvolume/127.0;
|
||||
if (insertion==0) volume=1.0;
|
||||
else volume=outvolume;
|
||||
};
|
||||
|
||||
void Chorus::setpanning(const unsigned char &Ppanning)
|
||||
{
|
||||
this->Ppanning=Ppanning;
|
||||
panning=Ppanning/127.0;
|
||||
};
|
||||
|
||||
void Chorus::setlrcross(const unsigned char &Plrcross)
|
||||
{
|
||||
this->Plrcross=Plrcross;
|
||||
lrcross=Plrcross/127.0;
|
||||
};
|
||||
|
||||
void Chorus::setpreset(unsigned char npreset)
|
||||
{
|
||||
const int PRESET_SIZE=12;
|
||||
const int NUM_PRESETS=10;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//Chorus1
|
||||
{64,64,50,0,0,90,40,85,64,119,0,0},
|
||||
//Chorus2
|
||||
{64,64,45,0,0,98,56,90,64,19,0,0},
|
||||
//Chorus3
|
||||
{64,64,29,0,1,42,97,95,90,127,0,0},
|
||||
//Celeste1
|
||||
{64,64,26,0,0,42,115,18,90,127,0,0},
|
||||
//Celeste2
|
||||
{64,64,29,117,0,50,115,9,31,127,0,1},
|
||||
//Flange1
|
||||
{64,64,57,0,0,60,23,3,62,0,0,0},
|
||||
//Flange2
|
||||
{64,64,33,34,1,40,35,3,109,0,0,0},
|
||||
//Flange3
|
||||
{64,64,53,34,1,94,35,3,54,0,0,1},
|
||||
//Flange4
|
||||
{64,64,40,0,1,62,12,19,97,0,0,0},
|
||||
//Flange5
|
||||
{64,64,55,105,0,24,39,19,17,0,0,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 Chorus::changepar(const int &npar,const unsigned char &value)
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
setvolume(value);
|
||||
break;
|
||||
case 1:
|
||||
setpanning(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();
|
||||
break;
|
||||
case 5:
|
||||
lfo.Pstereo=value;
|
||||
lfo.updateparams();
|
||||
break;
|
||||
case 6:
|
||||
setdepth(value);
|
||||
break;
|
||||
case 7:
|
||||
setdelay(value);
|
||||
break;
|
||||
case 8:
|
||||
setfb(value);
|
||||
break;
|
||||
case 9:
|
||||
setlrcross(value);
|
||||
break;
|
||||
case 10:
|
||||
if (value>1) Pflangemode=1;
|
||||
else Pflangemode=value;
|
||||
break;
|
||||
case 11:
|
||||
if (value>1) Poutsub=1;
|
||||
else Poutsub=value;
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char Chorus::getpar(const int &npar)const
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
return(Pvolume);
|
||||
break;
|
||||
case 1:
|
||||
return(Ppanning);
|
||||
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(Pdepth);
|
||||
break;
|
||||
case 7:
|
||||
return(Pdelay);
|
||||
break;
|
||||
case 8:
|
||||
return(Pfb);
|
||||
break;
|
||||
case 9:
|
||||
return(Plrcross);
|
||||
break;
|
||||
case 10:
|
||||
return(Pflangemode);
|
||||
break;
|
||||
case 11:
|
||||
return(Poutsub);
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Chorus.h - Chorus and Flange effects
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -25,86 +25,91 @@
|
||||
#include "../globals.h"
|
||||
#include "Effect.h"
|
||||
#include "EffectLFO.h"
|
||||
#include "../Samples/AuSample.h"
|
||||
#include "../Misc/Stereo.h"
|
||||
|
||||
#define MAX_CHORUS_DELAY 250.0 //ms
|
||||
|
||||
/**Chorus and Flange effects*/
|
||||
class Chorus:public Effect {
|
||||
public:
|
||||
Chorus(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
/**Destructor*/
|
||||
~Chorus();
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpsr);
|
||||
void setpreset(unsigned char npreset);
|
||||
/**
|
||||
* Sets the value of the chosen variable
|
||||
*
|
||||
* The possible parameters are:
|
||||
* -# Volume
|
||||
* -# Panning
|
||||
* -# LFO Frequency
|
||||
* -# LFO Randomness
|
||||
* -# LFO Type
|
||||
* -# LFO stereo
|
||||
* -# Depth
|
||||
* -# Delay
|
||||
* -# Feedback
|
||||
* -# Flange Mode
|
||||
* -# Subtractive
|
||||
* @param npar number of chosen parameter
|
||||
* @param value the new value
|
||||
*/
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
/**
|
||||
* Gets the value of the chosen variable
|
||||
*
|
||||
* The possible parameters are:
|
||||
* -# Volume
|
||||
* -# Panning
|
||||
* -# LFO Frequency
|
||||
* -# LFO Randomness
|
||||
* -# LFO Type
|
||||
* -# LFO stereo
|
||||
* -# Depth
|
||||
* -# Delay
|
||||
* -# Feedback
|
||||
* -# Flange Mode
|
||||
* -# Subtractive
|
||||
* @param npar number of chosen parameter
|
||||
* @return the value of the parameter
|
||||
*/
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
|
||||
private:
|
||||
//Chorus Parameters
|
||||
EffectLFO lfo;//lfo-ul chorus
|
||||
unsigned char Pvolume;
|
||||
unsigned char Ppanning;
|
||||
unsigned char Pdepth;//the depth of the Chorus(ms)
|
||||
unsigned char Pdelay;//the delay (ms)
|
||||
unsigned char Pfb;//feedback
|
||||
unsigned char Plrcross;//feedback
|
||||
unsigned char Pflangemode;//how the LFO is scaled, to result chorus or flange
|
||||
unsigned char Poutsub;//if I wish to substract the output instead of the adding it
|
||||
class Chorus:public Effect
|
||||
{
|
||||
public:
|
||||
Chorus(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
/**Destructor*/
|
||||
~Chorus();
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpsr);
|
||||
void out(const Stereo<AuSample> &input);
|
||||
void setpreset(unsigned char npreset);
|
||||
/**
|
||||
* Sets the value of the chosen variable
|
||||
*
|
||||
* The possible parameters are:
|
||||
* -# Volume
|
||||
* -# Panning
|
||||
* -# LFO Frequency
|
||||
* -# LFO Randomness
|
||||
* -# LFO Type
|
||||
* -# LFO stereo
|
||||
* -# Depth
|
||||
* -# Delay
|
||||
* -# Feedback
|
||||
* -# Flange Mode
|
||||
* -# Subtractive
|
||||
* @param npar number of chosen parameter
|
||||
* @param value the new value
|
||||
*/
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
/**
|
||||
* Gets the value of the chosen variable
|
||||
*
|
||||
* The possible parameters are:
|
||||
* -# Volume
|
||||
* -# Panning
|
||||
* -# LFO Frequency
|
||||
* -# LFO Randomness
|
||||
* -# LFO Type
|
||||
* -# LFO stereo
|
||||
* -# Depth
|
||||
* -# Delay
|
||||
* -# Feedback
|
||||
* -# Flange Mode
|
||||
* -# Subtractive
|
||||
* @param npar number of chosen parameter
|
||||
* @return the value of the parameter
|
||||
*/
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
|
||||
|
||||
//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);
|
||||
private:
|
||||
//Chorus Parameters
|
||||
EffectLFO lfo;//lfo-ul chorus
|
||||
unsigned char Pvolume;
|
||||
unsigned char Ppanning;
|
||||
unsigned char Pdepth;//the depth of the Chorus(ms)
|
||||
unsigned char Pdelay;//the delay (ms)
|
||||
unsigned char Pfb;//feedback
|
||||
unsigned char Plrcross;//feedback
|
||||
unsigned char Pflangemode;//how the LFO is scaled, to result chorus or flange
|
||||
unsigned char Poutsub;//if I wish to substract the output instead of the adding it
|
||||
|
||||
//Internal Values
|
||||
REALTYPE depth,delay,fb,lrcross,panning;
|
||||
REALTYPE dl1,dl2,dr1,dr2,lfol,lfor;
|
||||
int maxdelay;
|
||||
REALTYPE *delayl,*delayr;
|
||||
int dlk,drk,dlhi,dlhi2;
|
||||
REALTYPE getdelay(REALTYPE xlfo);
|
||||
REALTYPE dllo,mdel;
|
||||
|
||||
//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);
|
||||
|
||||
//Internal Values
|
||||
REALTYPE depth,delay,fb,lrcross,panning;
|
||||
REALTYPE dl1,dl2,dr1,dr2,lfol,lfor;
|
||||
int maxdelay;
|
||||
Stereo<AuSample> delaySample;
|
||||
//REALTYPE *delayl,*delayr;
|
||||
int dlk,drk,dlhi,dlhi2;
|
||||
REALTYPE getdelay(REALTYPE xlfo);
|
||||
REALTYPE dllo,mdel;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Distorsion.C - Distorsion effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Distorsion.h"
|
||||
|
||||
|
||||
/*
|
||||
* Waveshape (this is called by OscilGen::waveshape and Distorsion::process)
|
||||
*/
|
||||
|
||||
void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive){
|
||||
int i;
|
||||
REALTYPE ws=drive/127.0;
|
||||
REALTYPE tmpv;
|
||||
|
||||
switch(type){
|
||||
case 1: ws=pow(10,ws*ws*3.0)-1.0+0.001;//Arctangent
|
||||
for (i=0;i<n;i++)
|
||||
smps[i]=atan(smps[i]*ws)/atan(ws);
|
||||
break;
|
||||
case 2: ws=ws*ws*32.0+0.0001;//Asymmetric
|
||||
if (ws<1.0) tmpv=sin(ws)+0.1;
|
||||
else tmpv=1.1;
|
||||
for (i=0;i<n;i++) {
|
||||
smps[i]=sin(smps[i]*(0.1+ws-ws*smps[i]))/tmpv;
|
||||
};
|
||||
break;
|
||||
case 3: ws=ws*ws*ws*20.0+0.0001;//Pow
|
||||
for (i=0;i<n;i++) {
|
||||
smps[i]*=ws;
|
||||
if (fabs(smps[i])<1.0) {
|
||||
smps[i]=(smps[i]-pow(smps[i],3.0))*3.0;
|
||||
if (ws<1.0) smps[i]/=ws;
|
||||
} else smps[i]=0.0;
|
||||
};
|
||||
break;
|
||||
case 4: ws=ws*ws*ws*32.0+0.0001;//Sine
|
||||
if (ws<1.57) tmpv=sin(ws);
|
||||
else tmpv=1.0;
|
||||
for (i=0;i<n;i++) smps[i]=sin(smps[i]*ws)/tmpv;
|
||||
break;
|
||||
case 5: ws=ws*ws+0.000001;//Quantisize
|
||||
for (i=0;i<n;i++)
|
||||
smps[i]=floor(smps[i]/ws+0.5)*ws;
|
||||
break;
|
||||
case 6: ws=ws*ws*ws*32+0.0001;//Zigzag
|
||||
if (ws<1.0) tmpv=sin(ws);
|
||||
else tmpv=1.0;
|
||||
for (i=0;i<n;i++)
|
||||
smps[i]=asin(sin(smps[i]*ws))/tmpv;
|
||||
break;
|
||||
case 7: ws=pow(2.0,-ws*ws*8.0); //Limiter
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i];
|
||||
if (fabs(tmp)>ws) {
|
||||
if (tmp>=0.0) smps[i]=1.0;
|
||||
else smps[i]=-1.0;
|
||||
} else smps[i]/=ws;
|
||||
};
|
||||
break;
|
||||
case 8: ws=pow(2.0,-ws*ws*8.0); //Upper Limiter
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i];
|
||||
if (tmp>ws) smps[i]=ws;
|
||||
smps[i]*=2.0;
|
||||
};
|
||||
break;
|
||||
case 9: ws=pow(2.0,-ws*ws*8.0); //Lower Limiter
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i];
|
||||
if (tmp<-ws) smps[i]=-ws;
|
||||
smps[i]*=2.0;
|
||||
};
|
||||
break;
|
||||
case 10:ws=(pow(2.0,ws*6.0)-1.0)/pow(2.0,6.0); //Inverse Limiter
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i];
|
||||
if (fabs(tmp)>ws) {
|
||||
if (tmp>=0.0) smps[i]=tmp-ws;
|
||||
else smps[i]=tmp+ws;
|
||||
} else smps[i]=0;
|
||||
};
|
||||
break;
|
||||
case 11:ws=pow(5,ws*ws*1.0)-1.0;//Clip
|
||||
for (i=0;i<n;i++)
|
||||
smps[i]=smps[i]*(ws+0.5)*0.9999-floor(0.5+smps[i]*(ws+0.5)*0.9999);
|
||||
break;
|
||||
case 12:ws=ws*ws*ws*30+0.001;//Asym2
|
||||
if (ws<0.3) tmpv=ws;
|
||||
else tmpv=1.0;
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i]*ws;
|
||||
if ((tmp>-2.0) && (tmp<1.0)) smps[i]=tmp*(1.0-tmp)*(tmp+2.0)/tmpv;
|
||||
else smps[i]=0.0;
|
||||
};
|
||||
break;
|
||||
case 13:ws=ws*ws*ws*32.0+0.0001;//Pow2
|
||||
if (ws<1.0) tmpv=ws*(1+ws)/2.0;
|
||||
else tmpv=1.0;
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i]*ws;
|
||||
if ((tmp>-1.0)&&(tmp<1.618034)) smps[i]=tmp*(1.0-tmp)/tmpv;
|
||||
else if (tmp>0.0) smps[i]=-1.0;
|
||||
else smps[i]=-2.0;
|
||||
};
|
||||
break;
|
||||
case 14:ws=pow(ws,5.0)*80.0+0.0001;//sigmoid
|
||||
if (ws>10.0) tmpv=0.5;
|
||||
else tmpv=0.5-1.0/(exp(ws)+1.0);
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i]*ws;
|
||||
if (tmp<-10.0) tmp=-10.0;
|
||||
else if (tmp>10.0) tmp=10.0;
|
||||
tmp=0.5-1.0/(exp(tmp)+1.0);
|
||||
smps[i]=tmp/tmpv;
|
||||
};
|
||||
break;
|
||||
/**\todo update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions*/
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
Distorsion::Distorsion(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0)
|
||||
{
|
||||
|
||||
lpfl=new AnalogFilter(2,22000,1,0);
|
||||
lpfr=new AnalogFilter(2,22000,1,0);
|
||||
hpfl=new AnalogFilter(3,20,1,0);
|
||||
hpfr=new AnalogFilter(3,20,1,0);
|
||||
|
||||
|
||||
//default values
|
||||
Pvolume=50;
|
||||
Plrcross=40;
|
||||
Pdrive=90;
|
||||
Plevel=64;
|
||||
Ptype=0;
|
||||
Pnegate=0;
|
||||
Plpf=127;
|
||||
Phpf=0;
|
||||
Pstereo=0;
|
||||
Pprefiltering=0;
|
||||
|
||||
setpreset(Ppreset);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
Distorsion::~Distorsion(){
|
||||
delete lpfl;
|
||||
delete lpfr;
|
||||
delete hpfl;
|
||||
delete hpfr;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Distorsion::cleanup(){
|
||||
lpfl->cleanup();
|
||||
hpfl->cleanup();
|
||||
lpfr->cleanup();
|
||||
hpfr->cleanup();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Apply the filters
|
||||
*/
|
||||
|
||||
void Distorsion::applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr){
|
||||
lpfl->filterout(efxoutl);
|
||||
hpfl->filterout(efxoutl);
|
||||
if (Pstereo!=0){//stereo
|
||||
lpfr->filterout(efxoutr);
|
||||
hpfr->filterout(efxoutr);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Effect output
|
||||
*/
|
||||
void Distorsion::out(REALTYPE *smpsl,REALTYPE *smpsr){
|
||||
int i;
|
||||
REALTYPE l,r,lout,rout;
|
||||
|
||||
REALTYPE inputvol=pow(5.0,(Pdrive-32.0)/127.0);
|
||||
if (Pnegate!=0) inputvol*=-1.0;
|
||||
|
||||
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);
|
||||
};
|
||||
} else {
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i]=( smpsl[i]*panning + smpsr[i]*(1.0-panning) ) * inputvol;
|
||||
};
|
||||
};
|
||||
|
||||
if (Pprefiltering!=0) applyfilters(efxoutl,efxoutr);
|
||||
|
||||
//no optimised, yet (no look table)
|
||||
waveshapesmps(SOUND_BUFFER_SIZE,efxoutl,Ptype+1,Pdrive);
|
||||
if (Pstereo!=0) waveshapesmps(SOUND_BUFFER_SIZE,efxoutr,Ptype+1,Pdrive);
|
||||
|
||||
if (Pprefiltering==0) applyfilters(efxoutl,efxoutr);
|
||||
|
||||
if (Pstereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) efxoutr[i]=efxoutl[i];
|
||||
|
||||
REALTYPE level=dB2rap(60.0*Plevel/127.0-40.0);
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
lout=efxoutl[i];
|
||||
rout=efxoutr[i];
|
||||
l=lout*(1.0-lrcross)+rout*lrcross;
|
||||
r=rout*(1.0-lrcross)+lout*lrcross;
|
||||
lout=l;rout=r;
|
||||
|
||||
efxoutl[i]=lout*2.0*level;
|
||||
efxoutr[i]=rout*2.0*level;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Distorsion::setvolume(const unsigned char &Pvolume){
|
||||
this->Pvolume=Pvolume;
|
||||
|
||||
if (insertion==0) {
|
||||
outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0;
|
||||
volume=1.0;
|
||||
} else {
|
||||
volume=outvolume=Pvolume/127.0;
|
||||
};
|
||||
if (Pvolume==0) cleanup();
|
||||
|
||||
};
|
||||
|
||||
void Distorsion::setpanning(const unsigned char &Ppanning){
|
||||
this->Ppanning=Ppanning;
|
||||
panning=(Ppanning+0.5)/127.0;
|
||||
};
|
||||
|
||||
|
||||
void Distorsion::setlrcross(const unsigned char &Plrcross){
|
||||
this->Plrcross=Plrcross;
|
||||
lrcross=Plrcross/127.0*1.0;
|
||||
};
|
||||
|
||||
void Distorsion::setlpf(const unsigned char &Plpf){
|
||||
this->Plpf=Plpf;
|
||||
REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40;
|
||||
lpfl->setfreq(fr);
|
||||
lpfr->setfreq(fr);
|
||||
};
|
||||
|
||||
void Distorsion::sethpf(const unsigned char &Phpf){
|
||||
this->Phpf=Phpf;
|
||||
REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(25000.0))+20.0;
|
||||
hpfl->setfreq(fr);
|
||||
hpfr->setfreq(fr);
|
||||
};
|
||||
|
||||
|
||||
void Distorsion::setpreset(unsigned char npreset){
|
||||
const int PRESET_SIZE=11;
|
||||
const int NUM_PRESETS=6;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//Overdrive 1
|
||||
{127,64,35,56,70,0,0,96,0,0,0},
|
||||
//Overdrive 2
|
||||
{127,64,35,29,75,1,0,127,0,0,0},
|
||||
//A. Exciter 1
|
||||
{64,64,35,75,80,5,0,127,105,1,0},
|
||||
//A. Exciter 2
|
||||
{64,64,35,85,62,1,0,127,118,1,0},
|
||||
//Guitar Amp
|
||||
{127,64,35,63,75,2,0,55,0,0,0},
|
||||
//Quantisize
|
||||
{127,64,35,88,75,4,0,127,0,1,0}};
|
||||
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
|
||||
if (insertion==0) changepar(0,(int) (presets[npreset][0]/1.5));//lower the volume if this is system effect
|
||||
Ppreset=npreset;
|
||||
cleanup();
|
||||
};
|
||||
|
||||
|
||||
void Distorsion::changepar(const int &npar,const unsigned char &value){
|
||||
switch (npar){
|
||||
case 0: setvolume(value);
|
||||
break;
|
||||
case 1: setpanning(value);
|
||||
break;
|
||||
case 2: setlrcross(value);
|
||||
break;
|
||||
case 3: Pdrive=value;
|
||||
break;
|
||||
case 4: Plevel=value;
|
||||
break;
|
||||
case 5: if (value>13) Ptype=13;//this must be increased if more distorsion types are added
|
||||
else Ptype=value;
|
||||
break;
|
||||
case 6: if (value>1) Pnegate=1;
|
||||
else Pnegate=value;
|
||||
break;
|
||||
case 7: setlpf(value);
|
||||
break;
|
||||
case 8: sethpf(value);
|
||||
break;
|
||||
case 9: if (value>1) Pstereo=1;
|
||||
else Pstereo=value;
|
||||
break;
|
||||
case 10:Pprefiltering=value;
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char Distorsion::getpar(const int &npar)const{
|
||||
switch (npar){
|
||||
case 0: return(Pvolume);
|
||||
break;
|
||||
case 1: return(Ppanning);
|
||||
break;
|
||||
case 2: return(Plrcross);
|
||||
break;
|
||||
case 3: return(Pdrive);
|
||||
break;
|
||||
case 4: return(Plevel);
|
||||
break;
|
||||
case 5: return(Ptype);
|
||||
break;
|
||||
case 6: return(Pnegate);
|
||||
break;
|
||||
case 7: return(Plpf);
|
||||
break;
|
||||
case 8: return(Phpf);
|
||||
break;
|
||||
case 9: return(Pstereo);
|
||||
break;
|
||||
case 10:return(Pprefiltering);
|
||||
break;
|
||||
};
|
||||
return(0);//in case of bogus parameter number
|
||||
};
|
||||
|
||||
427
plugins/zynaddsubfx/src/Effects/Distorsion.cpp
Normal file
427
plugins/zynaddsubfx/src/Effects/Distorsion.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Distorsion.C - Distorsion effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Distorsion.h"
|
||||
|
||||
|
||||
/*
|
||||
* Waveshape (this is called by OscilGen::waveshape and Distorsion::process)
|
||||
*/
|
||||
|
||||
void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive)
|
||||
{
|
||||
int i;
|
||||
REALTYPE ws=drive/127.0;
|
||||
REALTYPE tmpv;
|
||||
|
||||
switch (type) {
|
||||
case 1:
|
||||
ws=pow(10,ws*ws*3.0)-1.0+0.001;//Arctangent
|
||||
for (i=0;i<n;i++)
|
||||
smps[i]=atan(smps[i]*ws)/atan(ws);
|
||||
break;
|
||||
case 2:
|
||||
ws=ws*ws*32.0+0.0001;//Asymmetric
|
||||
if (ws<1.0) tmpv=sin(ws)+0.1;
|
||||
else tmpv=1.1;
|
||||
for (i=0;i<n;i++) {
|
||||
smps[i]=sin(smps[i]*(0.1+ws-ws*smps[i]))/tmpv;
|
||||
};
|
||||
break;
|
||||
case 3:
|
||||
ws=ws*ws*ws*20.0+0.0001;//Pow
|
||||
for (i=0;i<n;i++) {
|
||||
smps[i]*=ws;
|
||||
if (fabs(smps[i])<1.0) {
|
||||
smps[i]=(smps[i]-pow(smps[i],3.0))*3.0;
|
||||
if (ws<1.0) smps[i]/=ws;
|
||||
} else smps[i]=0.0;
|
||||
};
|
||||
break;
|
||||
case 4:
|
||||
ws=ws*ws*ws*32.0+0.0001;//Sine
|
||||
if (ws<1.57) tmpv=sin(ws);
|
||||
else tmpv=1.0;
|
||||
for (i=0;i<n;i++) smps[i]=sin(smps[i]*ws)/tmpv;
|
||||
break;
|
||||
case 5:
|
||||
ws=ws*ws+0.000001;//Quantisize
|
||||
for (i=0;i<n;i++)
|
||||
smps[i]=floor(smps[i]/ws+0.5)*ws;
|
||||
break;
|
||||
case 6:
|
||||
ws=ws*ws*ws*32+0.0001;//Zigzag
|
||||
if (ws<1.0) tmpv=sin(ws);
|
||||
else tmpv=1.0;
|
||||
for (i=0;i<n;i++)
|
||||
smps[i]=asin(sin(smps[i]*ws))/tmpv;
|
||||
break;
|
||||
case 7:
|
||||
ws=pow(2.0,-ws*ws*8.0); //Limiter
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i];
|
||||
if (fabs(tmp)>ws) {
|
||||
if (tmp>=0.0) smps[i]=1.0;
|
||||
else smps[i]=-1.0;
|
||||
} else smps[i]/=ws;
|
||||
};
|
||||
break;
|
||||
case 8:
|
||||
ws=pow(2.0,-ws*ws*8.0); //Upper Limiter
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i];
|
||||
if (tmp>ws) smps[i]=ws;
|
||||
smps[i]*=2.0;
|
||||
};
|
||||
break;
|
||||
case 9:
|
||||
ws=pow(2.0,-ws*ws*8.0); //Lower Limiter
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i];
|
||||
if (tmp<-ws) smps[i]=-ws;
|
||||
smps[i]*=2.0;
|
||||
};
|
||||
break;
|
||||
case 10:
|
||||
ws=(pow(2.0,ws*6.0)-1.0)/pow(2.0,6.0); //Inverse Limiter
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i];
|
||||
if (fabs(tmp)>ws) {
|
||||
if (tmp>=0.0) smps[i]=tmp-ws;
|
||||
else smps[i]=tmp+ws;
|
||||
} else smps[i]=0;
|
||||
};
|
||||
break;
|
||||
case 11:
|
||||
ws=pow(5,ws*ws*1.0)-1.0;//Clip
|
||||
for (i=0;i<n;i++)
|
||||
smps[i]=smps[i]*(ws+0.5)*0.9999-floor(0.5+smps[i]*(ws+0.5)*0.9999);
|
||||
break;
|
||||
case 12:
|
||||
ws=ws*ws*ws*30+0.001;//Asym2
|
||||
if (ws<0.3) tmpv=ws;
|
||||
else tmpv=1.0;
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i]*ws;
|
||||
if ((tmp>-2.0) && (tmp<1.0)) smps[i]=tmp*(1.0-tmp)*(tmp+2.0)/tmpv;
|
||||
else smps[i]=0.0;
|
||||
};
|
||||
break;
|
||||
case 13:
|
||||
ws=ws*ws*ws*32.0+0.0001;//Pow2
|
||||
if (ws<1.0) tmpv=ws*(1+ws)/2.0;
|
||||
else tmpv=1.0;
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i]*ws;
|
||||
if ((tmp>-1.0)&&(tmp<1.618034)) smps[i]=tmp*(1.0-tmp)/tmpv;
|
||||
else if (tmp>0.0) smps[i]=-1.0;
|
||||
else smps[i]=-2.0;
|
||||
};
|
||||
break;
|
||||
case 14:
|
||||
ws=pow(ws,5.0)*80.0+0.0001;//sigmoid
|
||||
if (ws>10.0) tmpv=0.5;
|
||||
else tmpv=0.5-1.0/(exp(ws)+1.0);
|
||||
for (i=0;i<n;i++) {
|
||||
REALTYPE tmp=smps[i]*ws;
|
||||
if (tmp<-10.0) tmp=-10.0;
|
||||
else if (tmp>10.0) tmp=10.0;
|
||||
tmp=0.5-1.0/(exp(tmp)+1.0);
|
||||
smps[i]=tmp/tmpv;
|
||||
};
|
||||
break;
|
||||
/**\todo update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions*/
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
Distorsion::Distorsion(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0)
|
||||
{
|
||||
|
||||
lpfl=new AnalogFilter(2,22000,1,0);
|
||||
lpfr=new AnalogFilter(2,22000,1,0);
|
||||
hpfl=new AnalogFilter(3,20,1,0);
|
||||
hpfr=new AnalogFilter(3,20,1,0);
|
||||
|
||||
|
||||
//default values
|
||||
Pvolume=50;
|
||||
Plrcross=40;
|
||||
Pdrive=90;
|
||||
Plevel=64;
|
||||
Ptype=0;
|
||||
Pnegate=0;
|
||||
Plpf=127;
|
||||
Phpf=0;
|
||||
Pstereo=0;
|
||||
Pprefiltering=0;
|
||||
|
||||
setpreset(Ppreset);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
Distorsion::~Distorsion()
|
||||
{
|
||||
delete lpfl;
|
||||
delete lpfr;
|
||||
delete hpfl;
|
||||
delete hpfr;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Distorsion::cleanup()
|
||||
{
|
||||
lpfl->cleanup();
|
||||
hpfl->cleanup();
|
||||
lpfr->cleanup();
|
||||
hpfr->cleanup();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Apply the filters
|
||||
*/
|
||||
|
||||
void Distorsion::applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr)
|
||||
{
|
||||
lpfl->filterout(efxoutl);
|
||||
hpfl->filterout(efxoutl);
|
||||
if (Pstereo!=0) {//stereo
|
||||
lpfr->filterout(efxoutr);
|
||||
hpfr->filterout(efxoutr);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Effect output
|
||||
*/
|
||||
void Distorsion::out(REALTYPE *smpsl,REALTYPE *smpsr)
|
||||
{
|
||||
int i;
|
||||
REALTYPE l,r,lout,rout;
|
||||
|
||||
REALTYPE inputvol=pow(5.0,(Pdrive-32.0)/127.0);
|
||||
if (Pnegate!=0) inputvol*=-1.0;
|
||||
|
||||
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);
|
||||
};
|
||||
} else {
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
efxoutl[i]=( smpsl[i]*panning + smpsr[i]*(1.0-panning) ) * inputvol;
|
||||
};
|
||||
};
|
||||
|
||||
if (Pprefiltering!=0) applyfilters(efxoutl,efxoutr);
|
||||
|
||||
//no optimised, yet (no look table)
|
||||
waveshapesmps(SOUND_BUFFER_SIZE,efxoutl,Ptype+1,Pdrive);
|
||||
if (Pstereo!=0) waveshapesmps(SOUND_BUFFER_SIZE,efxoutr,Ptype+1,Pdrive);
|
||||
|
||||
if (Pprefiltering==0) applyfilters(efxoutl,efxoutr);
|
||||
|
||||
if (Pstereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) efxoutr[i]=efxoutl[i];
|
||||
|
||||
REALTYPE level=dB2rap(60.0*Plevel/127.0-40.0);
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
lout=efxoutl[i];
|
||||
rout=efxoutr[i];
|
||||
l=lout*(1.0-lrcross)+rout*lrcross;
|
||||
r=rout*(1.0-lrcross)+lout*lrcross;
|
||||
lout=l;
|
||||
rout=r;
|
||||
|
||||
efxoutl[i]=lout*2.0*level;
|
||||
efxoutr[i]=rout*2.0*level;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Distorsion::setvolume(const unsigned char &Pvolume)
|
||||
{
|
||||
this->Pvolume=Pvolume;
|
||||
|
||||
if (insertion==0) {
|
||||
outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0;
|
||||
volume=1.0;
|
||||
} else {
|
||||
volume=outvolume=Pvolume/127.0;
|
||||
};
|
||||
if (Pvolume==0) cleanup();
|
||||
|
||||
};
|
||||
|
||||
void Distorsion::setpanning(const unsigned char &Ppanning)
|
||||
{
|
||||
this->Ppanning=Ppanning;
|
||||
panning=(Ppanning+0.5)/127.0;
|
||||
};
|
||||
|
||||
|
||||
void Distorsion::setlrcross(const unsigned char &Plrcross)
|
||||
{
|
||||
this->Plrcross=Plrcross;
|
||||
lrcross=Plrcross/127.0*1.0;
|
||||
};
|
||||
|
||||
void Distorsion::setlpf(const unsigned char &Plpf)
|
||||
{
|
||||
this->Plpf=Plpf;
|
||||
REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40;
|
||||
lpfl->setfreq(fr);
|
||||
lpfr->setfreq(fr);
|
||||
};
|
||||
|
||||
void Distorsion::sethpf(const unsigned char &Phpf)
|
||||
{
|
||||
this->Phpf=Phpf;
|
||||
REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(25000.0))+20.0;
|
||||
hpfl->setfreq(fr);
|
||||
hpfr->setfreq(fr);
|
||||
};
|
||||
|
||||
|
||||
void Distorsion::setpreset(unsigned char npreset)
|
||||
{
|
||||
const int PRESET_SIZE=11;
|
||||
const int NUM_PRESETS=6;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//Overdrive 1
|
||||
{127,64,35,56,70,0,0,96,0,0,0},
|
||||
//Overdrive 2
|
||||
{127,64,35,29,75,1,0,127,0,0,0},
|
||||
//A. Exciter 1
|
||||
{64,64,35,75,80,5,0,127,105,1,0},
|
||||
//A. Exciter 2
|
||||
{64,64,35,85,62,1,0,127,118,1,0},
|
||||
//Guitar Amp
|
||||
{127,64,35,63,75,2,0,55,0,0,0},
|
||||
//Quantisize
|
||||
{127,64,35,88,75,4,0,127,0,1,0}
|
||||
};
|
||||
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
|
||||
if (insertion==0) changepar(0,(int) (presets[npreset][0]/1.5));//lower the volume if this is system effect
|
||||
Ppreset=npreset;
|
||||
cleanup();
|
||||
};
|
||||
|
||||
|
||||
void Distorsion::changepar(const int &npar,const unsigned char &value)
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
setvolume(value);
|
||||
break;
|
||||
case 1:
|
||||
setpanning(value);
|
||||
break;
|
||||
case 2:
|
||||
setlrcross(value);
|
||||
break;
|
||||
case 3:
|
||||
Pdrive=value;
|
||||
break;
|
||||
case 4:
|
||||
Plevel=value;
|
||||
break;
|
||||
case 5:
|
||||
if (value>13) Ptype=13;//this must be increased if more distorsion types are added
|
||||
else Ptype=value;
|
||||
break;
|
||||
case 6:
|
||||
if (value>1) Pnegate=1;
|
||||
else Pnegate=value;
|
||||
break;
|
||||
case 7:
|
||||
setlpf(value);
|
||||
break;
|
||||
case 8:
|
||||
sethpf(value);
|
||||
break;
|
||||
case 9:
|
||||
if (value>1) Pstereo=1;
|
||||
else Pstereo=value;
|
||||
break;
|
||||
case 10:
|
||||
Pprefiltering=value;
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char Distorsion::getpar(const int &npar)const
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
return(Pvolume);
|
||||
break;
|
||||
case 1:
|
||||
return(Ppanning);
|
||||
break;
|
||||
case 2:
|
||||
return(Plrcross);
|
||||
break;
|
||||
case 3:
|
||||
return(Pdrive);
|
||||
break;
|
||||
case 4:
|
||||
return(Plevel);
|
||||
break;
|
||||
case 5:
|
||||
return(Ptype);
|
||||
break;
|
||||
case 6:
|
||||
return(Pnegate);
|
||||
break;
|
||||
case 7:
|
||||
return(Plpf);
|
||||
break;
|
||||
case 8:
|
||||
return(Phpf);
|
||||
break;
|
||||
case 9:
|
||||
return(Pstereo);
|
||||
break;
|
||||
case 10:
|
||||
return(Pprefiltering);
|
||||
break;
|
||||
};
|
||||
return(0);//in case of bogus parameter number
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Distorsion.h - Distorsion Effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -30,40 +30,41 @@
|
||||
//Waveshaping(called by Distorsion effect and waveshape from OscilGen)
|
||||
void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive);
|
||||
/**Distortion Effect*/
|
||||
class Distorsion:public Effect{
|
||||
public:
|
||||
Distorsion(const int &insertion,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
~Distorsion();
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpr);
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
void applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr);
|
||||
class Distorsion:public Effect
|
||||
{
|
||||
public:
|
||||
Distorsion(const int &insertion,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
~Distorsion();
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpr);
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const 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 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);
|
||||
|
||||
//Real Parameters
|
||||
REALTYPE panning,lrcross;
|
||||
AnalogFilter *lpfl,*lpfr,*hpfl,*hpfr;
|
||||
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 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);
|
||||
|
||||
//Real Parameters
|
||||
REALTYPE panning,lrcross;
|
||||
AnalogFilter *lpfl,*lpfr,*hpfl,*hpfr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
DynamicFilter.C - "WahWah" effect and others
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "DynamicFilter.h"
|
||||
|
||||
DynamicFilter::DynamicFilter(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,new FilterParams(0,64,64),0),
|
||||
filterl(NULL),filterr(NULL)
|
||||
{
|
||||
setpreset(Ppreset);
|
||||
cleanup();
|
||||
/**\todo fix intialization issues here*/
|
||||
};
|
||||
|
||||
DynamicFilter::~DynamicFilter(){
|
||||
delete filterpars;
|
||||
delete filterl;
|
||||
delete filterr;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Apply the effect
|
||||
*/
|
||||
void DynamicFilter::out(REALTYPE *smpsl,REALTYPE *smpsr){
|
||||
int i;
|
||||
if (filterpars->changed){
|
||||
filterpars->changed=false;
|
||||
cleanup();
|
||||
};
|
||||
|
||||
REALTYPE lfol,lfor;
|
||||
lfo.effectlfoout(&lfol,&lfor);
|
||||
lfol*=depth*5.0;lfor*=depth*5.0;
|
||||
REALTYPE freq=filterpars->getfreq();
|
||||
REALTYPE q=filterpars->getq();
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i]=smpsl[i];
|
||||
efxoutr[i]=smpsr[i];
|
||||
|
||||
REALTYPE x=(fabs(smpsl[i])+fabs(smpsr[i]))*0.5;
|
||||
ms1=ms1*(1.0-ampsmooth)+x*ampsmooth+1e-10;
|
||||
};
|
||||
|
||||
|
||||
REALTYPE ampsmooth2=pow(ampsmooth,0.2)*0.3;
|
||||
ms2=ms2*(1.0-ampsmooth2)+ms1*ampsmooth2;
|
||||
ms3=ms3*(1.0-ampsmooth2)+ms2*ampsmooth2;
|
||||
ms4=ms4*(1.0-ampsmooth2)+ms3*ampsmooth2;
|
||||
REALTYPE rms=(sqrt(ms4))*ampsns;
|
||||
|
||||
REALTYPE frl=filterl->getrealfreq(freq+lfol+rms);
|
||||
REALTYPE frr=filterr->getrealfreq(freq+lfor+rms);
|
||||
|
||||
filterl->setfreq_and_q(frl,q);
|
||||
filterr->setfreq_and_q(frr,q);
|
||||
|
||||
|
||||
filterl->filterout(efxoutl);
|
||||
filterr->filterout(efxoutr);
|
||||
|
||||
//panning
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i]*=panning;
|
||||
efxoutr[i]*=(1.0-panning);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void DynamicFilter::cleanup(){
|
||||
reinitfilter();
|
||||
ms1=0.0;
|
||||
ms2=0.0;
|
||||
ms3=0.0;
|
||||
ms4=0.0;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
|
||||
void DynamicFilter::setdepth(const unsigned char &Pdepth){
|
||||
this->Pdepth=Pdepth;
|
||||
depth=pow((Pdepth/127.0),2.0);
|
||||
};
|
||||
|
||||
|
||||
void DynamicFilter::setvolume(const unsigned char &Pvolume){
|
||||
this->Pvolume=Pvolume;
|
||||
outvolume=Pvolume/127.0;
|
||||
if (insertion==0) volume=1.0;
|
||||
else volume=outvolume;
|
||||
};
|
||||
|
||||
void DynamicFilter::setpanning(const unsigned char &Ppanning){
|
||||
this->Ppanning=Ppanning;
|
||||
panning=Ppanning/127.0;
|
||||
};
|
||||
|
||||
|
||||
void DynamicFilter::setampsns(const unsigned char &Pampsns){
|
||||
ampsns=pow(Pampsns/127.0,2.5)*10.0;
|
||||
if (Pampsnsinv!=0) ampsns=-ampsns;
|
||||
ampsmooth=exp(-Pampsmooth/127.0*10.0)*0.99;/**\todo currently Pampsmooth is
|
||||
* uninitialized when this is
|
||||
* called. Please fix.
|
||||
*/
|
||||
this->Pampsns=Pampsns;
|
||||
};
|
||||
|
||||
void DynamicFilter::reinitfilter(){
|
||||
if (filterl!=NULL) delete(filterl);
|
||||
if (filterr!=NULL) delete(filterr);
|
||||
filterl=new Filter(filterpars);
|
||||
filterr=new Filter(filterpars);
|
||||
};
|
||||
|
||||
void DynamicFilter::setpreset(unsigned char npreset){
|
||||
const int PRESET_SIZE=10;
|
||||
const int NUM_PRESETS=5;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//WahWah
|
||||
{110,64,80,0,0,64,0,90,0,60},
|
||||
//AutoWah
|
||||
{110,64,70,0,0,80,70,0,0,60},
|
||||
//Sweep
|
||||
{100,64,30,0,0,50,80,0,0,60},
|
||||
//VocalMorph1
|
||||
{110,64,80,0,0,64,0,64,0,60},
|
||||
//VocalMorph1
|
||||
{127,64,50,0,0,96,64,0,0,60}};
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
|
||||
|
||||
filterpars->defaults();
|
||||
switch(npreset){
|
||||
case 0:
|
||||
filterpars->Pcategory=0;
|
||||
filterpars->Ptype=2;
|
||||
filterpars->Pfreq=45;
|
||||
filterpars->Pq=64;
|
||||
filterpars->Pstages=1;
|
||||
filterpars->Pgain=64;
|
||||
break;
|
||||
case 1:
|
||||
filterpars->Pcategory=2;
|
||||
filterpars->Ptype=0;
|
||||
filterpars->Pfreq=72;
|
||||
filterpars->Pq=64;
|
||||
filterpars->Pstages=0;
|
||||
filterpars->Pgain=64;
|
||||
break;
|
||||
case 2:
|
||||
filterpars->Pcategory=0;
|
||||
filterpars->Ptype=4;
|
||||
filterpars->Pfreq=64;
|
||||
filterpars->Pq=64;
|
||||
filterpars->Pstages=2;
|
||||
filterpars->Pgain=64;
|
||||
break;
|
||||
case 3:
|
||||
filterpars->Pcategory=1;
|
||||
filterpars->Ptype=0;
|
||||
filterpars->Pfreq=50;
|
||||
filterpars->Pq=70;
|
||||
filterpars->Pstages=1;
|
||||
filterpars->Pgain=64;
|
||||
|
||||
filterpars->Psequencesize=2;
|
||||
// "I"
|
||||
filterpars->Pvowels[0].formants[0].freq=34;
|
||||
filterpars->Pvowels[0].formants[0].amp=127;
|
||||
filterpars->Pvowels[0].formants[0].q=64;
|
||||
filterpars->Pvowels[0].formants[1].freq=99;
|
||||
filterpars->Pvowels[0].formants[1].amp=122;
|
||||
filterpars->Pvowels[0].formants[1].q=64;
|
||||
filterpars->Pvowels[0].formants[2].freq=108;
|
||||
filterpars->Pvowels[0].formants[2].amp=112;
|
||||
filterpars->Pvowels[0].formants[2].q=64;
|
||||
// "A"
|
||||
filterpars->Pvowels[1].formants[0].freq=61;
|
||||
filterpars->Pvowels[1].formants[0].amp=127;
|
||||
filterpars->Pvowels[1].formants[0].q=64;
|
||||
filterpars->Pvowels[1].formants[1].freq=71;
|
||||
filterpars->Pvowels[1].formants[1].amp=121;
|
||||
filterpars->Pvowels[1].formants[1].q=64;
|
||||
filterpars->Pvowels[1].formants[2].freq=99;
|
||||
filterpars->Pvowels[1].formants[2].amp=117;
|
||||
filterpars->Pvowels[1].formants[2].q=64;
|
||||
break;
|
||||
case 4:
|
||||
filterpars->Pcategory=1;
|
||||
filterpars->Ptype=0;
|
||||
filterpars->Pfreq=64;
|
||||
filterpars->Pq=70;
|
||||
filterpars->Pstages=1;
|
||||
filterpars->Pgain=64;
|
||||
|
||||
filterpars->Psequencesize=2;
|
||||
filterpars->Pnumformants=2;
|
||||
filterpars->Pvowelclearness=0;
|
||||
|
||||
filterpars->Pvowels[0].formants[0].freq=70;
|
||||
filterpars->Pvowels[0].formants[0].amp=127;
|
||||
filterpars->Pvowels[0].formants[0].q=64;
|
||||
filterpars->Pvowels[0].formants[1].freq=80;
|
||||
filterpars->Pvowels[0].formants[1].amp=122;
|
||||
filterpars->Pvowels[0].formants[1].q=64;
|
||||
|
||||
filterpars->Pvowels[1].formants[0].freq=20;
|
||||
filterpars->Pvowels[1].formants[0].amp=127;
|
||||
filterpars->Pvowels[1].formants[0].q=64;
|
||||
filterpars->Pvowels[1].formants[1].freq=100;
|
||||
filterpars->Pvowels[1].formants[1].amp=121;
|
||||
filterpars->Pvowels[1].formants[1].q=64;
|
||||
break;
|
||||
};
|
||||
|
||||
// for (int i=0;i<5;i++){
|
||||
// printf("freq=%d amp=%d q=%d\n",filterpars->Pvowels[0].formants[i].freq,filterpars->Pvowels[0].formants[i].amp,filterpars->Pvowels[0].formants[i].q);
|
||||
// };
|
||||
if (insertion==0) changepar(0,presets[npreset][0]/2);//lower the volume if this is system effect
|
||||
Ppreset=npreset;
|
||||
|
||||
reinitfilter();
|
||||
};
|
||||
|
||||
|
||||
void DynamicFilter::changepar(const int &npar,const unsigned char &value){
|
||||
switch(npar){
|
||||
case 0: setvolume(value);
|
||||
break;
|
||||
case 1: setpanning(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();
|
||||
break;
|
||||
case 5: lfo.Pstereo=value;
|
||||
lfo.updateparams();
|
||||
break;
|
||||
case 6: setdepth(value);
|
||||
break;
|
||||
case 7: setampsns(value);
|
||||
break;
|
||||
case 8: Pampsnsinv=value;
|
||||
setampsns(Pampsns);
|
||||
break;
|
||||
case 9: Pampsmooth=value;
|
||||
setampsns(Pampsns);
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char DynamicFilter::getpar(const int &npar)const{
|
||||
switch (npar){
|
||||
case 0: return(Pvolume);
|
||||
break;
|
||||
case 1: return(Ppanning);
|
||||
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(Pdepth);
|
||||
break;
|
||||
case 7: return(Pampsns);
|
||||
break;
|
||||
case 8: return(Pampsnsinv);
|
||||
break;
|
||||
case 9: return(Pampsmooth);
|
||||
break;
|
||||
default:return (0);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
344
plugins/zynaddsubfx/src/Effects/DynamicFilter.cpp
Normal file
344
plugins/zynaddsubfx/src/Effects/DynamicFilter.cpp
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
DynamicFilter.C - "WahWah" effect and others
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "DynamicFilter.h"
|
||||
|
||||
DynamicFilter::DynamicFilter(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,new FilterParams(0,64,64),0),
|
||||
Pvolume(110),Ppanning(64),Pdepth(0),Pampsns(90),
|
||||
Pampsnsinv(0),Pampsmooth(60),
|
||||
filterl(NULL),filterr(NULL)
|
||||
{
|
||||
setpreset(Ppreset);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
DynamicFilter::~DynamicFilter()
|
||||
{
|
||||
delete filterpars;
|
||||
delete filterl;
|
||||
delete filterr;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Apply the effect
|
||||
*/
|
||||
void DynamicFilter::out(REALTYPE *smpsl,REALTYPE *smpsr)
|
||||
{
|
||||
int i;
|
||||
if (filterpars->changed) {
|
||||
filterpars->changed=false;
|
||||
cleanup();
|
||||
};
|
||||
|
||||
REALTYPE lfol,lfor;
|
||||
lfo.effectlfoout(&lfol,&lfor);
|
||||
lfol*=depth*5.0;
|
||||
lfor*=depth*5.0;
|
||||
REALTYPE freq=filterpars->getfreq();
|
||||
REALTYPE q=filterpars->getq();
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
efxoutl[i]=smpsl[i];
|
||||
efxoutr[i]=smpsr[i];
|
||||
|
||||
REALTYPE x=(fabs(smpsl[i])+fabs(smpsr[i]))*0.5;
|
||||
ms1=ms1*(1.0-ampsmooth)+x*ampsmooth+1e-10;
|
||||
};
|
||||
|
||||
|
||||
REALTYPE ampsmooth2=pow(ampsmooth,0.2)*0.3;
|
||||
ms2=ms2*(1.0-ampsmooth2)+ms1*ampsmooth2;
|
||||
ms3=ms3*(1.0-ampsmooth2)+ms2*ampsmooth2;
|
||||
ms4=ms4*(1.0-ampsmooth2)+ms3*ampsmooth2;
|
||||
REALTYPE rms=(sqrt(ms4))*ampsns;
|
||||
|
||||
REALTYPE frl=filterl->getrealfreq(freq+lfol+rms);
|
||||
REALTYPE frr=filterr->getrealfreq(freq+lfor+rms);
|
||||
|
||||
filterl->setfreq_and_q(frl,q);
|
||||
filterr->setfreq_and_q(frr,q);
|
||||
|
||||
|
||||
filterl->filterout(efxoutl);
|
||||
filterr->filterout(efxoutr);
|
||||
|
||||
//panning
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
efxoutl[i]*=panning;
|
||||
efxoutr[i]*=(1.0-panning);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void DynamicFilter::cleanup()
|
||||
{
|
||||
reinitfilter();
|
||||
ms1=0.0;
|
||||
ms2=0.0;
|
||||
ms3=0.0;
|
||||
ms4=0.0;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
|
||||
void DynamicFilter::setdepth(const unsigned char &Pdepth)
|
||||
{
|
||||
this->Pdepth=Pdepth;
|
||||
depth=pow((Pdepth/127.0),2.0);
|
||||
};
|
||||
|
||||
|
||||
void DynamicFilter::setvolume(const unsigned char &Pvolume)
|
||||
{
|
||||
this->Pvolume=Pvolume;
|
||||
outvolume=Pvolume/127.0;
|
||||
if (insertion==0) volume=1.0;
|
||||
else volume=outvolume;
|
||||
};
|
||||
|
||||
void DynamicFilter::setpanning(const unsigned char &Ppanning)
|
||||
{
|
||||
this->Ppanning=Ppanning;
|
||||
panning=Ppanning/127.0;
|
||||
};
|
||||
|
||||
|
||||
void DynamicFilter::setampsns(const unsigned char &Pampsns)
|
||||
{
|
||||
ampsns=pow(Pampsns/127.0,2.5)*10.0;
|
||||
if (Pampsnsinv!=0) ampsns=-ampsns;
|
||||
ampsmooth=exp(-Pampsmooth/127.0*10.0)*0.99;
|
||||
this->Pampsns=Pampsns;
|
||||
};
|
||||
|
||||
void DynamicFilter::reinitfilter()
|
||||
{
|
||||
if (filterl!=NULL) delete(filterl);
|
||||
if (filterr!=NULL) delete(filterr);
|
||||
filterl=new Filter(filterpars);
|
||||
filterr=new Filter(filterpars);
|
||||
};
|
||||
|
||||
void DynamicFilter::setpreset(unsigned char npreset)
|
||||
{
|
||||
const int PRESET_SIZE=10;
|
||||
const int NUM_PRESETS=5;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//WahWah
|
||||
{110,64,80,0,0,64,0,90,0,60},
|
||||
//AutoWah
|
||||
{110,64,70,0,0,80,70,0,0,60},
|
||||
//Sweep
|
||||
{100,64,30,0,0,50,80,0,0,60},
|
||||
//VocalMorph1
|
||||
{110,64,80,0,0,64,0,64,0,60},
|
||||
//VocalMorph1
|
||||
{127,64,50,0,0,96,64,0,0,60}
|
||||
};
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
|
||||
|
||||
filterpars->defaults();
|
||||
switch (npreset) {
|
||||
case 0:
|
||||
filterpars->Pcategory=0;
|
||||
filterpars->Ptype=2;
|
||||
filterpars->Pfreq=45;
|
||||
filterpars->Pq=64;
|
||||
filterpars->Pstages=1;
|
||||
filterpars->Pgain=64;
|
||||
break;
|
||||
case 1:
|
||||
filterpars->Pcategory=2;
|
||||
filterpars->Ptype=0;
|
||||
filterpars->Pfreq=72;
|
||||
filterpars->Pq=64;
|
||||
filterpars->Pstages=0;
|
||||
filterpars->Pgain=64;
|
||||
break;
|
||||
case 2:
|
||||
filterpars->Pcategory=0;
|
||||
filterpars->Ptype=4;
|
||||
filterpars->Pfreq=64;
|
||||
filterpars->Pq=64;
|
||||
filterpars->Pstages=2;
|
||||
filterpars->Pgain=64;
|
||||
break;
|
||||
case 3:
|
||||
filterpars->Pcategory=1;
|
||||
filterpars->Ptype=0;
|
||||
filterpars->Pfreq=50;
|
||||
filterpars->Pq=70;
|
||||
filterpars->Pstages=1;
|
||||
filterpars->Pgain=64;
|
||||
|
||||
filterpars->Psequencesize=2;
|
||||
// "I"
|
||||
filterpars->Pvowels[0].formants[0].freq=34;
|
||||
filterpars->Pvowels[0].formants[0].amp=127;
|
||||
filterpars->Pvowels[0].formants[0].q=64;
|
||||
filterpars->Pvowels[0].formants[1].freq=99;
|
||||
filterpars->Pvowels[0].formants[1].amp=122;
|
||||
filterpars->Pvowels[0].formants[1].q=64;
|
||||
filterpars->Pvowels[0].formants[2].freq=108;
|
||||
filterpars->Pvowels[0].formants[2].amp=112;
|
||||
filterpars->Pvowels[0].formants[2].q=64;
|
||||
// "A"
|
||||
filterpars->Pvowels[1].formants[0].freq=61;
|
||||
filterpars->Pvowels[1].formants[0].amp=127;
|
||||
filterpars->Pvowels[1].formants[0].q=64;
|
||||
filterpars->Pvowels[1].formants[1].freq=71;
|
||||
filterpars->Pvowels[1].formants[1].amp=121;
|
||||
filterpars->Pvowels[1].formants[1].q=64;
|
||||
filterpars->Pvowels[1].formants[2].freq=99;
|
||||
filterpars->Pvowels[1].formants[2].amp=117;
|
||||
filterpars->Pvowels[1].formants[2].q=64;
|
||||
break;
|
||||
case 4:
|
||||
filterpars->Pcategory=1;
|
||||
filterpars->Ptype=0;
|
||||
filterpars->Pfreq=64;
|
||||
filterpars->Pq=70;
|
||||
filterpars->Pstages=1;
|
||||
filterpars->Pgain=64;
|
||||
|
||||
filterpars->Psequencesize=2;
|
||||
filterpars->Pnumformants=2;
|
||||
filterpars->Pvowelclearness=0;
|
||||
|
||||
filterpars->Pvowels[0].formants[0].freq=70;
|
||||
filterpars->Pvowels[0].formants[0].amp=127;
|
||||
filterpars->Pvowels[0].formants[0].q=64;
|
||||
filterpars->Pvowels[0].formants[1].freq=80;
|
||||
filterpars->Pvowels[0].formants[1].amp=122;
|
||||
filterpars->Pvowels[0].formants[1].q=64;
|
||||
|
||||
filterpars->Pvowels[1].formants[0].freq=20;
|
||||
filterpars->Pvowels[1].formants[0].amp=127;
|
||||
filterpars->Pvowels[1].formants[0].q=64;
|
||||
filterpars->Pvowels[1].formants[1].freq=100;
|
||||
filterpars->Pvowels[1].formants[1].amp=121;
|
||||
filterpars->Pvowels[1].formants[1].q=64;
|
||||
break;
|
||||
};
|
||||
|
||||
// for (int i=0;i<5;i++){
|
||||
// printf("freq=%d amp=%d q=%d\n",filterpars->Pvowels[0].formants[i].freq,filterpars->Pvowels[0].formants[i].amp,filterpars->Pvowels[0].formants[i].q);
|
||||
// };
|
||||
if (insertion==0) changepar(0,presets[npreset][0]/2);//lower the volume if this is system effect
|
||||
Ppreset=npreset;
|
||||
|
||||
reinitfilter();
|
||||
};
|
||||
|
||||
|
||||
void DynamicFilter::changepar(const int &npar,const unsigned char &value)
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
setvolume(value);
|
||||
break;
|
||||
case 1:
|
||||
setpanning(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();
|
||||
break;
|
||||
case 5:
|
||||
lfo.Pstereo=value;
|
||||
lfo.updateparams();
|
||||
break;
|
||||
case 6:
|
||||
setdepth(value);
|
||||
break;
|
||||
case 7:
|
||||
setampsns(value);
|
||||
break;
|
||||
case 8:
|
||||
Pampsnsinv=value;
|
||||
setampsns(Pampsns);
|
||||
break;
|
||||
case 9:
|
||||
Pampsmooth=value;
|
||||
setampsns(Pampsns);
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char DynamicFilter::getpar(const int &npar)const
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
return(Pvolume);
|
||||
break;
|
||||
case 1:
|
||||
return(Ppanning);
|
||||
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(Pdepth);
|
||||
break;
|
||||
case 7:
|
||||
return(Pampsns);
|
||||
break;
|
||||
case 8:
|
||||
return(Pampsnsinv);
|
||||
break;
|
||||
case 9:
|
||||
return(Pampsmooth);
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
DynamicFilter.h - "WahWah" effect and others
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -28,43 +28,44 @@
|
||||
|
||||
#include "../DSP/Filter.h"
|
||||
/**DynamicFilter Effect*/
|
||||
class DynamicFilter:public Effect {
|
||||
public:
|
||||
DynamicFilter(int insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
~DynamicFilter();
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpsr);
|
||||
class DynamicFilter:public Effect
|
||||
{
|
||||
public:
|
||||
DynamicFilter(int insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
~DynamicFilter();
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpsr);
|
||||
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
|
||||
// void setdryonly();
|
||||
|
||||
private:
|
||||
//Parametrii DynamicFilter
|
||||
EffectLFO lfo;//lfo-ul DynamicFilter
|
||||
unsigned char Pvolume;
|
||||
unsigned char Ppanning;
|
||||
unsigned char Pdepth;/**<the depth of the lfo of the DynamicFilter*/
|
||||
unsigned char Pampsns;/**<how the filter varies according to the input amplitude*/
|
||||
unsigned char Pampsnsinv;//if the filter freq is lowered if the input amplitude rises
|
||||
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 reinitfilter();
|
||||
|
||||
//Internal Values
|
||||
REALTYPE panning,depth,ampsns,ampsmooth;
|
||||
|
||||
Filter *filterl,*filterr;
|
||||
|
||||
REALTYPE ms1,ms2,ms3,ms4;//mean squares
|
||||
|
||||
private:
|
||||
//Parametrii DynamicFilter
|
||||
EffectLFO lfo;//lfo-ul DynamicFilter
|
||||
unsigned char Pvolume;
|
||||
unsigned char Ppanning;
|
||||
unsigned char Pdepth;/**<the depth of the lfo of the DynamicFilter*/
|
||||
unsigned char Pampsns;/**<how the filter varies according to the input amplitude*/
|
||||
unsigned char Pampsnsinv;//if the filter freq is lowered if the input amplitude rises
|
||||
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 reinitfilter();
|
||||
|
||||
//Internal Values
|
||||
REALTYPE panning,depth,ampsns,ampsmooth;
|
||||
|
||||
Filter *filterl,*filterr;
|
||||
|
||||
REALTYPE ms1,ms2,ms3,ms4;//mean squares
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
EQ.C - EQ effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "EQ.h"
|
||||
|
||||
EQ::EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0)
|
||||
{
|
||||
|
||||
for (int i=0;i<MAX_EQ_BANDS;i++){
|
||||
filter[i].Ptype=0;
|
||||
filter[i].Pfreq=64;
|
||||
filter[i].Pgain=64;
|
||||
filter[i].Pq=64;
|
||||
filter[i].Pstages=0;
|
||||
filter[i].l=new AnalogFilter(6,1000.0,1.0,0);
|
||||
filter[i].r=new AnalogFilter(6,1000.0,1.0,0);
|
||||
};
|
||||
//default values
|
||||
Pvolume=50;
|
||||
|
||||
setpreset(Ppreset);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
EQ::~EQ(){
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void EQ::cleanup(){
|
||||
for (int i=0;i<MAX_EQ_BANDS;i++){
|
||||
filter[i].l->cleanup();
|
||||
filter[i].r->cleanup();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Effect output
|
||||
*/
|
||||
void EQ::out(REALTYPE *smpsl,REALTYPE *smpsr){
|
||||
int i;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i]=smpsl[i]*volume;
|
||||
efxoutr[i]=smpsr[i]*volume;
|
||||
};
|
||||
|
||||
for (i=0;i<MAX_EQ_BANDS;i++){
|
||||
if (filter[i].Ptype==0) continue;
|
||||
filter[i].l->filterout(efxoutl);
|
||||
filter[i].r->filterout(efxoutr);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void EQ::setvolume(const unsigned char &Pvolume){
|
||||
this->Pvolume=Pvolume;
|
||||
|
||||
outvolume=pow(0.005,(1.0-Pvolume/127.0))*10.0;
|
||||
if (insertion==0) {
|
||||
volume=1.0;
|
||||
} else {
|
||||
volume=outvolume;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
void EQ::setpreset(unsigned char npreset){
|
||||
const int PRESET_SIZE=1;
|
||||
const int NUM_PRESETS=2;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//EQ 1
|
||||
{67},
|
||||
//EQ 2
|
||||
{67}};
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
|
||||
Ppreset=npreset;
|
||||
};
|
||||
|
||||
|
||||
void EQ::changepar(const int &npar,const unsigned char &value){
|
||||
switch (npar){
|
||||
case 0: setvolume(value);
|
||||
break;
|
||||
};
|
||||
if (npar<10) return;
|
||||
|
||||
int nb=(npar-10)/5;//number of the band (filter)
|
||||
if (nb>=MAX_EQ_BANDS) return;
|
||||
int bp=npar%5;//band paramenter
|
||||
|
||||
REALTYPE tmp;
|
||||
switch(bp){
|
||||
case 0: filter[nb].Ptype=value;
|
||||
if (value>9) filter[nb].Ptype=0;//has to be changed if more filters will be added
|
||||
if (filter[nb].Ptype!=0){
|
||||
filter[nb].l->settype(value-1);
|
||||
filter[nb].r->settype(value-1);
|
||||
};
|
||||
break;
|
||||
case 1: filter[nb].Pfreq=value;
|
||||
tmp=600.0*pow(30.0,(value-64.0)/64.0);
|
||||
filter[nb].l->setfreq(tmp);
|
||||
filter[nb].r->setfreq(tmp);
|
||||
break;
|
||||
case 2: filter[nb].Pgain=value;
|
||||
tmp=30.0*(value-64.0)/64.0;
|
||||
filter[nb].l->setgain(tmp);
|
||||
filter[nb].r->setgain(tmp);
|
||||
break;
|
||||
case 3: filter[nb].Pq=value;
|
||||
tmp=pow(30.0,(value-64.0)/64.0);
|
||||
filter[nb].l->setq(tmp);
|
||||
filter[nb].r->setq(tmp);
|
||||
break;
|
||||
case 4: filter[nb].Pstages=value;
|
||||
if (value>=MAX_FILTER_STAGES) filter[nb].Pstages=MAX_FILTER_STAGES-1;
|
||||
filter[nb].l->setstages(value);
|
||||
filter[nb].r->setstages(value);
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char EQ::getpar(const int &npar)const{
|
||||
switch (npar){
|
||||
case 0: return(Pvolume);
|
||||
break;
|
||||
};
|
||||
|
||||
if (npar<10) return(0);
|
||||
|
||||
int nb=(npar-10)/5;//number of the band (filter)
|
||||
if (nb>=MAX_EQ_BANDS) return(0);
|
||||
int bp=npar%5;//band paramenter
|
||||
switch(bp){
|
||||
case 0: return(filter[nb].Ptype);
|
||||
break;
|
||||
case 1: return(filter[nb].Pfreq);
|
||||
break;
|
||||
case 2: return(filter[nb].Pgain);
|
||||
break;
|
||||
case 3: return(filter[nb].Pq);
|
||||
break;
|
||||
case 4: return(filter[nb].Pstages);
|
||||
break;
|
||||
};
|
||||
|
||||
return(0);//in case of bogus parameter number
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
REALTYPE EQ::getfreqresponse(REALTYPE freq){
|
||||
REALTYPE resp=1.0;
|
||||
|
||||
for (int i=0;i<MAX_EQ_BANDS;i++){
|
||||
if (filter[i].Ptype==0) continue;
|
||||
resp*=filter[i].l->H(freq);
|
||||
};
|
||||
return(rap2dB(resp*outvolume));
|
||||
};
|
||||
|
||||
|
||||
214
plugins/zynaddsubfx/src/Effects/EQ.cpp
Normal file
214
plugins/zynaddsubfx/src/Effects/EQ.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
EQ.C - EQ effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "EQ.h"
|
||||
|
||||
EQ::EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0)
|
||||
{
|
||||
|
||||
for (int i=0;i<MAX_EQ_BANDS;i++) {
|
||||
filter[i].Ptype=0;
|
||||
filter[i].Pfreq=64;
|
||||
filter[i].Pgain=64;
|
||||
filter[i].Pq=64;
|
||||
filter[i].Pstages=0;
|
||||
filter[i].l=new AnalogFilter(6,1000.0,1.0,0);
|
||||
filter[i].r=new AnalogFilter(6,1000.0,1.0,0);
|
||||
};
|
||||
//default values
|
||||
Pvolume=50;
|
||||
|
||||
setpreset(Ppreset);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
EQ::~EQ()
|
||||
{
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void EQ::cleanup()
|
||||
{
|
||||
for (int i=0;i<MAX_EQ_BANDS;i++) {
|
||||
filter[i].l->cleanup();
|
||||
filter[i].r->cleanup();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Effect output
|
||||
*/
|
||||
void EQ::out(REALTYPE *smpsl,REALTYPE *smpsr)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
efxoutl[i]=smpsl[i]*volume;
|
||||
efxoutr[i]=smpsr[i]*volume;
|
||||
};
|
||||
|
||||
for (i=0;i<MAX_EQ_BANDS;i++) {
|
||||
if (filter[i].Ptype==0) continue;
|
||||
filter[i].l->filterout(efxoutl);
|
||||
filter[i].r->filterout(efxoutr);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void EQ::setvolume(const unsigned char &Pvolume)
|
||||
{
|
||||
this->Pvolume=Pvolume;
|
||||
|
||||
outvolume=pow(0.005,(1.0-Pvolume/127.0))*10.0;
|
||||
if (insertion==0) {
|
||||
volume=1.0;
|
||||
} else {
|
||||
volume=outvolume;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
void EQ::setpreset(unsigned char npreset)
|
||||
{
|
||||
const int PRESET_SIZE=1;
|
||||
const int NUM_PRESETS=2;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//EQ 1
|
||||
{67},
|
||||
//EQ 2
|
||||
{67}
|
||||
};
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
|
||||
Ppreset=npreset;
|
||||
};
|
||||
|
||||
|
||||
void EQ::changepar(const int &npar,const unsigned char &value)
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
setvolume(value);
|
||||
break;
|
||||
};
|
||||
if (npar<10) return;
|
||||
|
||||
int nb=(npar-10)/5;//number of the band (filter)
|
||||
if (nb>=MAX_EQ_BANDS) return;
|
||||
int bp=npar%5;//band paramenter
|
||||
|
||||
REALTYPE tmp;
|
||||
switch (bp) {
|
||||
case 0:
|
||||
filter[nb].Ptype=value;
|
||||
if (value>9) filter[nb].Ptype=0;//has to be changed if more filters will be added
|
||||
if (filter[nb].Ptype!=0) {
|
||||
filter[nb].l->settype(value-1);
|
||||
filter[nb].r->settype(value-1);
|
||||
};
|
||||
break;
|
||||
case 1:
|
||||
filter[nb].Pfreq=value;
|
||||
tmp=600.0*pow(30.0,(value-64.0)/64.0);
|
||||
filter[nb].l->setfreq(tmp);
|
||||
filter[nb].r->setfreq(tmp);
|
||||
break;
|
||||
case 2:
|
||||
filter[nb].Pgain=value;
|
||||
tmp=30.0*(value-64.0)/64.0;
|
||||
filter[nb].l->setgain(tmp);
|
||||
filter[nb].r->setgain(tmp);
|
||||
break;
|
||||
case 3:
|
||||
filter[nb].Pq=value;
|
||||
tmp=pow(30.0,(value-64.0)/64.0);
|
||||
filter[nb].l->setq(tmp);
|
||||
filter[nb].r->setq(tmp);
|
||||
break;
|
||||
case 4:
|
||||
filter[nb].Pstages=value;
|
||||
if (value>=MAX_FILTER_STAGES) filter[nb].Pstages=MAX_FILTER_STAGES-1;
|
||||
filter[nb].l->setstages(value);
|
||||
filter[nb].r->setstages(value);
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char EQ::getpar(const int &npar)const
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
return(Pvolume);
|
||||
break;
|
||||
};
|
||||
|
||||
if (npar<10) return(0);
|
||||
|
||||
int nb=(npar-10)/5;//number of the band (filter)
|
||||
if (nb>=MAX_EQ_BANDS) return(0);
|
||||
int bp=npar%5;//band paramenter
|
||||
switch (bp) {
|
||||
case 0:
|
||||
return(filter[nb].Ptype);
|
||||
break;
|
||||
case 1:
|
||||
return(filter[nb].Pfreq);
|
||||
break;
|
||||
case 2:
|
||||
return(filter[nb].Pgain);
|
||||
break;
|
||||
case 3:
|
||||
return(filter[nb].Pq);
|
||||
break;
|
||||
case 4:
|
||||
return(filter[nb].Pstages);
|
||||
break;
|
||||
};
|
||||
|
||||
return(0);//in case of bogus parameter number
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
REALTYPE EQ::getfreqresponse(REALTYPE freq)
|
||||
{
|
||||
REALTYPE resp=1.0;
|
||||
|
||||
for (int i=0;i<MAX_EQ_BANDS;i++) {
|
||||
if (filter[i].Ptype==0) continue;
|
||||
resp*=filter[i].l->H(freq);
|
||||
};
|
||||
return(rap2dB(resp*outvolume));
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
EQ.h - EQ Effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -28,29 +28,30 @@
|
||||
#include "Effect.h"
|
||||
|
||||
/**EQ Effect*/
|
||||
class EQ:public Effect{
|
||||
public:
|
||||
EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
~EQ();
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpr);
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
REALTYPE getfreqresponse(REALTYPE freq);
|
||||
private:
|
||||
//Parameters
|
||||
unsigned char Pvolume;/**<Volume*/
|
||||
|
||||
void setvolume(const unsigned char &Pvolume);
|
||||
|
||||
struct {
|
||||
//parameters
|
||||
unsigned char Ptype,Pfreq,Pgain,Pq,Pstages;
|
||||
//internal values
|
||||
AnalogFilter *l,*r;
|
||||
}filter[MAX_EQ_BANDS];
|
||||
|
||||
class EQ:public Effect
|
||||
{
|
||||
public:
|
||||
EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
~EQ();
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpr);
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
REALTYPE getfreqresponse(REALTYPE freq);
|
||||
private:
|
||||
//Parameters
|
||||
unsigned char Pvolume;/**<Volume*/
|
||||
|
||||
void setvolume(const unsigned char &Pvolume);
|
||||
|
||||
struct {
|
||||
//parameters
|
||||
unsigned char Ptype,Pfreq,Pgain,Pq,Pstages;
|
||||
//internal values
|
||||
AnalogFilter *l,*r;
|
||||
}filter[MAX_EQ_BANDS];
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Echo.C - Echo effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Echo.h"
|
||||
|
||||
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),ldelay(NULL),rdelay(NULL)
|
||||
{
|
||||
setpreset(Ppreset);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
Echo::~Echo(){
|
||||
delete[] ldelay;
|
||||
delete[] rdelay;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Echo::cleanup(){
|
||||
int i;
|
||||
for (i=0;i<dl;i++) ldelay[i]=0.0;
|
||||
for (i=0;i<dr;i++) rdelay[i]=0.0;
|
||||
oldl=0.0;
|
||||
oldr=0.0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the delays
|
||||
*/
|
||||
void Echo::initdelays(){
|
||||
kl=0;kr=0;
|
||||
dl=delay-lrdelay;if (dl<1) dl=1;
|
||||
dr=delay+lrdelay;if (dr<1) dr=1;
|
||||
|
||||
if (ldelay!=NULL) delete [] ldelay;
|
||||
if (rdelay!=NULL) delete [] rdelay;
|
||||
ldelay=new REALTYPE[dl];
|
||||
rdelay=new REALTYPE[dr];
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/*
|
||||
* Effect output
|
||||
*/
|
||||
void Echo::out(REALTYPE *const smpsl,REALTYPE *const smpsr){
|
||||
int i;
|
||||
REALTYPE l,r,ldl,rdl;
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
ldl=ldelay[kl];
|
||||
rdl=rdelay[kr];
|
||||
l=ldl*(1.0-lrcross)+rdl*lrcross;
|
||||
r=rdl*(1.0-lrcross)+ldl*lrcross;
|
||||
ldl=l;rdl=r;
|
||||
|
||||
efxoutl[i]=ldl*2.0;
|
||||
efxoutr[i]=rdl*2.0;
|
||||
ldl=smpsl[i]*panning-ldl*fb;
|
||||
rdl=smpsr[i]*(1.0-panning)-rdl*fb;
|
||||
|
||||
//LowPass Filter
|
||||
ldelay[kl]=ldl=ldl*hidamp+oldl*(1.0-hidamp);
|
||||
rdelay[kr]=rdl=rdl*hidamp+oldr*(1.0-hidamp);
|
||||
oldl=ldl;
|
||||
oldr=rdl;
|
||||
|
||||
if (++kl>=dl) kl=0;
|
||||
if (++kr>=dr) kr=0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Echo::setvolume(const unsigned char & Pvolume){
|
||||
this->Pvolume=Pvolume;
|
||||
|
||||
if (insertion==0) {
|
||||
outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0;
|
||||
volume=1.0;
|
||||
} else {
|
||||
volume=outvolume=Pvolume/127.0;
|
||||
};
|
||||
if (Pvolume==0) cleanup();
|
||||
|
||||
}
|
||||
|
||||
void Echo::setpanning(const unsigned char & Ppanning){
|
||||
this->Ppanning=Ppanning;
|
||||
panning=(Ppanning+0.5)/127.0;
|
||||
}
|
||||
|
||||
void Echo::setdelay(const unsigned char & 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){
|
||||
REALTYPE tmp;
|
||||
this->Plrdelay=Plrdelay;
|
||||
tmp=(pow(2,fabs(Plrdelay-64.0)/64.0*9)-1.0)/1000.0*SAMPLE_RATE;
|
||||
if (Plrdelay<64.0) tmp=-tmp;
|
||||
lrdelay=(int) tmp;
|
||||
initdelays();
|
||||
}
|
||||
|
||||
void Echo::setlrcross(const unsigned char & Plrcross){
|
||||
this->Plrcross=Plrcross;
|
||||
lrcross=Plrcross/127.0*1.0;
|
||||
}
|
||||
|
||||
void Echo::setfb(const unsigned char & Pfb){
|
||||
this->Pfb=Pfb;
|
||||
fb=Pfb/128.0;
|
||||
}
|
||||
|
||||
void Echo::sethidamp(const unsigned char & Phidamp){
|
||||
this->Phidamp=Phidamp;
|
||||
hidamp=1.0-Phidamp/127.0;
|
||||
}
|
||||
|
||||
void Echo::setpreset(unsigned char npreset){
|
||||
/**\todo see if the preset array can be replaced with a struct or a class*/
|
||||
const int PRESET_SIZE=7;
|
||||
const int NUM_PRESETS=9;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//Echo 1
|
||||
{67,64,35,64,30,59,0},
|
||||
//Echo 2
|
||||
{67,64,21,64,30,59,0},
|
||||
//Echo 3
|
||||
{67,75,60,64,30,59,10},
|
||||
//Simple Echo
|
||||
{67,60,44,64,30,0,0},
|
||||
//Canyon
|
||||
{67,60,102,50,30,82,48},
|
||||
//Panning Echo 1
|
||||
{67,64,44,17,0,82,24},
|
||||
//Panning Echo 2
|
||||
{81,60,46,118,100,68,18},
|
||||
//Panning Echo 3
|
||||
{81,60,26,100,127,67,36},
|
||||
//Feedback Echo
|
||||
{62,64,28,64,100,90,55}};
|
||||
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
|
||||
if (insertion!=0) setvolume(presets[npreset][0]/2);//lower the volume if this is insertion effect
|
||||
Ppreset=npreset;
|
||||
}
|
||||
|
||||
|
||||
void Echo::changepar(const int & npar,const unsigned char & value){
|
||||
/**\todo get rid of this leaky abstraction*/
|
||||
switch (npar){
|
||||
case 0: setvolume(value);
|
||||
break;
|
||||
case 1: setpanning(value);
|
||||
break;
|
||||
case 2: setdelay(value);
|
||||
break;
|
||||
case 3: setlrdelay(value);
|
||||
break;
|
||||
case 4: setlrcross(value);
|
||||
break;
|
||||
case 5: setfb(value);
|
||||
break;
|
||||
case 6: sethidamp(value);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
unsigned char Echo::getpar(const int & npar)const{
|
||||
/**\todo get rid of this leaky abstraction*/
|
||||
switch (npar){
|
||||
case 0: return(Pvolume);
|
||||
break;
|
||||
case 1: return(Ppanning);
|
||||
break;
|
||||
case 2: return(Pdelay);
|
||||
break;
|
||||
case 3: return(Plrdelay);
|
||||
break;
|
||||
case 4: return(Plrcross);
|
||||
break;
|
||||
case 5: return(Pfb);
|
||||
break;
|
||||
case 6: return(Phidamp);
|
||||
break;
|
||||
};
|
||||
return(0);// in case of bogus parameter number
|
||||
}
|
||||
|
||||
257
plugins/zynaddsubfx/src/Effects/Echo.cpp
Normal file
257
plugins/zynaddsubfx/src/Effects/Echo.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Echo.C - Echo effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <iostream>
|
||||
#include "Echo.h"
|
||||
|
||||
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)
|
||||
{
|
||||
setpreset(Ppreset);
|
||||
}
|
||||
|
||||
Echo::~Echo() {}
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Echo::cleanup()
|
||||
{
|
||||
delaySample.l().clear();
|
||||
delaySample.r().clear();
|
||||
old=Stereo<REALTYPE>(0.0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
old=Stereo<REALTYPE>(0.0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
void Echo::out(const Stereo<AuSample> &input)
|
||||
{
|
||||
//void Echo::out(const Stereo<AuSample> & input){ //ideal
|
||||
REALTYPE l,r,ldl,rdl;/**\todo move l+r->? 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;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Echo::setvolume(const unsigned char & Pvolume)
|
||||
{
|
||||
this->Pvolume=Pvolume;
|
||||
|
||||
if (insertion==0) {
|
||||
outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0;
|
||||
volume=1.0;
|
||||
} else {
|
||||
volume=outvolume=Pvolume/127.0;
|
||||
};
|
||||
if (Pvolume==0) cleanup();
|
||||
|
||||
}
|
||||
|
||||
void Echo::setpanning(const unsigned char & Ppanning)
|
||||
{
|
||||
this->Ppanning=Ppanning;
|
||||
panning=(Ppanning+0.5)/127.0;
|
||||
}
|
||||
|
||||
void Echo::setdelay(const unsigned char & Pdelay)
|
||||
{
|
||||
delay.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)
|
||||
{
|
||||
REALTYPE tmp;
|
||||
this->Plrdelay=Plrdelay;
|
||||
tmp=(pow(2,fabs(Plrdelay-64.0)/64.0*9)-1.0)/1000.0*SAMPLE_RATE;
|
||||
if (Plrdelay<64.0) tmp=-tmp;
|
||||
lrdelay=(int) tmp;
|
||||
initdelays();
|
||||
}
|
||||
|
||||
void Echo::setlrcross(const unsigned char & Plrcross)
|
||||
{
|
||||
this->Plrcross=Plrcross;
|
||||
lrcross=Plrcross/127.0*1.0;
|
||||
}
|
||||
|
||||
void Echo::setfb(const unsigned char & Pfb)
|
||||
{
|
||||
this->Pfb=Pfb;
|
||||
fb=Pfb/128.0;
|
||||
}
|
||||
|
||||
void Echo::sethidamp(const unsigned char & Phidamp)
|
||||
{
|
||||
this->Phidamp=Phidamp;
|
||||
hidamp=1.0-Phidamp/127.0;
|
||||
}
|
||||
|
||||
void Echo::setpreset(unsigned char npreset)
|
||||
{
|
||||
/**\todo see if the preset array can be replaced with a struct or a class*/
|
||||
const int PRESET_SIZE=7;
|
||||
const int NUM_PRESETS=9;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//Echo 1
|
||||
{67,64,35,64,30,59,0},
|
||||
//Echo 2
|
||||
{67,64,21,64,30,59,0},
|
||||
//Echo 3
|
||||
{67,75,60,64,30,59,10},
|
||||
//Simple Echo
|
||||
{67,60,44,64,30,0,0},
|
||||
//Canyon
|
||||
{67,60,102,50,30,82,48},
|
||||
//Panning Echo 1
|
||||
{67,64,44,17,0,82,24},
|
||||
//Panning Echo 2
|
||||
{81,60,46,118,100,68,18},
|
||||
//Panning Echo 3
|
||||
{81,60,26,100,127,67,36},
|
||||
//Feedback Echo
|
||||
{62,64,28,64,100,90,55}
|
||||
};
|
||||
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
|
||||
if (insertion) setvolume(presets[npreset][0]/2);//lower the volume if this is insertion effect
|
||||
Ppreset=npreset;
|
||||
}
|
||||
|
||||
|
||||
void Echo::changepar(const int & npar,const unsigned char & value)
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
setvolume(value);
|
||||
break;
|
||||
case 1:
|
||||
setpanning(value);
|
||||
break;
|
||||
case 2:
|
||||
setdelay(value);
|
||||
break;
|
||||
case 3:
|
||||
setlrdelay(value);
|
||||
break;
|
||||
case 4:
|
||||
setlrcross(value);
|
||||
break;
|
||||
case 5:
|
||||
setfb(value);
|
||||
break;
|
||||
case 6:
|
||||
sethidamp(value);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
unsigned char Echo::getpar(const int & npar)const
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
return(Pvolume);
|
||||
break;
|
||||
case 1:
|
||||
return(Ppanning);
|
||||
break;
|
||||
case 2:
|
||||
return(delay.getmVal());
|
||||
break;
|
||||
case 3:
|
||||
return(Plrdelay);
|
||||
break;
|
||||
case 4:
|
||||
return(Plrcross);
|
||||
break;
|
||||
case 5:
|
||||
return(Pfb);
|
||||
break;
|
||||
case 6:
|
||||
return(Phidamp);
|
||||
break;
|
||||
};
|
||||
return(0);// in case of bogus parameter number
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Echo.h - Echo Effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -25,108 +25,112 @@
|
||||
|
||||
#include "../globals.h"
|
||||
#include "Effect.h"
|
||||
#include "../Samples/AuSample.h"
|
||||
#include "../Misc/Stereo.h"
|
||||
#include "../Controls/DelayCtl.h"
|
||||
|
||||
/**Echo Effect*/
|
||||
class Echo:public Effect{
|
||||
public:
|
||||
class Echo:public Effect
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* The Constructor For Echo
|
||||
* @param insertion_ integer to determine if Echo is an insertion effect
|
||||
* or not
|
||||
* @param efxoutl_ Effect out Left Channel
|
||||
* @param efxoutr_ Effect out Right Channel
|
||||
* @return An initialized Echo Object
|
||||
*/
|
||||
Echo(const int & insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_);
|
||||
/**
|
||||
* The Constructor For Echo
|
||||
* @param insertion_ integer to determine if Echo is an insertion effect
|
||||
* or not
|
||||
* @param efxoutl_ Effect out Left Channel
|
||||
* @param efxoutr_ Effect out Right Channel
|
||||
* @return An initialized Echo Object
|
||||
*/
|
||||
Echo(const int & insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_);
|
||||
|
||||
/**
|
||||
* The destructor
|
||||
*/
|
||||
~Echo();
|
||||
/**
|
||||
* The destructor
|
||||
*/
|
||||
~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
|
||||
*/
|
||||
void out(REALTYPE *const smpsl,REALTYPE *const smpr);
|
||||
|
||||
/**
|
||||
* Sets the state of Echo to the specified preset
|
||||
* @param npreset number of chosen preset
|
||||
*/
|
||||
void setpreset(unsigned char npreset);
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Sets the value of the chosen variable
|
||||
*
|
||||
* The possible parameters are:
|
||||
* -# Volume
|
||||
* -# Panning
|
||||
* -# Delay
|
||||
* -# L/R Delay
|
||||
* -# L/R Crossover
|
||||
* -# Feedback
|
||||
* -# Dampening
|
||||
* @param npar number of chosen parameter
|
||||
* @param value the new value
|
||||
*/
|
||||
void changepar(const int & npar,const unsigned char & value);
|
||||
/**
|
||||
* Sets the state of Echo to the specified preset
|
||||
* @param npreset number of chosen preset
|
||||
*/
|
||||
void setpreset(unsigned char npreset);
|
||||
|
||||
/**
|
||||
* Gets the specified parameter
|
||||
*
|
||||
* The possible parameters are
|
||||
* -# Volume
|
||||
* -# Panning
|
||||
* -# Delay
|
||||
* -# L/R Delay
|
||||
* -# L/R Crossover
|
||||
* -# Feedback
|
||||
* -# Dampening
|
||||
* @param npar number of chosen parameter
|
||||
* @return value of parameter
|
||||
*
|
||||
* \todo make this method use constant variables by reference
|
||||
*Currently doing so results in strange behavior
|
||||
*/
|
||||
unsigned char getpar(const int & npar)const;
|
||||
/**
|
||||
* Sets the value of the chosen variable
|
||||
*
|
||||
* The possible parameters are:
|
||||
* -# Volume
|
||||
* -# Panning
|
||||
* -# Delay
|
||||
* -# L/R Delay
|
||||
* -# L/R Crossover
|
||||
* -# Feedback
|
||||
* -# Dampening
|
||||
* @param npar number of chosen parameter
|
||||
* @param value the new value
|
||||
*/
|
||||
void changepar(const int & npar,const unsigned char & value);
|
||||
|
||||
/**Zeros out the state of the Echo*/
|
||||
void cleanup();
|
||||
|
||||
/**\todo This function needs to be implemented or the prototype should be removed*/
|
||||
void setdryonly();
|
||||
private:
|
||||
/**\todo remove all of these once they have been depreciated*/
|
||||
//Parameters
|
||||
unsigned char Pvolume;/**<#1 Volume or Dry/Wetness*/
|
||||
unsigned char Ppanning;/**<#2 Panning*/
|
||||
unsigned char Pdelay;/**<#3 Delay of the Echo*/
|
||||
unsigned char Plrdelay;/**<#4 L/R delay difference*/
|
||||
unsigned char Plrcross;/**<#5 L/R Mixing*/
|
||||
unsigned char Pfb;/**<#6Feedback*/
|
||||
unsigned 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);
|
||||
/**
|
||||
* Gets the specified parameter
|
||||
*
|
||||
* The possible parameters are
|
||||
* -# Volume
|
||||
* -# Panning
|
||||
* -# Delay
|
||||
* -# L/R Delay
|
||||
* -# L/R Crossover
|
||||
* -# Feedback
|
||||
* -# Dampening
|
||||
* @param npar number of chosen parameter
|
||||
* @return value of parameter
|
||||
*/
|
||||
unsigned char getpar(const int & npar)const;
|
||||
|
||||
//Real Parameters
|
||||
REALTYPE panning,lrcross,fb,hidamp;
|
||||
int dl,dr,delay,lrdelay;
|
||||
|
||||
void initdelays();
|
||||
REALTYPE *ldelay,*rdelay;
|
||||
REALTYPE oldl,oldr;//pt. lpf
|
||||
int kl,kr;
|
||||
int getnumparams();
|
||||
|
||||
/**Zeros out the state of the Echo*/
|
||||
void cleanup();
|
||||
|
||||
/**\todo This function needs to be implemented or the prototype should be removed*/
|
||||
void setdryonly();
|
||||
private:
|
||||
//Parameters
|
||||
char Pvolume;/**<#1 Volume or Dry/Wetness*/
|
||||
char Ppanning;/**<#2 Panning*/
|
||||
DelayCtl delay;/**<#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*/
|
||||
|
||||
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);
|
||||
|
||||
//Real Parameters
|
||||
REALTYPE panning,lrcross,fb,hidamp; //needs better names
|
||||
int dl,dr,lrdelay; //needs better names
|
||||
|
||||
void initdelays();
|
||||
Stereo<AuSample> delaySample;
|
||||
Stereo<REALTYPE> old;
|
||||
|
||||
int kl,kr;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Effect.C - this class is inherited by the all effects(Reverb, Echo, ..)
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -22,9 +22,9 @@
|
||||
|
||||
#include "Effect.h"
|
||||
|
||||
|
||||
Effect::Effect(const int & insertion_,REALTYPE *const efxoutl_,
|
||||
|
||||
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_){}
|
||||
:Ppreset(Ppreset_),efxoutl(efxoutl_),efxoutr(efxoutr_),
|
||||
filterpars(filterpars_),insertion(insertion_) {}
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Effect.h - this class is inherited by the all effects(Reverb, Echo, ..)
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -23,82 +23,81 @@
|
||||
#ifndef EFFECT_H
|
||||
#define EFFECT_H
|
||||
|
||||
#include <valarray>
|
||||
#include "../Misc/Util.h"
|
||||
#include "../globals.h"
|
||||
#include "../Params/FilterParams.h"
|
||||
|
||||
|
||||
/**this class is inherited by the all effects(Reverb, Echo, ..)*/
|
||||
class Effect{
|
||||
public:
|
||||
/**
|
||||
* Effect Constructor
|
||||
* @param insertion_ 1 when it is an insertion Effect and 0 when it
|
||||
* is not an insertion Effect
|
||||
* @param efxoutl_ Effect output buffer Left channel
|
||||
* @param efxoutr_ Effect output buffer Right channel
|
||||
* @param filterpars_ pointer to FilterParams array
|
||||
* @param Ppreset_ chosen preset
|
||||
* @return Initialized Effect object*/
|
||||
Effect(const int & insertion_,REALTYPE *const efxoutl_,
|
||||
REALTYPE *const efxoutr_,FilterParams *filterpars_,
|
||||
const unsigned char & Ppreset_);
|
||||
/**Deconstructor
|
||||
*
|
||||
* Deconstructs the Effect and releases any resouces that it has
|
||||
* allocated for itself*/
|
||||
virtual ~Effect(){};
|
||||
/**
|
||||
* Choose a preset
|
||||
* @param npreset number of chosen preset*/
|
||||
virtual void setpreset(unsigned char npreset)=0;
|
||||
/**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;
|
||||
/**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;
|
||||
/**Output result of effect based on the given buffers
|
||||
*
|
||||
* This method should result in the effect generating its results
|
||||
* and placing them into the efxoutl and efxoutr buffers.
|
||||
* Every Effect should overide this method.
|
||||
*
|
||||
* @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;
|
||||
/**Reset the state of the effect*/
|
||||
virtual void cleanup(){};
|
||||
/**This is only used for EQ (for user interface)*/
|
||||
virtual REALTYPE getfreqresponse(REALTYPE freq){return (0);};
|
||||
class Effect
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Effect Constructor
|
||||
* @param insertion_ 1 when it is an insertion Effect and 0 when it
|
||||
* is not an insertion Effect
|
||||
* @param efxoutl_ Effect output buffer Left channel
|
||||
* @param efxoutr_ Effect output buffer Right channel
|
||||
* @param filterpars_ pointer to FilterParams array
|
||||
* @param Ppreset_ chosen preset
|
||||
* @return Initialized Effect object*/
|
||||
Effect(bool insertion_,REALTYPE *const efxoutl_,
|
||||
REALTYPE *const efxoutr_,FilterParams *filterpars_,
|
||||
const unsigned char & Ppreset_);
|
||||
/**Deconstructor
|
||||
*
|
||||
* Deconstructs the Effect and releases any resouces that it has
|
||||
* allocated for itself*/
|
||||
virtual ~Effect() {};
|
||||
/**
|
||||
* Choose a preset
|
||||
* @param npreset number of chosen preset*/
|
||||
virtual void setpreset(unsigned char npreset)=0;
|
||||
/**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;
|
||||
/**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;
|
||||
/**Output result of effect based on the given buffers
|
||||
*
|
||||
* This method should result in the effect generating its results
|
||||
* and placing them into the efxoutl and efxoutr buffers.
|
||||
* Every Effect should overide this method.
|
||||
*
|
||||
* @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;
|
||||
/**Reset the state of the effect*/
|
||||
virtual void cleanup() {};
|
||||
/**This is only used for EQ (for user interface)*/
|
||||
virtual REALTYPE getfreqresponse(REALTYPE freq) {
|
||||
return (0);
|
||||
};
|
||||
|
||||
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*/
|
||||
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*/
|
||||
|
||||
REALTYPE outvolume;/**<This is the volume of effect and is public because
|
||||
REALTYPE outvolume;/**<This is the volume of effect and is public because
|
||||
* it is needed in system effects.
|
||||
* The out volume of such effects are always 1.0, so
|
||||
* this setting tells me how is the volume to the
|
||||
* Master Output only.*/
|
||||
|
||||
REALTYPE volume;
|
||||
REALTYPE volume;
|
||||
|
||||
FilterParams *filterpars;/**<Parameters for filters used by Effect*/
|
||||
protected:
|
||||
FilterParams *filterpars;/**<Parameters for filters used by Effect*/
|
||||
protected:
|
||||
|
||||
const int insertion;/**<If Effect is an insertion effect, insertion=1
|
||||
const bool insertion;/**<If Effect is an insertion effect, insertion=1
|
||||
*otherwise, it should be insertion=0*/
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
EffectLFO.C - Stereo LFO used by some effects
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -26,13 +26,15 @@
|
||||
#include "EffectLFO.h"
|
||||
|
||||
|
||||
EffectLFO::EffectLFO(){
|
||||
xl=0.0;xr=0.0;
|
||||
EffectLFO::EffectLFO()
|
||||
{
|
||||
xl=0.0;
|
||||
xr=0.0;
|
||||
Pfreq=40;
|
||||
Prandomness=0;
|
||||
PLFOtype=0;
|
||||
Pstereo=96;
|
||||
|
||||
|
||||
updateparams();
|
||||
|
||||
ampl1=(1-lfornd)+lfornd*RND;
|
||||
@@ -41,20 +43,23 @@ EffectLFO::EffectLFO(){
|
||||
ampr2=(1-lfornd)+lfornd*RND;
|
||||
};
|
||||
|
||||
EffectLFO::~EffectLFO(){
|
||||
EffectLFO::~EffectLFO()
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Update the changed parameters
|
||||
*/
|
||||
void EffectLFO::updateparams(){
|
||||
void EffectLFO::updateparams()
|
||||
{
|
||||
REALTYPE lfofreq=(pow(2,Pfreq/127.0*10.0)-1.0)*0.03;
|
||||
incx=fabs(lfofreq)*(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE;
|
||||
if (incx>0.49999999) incx=0.499999999; //Limit the Frequency
|
||||
|
||||
lfornd=Prandomness/127.0;
|
||||
if (lfornd<0.0) lfornd=0.0; else if (lfornd>1.0) lfornd=1.0;
|
||||
if (lfornd<0.0) lfornd=0.0;
|
||||
else if (lfornd>1.0) lfornd=1.0;
|
||||
|
||||
if (PLFOtype>1) PLFOtype=1;//this has to be updated if more lfo's are added
|
||||
lfotype=PLFOtype;
|
||||
@@ -66,16 +71,18 @@ void EffectLFO::updateparams(){
|
||||
/*
|
||||
* Compute the shape of the LFO
|
||||
*/
|
||||
REALTYPE EffectLFO::getlfoshape(REALTYPE x){
|
||||
REALTYPE EffectLFO::getlfoshape(REALTYPE x)
|
||||
{
|
||||
REALTYPE out;
|
||||
switch (lfotype){
|
||||
case 1: //EffectLFO_TRIANGLE
|
||||
if ((x>0.0)&&(x<0.25)) out=4.0*x;
|
||||
else if ((x>0.25)&&(x<0.75)) out=2-4*x;
|
||||
else out=4.0*x-4.0;
|
||||
break;
|
||||
/**\todo more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)*/
|
||||
default:out=cos(x*2*PI);//EffectLFO_SINE
|
||||
switch (lfotype) {
|
||||
case 1: //EffectLFO_TRIANGLE
|
||||
if ((x>0.0)&&(x<0.25)) out=4.0*x;
|
||||
else if ((x>0.25)&&(x<0.75)) out=2-4*x;
|
||||
else out=4.0*x-4.0;
|
||||
break;
|
||||
/**\todo more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)*/
|
||||
default:
|
||||
out=cos(x*2*PI);//EffectLFO_SINE
|
||||
};
|
||||
return(out);
|
||||
};
|
||||
@@ -83,16 +90,17 @@ REALTYPE EffectLFO::getlfoshape(REALTYPE x){
|
||||
/*
|
||||
* LFO output
|
||||
*/
|
||||
void EffectLFO::effectlfoout(REALTYPE *outl,REALTYPE *outr){
|
||||
REALTYPE out;
|
||||
|
||||
void EffectLFO::effectlfoout(REALTYPE *outl,REALTYPE *outr)
|
||||
{
|
||||
REALTYPE out;
|
||||
|
||||
out=getlfoshape(xl);
|
||||
if ((lfotype==0)||(lfotype==1)) out*=(ampl1+xl*(ampl2-ampl1));
|
||||
xl+=incx;
|
||||
if (xl>1.0) {
|
||||
xl-=1.0;
|
||||
ampl1=ampl2;
|
||||
ampl2=(1.0-lfornd)+lfornd*RND;
|
||||
xl-=1.0;
|
||||
ampl1=ampl2;
|
||||
ampl2=(1.0-lfornd)+lfornd*RND;
|
||||
};
|
||||
*outl=(out+1.0)*0.5;
|
||||
|
||||
@@ -100,9 +108,9 @@ void EffectLFO::effectlfoout(REALTYPE *outl,REALTYPE *outr){
|
||||
if ((lfotype==0)||(lfotype==1)) out*=(ampr1+xr*(ampr2-ampr1));
|
||||
xr+=incx;
|
||||
if (xr>1.0) {
|
||||
xr-=1.0;
|
||||
ampr1=ampr2;
|
||||
ampr2=(1.0-lfornd)+lfornd*RND;
|
||||
xr-=1.0;
|
||||
ampr1=ampr2;
|
||||
ampr2=(1.0-lfornd)+lfornd*RND;
|
||||
};
|
||||
*outr=(out+1.0)*0.5;
|
||||
};
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
EffectLFO.h - Stereo LFO used by some effects
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -24,9 +24,11 @@
|
||||
#define EFFECT_LFO_H
|
||||
|
||||
#include "../globals.h"
|
||||
/**LFO for some of the Effect objects*/
|
||||
class EffectLFO{
|
||||
public:
|
||||
/**LFO for some of the Effect objects
|
||||
* \todo see if this should inherit LFO*/
|
||||
class EffectLFO
|
||||
{
|
||||
public:
|
||||
EffectLFO();
|
||||
~EffectLFO();
|
||||
void effectlfoout(REALTYPE *outl,REALTYPE *outr);
|
||||
@@ -35,15 +37,15 @@ class EffectLFO{
|
||||
unsigned char Prandomness;
|
||||
unsigned char PLFOtype;
|
||||
unsigned char Pstereo;//"64"=0
|
||||
private:
|
||||
private:
|
||||
REALTYPE getlfoshape(REALTYPE x);
|
||||
|
||||
|
||||
REALTYPE xl,xr;
|
||||
REALTYPE incx;
|
||||
REALTYPE ampl1,ampl2,ampr1,ampr2;//necessary for "randomness"
|
||||
REALTYPE lfointensity;
|
||||
REALTYPE lfornd;
|
||||
char lfotype; /**\todo GET RID OF CHAR (use a subclass if types are needed)*/
|
||||
char lfotype; /**\todo GET RID OF CHAR (replace with short or enum)*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
EffectMgr.C - Effect manager, an interface betwen the program and effects
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "EffectMgr.h"
|
||||
|
||||
EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_)
|
||||
:insertion(insertion_),
|
||||
efxoutl(new REALTYPE[SOUND_BUFFER_SIZE]),
|
||||
efxoutr(new REALTYPE[SOUND_BUFFER_SIZE]),
|
||||
filterpars(NULL),nefx(0),efx(NULL),mutex(mutex_),dryonly(false)
|
||||
{
|
||||
setpresettype("Peffect"); /**\todo Figure out what this is doing
|
||||
* , as it might be another leaky abstraction.*/
|
||||
// efx=NULL;
|
||||
// nefx=0;
|
||||
// insertion=insertion_;
|
||||
// mutex=mutex_;
|
||||
// efxoutl=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
// efxoutr=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i]=0.0;
|
||||
efxoutr[i]=0.0;
|
||||
};
|
||||
// filterpars=NULL;
|
||||
// dryonly=false;
|
||||
defaults();
|
||||
}
|
||||
|
||||
|
||||
EffectMgr::~EffectMgr(){
|
||||
if (efx!=NULL) delete efx;
|
||||
delete []efxoutl;
|
||||
delete []efxoutr;
|
||||
}
|
||||
|
||||
void EffectMgr::defaults(){
|
||||
changeeffect(0);
|
||||
setdryonly(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the effect
|
||||
*/
|
||||
void EffectMgr::changeeffect(int nefx_){
|
||||
cleanup();
|
||||
if (nefx==nefx_) return;
|
||||
nefx=nefx_;
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i]=0.0;
|
||||
efxoutr[i]=0.0;
|
||||
};
|
||||
|
||||
if (efx!=NULL) delete efx;
|
||||
switch (nefx){ /**\todo replace leaky abstraction*/
|
||||
case 1:efx=new Reverb(insertion,efxoutl,efxoutr);break;
|
||||
case 2:efx=new Echo(insertion,efxoutl,efxoutr);break;
|
||||
case 3:efx=new Chorus(insertion,efxoutl,efxoutr);break;
|
||||
case 4:efx=new Phaser(insertion,efxoutl,efxoutr);break;
|
||||
case 5:efx=new Alienwah(insertion,efxoutl,efxoutr);break;
|
||||
case 6:efx=new Distorsion(insertion,efxoutl,efxoutr);break;
|
||||
case 7:efx=new EQ(insertion,efxoutl,efxoutr);break;
|
||||
case 8:efx=new DynamicFilter(insertion,efxoutl,efxoutr);break;
|
||||
//put more effect here
|
||||
default:efx=NULL;break;//no effect (thru)
|
||||
};
|
||||
|
||||
if (efx!=NULL) filterpars=efx->filterpars;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the effect number
|
||||
*/
|
||||
int EffectMgr::geteffect(){
|
||||
return (nefx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup the current effect
|
||||
*/
|
||||
void EffectMgr::cleanup(){
|
||||
if (efx!=NULL) efx->cleanup();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the preset of the current effect
|
||||
*/
|
||||
|
||||
unsigned char EffectMgr::getpreset(){
|
||||
if (efx!=NULL) return(efx->Ppreset);
|
||||
else return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the preset of the current effect
|
||||
*/
|
||||
void EffectMgr::changepreset_nolock(unsigned char npreset){
|
||||
if (efx!=NULL) efx->setpreset(npreset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the preset of the current effect(with thread locking)
|
||||
*/
|
||||
void EffectMgr::changepreset(unsigned char npreset){
|
||||
pthread_mutex_lock(mutex);
|
||||
changepreset_nolock(npreset);
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Change a parameter of the current effect
|
||||
*/
|
||||
void EffectMgr::seteffectpar_nolock(int npar,unsigned char value){
|
||||
if (efx==NULL) return;
|
||||
efx->changepar(npar,value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change a parameter of the current effect (with thread locking)
|
||||
*/
|
||||
void EffectMgr::seteffectpar(int npar,unsigned char value){
|
||||
pthread_mutex_lock(mutex);
|
||||
seteffectpar_nolock(npar,value);
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a parameter of the current effect
|
||||
*/
|
||||
unsigned char EffectMgr::geteffectpar(int npar){
|
||||
if (efx==NULL) return(0);
|
||||
return(efx->getpar(npar));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Apply the effect
|
||||
*/
|
||||
void EffectMgr::out(REALTYPE *smpsl,REALTYPE *smpsr){
|
||||
int i;
|
||||
if (efx==NULL){
|
||||
if (insertion==0)
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
smpsl[i]=0.0;smpsr[i]=0.0;
|
||||
efxoutl[i]=0.0;efxoutr[i]=0.0;
|
||||
};
|
||||
return;
|
||||
};
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
smpsl[i]+=denormalkillbuf[i];
|
||||
smpsr[i]+=denormalkillbuf[i];
|
||||
efxoutl[i]=0.0;
|
||||
efxoutr[i]=0.0;
|
||||
};
|
||||
efx->out(smpsl,smpsr);
|
||||
|
||||
REALTYPE volume=efx->volume;
|
||||
|
||||
if (nefx==7){//this is need only for the EQ effect
|
||||
/**\todo figure out why*/
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
smpsl[i]=efxoutl[i];
|
||||
smpsr[i]=efxoutr[i];
|
||||
};
|
||||
return;
|
||||
};
|
||||
|
||||
//Insertion effect
|
||||
if (insertion!=0) {
|
||||
REALTYPE v1,v2;
|
||||
if (volume<0.5) {
|
||||
v1=1.0;
|
||||
v2=volume*2.0;
|
||||
} else {
|
||||
v1=(1.0-volume)*2.0;
|
||||
v2=1.0;
|
||||
};
|
||||
if ((nefx==1)||(nefx==2)) v2*=v2;//for Reverb and Echo, the wet function is not liniar
|
||||
|
||||
if (dryonly){//this is used for instrument effect only
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
smpsl[i]*=v1;
|
||||
smpsr[i]*=v1;
|
||||
efxoutl[i]*=v2;
|
||||
efxoutr[i]*=v2;
|
||||
};
|
||||
}else{//normal instrument/insertion effect
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
smpsl[i]=smpsl[i]*v1+efxoutl[i]*v2;
|
||||
smpsr[i]=smpsr[i]*v1+efxoutr[i]*v2;
|
||||
};
|
||||
};
|
||||
} else {//System effect
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i]*=2.0*volume;
|
||||
efxoutr[i]*=2.0*volume;
|
||||
smpsl[i]=efxoutl[i];
|
||||
smpsr[i]=efxoutr[i];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the effect volume for the system effect
|
||||
*/
|
||||
REALTYPE EffectMgr::sysefxgetvolume(){
|
||||
if (efx==NULL) return (1.0);
|
||||
else return(efx->outvolume);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the EQ response
|
||||
*/
|
||||
REALTYPE EffectMgr::getEQfreqresponse(REALTYPE freq){
|
||||
if (nefx==7) return(efx->getfreqresponse(freq));
|
||||
else return(0.0);
|
||||
}
|
||||
|
||||
|
||||
void EffectMgr::setdryonly(bool value){
|
||||
dryonly=value;
|
||||
}
|
||||
|
||||
void EffectMgr::add2XML(XMLwrapper *xml){
|
||||
xml->addpar("type",geteffect());
|
||||
|
||||
if ((efx==NULL)||(geteffect()==0)) return;
|
||||
xml->addpar("preset",efx->Ppreset);
|
||||
|
||||
xml->beginbranch("EFFECT_PARAMETERS");
|
||||
for (int n=0;n<128;n++){ /**\todo evaluate who should oversee saving
|
||||
* and loading of parameters*/
|
||||
int par=geteffectpar(n);
|
||||
if (par==0) continue;
|
||||
xml->beginbranch("par_no",n);
|
||||
xml->addpar("par",par);
|
||||
xml->endbranch();
|
||||
};
|
||||
if (filterpars!=NULL){
|
||||
xml->beginbranch("FILTER");
|
||||
filterpars->add2XML(xml);
|
||||
xml->endbranch();
|
||||
};
|
||||
xml->endbranch();
|
||||
}
|
||||
|
||||
void EffectMgr::getfromXML(XMLwrapper *xml){
|
||||
changeeffect(xml->getpar127("type",geteffect()));
|
||||
|
||||
if ((efx==NULL)||(geteffect()==0)) return;
|
||||
|
||||
efx->Ppreset=xml->getpar127("preset",efx->Ppreset);
|
||||
|
||||
if (xml->enterbranch("EFFECT_PARAMETERS")){
|
||||
for (int n=0;n<128;n++){
|
||||
seteffectpar_nolock(n,0);//erase effect parameter
|
||||
if (xml->enterbranch("par_no",n)==0) continue;
|
||||
|
||||
int par=geteffectpar(n);
|
||||
seteffectpar_nolock(n,xml->getpar127("par",par));
|
||||
xml->exitbranch();
|
||||
};
|
||||
if (filterpars!=NULL){
|
||||
if (xml->enterbranch("FILTER")){
|
||||
filterpars->getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
};
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
cleanup();
|
||||
}
|
||||
|
||||
332
plugins/zynaddsubfx/src/Effects/EffectMgr.cpp
Normal file
332
plugins/zynaddsubfx/src/Effects/EffectMgr.cpp
Normal file
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
EffectMgr.C - Effect manager, an interface betwen the program and effects
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "EffectMgr.h"
|
||||
|
||||
EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_)
|
||||
:insertion(insertion_),
|
||||
efxoutl(new REALTYPE[SOUND_BUFFER_SIZE]),
|
||||
efxoutr(new REALTYPE[SOUND_BUFFER_SIZE]),
|
||||
filterpars(NULL),nefx(0),efx(NULL),mutex(mutex_),dryonly(false)
|
||||
{
|
||||
setpresettype("Peffect"); /**\todo Figure out what this is doing
|
||||
* , as it might be another leaky abstraction.*/
|
||||
// efx=NULL;
|
||||
// nefx=0;
|
||||
// insertion=insertion_;
|
||||
// mutex=mutex_;
|
||||
// efxoutl=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
// efxoutr=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
efxoutl[i]=0.0;
|
||||
efxoutr[i]=0.0;
|
||||
};
|
||||
// filterpars=NULL;
|
||||
// dryonly=false;
|
||||
defaults();
|
||||
}
|
||||
|
||||
|
||||
EffectMgr::~EffectMgr()
|
||||
{
|
||||
if (efx!=NULL) delete efx;
|
||||
delete []efxoutl;
|
||||
delete []efxoutr;
|
||||
}
|
||||
|
||||
void EffectMgr::defaults()
|
||||
{
|
||||
changeeffect(0);
|
||||
setdryonly(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the effect
|
||||
*/
|
||||
void EffectMgr::changeeffect(int nefx_)
|
||||
{
|
||||
cleanup();
|
||||
if (nefx==nefx_) return;
|
||||
nefx=nefx_;
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
efxoutl[i]=0.0;
|
||||
efxoutr[i]=0.0;
|
||||
};
|
||||
|
||||
if (efx!=NULL) delete efx;
|
||||
switch (nefx) { /**\todo replace leaky abstraction*/
|
||||
case 1:
|
||||
efx=new Reverb(insertion,efxoutl,efxoutr);
|
||||
break;
|
||||
case 2:
|
||||
efx=new Echo(insertion,efxoutl,efxoutr);
|
||||
break;
|
||||
case 3:
|
||||
efx=new Chorus(insertion,efxoutl,efxoutr);
|
||||
break;
|
||||
case 4:
|
||||
efx=new Phaser(insertion,efxoutl,efxoutr);
|
||||
break;
|
||||
case 5:
|
||||
efx=new Alienwah(insertion,efxoutl,efxoutr);
|
||||
break;
|
||||
case 6:
|
||||
efx=new Distorsion(insertion,efxoutl,efxoutr);
|
||||
break;
|
||||
case 7:
|
||||
efx=new EQ(insertion,efxoutl,efxoutr);
|
||||
break;
|
||||
case 8:
|
||||
efx=new DynamicFilter(insertion,efxoutl,efxoutr);
|
||||
break;
|
||||
//put more effect here
|
||||
default:
|
||||
efx=NULL;
|
||||
break;//no effect (thru)
|
||||
};
|
||||
|
||||
if (efx!=NULL) filterpars=efx->filterpars;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the effect number
|
||||
*/
|
||||
int EffectMgr::geteffect()
|
||||
{
|
||||
return (nefx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup the current effect
|
||||
*/
|
||||
void EffectMgr::cleanup()
|
||||
{
|
||||
if (efx!=NULL) efx->cleanup();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the preset of the current effect
|
||||
*/
|
||||
|
||||
unsigned char EffectMgr::getpreset()
|
||||
{
|
||||
if (efx!=NULL) return(efx->Ppreset);
|
||||
else return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the preset of the current effect
|
||||
*/
|
||||
void EffectMgr::changepreset_nolock(unsigned char npreset)
|
||||
{
|
||||
if (efx!=NULL) efx->setpreset(npreset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the preset of the current effect(with thread locking)
|
||||
*/
|
||||
void EffectMgr::changepreset(unsigned char npreset)
|
||||
{
|
||||
pthread_mutex_lock(mutex);
|
||||
changepreset_nolock(npreset);
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Change a parameter of the current effect
|
||||
*/
|
||||
void EffectMgr::seteffectpar_nolock(int npar,unsigned char value)
|
||||
{
|
||||
if (efx==NULL) return;
|
||||
efx->changepar(npar,value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change a parameter of the current effect (with thread locking)
|
||||
*/
|
||||
void EffectMgr::seteffectpar(int npar,unsigned char value)
|
||||
{
|
||||
pthread_mutex_lock(mutex);
|
||||
seteffectpar_nolock(npar,value);
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a parameter of the current effect
|
||||
*/
|
||||
unsigned char EffectMgr::geteffectpar(int npar)
|
||||
{
|
||||
if (efx==NULL) return(0);
|
||||
return(efx->getpar(npar));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Apply the effect
|
||||
*/
|
||||
void EffectMgr::out(REALTYPE *smpsl,REALTYPE *smpsr)
|
||||
{
|
||||
int i;
|
||||
if (efx==NULL) {
|
||||
if (insertion==0)
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
smpsl[i]=0.0;
|
||||
smpsr[i]=0.0;
|
||||
efxoutl[i]=0.0;
|
||||
efxoutr[i]=0.0;
|
||||
};
|
||||
return;
|
||||
};
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
smpsl[i]+=denormalkillbuf[i];
|
||||
smpsr[i]+=denormalkillbuf[i];
|
||||
efxoutl[i]=0.0;
|
||||
efxoutr[i]=0.0;
|
||||
};
|
||||
efx->out(smpsl,smpsr);
|
||||
|
||||
REALTYPE volume=efx->volume;
|
||||
|
||||
if (nefx==7) {//this is need only for the EQ effect
|
||||
/**\todo figure out why*/
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
smpsl[i]=efxoutl[i];
|
||||
smpsr[i]=efxoutr[i];
|
||||
};
|
||||
return;
|
||||
};
|
||||
|
||||
//Insertion effect
|
||||
if (insertion!=0) {
|
||||
REALTYPE v1,v2;
|
||||
if (volume<0.5) {
|
||||
v1=1.0;
|
||||
v2=volume*2.0;
|
||||
} else {
|
||||
v1=(1.0-volume)*2.0;
|
||||
v2=1.0;
|
||||
};
|
||||
if ((nefx==1)||(nefx==2)) v2*=v2;//for Reverb and Echo, the wet function is not liniar
|
||||
|
||||
if (dryonly) {//this is used for instrument effect only
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
smpsl[i]*=v1;
|
||||
smpsr[i]*=v1;
|
||||
efxoutl[i]*=v2;
|
||||
efxoutr[i]*=v2;
|
||||
};
|
||||
} else {//normal instrument/insertion effect
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
smpsl[i]=smpsl[i]*v1+efxoutl[i]*v2;
|
||||
smpsr[i]=smpsr[i]*v1+efxoutr[i]*v2;
|
||||
};
|
||||
};
|
||||
} else {//System effect
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
efxoutl[i]*=2.0*volume;
|
||||
efxoutr[i]*=2.0*volume;
|
||||
smpsl[i]=efxoutl[i];
|
||||
smpsr[i]=efxoutr[i];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the effect volume for the system effect
|
||||
*/
|
||||
REALTYPE EffectMgr::sysefxgetvolume()
|
||||
{
|
||||
if (efx==NULL) return (1.0);
|
||||
else return(efx->outvolume);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the EQ response
|
||||
*/
|
||||
REALTYPE EffectMgr::getEQfreqresponse(REALTYPE freq)
|
||||
{
|
||||
if (nefx==7) return(efx->getfreqresponse(freq));
|
||||
else return(0.0);
|
||||
}
|
||||
|
||||
|
||||
void EffectMgr::setdryonly(bool value)
|
||||
{
|
||||
dryonly=value;
|
||||
}
|
||||
|
||||
void EffectMgr::add2XML(XMLwrapper *xml)
|
||||
{
|
||||
xml->addpar("type",geteffect());
|
||||
|
||||
if ((efx==NULL)||(geteffect()==0)) return;
|
||||
xml->addpar("preset",efx->Ppreset);
|
||||
|
||||
xml->beginbranch("EFFECT_PARAMETERS");
|
||||
for (int n=0;n<128;n++) { /**\todo evaluate who should oversee saving
|
||||
* and loading of parameters*/
|
||||
int par=geteffectpar(n);
|
||||
if (par==0) continue;
|
||||
xml->beginbranch("par_no",n);
|
||||
xml->addpar("par",par);
|
||||
xml->endbranch();
|
||||
};
|
||||
if (filterpars!=NULL) {
|
||||
xml->beginbranch("FILTER");
|
||||
filterpars->add2XML(xml);
|
||||
xml->endbranch();
|
||||
};
|
||||
xml->endbranch();
|
||||
}
|
||||
|
||||
void EffectMgr::getfromXML(XMLwrapper *xml)
|
||||
{
|
||||
changeeffect(xml->getpar127("type",geteffect()));
|
||||
|
||||
if ((efx==NULL)||(geteffect()==0)) return;
|
||||
|
||||
efx->Ppreset=xml->getpar127("preset",efx->Ppreset);
|
||||
|
||||
if (xml->enterbranch("EFFECT_PARAMETERS")) {
|
||||
for (int n=0;n<128;n++) {
|
||||
seteffectpar_nolock(n,0);//erase effect parameter
|
||||
if (xml->enterbranch("par_no",n)==0) continue;
|
||||
|
||||
int par=geteffectpar(n);
|
||||
seteffectpar_nolock(n,xml->getpar127("par",par));
|
||||
xml->exitbranch();
|
||||
};
|
||||
if (filterpars!=NULL) {
|
||||
if (xml->enterbranch("FILTER")) {
|
||||
filterpars->getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
};
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
EffectMgr.h - Effect manager, an interface betwen the program and effects
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -39,67 +39,64 @@
|
||||
|
||||
|
||||
/**Effect manager, an interface betwen the program and effects*/
|
||||
class EffectMgr:public Presets{
|
||||
public:
|
||||
EffectMgr(int insertion_,pthread_mutex_t *mutex_);
|
||||
~EffectMgr();
|
||||
class EffectMgr:public Presets
|
||||
{
|
||||
public:
|
||||
EffectMgr(int insertion_,pthread_mutex_t *mutex_);
|
||||
~EffectMgr();
|
||||
|
||||
void add2XML(XMLwrapper *xml);
|
||||
void defaults();
|
||||
void getfromXML(XMLwrapper *xml);
|
||||
void add2XML(XMLwrapper *xml);
|
||||
void defaults();
|
||||
void getfromXML(XMLwrapper *xml);
|
||||
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpsr);
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpsr);
|
||||
|
||||
void setdryonly(bool value);
|
||||
|
||||
/**get the output(to speakers) volume of the systemeffect*/
|
||||
REALTYPE sysefxgetvolume();
|
||||
void setdryonly(bool value);
|
||||
|
||||
void cleanup();/**<cleanup the effect*/
|
||||
/**get the output(to speakers) volume of the systemeffect*/
|
||||
REALTYPE sysefxgetvolume();
|
||||
|
||||
/**change effect to the given int
|
||||
void cleanup();/**<cleanup the effect*/
|
||||
|
||||
/**change effect to the given int
|
||||
* @param nefx_ the number of the effect*/
|
||||
void changeeffect(int nefx_);
|
||||
/**Get the number of the effect
|
||||
* @return the number
|
||||
* \todo try to fix abstraction failure*/
|
||||
int geteffect();
|
||||
/**
|
||||
* Change the preset to the given one
|
||||
* @param npreset number of the chosen preset
|
||||
* \todo figure out why this is binary
|
||||
*/
|
||||
void changepreset(unsigned char npreset);
|
||||
/**
|
||||
* Change the preset to the given one without locking the thread
|
||||
* @param npreset number of the chosen preset
|
||||
* \todo figure out why this is binary
|
||||
*/
|
||||
void changepreset_nolock(unsigned char npreset);
|
||||
/**
|
||||
* Get the current preset
|
||||
* @return the current preset*/
|
||||
unsigned char getpreset();
|
||||
/**sets the effect par*/
|
||||
void seteffectpar(int npar,unsigned char value);
|
||||
/**<sets the effect par without thread lock*/
|
||||
void seteffectpar_nolock(int npar,unsigned char value);
|
||||
unsigned char geteffectpar(int npar);
|
||||
int insertion;/**<1 if the effect is connected as insertion effect
|
||||
* \todo figure out why this is not a bool*/
|
||||
REALTYPE *efxoutl,*efxoutr;
|
||||
void changeeffect(int nefx_);
|
||||
/**Get the number of the effect
|
||||
* @return the number*/
|
||||
int geteffect();
|
||||
/**
|
||||
* Change the preset to the given one
|
||||
* @param npreset number of the chosen preset
|
||||
*/
|
||||
void changepreset(unsigned char npreset);
|
||||
/**
|
||||
* Change the preset to the given one without locking the thread
|
||||
* @param npreset number of the chosen preset
|
||||
*/
|
||||
void changepreset_nolock(unsigned char npreset);
|
||||
/**
|
||||
* Get the current preset
|
||||
* @return the current preset*/
|
||||
unsigned char getpreset();
|
||||
/**sets the effect par*/
|
||||
void seteffectpar(int npar,unsigned char value);
|
||||
/**<sets the effect par without thread lock*/
|
||||
void seteffectpar_nolock(int npar,unsigned char value);
|
||||
unsigned char geteffectpar(int npar);
|
||||
const bool insertion;/**<1 if the effect is connected as insertion effect*/
|
||||
REALTYPE *efxoutl,*efxoutr;
|
||||
|
||||
/**used by UI
|
||||
/**used by UI
|
||||
* \todo needs to be decoupled*/
|
||||
REALTYPE getEQfreqresponse(REALTYPE freq);
|
||||
REALTYPE getEQfreqresponse(REALTYPE freq);
|
||||
|
||||
FilterParams *filterpars;
|
||||
|
||||
private:
|
||||
int nefx;
|
||||
Effect *efx;
|
||||
pthread_mutex_t *mutex;
|
||||
bool dryonly;
|
||||
FilterParams *filterpars;
|
||||
|
||||
private:
|
||||
int nefx;
|
||||
Effect *efx;
|
||||
pthread_mutex_t *mutex;
|
||||
bool dryonly;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Phaser.C - Phaser effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Phaser.h"
|
||||
/**\todo figure out why this define was made*/
|
||||
#define PHASER_LFO_SHAPE 2
|
||||
|
||||
Phaser::Phaser(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0),oldl(NULL),oldr(NULL)
|
||||
{
|
||||
setpreset(Ppreset);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
Phaser::~Phaser(){
|
||||
if (oldl!=NULL) delete [] oldl;
|
||||
if (oldr!=NULL) delete [] oldr;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Effect output
|
||||
*/
|
||||
void Phaser::out(REALTYPE *smpsl,REALTYPE *smpsr){
|
||||
int i,j;
|
||||
REALTYPE lfol,lfor,lgain,rgain,tmp;
|
||||
|
||||
lfo.effectlfoout(&lfol,&lfor);
|
||||
lgain=lfol;
|
||||
rgain=lfor;
|
||||
lgain=(exp(lgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0);
|
||||
rgain=(exp(rgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0);
|
||||
|
||||
|
||||
lgain=1.0-phase*(1.0-depth)-(1.0-phase)*lgain*depth;
|
||||
rgain=1.0-phase*(1.0-depth)-(1.0-phase)*rgain*depth;
|
||||
|
||||
if (lgain>1.0) lgain=1.0;else if (lgain<0.0) lgain=0.0;
|
||||
if (rgain>1.0) rgain=1.0;else if (rgain<0.0) rgain=0.0;
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
REALTYPE x=(REALTYPE) i /SOUND_BUFFER_SIZE;
|
||||
REALTYPE x1=1.0-x;
|
||||
REALTYPE gl=lgain*x+oldlgain*x1;
|
||||
REALTYPE gr=rgain*x+oldrgain*x1;
|
||||
REALTYPE inl=smpsl[i]*panning+fbl;
|
||||
REALTYPE inr=smpsr[i]*(1.0-panning)+fbr;
|
||||
|
||||
//Left channel
|
||||
for (j=0;j<Pstages*2;j++){//Phasing routine
|
||||
tmp=oldl[j];
|
||||
oldl[j]=gl*tmp+inl;
|
||||
inl=tmp-gl*oldl[j];
|
||||
};
|
||||
//Right channel
|
||||
for (j=0;j<Pstages*2;j++){//Phasing routine
|
||||
tmp=oldr[j];
|
||||
oldr[j]=gr*tmp+inr;
|
||||
inr=tmp-gr*oldr[j];
|
||||
};
|
||||
//Left/Right crossing
|
||||
REALTYPE l=inl;
|
||||
REALTYPE r=inr;
|
||||
inl=l*(1.0-lrcross)+r*lrcross;
|
||||
inr=r*(1.0-lrcross)+l*lrcross;
|
||||
|
||||
fbl=inl*fb;
|
||||
fbr=inr*fb;
|
||||
efxoutl[i]=inl;
|
||||
efxoutr[i]=inr;
|
||||
|
||||
};
|
||||
|
||||
oldlgain=lgain; oldrgain=rgain;
|
||||
|
||||
if (Poutsub!=0)
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i]*= -1.0;
|
||||
efxoutr[i]*= -1.0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Phaser::cleanup(){
|
||||
fbl=0.0;fbr=0.0;
|
||||
oldlgain=0.0;
|
||||
oldrgain=0.0;
|
||||
for (int i=0;i<Pstages*2;i++) {
|
||||
oldl[i]=0.0;
|
||||
oldr[i]=0.0;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Phaser::setdepth(const unsigned char &Pdepth){
|
||||
this->Pdepth=Pdepth;
|
||||
depth=(Pdepth/127.0);
|
||||
};
|
||||
|
||||
|
||||
void Phaser::setfb(const unsigned char &Pfb){
|
||||
this->Pfb=Pfb;
|
||||
fb=(Pfb-64.0)/64.1;
|
||||
};
|
||||
|
||||
void Phaser::setvolume(const unsigned char &Pvolume){
|
||||
this->Pvolume=Pvolume;
|
||||
outvolume=Pvolume/127.0;
|
||||
if (insertion==0) volume=1.0;
|
||||
else volume=outvolume;
|
||||
};
|
||||
|
||||
void Phaser::setpanning(const unsigned char &Ppanning){
|
||||
this->Ppanning=Ppanning;
|
||||
panning=Ppanning/127.0;
|
||||
};
|
||||
|
||||
void Phaser::setlrcross(const unsigned char &Plrcross){
|
||||
this->Plrcross=Plrcross;
|
||||
lrcross=Plrcross/127.0;
|
||||
};
|
||||
|
||||
void Phaser::setstages(const unsigned char &Pstages){
|
||||
if (oldl!=NULL) delete [] oldl;
|
||||
if (oldr!=NULL) delete [] oldr;
|
||||
if (Pstages>=MAX_PHASER_STAGES) this->Pstages=MAX_PHASER_STAGES-1;
|
||||
else this->Pstages=Pstages;
|
||||
oldl=new REALTYPE[Pstages*2];
|
||||
oldr=new REALTYPE[Pstages*2];
|
||||
cleanup();
|
||||
};
|
||||
|
||||
void Phaser::setphase(const unsigned char &Pphase){
|
||||
this->Pphase=Pphase;
|
||||
phase=(Pphase/127.0);
|
||||
};
|
||||
|
||||
|
||||
void Phaser::setpreset(unsigned char npreset){
|
||||
const int PRESET_SIZE=12;
|
||||
const int NUM_PRESETS=6;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//Phaser1
|
||||
{64,64,36,0,0,64,110,64,1,0,0,20},
|
||||
//Phaser2
|
||||
{64,64,35,0,0,88,40,64,3,0,0,20},
|
||||
//Phaser3
|
||||
{64,64,31,0,0,66,68,107,2,0,0,20},
|
||||
//Phaser4
|
||||
{39,64,22,0,0,66,67,10,5,0,1,20},
|
||||
//Phaser5
|
||||
{64,64,20,0,1,110,67,78,10,0,0,20},
|
||||
//Phaser6
|
||||
{64,64,53,100,0,58,37,78,3,0,0,20}};
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
|
||||
Ppreset=npreset;
|
||||
};
|
||||
|
||||
|
||||
void Phaser::changepar(const int &npar,const unsigned char &value){
|
||||
switch(npar){
|
||||
case 0: setvolume(value);
|
||||
break;
|
||||
case 1: setpanning(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();
|
||||
break;
|
||||
case 5: lfo.Pstereo=value;
|
||||
lfo.updateparams();
|
||||
break;
|
||||
case 6: setdepth(value);
|
||||
break;
|
||||
case 7: setfb(value);
|
||||
break;
|
||||
case 8: setstages(value);
|
||||
break;
|
||||
case 9: setlrcross(value);
|
||||
break;
|
||||
case 10:if (value>1) Poutsub=1;
|
||||
else Poutsub=value;
|
||||
break;
|
||||
case 11:setphase(value);
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char Phaser::getpar(const int &npar)const{
|
||||
switch (npar){
|
||||
case 0: return(Pvolume);
|
||||
break;
|
||||
case 1: return(Ppanning);
|
||||
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(Pdepth);
|
||||
break;
|
||||
case 7: return(Pfb);
|
||||
break;
|
||||
case 8: return(Pstages);
|
||||
break;
|
||||
case 9: return(Plrcross);
|
||||
break;
|
||||
case 10:return(Poutsub);
|
||||
break;
|
||||
case 11:return(Pphase);
|
||||
break;
|
||||
default:return (0);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
283
plugins/zynaddsubfx/src/Effects/Phaser.cpp
Normal file
283
plugins/zynaddsubfx/src/Effects/Phaser.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Phaser.C - Phaser effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Phaser.h"
|
||||
#define PHASER_LFO_SHAPE 2
|
||||
|
||||
Phaser::Phaser(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0),old(1),oldgain(0.0)
|
||||
{
|
||||
setpreset(Ppreset);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
Phaser::~Phaser()
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Effect output
|
||||
*/
|
||||
void Phaser::out(REALTYPE *smpsl,REALTYPE *smpsr)
|
||||
{
|
||||
int i,j;
|
||||
REALTYPE lfol,lfor,lgain,rgain,tmp;
|
||||
|
||||
lfo.effectlfoout(&lfol,&lfor);
|
||||
lgain=lfol;
|
||||
rgain=lfor;
|
||||
lgain=(exp(lgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0);
|
||||
rgain=(exp(rgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0);
|
||||
|
||||
|
||||
lgain=1.0-phase*(1.0-depth)-(1.0-phase)*lgain*depth;
|
||||
rgain=1.0-phase*(1.0-depth)-(1.0-phase)*rgain*depth;
|
||||
|
||||
if (lgain>1.0) lgain=1.0;
|
||||
else if (lgain<0.0) lgain=0.0;
|
||||
if (rgain>1.0) rgain=1.0;
|
||||
else if (rgain<0.0) rgain=0.0;
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE x=(REALTYPE) i /SOUND_BUFFER_SIZE;
|
||||
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;
|
||||
|
||||
//Left channel
|
||||
for (j=0;j<Pstages*2;j++) {//Phasing routine
|
||||
tmp=old.left()[j];
|
||||
old.left()[j]=gl*tmp+inl;
|
||||
inl=tmp-gl*old.left()[j];
|
||||
};
|
||||
//Right channel
|
||||
for (j=0;j<Pstages*2;j++) {//Phasing routine
|
||||
tmp=old.right()[j];
|
||||
old.right()[j]=gr*tmp+inr;
|
||||
inr=tmp-gr*old.right()[j];
|
||||
};
|
||||
//Left/Right crossing
|
||||
REALTYPE l=inl;
|
||||
REALTYPE r=inr;
|
||||
inl=l*(1.0-lrcross)+r*lrcross;
|
||||
inr=r*(1.0-lrcross)+l*lrcross;
|
||||
|
||||
fbl=inl*fb;
|
||||
fbr=inr*fb;
|
||||
efxoutl[i]=inl;
|
||||
efxoutr[i]=inr;
|
||||
|
||||
};
|
||||
|
||||
oldgain=Stereo<REALTYPE>(lgain,rgain);
|
||||
|
||||
if (Poutsub!=0)
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
efxoutl[i]*= -1.0;
|
||||
efxoutr[i]*= -1.0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Phaser::cleanup()
|
||||
{
|
||||
fbl=0.0;
|
||||
fbr=0.0;
|
||||
oldgain=Stereo<REALTYPE>(0.0);
|
||||
old.l().clear();
|
||||
old.r().clear();
|
||||
};
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Phaser::setdepth(const unsigned char &Pdepth)
|
||||
{
|
||||
this->Pdepth=Pdepth;
|
||||
depth=(Pdepth/127.0);
|
||||
};
|
||||
|
||||
|
||||
void Phaser::setfb(const unsigned char &Pfb)
|
||||
{
|
||||
this->Pfb=Pfb;
|
||||
fb=(Pfb-64.0)/64.1;
|
||||
};
|
||||
|
||||
void Phaser::setvolume(const unsigned char &Pvolume)
|
||||
{
|
||||
this->Pvolume=Pvolume;
|
||||
outvolume=Pvolume/127.0;
|
||||
if (insertion==0) volume=1.0;
|
||||
else volume=outvolume;
|
||||
};
|
||||
|
||||
void Phaser::setpanning(const unsigned char &Ppanning)
|
||||
{
|
||||
this->Ppanning=Ppanning;
|
||||
panning=Ppanning/127.0;
|
||||
};
|
||||
|
||||
void Phaser::setlrcross(const unsigned char &Plrcross)
|
||||
{
|
||||
this->Plrcross=Plrcross;
|
||||
lrcross=Plrcross/127.0;
|
||||
};
|
||||
|
||||
void Phaser::setstages(const unsigned char &Pstages)
|
||||
{
|
||||
if (Pstages>=MAX_PHASER_STAGES) this->Pstages=MAX_PHASER_STAGES-1;
|
||||
else this->Pstages=Pstages;
|
||||
old=Stereo<AuSample>(Pstages*2);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
void Phaser::setphase(const unsigned char &Pphase)
|
||||
{
|
||||
this->Pphase=Pphase;
|
||||
phase=(Pphase/127.0);
|
||||
};
|
||||
|
||||
|
||||
void Phaser::setpreset(unsigned char npreset)
|
||||
{
|
||||
const int PRESET_SIZE=12;
|
||||
const int NUM_PRESETS=6;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//Phaser1
|
||||
{64,64,36,0,0,64,110,64,1,0,0,20},
|
||||
//Phaser2
|
||||
{64,64,35,0,0,88,40,64,3,0,0,20},
|
||||
//Phaser3
|
||||
{64,64,31,0,0,66,68,107,2,0,0,20},
|
||||
//Phaser4
|
||||
{39,64,22,0,0,66,67,10,5,0,1,20},
|
||||
//Phaser5
|
||||
{64,64,20,0,1,110,67,78,10,0,0,20},
|
||||
//Phaser6
|
||||
{64,64,53,100,0,58,37,78,3,0,0,20}
|
||||
};
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
|
||||
Ppreset=npreset;
|
||||
};
|
||||
|
||||
|
||||
void Phaser::changepar(const int &npar,const unsigned char &value)
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
setvolume(value);
|
||||
break;
|
||||
case 1:
|
||||
setpanning(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();
|
||||
break;
|
||||
case 5:
|
||||
lfo.Pstereo=value;
|
||||
lfo.updateparams();
|
||||
break;
|
||||
case 6:
|
||||
setdepth(value);
|
||||
break;
|
||||
case 7:
|
||||
setfb(value);
|
||||
break;
|
||||
case 8:
|
||||
setstages(value);
|
||||
break;
|
||||
case 9:
|
||||
setlrcross(value);
|
||||
break;
|
||||
case 10:
|
||||
if (value>1) Poutsub=1;
|
||||
else Poutsub=value;
|
||||
break;
|
||||
case 11:
|
||||
setphase(value);
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char Phaser::getpar(const int &npar)const
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
return(Pvolume);
|
||||
break;
|
||||
case 1:
|
||||
return(Ppanning);
|
||||
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(Pdepth);
|
||||
break;
|
||||
case 7:
|
||||
return(Pfb);
|
||||
break;
|
||||
case 8:
|
||||
return(Pstages);
|
||||
break;
|
||||
case 9:
|
||||
return(Plrcross);
|
||||
break;
|
||||
case 10:
|
||||
return(Poutsub);
|
||||
break;
|
||||
case 11:
|
||||
return(Pphase);
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -1,71 +1,76 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Phaser.h - Phaser effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 PHASER_H
|
||||
#define PHASER_H
|
||||
#include "../globals.h"
|
||||
#include "Effect.h"
|
||||
#include "EffectLFO.h"
|
||||
|
||||
#define MAX_PHASER_STAGES 12
|
||||
/**Phaser Effect*/
|
||||
class Phaser:public Effect {
|
||||
public:
|
||||
Phaser(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
~Phaser();
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpsr);
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
void setdryonly();
|
||||
|
||||
private:
|
||||
//Parametrii Phaser
|
||||
EffectLFO lfo;/**<lfo-ul Phaser*/
|
||||
unsigned char Pvolume;
|
||||
unsigned char Ppanning;
|
||||
unsigned char Pdepth;/**<the depth of the Phaser*/
|
||||
unsigned char Pfb;/**<feedback*/
|
||||
unsigned char Plrcross;/**<feedback*/
|
||||
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);
|
||||
|
||||
//Internal Values
|
||||
//int insertion; //inherited from Effect
|
||||
REALTYPE panning,fb,depth,lrcross,fbl,fbr,phase;
|
||||
REALTYPE *oldl,*oldr;
|
||||
REALTYPE oldlgain,oldrgain;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Phaser.h - Phaser effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 PHASER_H
|
||||
#define PHASER_H
|
||||
#include "../globals.h"
|
||||
#include "../Misc/Stereo.h"
|
||||
#include "../Samples/AuSample.h"
|
||||
#include "Effect.h"
|
||||
#include "EffectLFO.h"
|
||||
|
||||
#define MAX_PHASER_STAGES 12
|
||||
/**Phaser Effect*/
|
||||
class Phaser:public Effect
|
||||
{
|
||||
public:
|
||||
Phaser(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
~Phaser();
|
||||
void out(REALTYPE *smpsl,REALTYPE *smpsr);
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
void cleanup();
|
||||
void setdryonly();
|
||||
|
||||
private:
|
||||
//Parametrii Phaser
|
||||
EffectLFO lfo;/**<lfo-ul Phaser*/
|
||||
unsigned char Pvolume;
|
||||
unsigned char Ppanning;
|
||||
unsigned char Pdepth;/**<the depth of the Phaser*/
|
||||
unsigned char Pfb;/**<feedback*/
|
||||
unsigned char Plrcross;/**<feedback*/
|
||||
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);
|
||||
|
||||
//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<REALTYPE> oldgain;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,430 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Reverb.C - Reverberation effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Reverb.h"
|
||||
|
||||
/**\todo: EarlyReflections,Prdelay,Perbalance */
|
||||
|
||||
Reverb::Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0)
|
||||
{
|
||||
inputbuf=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
|
||||
//defaults
|
||||
Pvolume=48;
|
||||
Ppan=64;
|
||||
Ptime=64;
|
||||
Pidelay=40;
|
||||
Pidelayfb=0;
|
||||
Prdelay=0;
|
||||
Plpf=127;
|
||||
Phpf=0;
|
||||
Perbalance=64;
|
||||
Plohidamp=80;
|
||||
Ptype=1;
|
||||
Proomsize=64;roomsize=1.0;rs=1.0;
|
||||
|
||||
for (int i=0;i<REV_COMBS*2;i++) {
|
||||
comblen[i]=800+(int)(RND*1400);
|
||||
combk[i]=0;
|
||||
lpcomb[i]=0;
|
||||
combfb[i]=-0.97;
|
||||
comb[i]=NULL;
|
||||
};
|
||||
|
||||
for (int i=0;i<REV_APS*2;i++) {
|
||||
aplen[i]=500+(int)(RND*500);
|
||||
apk[i]=0;
|
||||
ap[i]=NULL;
|
||||
};
|
||||
|
||||
lpf=NULL;hpf=NULL;//no filter
|
||||
idelay=NULL;
|
||||
|
||||
setpreset(Ppreset);
|
||||
cleanup();//do not call this before the comb initialisation
|
||||
};
|
||||
|
||||
|
||||
Reverb::~Reverb(){
|
||||
int i;
|
||||
if (idelay!=NULL) delete []idelay;
|
||||
if (hpf!=NULL) delete hpf;
|
||||
if (lpf!=NULL) delete lpf;
|
||||
|
||||
for (i=0;i<REV_APS*2;i++) delete [] ap[i];
|
||||
for (i=0;i<REV_COMBS*2;i++) delete [] comb[i];
|
||||
|
||||
delete [] inputbuf;
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Reverb::cleanup(){
|
||||
int i,j;
|
||||
for (i=0;i<REV_COMBS*2;i++){
|
||||
lpcomb[i]=0.0;
|
||||
for (j=0;j<comblen[i];j++) comb[i][j]=0.0;
|
||||
};
|
||||
|
||||
for (i=0;i<REV_APS*2;i++)
|
||||
for (j=0;j<aplen[i];j++) ap[i][j]=0.0;
|
||||
|
||||
if (idelay!=NULL) for (i=0;i<idelaylen;i++) idelay[i]=0.0;
|
||||
|
||||
if (hpf!=NULL) hpf->cleanup();
|
||||
if (lpf!=NULL) lpf->cleanup();
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Process one channel; 0=left,1=right
|
||||
*/
|
||||
void Reverb::processmono(int ch,REALTYPE *output){
|
||||
int i,j;
|
||||
REALTYPE fbout,tmp;
|
||||
/**\todo: implement the high part from lohidamp*/
|
||||
|
||||
for (j=REV_COMBS*ch;j<REV_COMBS*(ch+1);j++){
|
||||
|
||||
int ck=combk[j];
|
||||
int comblength=comblen[j];
|
||||
REALTYPE lpcombj=lpcomb[j];
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
fbout=comb[j][ck]*combfb[j];
|
||||
fbout=fbout*(1.0-lohifb)+lpcombj*lohifb;
|
||||
lpcombj=fbout;
|
||||
|
||||
comb[j][ck]=inputbuf[i]+fbout;
|
||||
output[i]+=fbout;
|
||||
|
||||
if ((++ck)>=comblength) ck=0;
|
||||
};
|
||||
|
||||
combk[j]=ck;
|
||||
lpcomb[j]=lpcombj;
|
||||
};
|
||||
|
||||
for (j=REV_APS*ch;j<REV_APS*(1+ch);j++){
|
||||
int ak=apk[j];
|
||||
int aplength=aplen[j];
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
tmp=ap[j][ak];
|
||||
ap[j][ak]=0.7*tmp+output[i];
|
||||
output[i]=tmp-0.7*ap[j][ak];
|
||||
if ((++ak)>=aplength) ak=0;
|
||||
};
|
||||
apk[j]=ak;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Effect output
|
||||
*/
|
||||
void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r){
|
||||
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;
|
||||
//Initial delay r
|
||||
if (idelay!=NULL){
|
||||
REALTYPE tmp=inputbuf[i]+idelay[idelayk]*idelayfb;
|
||||
inputbuf[i]=idelay[idelayk];
|
||||
idelay[idelayk]=tmp;
|
||||
idelayk++;if (idelayk>=idelaylen) idelayk=0;
|
||||
};
|
||||
};
|
||||
|
||||
if (lpf!=NULL) lpf->filterout(inputbuf);
|
||||
if (hpf!=NULL) hpf->filterout(inputbuf);
|
||||
|
||||
processmono(0,efxoutl);//left
|
||||
processmono(1,efxoutr);//right
|
||||
|
||||
REALTYPE lvol=rs/REV_COMBS*pan;
|
||||
REALTYPE rvol=rs/REV_COMBS*(1.0-pan);
|
||||
if (insertion!=0){
|
||||
lvol*=2;rvol*=2;
|
||||
};
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++){
|
||||
efxoutl[i]*=lvol;
|
||||
efxoutr[i]*=rvol;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Reverb::setvolume(const unsigned char &Pvolume){
|
||||
this->Pvolume=Pvolume;
|
||||
if (insertion==0) {
|
||||
outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0;
|
||||
volume=1.0;
|
||||
} else {
|
||||
volume=outvolume=Pvolume/127.0;
|
||||
if (Pvolume==0) cleanup();
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::setpan(const unsigned char &Ppan){
|
||||
this->Ppan=Ppan;
|
||||
pan=(REALTYPE)Ppan/127.0;
|
||||
};
|
||||
|
||||
void Reverb::settime(const unsigned char &Ptime){
|
||||
int i;
|
||||
REALTYPE t;
|
||||
this->Ptime=Ptime;
|
||||
t=pow(60.0,(REALTYPE)Ptime/127.0)-0.97;
|
||||
|
||||
for (i=0;i<REV_COMBS*2;i++){
|
||||
combfb[i]=-exp((REALTYPE)comblen[i]/(REALTYPE)SAMPLE_RATE*log(0.001)/t);
|
||||
//the feedback is negative because it removes the DC
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::setlohidamp(unsigned char Plohidamp){
|
||||
REALTYPE x;
|
||||
|
||||
if (Plohidamp<64) Plohidamp=64;//remove this when the high part from lohidamp will be added
|
||||
|
||||
this->Plohidamp=Plohidamp;
|
||||
if (Plohidamp==64) {
|
||||
lohidamptype=0;
|
||||
lohifb=0.0;
|
||||
} else {
|
||||
if (Plohidamp<64) lohidamptype=1;
|
||||
if (Plohidamp>64) lohidamptype=2;
|
||||
x=fabs((REALTYPE)(Plohidamp-64)/64.1);
|
||||
lohifb=x*x;
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::setidelay(const unsigned char &Pidelay){
|
||||
REALTYPE delay;
|
||||
this->Pidelay=Pidelay;
|
||||
delay=pow(50*Pidelay/127.0,2)-1.0;
|
||||
|
||||
if (idelay!=NULL) delete []idelay;
|
||||
idelay=NULL;
|
||||
|
||||
idelaylen=(int) (SAMPLE_RATE*delay/1000);
|
||||
if (idelaylen>1) {
|
||||
idelayk=0;
|
||||
idelay=new REALTYPE[idelaylen];
|
||||
for (int i=0;i<idelaylen;i++) idelay[i]=0.0;
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::setidelayfb(const unsigned char &Pidelayfb){
|
||||
this->Pidelayfb=Pidelayfb;
|
||||
idelayfb=Pidelayfb/128.0;
|
||||
};
|
||||
|
||||
void Reverb::sethpf(const unsigned char &Phpf){
|
||||
this->Phpf=Phpf;
|
||||
if (Phpf==0) {//No HighPass
|
||||
if (hpf!=NULL) delete hpf;
|
||||
hpf=NULL;
|
||||
}
|
||||
else{
|
||||
REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(10000.0))+20.0;
|
||||
if (hpf==NULL) hpf=new AnalogFilter(3,fr,1,0);
|
||||
else hpf->setfreq(fr);
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::setlpf(const unsigned char &Plpf){
|
||||
this->Plpf=Plpf;
|
||||
if (Plpf==127) {//No LowPass
|
||||
if (lpf!=NULL) delete lpf;
|
||||
lpf=NULL;
|
||||
}
|
||||
else{
|
||||
REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40;
|
||||
if (lpf==NULL) lpf=new AnalogFilter(2,fr,1,0);
|
||||
else lpf->setfreq(fr);
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::settype(unsigned char Ptype){
|
||||
const int NUM_TYPES=2;
|
||||
int combtunings[NUM_TYPES][REV_COMBS]={
|
||||
//this is unused (for random)
|
||||
{0,0,0,0,0,0,0,0},
|
||||
//Freeverb by Jezar at Dreampoint
|
||||
{1116,1188,1277,1356,1422,1491,1557,1617}
|
||||
};
|
||||
int aptunings[NUM_TYPES][REV_APS]={
|
||||
//this is unused (for random)
|
||||
{0,0,0,0},
|
||||
//Freeverb by Jezar at Dreampoint
|
||||
{225,341,441,556}
|
||||
};
|
||||
|
||||
if (Ptype>=NUM_TYPES) Ptype=NUM_TYPES-1;
|
||||
this->Ptype=Ptype;
|
||||
|
||||
REALTYPE tmp;
|
||||
for (int i=0;i<REV_COMBS*2;i++) {
|
||||
if (Ptype==0) tmp=800.0+(int)(RND*1400.0);
|
||||
else tmp=combtunings[Ptype][i%REV_COMBS];
|
||||
tmp*=roomsize;
|
||||
if (i>REV_COMBS) tmp+=23.0;
|
||||
tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate
|
||||
if (tmp<10) tmp=10;
|
||||
|
||||
comblen[i]=(int) tmp;
|
||||
combk[i]=0;
|
||||
lpcomb[i]=0;
|
||||
if (comb[i]!=NULL) delete []comb[i];
|
||||
comb[i]=new REALTYPE[comblen[i]];
|
||||
};
|
||||
|
||||
for (int i=0;i<REV_APS*2;i++) {
|
||||
if (Ptype==0) tmp=500+(int)(RND*500);
|
||||
else tmp=aptunings[Ptype][i%REV_APS];
|
||||
tmp*=roomsize;
|
||||
if (i>REV_APS) tmp+=23.0;
|
||||
tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate
|
||||
if (tmp<10) tmp=10;
|
||||
aplen[i]=(int) tmp;
|
||||
apk[i]=0;
|
||||
if (ap[i]!=NULL) delete []ap[i];
|
||||
ap[i]=new REALTYPE[aplen[i]];
|
||||
};
|
||||
settime(Ptime);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
void Reverb::setroomsize(const unsigned char &Proomsize){
|
||||
this->Proomsize=Proomsize;
|
||||
if (Proomsize==0) this->Proomsize=64;//this is because the older versions consider roomsize=0
|
||||
roomsize=(this->Proomsize-64.0)/64.0;
|
||||
if (roomsize>0.0) roomsize*=2.0;
|
||||
roomsize=pow(10.0,roomsize);
|
||||
rs=sqrt(roomsize);
|
||||
settype(Ptype);
|
||||
};
|
||||
|
||||
void Reverb::setpreset(unsigned char npreset){
|
||||
const int PRESET_SIZE=12;
|
||||
const int NUM_PRESETS=13;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//Cathedral1
|
||||
{80,64,63,24,0,0,0,85,5,83,1,64},
|
||||
//Cathedral2
|
||||
{80,64,69,35,0,0,0,127,0,71,0,64},
|
||||
//Cathedral3
|
||||
{80,64,69,24,0,0,0,127,75,78,1,85},
|
||||
//Hall1
|
||||
{90,64,51,10,0,0,0,127,21,78,1,64},
|
||||
//Hall2
|
||||
{90,64,53,20,0,0,0,127,75,71,1,64},
|
||||
//Room1
|
||||
{100,64,33,0,0,0,0,127,0,106,0,30},
|
||||
//Room2
|
||||
{100,64,21,26,0,0,0,62,0,77,1,45},
|
||||
//Basement
|
||||
{110,64,14,0,0,0,0,127,5,71,0,25},
|
||||
//Tunnel
|
||||
{85,80,84,20,42,0,0,51,0,78,1,105},
|
||||
//Echoed1
|
||||
{95,64,26,60,71,0,0,114,0,64,1,64},
|
||||
//Echoed2
|
||||
{90,64,40,88,71,0,0,114,0,88,1,64},
|
||||
//VeryLong1
|
||||
{90,64,93,15,0,0,0,114,0,77,0,95},
|
||||
//VeryLong2
|
||||
{90,64,111,30,0,0,0,114,90,74,1,80}};
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
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 reverb is insertion effect
|
||||
Ppreset=npreset;
|
||||
};
|
||||
|
||||
|
||||
void Reverb::changepar(const int &npar,const unsigned char &value){
|
||||
switch (npar){
|
||||
case 0: setvolume(value);
|
||||
break;
|
||||
case 1: setpan(value);
|
||||
break;
|
||||
case 2: settime(value);
|
||||
break;
|
||||
case 3: setidelay(value);
|
||||
break;
|
||||
case 4: setidelayfb(value);
|
||||
break;
|
||||
// case 5: setrdelay(value);
|
||||
// break;
|
||||
// case 6: seterbalance(value);
|
||||
// break;
|
||||
case 7: setlpf(value);
|
||||
break;
|
||||
case 8: sethpf(value);
|
||||
break;
|
||||
case 9: setlohidamp(value);
|
||||
break;
|
||||
case 10:settype(value);
|
||||
break;
|
||||
case 11:setroomsize(value);
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char Reverb::getpar(const int &npar)const{
|
||||
switch (npar){
|
||||
case 0: return(Pvolume);
|
||||
break;
|
||||
case 1: return(Ppan);
|
||||
break;
|
||||
case 2: return(Ptime);
|
||||
break;
|
||||
case 3: return(Pidelay);
|
||||
break;
|
||||
case 4: return(Pidelayfb);
|
||||
break;
|
||||
// case 5: return(Prdelay);
|
||||
// break;
|
||||
// case 6: return(Perbalance);
|
||||
// break;
|
||||
case 7: return(Plpf);
|
||||
break;
|
||||
case 8: return(Phpf);
|
||||
break;
|
||||
case 9: return(Plohidamp);
|
||||
break;
|
||||
case 10:return(Ptype);
|
||||
break;
|
||||
case 11:return(Proomsize);
|
||||
break;
|
||||
};
|
||||
return(0);//in case of bogus "parameter"
|
||||
};
|
||||
|
||||
471
plugins/zynaddsubfx/src/Effects/Reverb.cpp
Normal file
471
plugins/zynaddsubfx/src/Effects/Reverb.cpp
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Reverb.C - Reverberation effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Reverb.h"
|
||||
|
||||
/**\todo: EarlyReflections,Prdelay,Perbalance */
|
||||
|
||||
Reverb::Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_)
|
||||
:Effect(insertion_,efxoutl_,efxoutr_,NULL,0)
|
||||
{
|
||||
inputbuf=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
|
||||
//defaults
|
||||
Pvolume=48;
|
||||
Ppan=64;
|
||||
Ptime=64;
|
||||
Pidelay=40;
|
||||
Pidelayfb=0;
|
||||
Prdelay=0;
|
||||
Plpf=127;
|
||||
Phpf=0;
|
||||
Perbalance=64;
|
||||
Plohidamp=80;
|
||||
Ptype=1;
|
||||
Proomsize=64;
|
||||
roomsize=1.0;
|
||||
rs=1.0;
|
||||
|
||||
for (int i=0;i<REV_COMBS*2;i++) {
|
||||
comblen[i]=800+(int)(RND*1400);
|
||||
combk[i]=0;
|
||||
lpcomb[i]=0;
|
||||
combfb[i]=-0.97;
|
||||
comb[i]=NULL;
|
||||
};
|
||||
|
||||
for (int i=0;i<REV_APS*2;i++) {
|
||||
aplen[i]=500+(int)(RND*500);
|
||||
apk[i]=0;
|
||||
ap[i]=NULL;
|
||||
};
|
||||
|
||||
lpf=NULL;
|
||||
hpf=NULL;//no filter
|
||||
idelay=NULL;
|
||||
|
||||
setpreset(Ppreset);
|
||||
cleanup();//do not call this before the comb initialisation
|
||||
};
|
||||
|
||||
|
||||
Reverb::~Reverb()
|
||||
{
|
||||
int i;
|
||||
if (idelay!=NULL) delete []idelay;
|
||||
if (hpf!=NULL) delete hpf;
|
||||
if (lpf!=NULL) delete lpf;
|
||||
|
||||
for (i=0;i<REV_APS*2;i++) delete [] ap[i];
|
||||
for (i=0;i<REV_COMBS*2;i++) delete [] comb[i];
|
||||
|
||||
delete [] inputbuf;
|
||||
};
|
||||
|
||||
/*
|
||||
* Cleanup the effect
|
||||
*/
|
||||
void Reverb::cleanup()
|
||||
{
|
||||
int i,j;
|
||||
for (i=0;i<REV_COMBS*2;i++) {
|
||||
lpcomb[i]=0.0;
|
||||
for (j=0;j<comblen[i];j++) comb[i][j]=0.0;
|
||||
};
|
||||
|
||||
for (i=0;i<REV_APS*2;i++)
|
||||
for (j=0;j<aplen[i];j++) ap[i][j]=0.0;
|
||||
|
||||
if (idelay!=NULL) for (i=0;i<idelaylen;i++) idelay[i]=0.0;
|
||||
|
||||
if (hpf!=NULL) hpf->cleanup();
|
||||
if (lpf!=NULL) lpf->cleanup();
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Process one channel; 0=left,1=right
|
||||
*/
|
||||
void Reverb::processmono(int ch,REALTYPE *output)
|
||||
{
|
||||
int i,j;
|
||||
REALTYPE fbout,tmp;
|
||||
/**\todo: implement the high part from lohidamp*/
|
||||
|
||||
for (j=REV_COMBS*ch;j<REV_COMBS*(ch+1);j++) {
|
||||
|
||||
int ck=combk[j];
|
||||
int comblength=comblen[j];
|
||||
REALTYPE lpcombj=lpcomb[j];
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
fbout=comb[j][ck]*combfb[j];
|
||||
fbout=fbout*(1.0-lohifb)+lpcombj*lohifb;
|
||||
lpcombj=fbout;
|
||||
|
||||
comb[j][ck]=inputbuf[i]+fbout;
|
||||
output[i]+=fbout;
|
||||
|
||||
if ((++ck)>=comblength) ck=0;
|
||||
};
|
||||
|
||||
combk[j]=ck;
|
||||
lpcomb[j]=lpcombj;
|
||||
};
|
||||
|
||||
for (j=REV_APS*ch;j<REV_APS*(1+ch);j++) {
|
||||
int ak=apk[j];
|
||||
int aplength=aplen[j];
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
tmp=ap[j][ak];
|
||||
ap[j][ak]=0.7*tmp+output[i];
|
||||
output[i]=tmp-0.7*ap[j][ak];
|
||||
if ((++ak)>=aplength) ak=0;
|
||||
};
|
||||
apk[j]=ak;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Effect output
|
||||
*/
|
||||
void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r)
|
||||
{
|
||||
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;
|
||||
//Initial delay r
|
||||
if (idelay!=NULL) {
|
||||
REALTYPE tmp=inputbuf[i]+idelay[idelayk]*idelayfb;
|
||||
inputbuf[i]=idelay[idelayk];
|
||||
idelay[idelayk]=tmp;
|
||||
idelayk++;
|
||||
if (idelayk>=idelaylen) idelayk=0;
|
||||
};
|
||||
};
|
||||
|
||||
if (lpf!=NULL) lpf->filterout(inputbuf);
|
||||
if (hpf!=NULL) hpf->filterout(inputbuf);
|
||||
|
||||
processmono(0,efxoutl);//left
|
||||
processmono(1,efxoutr);//right
|
||||
|
||||
REALTYPE lvol=rs/REV_COMBS*pan;
|
||||
REALTYPE rvol=rs/REV_COMBS*(1.0-pan);
|
||||
if (insertion!=0) {
|
||||
lvol*=2;
|
||||
rvol*=2;
|
||||
};
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
efxoutl[i]*=lvol;
|
||||
efxoutr[i]*=rvol;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Reverb::setvolume(const unsigned char &Pvolume)
|
||||
{
|
||||
this->Pvolume=Pvolume;
|
||||
if (insertion==0) {
|
||||
outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0;
|
||||
volume=1.0;
|
||||
} else {
|
||||
volume=outvolume=Pvolume/127.0;
|
||||
if (Pvolume==0) cleanup();
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::setpan(const unsigned char &Ppan)
|
||||
{
|
||||
this->Ppan=Ppan;
|
||||
pan=(REALTYPE)Ppan/127.0;
|
||||
};
|
||||
|
||||
void Reverb::settime(const unsigned char &Ptime)
|
||||
{
|
||||
int i;
|
||||
REALTYPE t;
|
||||
this->Ptime=Ptime;
|
||||
t=pow(60.0,(REALTYPE)Ptime/127.0)-0.97;
|
||||
|
||||
for (i=0;i<REV_COMBS*2;i++) {
|
||||
combfb[i]=-exp((REALTYPE)comblen[i]/(REALTYPE)SAMPLE_RATE*log(0.001)/t);
|
||||
//the feedback is negative because it removes the DC
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::setlohidamp(unsigned char Plohidamp)
|
||||
{
|
||||
REALTYPE x;
|
||||
|
||||
if (Plohidamp<64) Plohidamp=64;//remove this when the high part from lohidamp will be added
|
||||
|
||||
this->Plohidamp=Plohidamp;
|
||||
if (Plohidamp==64) {
|
||||
lohidamptype=0;
|
||||
lohifb=0.0;
|
||||
} else {
|
||||
if (Plohidamp<64) lohidamptype=1;
|
||||
if (Plohidamp>64) lohidamptype=2;
|
||||
x=fabs((REALTYPE)(Plohidamp-64)/64.1);
|
||||
lohifb=x*x;
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::setidelay(const unsigned char &Pidelay)
|
||||
{
|
||||
REALTYPE delay;
|
||||
this->Pidelay=Pidelay;
|
||||
delay=pow(50*Pidelay/127.0,2)-1.0;
|
||||
|
||||
if (idelay!=NULL) delete []idelay;
|
||||
idelay=NULL;
|
||||
|
||||
idelaylen=(int) (SAMPLE_RATE*delay/1000);
|
||||
if (idelaylen>1) {
|
||||
idelayk=0;
|
||||
idelay=new REALTYPE[idelaylen];
|
||||
for (int i=0;i<idelaylen;i++) idelay[i]=0.0;
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::setidelayfb(const unsigned char &Pidelayfb)
|
||||
{
|
||||
this->Pidelayfb=Pidelayfb;
|
||||
idelayfb=Pidelayfb/128.0;
|
||||
};
|
||||
|
||||
void Reverb::sethpf(const unsigned char &Phpf)
|
||||
{
|
||||
this->Phpf=Phpf;
|
||||
if (Phpf==0) {//No HighPass
|
||||
if (hpf!=NULL) delete hpf;
|
||||
hpf=NULL;
|
||||
} else {
|
||||
REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(10000.0))+20.0;
|
||||
if (hpf==NULL) hpf=new AnalogFilter(3,fr,1,0);
|
||||
else hpf->setfreq(fr);
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::setlpf(const unsigned char &Plpf)
|
||||
{
|
||||
this->Plpf=Plpf;
|
||||
if (Plpf==127) {//No LowPass
|
||||
if (lpf!=NULL) delete lpf;
|
||||
lpf=NULL;
|
||||
} else {
|
||||
REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40;
|
||||
if (lpf==NULL) lpf=new AnalogFilter(2,fr,1,0);
|
||||
else lpf->setfreq(fr);
|
||||
};
|
||||
};
|
||||
|
||||
void Reverb::settype(unsigned char Ptype)
|
||||
{
|
||||
const int NUM_TYPES=2;
|
||||
int combtunings[NUM_TYPES][REV_COMBS]={
|
||||
//this is unused (for random)
|
||||
{0,0,0,0,0,0,0,0},
|
||||
//Freeverb by Jezar at Dreampoint
|
||||
{1116,1188,1277,1356,1422,1491,1557,1617}
|
||||
};
|
||||
int aptunings[NUM_TYPES][REV_APS]={
|
||||
//this is unused (for random)
|
||||
{0,0,0,0},
|
||||
//Freeverb by Jezar at Dreampoint
|
||||
{225,341,441,556}
|
||||
};
|
||||
|
||||
if (Ptype>=NUM_TYPES) Ptype=NUM_TYPES-1;
|
||||
this->Ptype=Ptype;
|
||||
|
||||
REALTYPE tmp;
|
||||
for (int i=0;i<REV_COMBS*2;i++) {
|
||||
if (Ptype==0) tmp=800.0+(int)(RND*1400.0);
|
||||
else tmp=combtunings[Ptype][i%REV_COMBS];
|
||||
tmp*=roomsize;
|
||||
if (i>REV_COMBS) tmp+=23.0;
|
||||
tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate
|
||||
if (tmp<10) tmp=10;
|
||||
|
||||
comblen[i]=(int) tmp;
|
||||
combk[i]=0;
|
||||
lpcomb[i]=0;
|
||||
if (comb[i]!=NULL) delete []comb[i];
|
||||
comb[i]=new REALTYPE[comblen[i]];
|
||||
};
|
||||
|
||||
for (int i=0;i<REV_APS*2;i++) {
|
||||
if (Ptype==0) tmp=500+(int)(RND*500);
|
||||
else tmp=aptunings[Ptype][i%REV_APS];
|
||||
tmp*=roomsize;
|
||||
if (i>REV_APS) tmp+=23.0;
|
||||
tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate
|
||||
if (tmp<10) tmp=10;
|
||||
aplen[i]=(int) tmp;
|
||||
apk[i]=0;
|
||||
if (ap[i]!=NULL) delete []ap[i];
|
||||
ap[i]=new REALTYPE[aplen[i]];
|
||||
};
|
||||
settime(Ptime);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
void Reverb::setroomsize(const unsigned char &Proomsize)
|
||||
{
|
||||
this->Proomsize=Proomsize;
|
||||
if (Proomsize==0) this->Proomsize=64;//this is because the older versions consider roomsize=0
|
||||
roomsize=(this->Proomsize-64.0)/64.0;
|
||||
if (roomsize>0.0) roomsize*=2.0;
|
||||
roomsize=pow(10.0,roomsize);
|
||||
rs=sqrt(roomsize);
|
||||
settype(Ptype);
|
||||
};
|
||||
|
||||
void Reverb::setpreset(unsigned char npreset)
|
||||
{
|
||||
const int PRESET_SIZE=12;
|
||||
const int NUM_PRESETS=13;
|
||||
unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
|
||||
//Cathedral1
|
||||
{80,64,63,24,0,0,0,85,5,83,1,64},
|
||||
//Cathedral2
|
||||
{80,64,69,35,0,0,0,127,0,71,0,64},
|
||||
//Cathedral3
|
||||
{80,64,69,24,0,0,0,127,75,78,1,85},
|
||||
//Hall1
|
||||
{90,64,51,10,0,0,0,127,21,78,1,64},
|
||||
//Hall2
|
||||
{90,64,53,20,0,0,0,127,75,71,1,64},
|
||||
//Room1
|
||||
{100,64,33,0,0,0,0,127,0,106,0,30},
|
||||
//Room2
|
||||
{100,64,21,26,0,0,0,62,0,77,1,45},
|
||||
//Basement
|
||||
{110,64,14,0,0,0,0,127,5,71,0,25},
|
||||
//Tunnel
|
||||
{85,80,84,20,42,0,0,51,0,78,1,105},
|
||||
//Echoed1
|
||||
{95,64,26,60,71,0,0,114,0,64,1,64},
|
||||
//Echoed2
|
||||
{90,64,40,88,71,0,0,114,0,88,1,64},
|
||||
//VeryLong1
|
||||
{90,64,93,15,0,0,0,114,0,77,0,95},
|
||||
//VeryLong2
|
||||
{90,64,111,30,0,0,0,114,90,74,1,80}
|
||||
};
|
||||
|
||||
if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
|
||||
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 reverb is insertion effect
|
||||
Ppreset=npreset;
|
||||
};
|
||||
|
||||
|
||||
void Reverb::changepar(const int &npar,const unsigned char &value)
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
setvolume(value);
|
||||
break;
|
||||
case 1:
|
||||
setpan(value);
|
||||
break;
|
||||
case 2:
|
||||
settime(value);
|
||||
break;
|
||||
case 3:
|
||||
setidelay(value);
|
||||
break;
|
||||
case 4:
|
||||
setidelayfb(value);
|
||||
break;
|
||||
// case 5: setrdelay(value);
|
||||
// break;
|
||||
// case 6: seterbalance(value);
|
||||
// break;
|
||||
case 7:
|
||||
setlpf(value);
|
||||
break;
|
||||
case 8:
|
||||
sethpf(value);
|
||||
break;
|
||||
case 9:
|
||||
setlohidamp(value);
|
||||
break;
|
||||
case 10:
|
||||
settype(value);
|
||||
break;
|
||||
case 11:
|
||||
setroomsize(value);
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned char Reverb::getpar(const int &npar)const
|
||||
{
|
||||
switch (npar) {
|
||||
case 0:
|
||||
return(Pvolume);
|
||||
break;
|
||||
case 1:
|
||||
return(Ppan);
|
||||
break;
|
||||
case 2:
|
||||
return(Ptime);
|
||||
break;
|
||||
case 3:
|
||||
return(Pidelay);
|
||||
break;
|
||||
case 4:
|
||||
return(Pidelayfb);
|
||||
break;
|
||||
// case 5: return(Prdelay);
|
||||
// break;
|
||||
// case 6: return(Perbalance);
|
||||
// break;
|
||||
case 7:
|
||||
return(Plpf);
|
||||
break;
|
||||
case 8:
|
||||
return(Phpf);
|
||||
break;
|
||||
case 9:
|
||||
return(Plohidamp);
|
||||
break;
|
||||
case 10:
|
||||
return(Ptype);
|
||||
break;
|
||||
case 11:
|
||||
return(Proomsize);
|
||||
break;
|
||||
};
|
||||
return(0);//in case of bogus "parameter"
|
||||
};
|
||||
|
||||
@@ -1,126 +1,127 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Reverb.h - Reverberation effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 REVERB_H
|
||||
#define REVERB_H
|
||||
|
||||
|
||||
#include "../globals.h"
|
||||
#include "../DSP/AnalogFilter.h"
|
||||
#include "Effect.h"
|
||||
|
||||
#define REV_COMBS 8
|
||||
#define REV_APS 4
|
||||
|
||||
/**Creates Reverberation Effects*/
|
||||
class Reverb:public Effect {
|
||||
public:
|
||||
Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
~Reverb();
|
||||
void out(REALTYPE *smps_l,REALTYPE *smps_r);
|
||||
void cleanup();
|
||||
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
|
||||
private:
|
||||
//Parametrii
|
||||
/**Amount of the reverb*/
|
||||
unsigned char Pvolume;
|
||||
|
||||
/**Left/Right Panning*/
|
||||
unsigned char Ppan;
|
||||
|
||||
/**duration of reverb*/
|
||||
unsigned char Ptime;
|
||||
|
||||
/**Initial delay*/
|
||||
unsigned char Pidelay;
|
||||
|
||||
/**Initial delay feedback*/
|
||||
unsigned char Pidelayfb;
|
||||
|
||||
/**delay between ER/Reverbs*/
|
||||
unsigned char Prdelay;
|
||||
|
||||
/**EarlyReflections/Reverb Balance*/
|
||||
unsigned char Perbalance;
|
||||
|
||||
/**HighPassFilter*/
|
||||
unsigned char Plpf;
|
||||
|
||||
/**LowPassFilter*/
|
||||
unsigned char Phpf;
|
||||
|
||||
/**Low/HighFrequency Damping
|
||||
* \todo 0..63 lpf,64=off,65..127=hpf(TODO)*/
|
||||
unsigned char Plohidamp;
|
||||
|
||||
/**Reverb type*/
|
||||
unsigned char Ptype;
|
||||
|
||||
/**Room Size*/
|
||||
unsigned char Proomsize;
|
||||
|
||||
//parameter control
|
||||
void setvolume(const unsigned char &Pvolume);
|
||||
void setpan(const unsigned char &Ppan);
|
||||
void settime(const 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 settype( unsigned char Ptype);
|
||||
void setroomsize(const unsigned char &Proomsize);
|
||||
|
||||
REALTYPE pan,erbalance;
|
||||
//Parametrii 2
|
||||
int lohidamptype;/**<0=disable,1=highdamp(lowpass),2=lowdamp(highpass)*/
|
||||
int idelaylen,rdelaylen;
|
||||
int idelayk;
|
||||
REALTYPE lohifb,idelayfb,roomsize,rs;//rs is used to "normalise" the volume according to the roomsize
|
||||
int comblen[REV_COMBS*2];
|
||||
int aplen[REV_APS*2];
|
||||
|
||||
//Internal Variables
|
||||
|
||||
REALTYPE *comb[REV_COMBS*2];
|
||||
|
||||
int combk[REV_COMBS*2];
|
||||
REALTYPE combfb[REV_COMBS*2];/**<feedback-ul fiecarui filtru "comb"*/
|
||||
REALTYPE lpcomb[REV_COMBS*2];/**<pentru Filtrul LowPass*/
|
||||
|
||||
REALTYPE *ap[REV_APS*2];
|
||||
|
||||
int apk[REV_APS*2];
|
||||
|
||||
REALTYPE *idelay;
|
||||
AnalogFilter *lpf,*hpf;//filters
|
||||
REALTYPE *inputbuf;
|
||||
|
||||
void processmono(int ch,REALTYPE *output);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Reverb.h - Reverberation effect
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 REVERB_H
|
||||
#define REVERB_H
|
||||
|
||||
|
||||
#include "../globals.h"
|
||||
#include "../DSP/AnalogFilter.h"
|
||||
#include "Effect.h"
|
||||
|
||||
#define REV_COMBS 8
|
||||
#define REV_APS 4
|
||||
|
||||
/**Creates Reverberation Effects*/
|
||||
class Reverb:public Effect
|
||||
{
|
||||
public:
|
||||
Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_);
|
||||
~Reverb();
|
||||
void out(REALTYPE *smps_l,REALTYPE *smps_r);
|
||||
void cleanup();
|
||||
|
||||
void setpreset(unsigned char npreset);
|
||||
void changepar(const int &npar,const unsigned char &value);
|
||||
unsigned char getpar(const int &npar)const;
|
||||
|
||||
private:
|
||||
//Parametrii
|
||||
/**Amount of the reverb*/
|
||||
unsigned char Pvolume;
|
||||
|
||||
/**Left/Right Panning*/
|
||||
unsigned char Ppan;
|
||||
|
||||
/**duration of reverb*/
|
||||
unsigned char Ptime;
|
||||
|
||||
/**Initial delay*/
|
||||
unsigned char Pidelay;
|
||||
|
||||
/**Initial delay feedback*/
|
||||
unsigned char Pidelayfb;
|
||||
|
||||
/**delay between ER/Reverbs*/
|
||||
unsigned char Prdelay;
|
||||
|
||||
/**EarlyReflections/Reverb Balance*/
|
||||
unsigned char Perbalance;
|
||||
|
||||
/**HighPassFilter*/
|
||||
unsigned char Plpf;
|
||||
|
||||
/**LowPassFilter*/
|
||||
unsigned char Phpf;
|
||||
|
||||
/**Low/HighFrequency Damping
|
||||
* \todo 0..63 lpf,64=off,65..127=hpf(TODO)*/
|
||||
unsigned char Plohidamp;
|
||||
|
||||
/**Reverb type*/
|
||||
unsigned char Ptype;
|
||||
|
||||
/**Room Size*/
|
||||
unsigned char Proomsize;
|
||||
|
||||
//parameter control
|
||||
void setvolume(const unsigned char &Pvolume);
|
||||
void setpan(const unsigned char &Ppan);
|
||||
void settime(const 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 settype( unsigned char Ptype);
|
||||
void setroomsize(const unsigned char &Proomsize);
|
||||
|
||||
REALTYPE pan,erbalance;
|
||||
//Parametrii 2
|
||||
int lohidamptype;/**<0=disable,1=highdamp(lowpass),2=lowdamp(highpass)*/
|
||||
int idelaylen,rdelaylen;
|
||||
int idelayk;
|
||||
REALTYPE lohifb,idelayfb,roomsize,rs;//rs is used to "normalise" the volume according to the roomsize
|
||||
int comblen[REV_COMBS*2];
|
||||
int aplen[REV_APS*2];
|
||||
|
||||
//Internal Variables
|
||||
|
||||
REALTYPE *comb[REV_COMBS*2];
|
||||
|
||||
int combk[REV_COMBS*2];
|
||||
REALTYPE combfb[REV_COMBS*2];/**<feedback-ul fiecarui filtru "comb"*/
|
||||
REALTYPE lpcomb[REV_COMBS*2];/**<pentru Filtrul LowPass*/
|
||||
|
||||
REALTYPE *ap[REV_APS*2];
|
||||
|
||||
int apk[REV_APS*2];
|
||||
|
||||
REALTYPE *idelay;
|
||||
AnalogFilter *lpf,*hpf;//filters
|
||||
REALTYPE *inputbuf;
|
||||
|
||||
void processmono(int ch,REALTYPE *output);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ A1) The name of the program comes from 4 words:
|
||||
|
||||
|
||||
Q2) How can I load files from older versions of ZynAddSubFX (like *.mas_zyn,etc)
|
||||
A2) You need to convert them into new format. Please use 2.0.0pre1 or (recomanded) 2.0.0pre2 versions of ZynAddSubFX to load old file formants and save them in the new formats
|
||||
A2) You need to convert them into new format. Please use 2.0.0pre1 or (recommended) 2.0.0pre2 versions of ZynAddSubFX to load old file formants and save them in the new formats
|
||||
|
||||
|
||||
Q3) How can I change the number of parts, voices to ADSynth, effects, etc. ?
|
||||
A3) Look in src/globals.h and change there theese values. You don't have to change anything else, just recompile all. But most settings must be below 128. As the rule of the thumb if a setting is 128 or below 128, please don't make it bigger than 128. Anyway, I don't belive that you'll need more than 128 for theese settings; for example you don't need 128(or more) effects same time? That's why I put the limit of 128 (using 7 bits of char).
|
||||
A3) Look in src/globals.h and change there these values. You don't have to change anything else, just recompile all. But most settings must be below 128. As the rule of the thumb if a setting is 128 or below 128, please don't make it bigger than 128. Anyway, I don't believe that you'll need more than 128 for these settings; for example you don't need 128(or more) effects same time? That's why I put the limit of 128 (using 7 bits of char).
|
||||
|
||||
|
||||
Q4) How do I enable Jack support on ZynAddSubFX ?
|
||||
A4) Look in "Makefile.inc" from "src/" directory for more information. It is highly recomanded that the Jack samplerate to be equal to ZynAddSubFX samplerate (SAMPLE_RATE from globals.h), otherwise the resampling will be done and this will decrease the quality a bit.
|
||||
A4) Look in "Makefile.inc" from "src/" directory for more information. It is highly recommended that the Jack samplerate to be equal to ZynAddSubFX samplerate (SAMPLE_RATE from globals.h), otherwise the resampling will be done and this will decrease the quality a bit.
|
||||
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
2.4.0 (21 Jun 2009)
|
||||
- extended mono functionality
|
||||
- legato mode
|
||||
- export functionality on PADsynth
|
||||
- inclusion of LASH client
|
||||
- inclusion of DSSI audio output
|
||||
- enabled tooltips for knobs (both description and value tooltips)
|
||||
- added support for newer JACK api
|
||||
- added quertz support for virtual keyboard
|
||||
- started to encorperate cxxtest for unit testing
|
||||
- many bugfixes
|
||||
- code cleanup
|
||||
|
||||
2.2.1 (28 Apr 2005)
|
||||
- made to work with mxml-2.2 (will NOT work on older versions)
|
||||
- it is possible to remove completely the graphical user interface (e.g. it can run without X). For this you need to modify the DISABLE_GUI option from the Makefile.inc
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
ALSAMidiIn.C - Midi input for ALSA (this creates an ALSA virtual port)
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "ALSAMidiIn.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
ALSAMidiIn::ALSAMidiIn(){
|
||||
int alsaport;
|
||||
inputok=0;
|
||||
char portname[50];
|
||||
sprintf(portname,"ZynAddSubFX");
|
||||
|
||||
midi_handle=NULL;
|
||||
|
||||
if (snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_INPUT,0)!=0) return;
|
||||
|
||||
snd_seq_set_client_name(midi_handle,"ZynAddSubFX");//thanks to Frank Neumann
|
||||
|
||||
alsaport = snd_seq_create_simple_port(midi_handle,portname
|
||||
,SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE
|
||||
,SND_SEQ_PORT_TYPE_SYNTH);
|
||||
if (alsaport<0) return;
|
||||
|
||||
inputok=1;
|
||||
};
|
||||
|
||||
ALSAMidiIn::~ALSAMidiIn(){
|
||||
if (midi_handle)
|
||||
snd_seq_close(midi_handle);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Get the midi command,channel and parameters
|
||||
*/
|
||||
void ALSAMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams){
|
||||
snd_seq_event_t *midievent=NULL;
|
||||
cmdtype=MidiNull;
|
||||
|
||||
if (inputok==0){
|
||||
/* The input is broken. We need to block for a while anyway so other
|
||||
non-RT threads get a chance to run. */
|
||||
sleep(1);
|
||||
return;
|
||||
};
|
||||
|
||||
snd_seq_event_input(midi_handle,&midievent);
|
||||
|
||||
if (midievent==NULL) return;
|
||||
switch (midievent->type){
|
||||
case SND_SEQ_EVENT_NOTEON:
|
||||
cmdtype=MidiNoteON;
|
||||
cmdchan=midievent->data.note.channel;
|
||||
cmdparams[0]=midievent->data.note.note;
|
||||
cmdparams[1]=midievent->data.note.velocity;
|
||||
break;
|
||||
case SND_SEQ_EVENT_NOTEOFF:
|
||||
cmdtype=MidiNoteOFF;
|
||||
cmdchan=midievent->data.note.channel;
|
||||
cmdparams[0]=midievent->data.note.note;
|
||||
break;
|
||||
case SND_SEQ_EVENT_PITCHBEND:
|
||||
cmdtype=MidiController;
|
||||
cmdchan=midievent->data.control.channel;
|
||||
cmdparams[0]=C_pitchwheel;//Pitch Bend
|
||||
cmdparams[1]=midievent->data.control.value;
|
||||
break;
|
||||
case SND_SEQ_EVENT_CONTROLLER:
|
||||
cmdtype=MidiController;
|
||||
cmdchan=midievent->data.control.channel;
|
||||
cmdparams[0]=getcontroller(midievent->data.control.param);
|
||||
cmdparams[1]=midievent->data.control.value;
|
||||
//fprintf(stderr,"t=%d val=%d\n",midievent->data.control.param,midievent->data.control.value);
|
||||
break;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
int ALSAMidiIn::getalsaid() {
|
||||
if (midi_handle) {
|
||||
snd_seq_client_info_t* seq_info;
|
||||
snd_seq_client_info_malloc(&seq_info);
|
||||
snd_seq_get_client_info(midi_handle, seq_info);
|
||||
int id = snd_seq_client_info_get_client(seq_info);
|
||||
snd_seq_client_info_free(seq_info);
|
||||
return id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
110
plugins/zynaddsubfx/src/Input/ALSAMidiIn.cpp
Normal file
110
plugins/zynaddsubfx/src/Input/ALSAMidiIn.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
ALSAMidiIn.C - Midi input for ALSA (this creates an ALSA virtual port)
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "ALSAMidiIn.h"
|
||||
|
||||
ALSAMidiIn::ALSAMidiIn()
|
||||
{
|
||||
int alsaport;
|
||||
inputok=false;
|
||||
|
||||
midi_handle=NULL;
|
||||
|
||||
if (snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_INPUT,0)!=0) return;
|
||||
|
||||
snd_seq_set_client_name(midi_handle,"ZynAddSubFX");//thanks to Frank Neumann
|
||||
|
||||
alsaport = snd_seq_create_simple_port(midi_handle,"ZynAddSubFX"
|
||||
,SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE
|
||||
,SND_SEQ_PORT_TYPE_SYNTH);
|
||||
if (alsaport<0) return;
|
||||
|
||||
inputok=true;
|
||||
};
|
||||
|
||||
ALSAMidiIn::~ALSAMidiIn()
|
||||
{
|
||||
if (midi_handle) snd_seq_close(midi_handle);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Get the midi command,channel and parameters
|
||||
*/
|
||||
void ALSAMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)
|
||||
{
|
||||
snd_seq_event_t *midievent=NULL;
|
||||
cmdtype=MidiNull;
|
||||
|
||||
if (inputok==false) {
|
||||
/* The input is broken. We need to block for a while anyway so other
|
||||
non-RT threads get a chance to run. */
|
||||
sleep(1);
|
||||
return;
|
||||
};
|
||||
|
||||
snd_seq_event_input(midi_handle,&midievent);
|
||||
|
||||
if (midievent==NULL) return;
|
||||
switch (midievent->type) {
|
||||
case SND_SEQ_EVENT_NOTEON:
|
||||
cmdtype=MidiNoteON;
|
||||
cmdchan=midievent->data.note.channel;
|
||||
cmdparams[0]=midievent->data.note.note;
|
||||
cmdparams[1]=midievent->data.note.velocity;
|
||||
break;
|
||||
case SND_SEQ_EVENT_NOTEOFF:
|
||||
cmdtype=MidiNoteOFF;
|
||||
cmdchan=midievent->data.note.channel;
|
||||
cmdparams[0]=midievent->data.note.note;
|
||||
break;
|
||||
case SND_SEQ_EVENT_PITCHBEND:
|
||||
cmdtype=MidiController;
|
||||
cmdchan=midievent->data.control.channel;
|
||||
cmdparams[0]=C_pitchwheel;//Pitch Bend
|
||||
cmdparams[1]=midievent->data.control.value;
|
||||
break;
|
||||
case SND_SEQ_EVENT_CONTROLLER:
|
||||
cmdtype=MidiController;
|
||||
cmdchan=midievent->data.control.channel;
|
||||
cmdparams[0]=getcontroller(midievent->data.control.param);
|
||||
cmdparams[1]=midievent->data.control.value;
|
||||
//fprintf(stderr,"t=%d val=%d\n",midievent->data.control.param,midievent->data.control.value);
|
||||
break;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
int ALSAMidiIn::getalsaid()
|
||||
{
|
||||
if (midi_handle) {
|
||||
snd_seq_client_info_t* seq_info;
|
||||
snd_seq_client_info_malloc(&seq_info);
|
||||
snd_seq_get_client_info(midi_handle, seq_info);
|
||||
int id = snd_seq_client_info_get_client(seq_info);
|
||||
snd_seq_client_info_free(seq_info);
|
||||
return id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
ALSAMidiIn.h - Midi input for ALSA (this creates an ALSA virtual port)
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -27,17 +27,23 @@
|
||||
#include "MidiIn.h"
|
||||
|
||||
|
||||
class ALSAMidiIn:public MidiIn{
|
||||
public:
|
||||
ALSAMidiIn();
|
||||
~ALSAMidiIn();
|
||||
void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams);
|
||||
int getalsaid();
|
||||
/**Midi input for ALSA (this creates an ALSA virtual port)*/
|
||||
class ALSAMidiIn:public MidiIn
|
||||
{
|
||||
public:
|
||||
/**Constructor*/
|
||||
ALSAMidiIn();
|
||||
/**Destructor*/
|
||||
~ALSAMidiIn();
|
||||
|
||||
private:
|
||||
snd_seq_t *midi_handle;
|
||||
void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams);
|
||||
/**Get the ALSA id
|
||||
* @return ALSA id*/
|
||||
int getalsaid();
|
||||
|
||||
private:
|
||||
snd_seq_t *midi_handle;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
19
plugins/zynaddsubfx/src/Input/CMakeLists.txt
Normal file
19
plugins/zynaddsubfx/src/Input/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
set(zynaddsubfx_input_SRCS
|
||||
MidiIn.cpp
|
||||
NULLMidiIn.cpp
|
||||
#OSSMidiIn.cpp #[TODO] get OSS midi detection and
|
||||
#WINMidiIn.cpp # Win midi detection working
|
||||
)
|
||||
|
||||
if(AlsaMidiInput)
|
||||
set(zynaddsubfx_input_SRCS
|
||||
${zynaddsubfx_input_SRCS}
|
||||
ALSAMidiIn.cpp
|
||||
)
|
||||
message(STATUS "Alsa midi input enabled")
|
||||
set(MIDIINPUT_LIBRARIES ${ASOUND_LIBRARY} PARENT_SCOPE)
|
||||
endif(AlsaMidiInput)
|
||||
|
||||
add_library(zynaddsubfx_input STATIC
|
||||
${zynaddsubfx_input_SRCS}
|
||||
)
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
MidiIn.C - This class is inherited by all the Midi input classes
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "../globals.h"
|
||||
#include "MidiIn.h"
|
||||
|
||||
int MidiIn::getcontroller(unsigned char b){
|
||||
int ctl=C_NULL;
|
||||
switch (b){
|
||||
case 1:ctl=C_modwheel;//Modulation Wheel
|
||||
break;
|
||||
case 7:ctl=C_volume;//Volume
|
||||
break;
|
||||
case 10:ctl=C_panning;//Panning
|
||||
break;
|
||||
case 11:ctl=C_expression;//Expression
|
||||
break;
|
||||
case 64:ctl=C_sustain;//Sustain pedal
|
||||
break;
|
||||
case 65:ctl=C_portamento;//Portamento
|
||||
break;
|
||||
case 71:ctl=C_filterq;//Filter Q (Sound Timbre)
|
||||
break;
|
||||
case 74:ctl=C_filtercutoff;//Filter Cutoff (Brightness)
|
||||
break;
|
||||
case 75:ctl=C_bandwidth;//BandWidth
|
||||
break;
|
||||
case 76:ctl=C_fmamp;//FM amplitude
|
||||
break;
|
||||
case 77:ctl=C_resonance_center;//Resonance Center Frequency
|
||||
break;
|
||||
case 78:ctl=C_resonance_bandwidth;//Resonance Bandwith
|
||||
break;
|
||||
case 120:ctl=C_allsoundsoff;//All Sounds OFF
|
||||
break;
|
||||
case 121:ctl=C_resetallcontrollers;//Reset All Controllers
|
||||
break;
|
||||
case 123:ctl=C_allnotesoff;//All Notes OFF
|
||||
break;
|
||||
//RPN and NRPN
|
||||
case 0x06:ctl=C_dataentryhi;//Data Entry (Coarse)
|
||||
break;
|
||||
case 0x26:ctl=C_dataentrylo;//Data Entry (Fine)
|
||||
break;
|
||||
case 99:ctl=C_nrpnhi;//NRPN (Coarse)
|
||||
break;
|
||||
case 98:ctl=C_nrpnlo;//NRPN (Fine)
|
||||
break;
|
||||
default:ctl=C_NULL;//unknown controller
|
||||
//fprintf(stderr,"Controller=%d , par=%d\n",midievent->data.control.param,cmdparams[1]);
|
||||
break;
|
||||
};
|
||||
return(ctl);
|
||||
};
|
||||
95
plugins/zynaddsubfx/src/Input/MidiIn.cpp
Normal file
95
plugins/zynaddsubfx/src/Input/MidiIn.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
MidiIn.C - This class is inherited by all the Midi input classes
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "../globals.h"
|
||||
#include "MidiIn.h"
|
||||
|
||||
int MidiIn::getcontroller(unsigned char b)
|
||||
{
|
||||
/**\todo there might be a better way to do this*/
|
||||
int ctl=C_NULL;
|
||||
switch (b) {
|
||||
case 1:
|
||||
ctl=C_modwheel;//Modulation Wheel
|
||||
break;
|
||||
case 7:
|
||||
ctl=C_volume;//Volume
|
||||
break;
|
||||
case 10:
|
||||
ctl=C_panning;//Panning
|
||||
break;
|
||||
case 11:
|
||||
ctl=C_expression;//Expression
|
||||
break;
|
||||
case 64:
|
||||
ctl=C_sustain;//Sustain pedal
|
||||
break;
|
||||
case 65:
|
||||
ctl=C_portamento;//Portamento
|
||||
break;
|
||||
case 71:
|
||||
ctl=C_filterq;//Filter Q (Sound Timbre)
|
||||
break;
|
||||
case 74:
|
||||
ctl=C_filtercutoff;//Filter Cutoff (Brightness)
|
||||
break;
|
||||
case 75:
|
||||
ctl=C_bandwidth;//BandWidth
|
||||
break;
|
||||
case 76:
|
||||
ctl=C_fmamp;//FM amplitude
|
||||
break;
|
||||
case 77:
|
||||
ctl=C_resonance_center;//Resonance Center Frequency
|
||||
break;
|
||||
case 78:
|
||||
ctl=C_resonance_bandwidth;//Resonance Bandwith
|
||||
break;
|
||||
case 120:
|
||||
ctl=C_allsoundsoff;//All Sounds OFF
|
||||
break;
|
||||
case 121:
|
||||
ctl=C_resetallcontrollers;//Reset All Controllers
|
||||
break;
|
||||
case 123:
|
||||
ctl=C_allnotesoff;//All Notes OFF
|
||||
break;
|
||||
//RPN and NRPN
|
||||
case 0x06:
|
||||
ctl=C_dataentryhi;//Data Entry (Coarse)
|
||||
break;
|
||||
case 0x26:
|
||||
ctl=C_dataentrylo;//Data Entry (Fine)
|
||||
break;
|
||||
case 99:
|
||||
ctl=C_nrpnhi;//NRPN (Coarse)
|
||||
break;
|
||||
case 98:
|
||||
ctl=C_nrpnlo;//NRPN (Fine)
|
||||
break;
|
||||
default:
|
||||
ctl=C_NULL;//unknown controller
|
||||
//fprintf(stderr,"Controller=%d , par=%d\n",midievent->data.control.param,cmdparams[1]);
|
||||
break;
|
||||
};
|
||||
return(ctl);
|
||||
};
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
MidiIn.h - This class is inherited by all the Midi input classes
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -25,18 +25,24 @@
|
||||
|
||||
#include "../globals.h"
|
||||
|
||||
enum MidiCmdType{MidiNull,MidiNoteOFF,MidiNoteON,MidiController};
|
||||
enum MidiCmdType {MidiNull,MidiNoteOFF,MidiNoteON,MidiController};
|
||||
#define MP_MAX_BYTES 4000 //in case of loooong SYS_EXes
|
||||
|
||||
class MidiIn{
|
||||
public:
|
||||
virtual void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams){};
|
||||
virtual ~MidiIn(){};
|
||||
int getcontroller(unsigned char b);
|
||||
protected:
|
||||
int inputok;//1 if I can read midi bytes from input ports
|
||||
/**This class is inherited by all the Midi input classes*/
|
||||
class MidiIn
|
||||
{
|
||||
public:
|
||||
/**Get the command,channel and parameters of the MIDI
|
||||
*
|
||||
* \todo make pure virtual
|
||||
* @param cmdtype the referece to the variable that will store the type
|
||||
* @param cmdchan the channel for the event
|
||||
* @param parameters for the event*/
|
||||
virtual void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)=0;
|
||||
int getcontroller(unsigned char b);
|
||||
protected:
|
||||
bool inputok;/**<1 if I can read midi bytes from input ports*/
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
NULLMidiIn.C - a dummy Midi port
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -21,23 +21,21 @@
|
||||
*/
|
||||
|
||||
#include "NULLMidiIn.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
NULLMidiIn::NULLMidiIn(){
|
||||
NULLMidiIn::NULLMidiIn()
|
||||
{
|
||||
};
|
||||
|
||||
NULLMidiIn::~NULLMidiIn(){
|
||||
NULLMidiIn::~NULLMidiIn()
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Get the midi command,channel and parameters
|
||||
* It returns MidiNull because it is a dummy driver
|
||||
*/
|
||||
void NULLMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,unsigned char *cmdparams){
|
||||
cmdtype=MidiNull;
|
||||
void NULLMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)
|
||||
{
|
||||
cmdtype=MidiNull;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
NULLMidiIn.h - a dummy Midi port
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -26,15 +26,23 @@
|
||||
#include "MidiIn.h"
|
||||
|
||||
|
||||
class NULLMidiIn:public MidiIn{
|
||||
public:
|
||||
NULLMidiIn();
|
||||
~NULLMidiIn();
|
||||
void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,unsigned char *cmdparams);
|
||||
/**a dummy Midi port*/
|
||||
class NULLMidiIn:public MidiIn
|
||||
{
|
||||
public:
|
||||
/**Dummy Constructor
|
||||
* \todo see if the default constructor would work here*/
|
||||
NULLMidiIn();
|
||||
/**Dummy Destructor
|
||||
* \todo see if the default destructor would work here*/
|
||||
~NULLMidiIn();
|
||||
/**Get the midi command,channel and parameters
|
||||
* It returns MidiNull because it is a dummy driver
|
||||
*/
|
||||
void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams);
|
||||
|
||||
private:
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
OSSMidiIn.C - Midi input for Open Sound System
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -31,34 +31,38 @@
|
||||
#include "OSSMidiIn.h"
|
||||
#include "../Misc/Util.h"
|
||||
|
||||
OSSMidiIn::OSSMidiIn(){
|
||||
inputok=0;
|
||||
OSSMidiIn::OSSMidiIn()
|
||||
{
|
||||
inputok=false;
|
||||
midi_handle=open(config.cfg.LinuxOSSSeqInDev,O_RDONLY,0);
|
||||
if (midi_handle!=-1) inputok=1;
|
||||
|
||||
if (midi_handle!=-1) inputok=true;
|
||||
|
||||
lastmidicmd=0;
|
||||
cmdtype=0;
|
||||
cmdchan=0;
|
||||
|
||||
};
|
||||
|
||||
OSSMidiIn::~OSSMidiIn(){
|
||||
OSSMidiIn::~OSSMidiIn()
|
||||
{
|
||||
close(midi_handle);
|
||||
};
|
||||
|
||||
unsigned char OSSMidiIn::readbyte(){
|
||||
unsigned char OSSMidiIn::readbyte()
|
||||
{
|
||||
unsigned char tmp[4];
|
||||
read(midi_handle,&tmp[0],1);
|
||||
while (tmp[0]!=SEQ_MIDIPUTC){
|
||||
read(midi_handle,&tmp[0],4);
|
||||
};
|
||||
while (tmp[0]!=SEQ_MIDIPUTC) {
|
||||
read(midi_handle,&tmp[0],4);
|
||||
}
|
||||
return(tmp[1]);
|
||||
};
|
||||
|
||||
unsigned char OSSMidiIn::getmidibyte(){
|
||||
unsigned char OSSMidiIn::getmidibyte()
|
||||
{
|
||||
unsigned char b;
|
||||
do {
|
||||
b=readbyte();
|
||||
b=readbyte();
|
||||
} while (b==0xfe);//drops the Active Sense Messages
|
||||
return(b);
|
||||
};
|
||||
@@ -66,50 +70,51 @@ unsigned char OSSMidiIn::getmidibyte(){
|
||||
/*
|
||||
* Get the midi command,channel and parameters
|
||||
*/
|
||||
void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams){
|
||||
void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)
|
||||
{
|
||||
unsigned char tmp,i;
|
||||
if (inputok==0) {
|
||||
cmdtype=MidiNull;
|
||||
return;
|
||||
};
|
||||
if (inputok==false) {
|
||||
cmdtype=MidiNull;
|
||||
return;
|
||||
}
|
||||
i=0;
|
||||
if (lastmidicmd==0){//asteapta prima data pana cand vine prima comanda midi
|
||||
while (tmp<0x80) tmp=getmidibyte();
|
||||
lastmidicmd=tmp;
|
||||
};
|
||||
if (lastmidicmd==0) {//asteapta prima data pana cand vine prima comanda midi
|
||||
while (tmp<0x80) tmp=getmidibyte();
|
||||
lastmidicmd=tmp;
|
||||
}
|
||||
|
||||
tmp=getmidibyte();
|
||||
|
||||
if (tmp>=0x80) {
|
||||
lastmidicmd=tmp;
|
||||
tmp=getmidibyte();
|
||||
};
|
||||
lastmidicmd=tmp;
|
||||
tmp=getmidibyte();
|
||||
}
|
||||
|
||||
if ((lastmidicmd>=0x80)&&(lastmidicmd<=0x8f)){//Note OFF
|
||||
cmdtype=MidiNoteOFF;
|
||||
cmdchan=lastmidicmd%16;
|
||||
cmdparams[0]=tmp;//note number
|
||||
};
|
||||
if ((lastmidicmd>=0x80)&&(lastmidicmd<=0x8f)) {//Note OFF
|
||||
cmdtype=MidiNoteOFF;
|
||||
cmdchan=lastmidicmd%16;
|
||||
cmdparams[0]=tmp;//note number
|
||||
}
|
||||
|
||||
if ((lastmidicmd>=0x90)&&(lastmidicmd<=0x9f)){//Note ON
|
||||
cmdtype=MidiNoteON;
|
||||
cmdchan=lastmidicmd%16;
|
||||
cmdparams[0]=tmp;//note number
|
||||
cmdparams[1]=getmidibyte();//velocity
|
||||
if (cmdparams[1]==0) cmdtype=MidiNoteOFF;//if velocity==0 then is note off
|
||||
};
|
||||
if ((lastmidicmd>=0xB0)&&(lastmidicmd<=0xBF)){//Controllers
|
||||
cmdtype=MidiController;
|
||||
cmdchan=lastmidicmd%16;
|
||||
cmdparams[0]=getcontroller(tmp);
|
||||
cmdparams[1]=getmidibyte();
|
||||
};
|
||||
if ((lastmidicmd>=0xE0)&&(lastmidicmd<=0xEF)){//Pitch Wheel
|
||||
cmdtype=MidiController;
|
||||
cmdchan=lastmidicmd%16;
|
||||
cmdparams[0]=C_pitchwheel;
|
||||
cmdparams[1]=(tmp+getmidibyte()*(int) 128)-8192;//hope this is correct
|
||||
};
|
||||
if ((lastmidicmd>=0x90)&&(lastmidicmd<=0x9f)) {//Note ON
|
||||
cmdtype=MidiNoteON;
|
||||
cmdchan=lastmidicmd%16;
|
||||
cmdparams[0]=tmp;//note number
|
||||
cmdparams[1]=getmidibyte();//velocity
|
||||
if (cmdparams[1]==0) cmdtype=MidiNoteOFF;//if velocity==0 then is note off
|
||||
}
|
||||
if ((lastmidicmd>=0xB0)&&(lastmidicmd<=0xBF)) {//Controllers
|
||||
cmdtype=MidiController;
|
||||
cmdchan=lastmidicmd%16;
|
||||
cmdparams[0]=getcontroller(tmp);
|
||||
cmdparams[1]=getmidibyte();
|
||||
}
|
||||
if ((lastmidicmd>=0xE0)&&(lastmidicmd<=0xEF)) {//Pitch Wheel
|
||||
cmdtype=MidiController;
|
||||
cmdchan=lastmidicmd%16;
|
||||
cmdparams[0]=C_pitchwheel;
|
||||
cmdparams[1]=(tmp+getmidibyte()*(int) 128)-8192;//hope this is correct
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
OSSMidiIn.h - Midi input for Open Sound System
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -25,21 +25,22 @@
|
||||
|
||||
#include "MidiIn.h"
|
||||
|
||||
class OSSMidiIn:public MidiIn{
|
||||
public:
|
||||
OSSMidiIn();
|
||||
~OSSMidiIn();
|
||||
unsigned char getmidibyte();
|
||||
unsigned char readbyte();
|
||||
class OSSMidiIn:public MidiIn
|
||||
{
|
||||
public:
|
||||
OSSMidiIn();
|
||||
~OSSMidiIn();
|
||||
unsigned char getmidibyte();
|
||||
unsigned char readbyte();
|
||||
|
||||
//Midi parser
|
||||
void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams);
|
||||
unsigned char cmdtype;//the Message Type (noteon,noteof,sysex..)
|
||||
unsigned char cmdchan;//the channel number
|
||||
//Midi parser
|
||||
void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams);
|
||||
unsigned char cmdtype;//the Message Type (noteon,noteof,sysex..)
|
||||
unsigned char cmdchan;//the channel number
|
||||
|
||||
private:
|
||||
int midi_handle;
|
||||
unsigned char lastmidicmd;//last byte (>=80) received from the Midi
|
||||
private:
|
||||
int midi_handle;
|
||||
unsigned char lastmidicmd;//last byte (>=80) received from the Midi
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
WINMidiIn.C - Midi input for Windows
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "WINMidiIn.h"
|
||||
#include "MidiIn.h"
|
||||
#include "../Misc/Util.h"
|
||||
|
||||
Master *winmaster;
|
||||
HMIDIIN winmidiinhandle;
|
||||
MidiIn midictl;//used to convert the controllers to ZynAddSubFX controllers
|
||||
|
||||
void CALLBACK WinMidiInProc(HMIDIIN hMidiIn,UINT wMsg,DWORD dwInstance,
|
||||
DWORD dwParam1,DWORD dwParam2){
|
||||
int midicommand=MidiNull;
|
||||
if (wMsg==MIM_DATA){
|
||||
int cmd,par1,par2;
|
||||
cmd=dwParam1&0xff;
|
||||
if (cmd==0xfe) return;
|
||||
par1=(dwParam1>>8)&0xff;
|
||||
par2=dwParam1>>16;
|
||||
//printf("%x %x %x\n",cmd,par1,par2);fflush(stdout);
|
||||
int cmdchan=cmd&0x0f;
|
||||
int cmdtype=(cmd>>4)&0x0f;
|
||||
|
||||
int tmp=0;
|
||||
pthread_mutex_lock(&winmaster->mutex);
|
||||
switch(cmdtype){
|
||||
case(0x8)://noteon
|
||||
winmaster->NoteOff(cmdchan,par1);
|
||||
break;
|
||||
case(0x9)://noteoff
|
||||
winmaster->NoteOn(cmdchan,par1,par2&0xff);
|
||||
break;
|
||||
case(0xb)://controller
|
||||
winmaster->SetController(cmdchan,midictl.getcontroller(par1),par2&0xff);
|
||||
break;
|
||||
case(0xe)://pitch wheel
|
||||
tmp=(par1+par2*(long int) 128)-8192;
|
||||
winmaster->SetController(cmdchan,C_pitchwheel,tmp);
|
||||
break;
|
||||
default:break;
|
||||
};
|
||||
pthread_mutex_unlock(&winmaster->mutex);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
void InitWinMidi(Master *master_){
|
||||
winmaster=master_;
|
||||
|
||||
long int result=midiInOpen(&winmidiinhandle,config.cfg.WindowsMidiInId,(DWORD)WinMidiInProc,0,CALLBACK_FUNCTION);
|
||||
result=midiInStart(winmidiinhandle);
|
||||
};
|
||||
|
||||
void StopWinMidi(){
|
||||
midiInStop(winmidiinhandle);
|
||||
midiInClose(winmidiinhandle);
|
||||
};
|
||||
87
plugins/zynaddsubfx/src/Input/WINMidiIn.cpp
Normal file
87
plugins/zynaddsubfx/src/Input/WINMidiIn.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
WINMidiIn.C - Midi input for Windows
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "WINMidiIn.h"
|
||||
#include "MidiIn.h"
|
||||
#include "../Misc/Util.h"
|
||||
|
||||
Master *winmaster;
|
||||
HMIDIIN winmidiinhandle;
|
||||
MidiIn midictl;//used to convert the controllers to ZynAddSubFX controllers
|
||||
|
||||
void CALLBACK WinMidiInProc(HMIDIIN hMidiIn,UINT wMsg,DWORD dwInstance,
|
||||
DWORD dwParam1,DWORD dwParam2)
|
||||
{
|
||||
int midicommand=MidiNull;
|
||||
if (wMsg==MIM_DATA) {
|
||||
int cmd,par1,par2;
|
||||
cmd=dwParam1&0xff;
|
||||
if (cmd==0xfe) return;
|
||||
par1=(dwParam1>>8)&0xff;
|
||||
par2=dwParam1>>16;
|
||||
//printf("%x %x %x\n",cmd,par1,par2);fflush(stdout);
|
||||
int cmdchan=cmd&0x0f;
|
||||
int cmdtype=(cmd>>4)&0x0f;
|
||||
|
||||
int tmp=0;
|
||||
pthread_mutex_lock(&winmaster->mutex);
|
||||
switch (cmdtype) {
|
||||
case(0x8)://noteon
|
||||
winmaster->NoteOff(cmdchan,par1);
|
||||
break;
|
||||
case(0x9)://noteoff
|
||||
winmaster->NoteOn(cmdchan,par1,par2&0xff);
|
||||
break;
|
||||
case(0xb)://controller
|
||||
winmaster->SetController(cmdchan,midictl.getcontroller(par1),par2&0xff);
|
||||
break;
|
||||
case(0xe)://pitch wheel
|
||||
tmp=(par1+par2*(long int) 128)-8192;
|
||||
winmaster->SetController(cmdchan,C_pitchwheel,tmp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
pthread_mutex_unlock(&winmaster->mutex);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
void InitWinMidi(Master *master_)
|
||||
{
|
||||
winmaster=master_;
|
||||
|
||||
long int result=midiInOpen(&winmidiinhandle,config.cfg.WindowsMidiInId,(DWORD)WinMidiInProc,0,CALLBACK_FUNCTION);
|
||||
result=midiInStart(winmidiinhandle);
|
||||
};
|
||||
|
||||
void StopWinMidi()
|
||||
{
|
||||
midiInStop(winmidiinhandle);
|
||||
midiInClose(winmidiinhandle);
|
||||
};
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
WINMidiIn.h - Midi input for Windows
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Bank.h - Instrument Bank
|
||||
|
||||
Bank.h - Instrument Bank
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -39,37 +39,39 @@
|
||||
//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
|
||||
#define FORCE_BANK_DIR_FILE ".bankdir"
|
||||
|
||||
Bank::Bank(){
|
||||
Bank::Bank()
|
||||
{
|
||||
|
||||
|
||||
ZERO(defaultinsname,PART_MAX_NAME_LEN);
|
||||
snprintf(defaultinsname,PART_MAX_NAME_LEN,"%s"," ");
|
||||
|
||||
for (int i=0;i<BANK_SIZE;i++){
|
||||
ins[i].used=false;
|
||||
ins[i].filename=NULL;
|
||||
ins[i].info.PADsynth_used=false;
|
||||
|
||||
for (int i=0;i<BANK_SIZE;i++) {
|
||||
ins[i].used=false;
|
||||
ins[i].filename=NULL;
|
||||
ins[i].info.PADsynth_used=false;
|
||||
};
|
||||
dirname=NULL;
|
||||
clearbank();
|
||||
|
||||
|
||||
|
||||
for (int i=0;i<MAX_NUM_BANKS;i++){
|
||||
banks[i].dir=NULL;
|
||||
banks[i].name=NULL;
|
||||
for (int i=0;i<MAX_NUM_BANKS;i++) {
|
||||
banks[i].dir=NULL;
|
||||
banks[i].name=NULL;
|
||||
};
|
||||
|
||||
|
||||
bankfiletitle=dirname;
|
||||
|
||||
loadbank(config.cfg.currentBankDir);
|
||||
|
||||
};
|
||||
|
||||
Bank::~Bank(){
|
||||
for (int i=0;i<MAX_NUM_BANKS;i++){
|
||||
if (banks[i].dir!=NULL) delete []banks[i].dir;
|
||||
if (banks[i].name!=NULL) delete []banks[i].name;
|
||||
Bank::~Bank()
|
||||
{
|
||||
for (int i=0;i<MAX_NUM_BANKS;i++) {
|
||||
if (banks[i].dir!=NULL) delete []banks[i].dir;
|
||||
if (banks[i].name!=NULL) delete []banks[i].name;
|
||||
};
|
||||
|
||||
clearbank();
|
||||
@@ -78,7 +80,8 @@ Bank::~Bank(){
|
||||
/*
|
||||
* Get the name of an instrument from the bank
|
||||
*/
|
||||
char *Bank::getname (unsigned int ninstrument){
|
||||
char *Bank::getname (unsigned int ninstrument)
|
||||
{
|
||||
if (emptyslot(ninstrument)) return (defaultinsname);
|
||||
return (ins[ninstrument].name);
|
||||
};
|
||||
@@ -86,7 +89,8 @@ char *Bank::getname (unsigned int ninstrument){
|
||||
/*
|
||||
* Get the numbered name of an instrument from the bank
|
||||
*/
|
||||
char *Bank::getnamenumbered (unsigned int ninstrument){
|
||||
char *Bank::getnamenumbered (unsigned int ninstrument)
|
||||
{
|
||||
if (emptyslot(ninstrument)) return (defaultinsname);
|
||||
snprintf(tmpinsname[ninstrument],PART_MAX_NAME_LEN+15,"%d. %s",ninstrument+1,getname(ninstrument));
|
||||
return(tmpinsname[ninstrument]);
|
||||
@@ -95,28 +99,29 @@ char *Bank::getnamenumbered (unsigned int ninstrument){
|
||||
/*
|
||||
* Changes the name of an instrument (and the filename)
|
||||
*/
|
||||
void Bank::setname(unsigned int ninstrument,const char *newname,int newslot){
|
||||
void Bank::setname(unsigned int ninstrument,const char *newname,int newslot)
|
||||
{
|
||||
if (emptyslot(ninstrument)) return;
|
||||
|
||||
|
||||
char newfilename[1000+1],tmpfilename[100+1];
|
||||
|
||||
|
||||
ZERO(newfilename,1001);
|
||||
ZERO(tmpfilename,101);
|
||||
if (newslot>=0) snprintf(tmpfilename,100,"%4d-%s",newslot+1,newname);
|
||||
else snprintf(tmpfilename,100,"%4d-%s",ninstrument+1,newname);
|
||||
|
||||
else snprintf(tmpfilename,100,"%4d-%s",ninstrument+1,newname);
|
||||
|
||||
//add the zeroes at the start of filename
|
||||
for (int i=0;i<4;i++) if (tmpfilename[i]==' ') tmpfilename[i]='0';
|
||||
|
||||
//make the filenames legal
|
||||
for (int i=0;i<(int) strlen(tmpfilename);i++) {
|
||||
char c=tmpfilename[i];
|
||||
if ((c>='0')&&(c<='9')) continue;
|
||||
if ((c>='A')&&(c<='Z')) continue;
|
||||
if ((c>='a')&&(c<='z')) continue;
|
||||
if ((c=='-')||(c==' ')) continue;
|
||||
|
||||
tmpfilename[i]='_';
|
||||
char c=tmpfilename[i];
|
||||
if ((c>='0')&&(c<='9')) continue;
|
||||
if ((c>='A')&&(c<='Z')) continue;
|
||||
if ((c>='a')&&(c<='z')) continue;
|
||||
if ((c=='-')||(c==' ')) continue;
|
||||
|
||||
tmpfilename[i]='_';
|
||||
};
|
||||
|
||||
snprintf(newfilename,1000,"%s/%s.xiz",dirname,tmpfilename);
|
||||
@@ -128,39 +133,42 @@ void Bank::setname(unsigned int ninstrument,const char *newname,int newslot){
|
||||
ins[ninstrument].filename=new char[strlen(newfilename)+5];
|
||||
snprintf(ins[ninstrument].filename,strlen(newfilename)+1,"%s",newfilename);
|
||||
snprintf(ins[ninstrument].name,PART_MAX_NAME_LEN,"%s",&tmpfilename[5]);
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Check if there is no instrument on a slot from the bank
|
||||
*/
|
||||
int Bank::emptyslot(unsigned int ninstrument){
|
||||
int Bank::emptyslot(unsigned int ninstrument)
|
||||
{
|
||||
if (ninstrument>=BANK_SIZE) return (1);
|
||||
if (ins[ninstrument].filename==NULL) return(1);
|
||||
|
||||
if (ins[ninstrument].used) return (0);
|
||||
else return(1);
|
||||
else return(1);
|
||||
};
|
||||
|
||||
/*
|
||||
* Removes the instrument from the bank
|
||||
*/
|
||||
void Bank::clearslot(unsigned int ninstrument){
|
||||
void Bank::clearslot(unsigned int ninstrument)
|
||||
{
|
||||
if (emptyslot(ninstrument)) return;
|
||||
|
||||
|
||||
// printf("remove %s \n",ins[ninstrument].filename);////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
remove(ins[ninstrument].filename);
|
||||
deletefrombank(ninstrument);
|
||||
};
|
||||
|
||||
/*
|
||||
* Save the instrument to a slot
|
||||
* Save the instrument to a slot
|
||||
*/
|
||||
void Bank::savetoslot(unsigned int ninstrument,Part *part){
|
||||
void Bank::savetoslot(unsigned int ninstrument,Part *part)
|
||||
{
|
||||
clearslot(ninstrument);
|
||||
|
||||
|
||||
const int maxfilename=200;
|
||||
char tmpfilename[maxfilename+20];
|
||||
ZERO(tmpfilename,maxfilename+20);
|
||||
@@ -169,16 +177,16 @@ void Bank::savetoslot(unsigned int ninstrument,Part *part){
|
||||
|
||||
//add the zeroes at the start of filename
|
||||
for (int i=0;i<4;i++) if (tmpfilename[i]==' ') tmpfilename[i]='0';
|
||||
|
||||
|
||||
//make the filenames legal
|
||||
for (int i=0;i<(int)strlen(tmpfilename);i++) {
|
||||
char c=tmpfilename[i];
|
||||
if ((c>='0')&&(c<='9')) continue;
|
||||
if ((c>='A')&&(c<='Z')) continue;
|
||||
if ((c>='a')&&(c<='z')) continue;
|
||||
if ((c=='-')||(c==' ')) continue;
|
||||
|
||||
tmpfilename[i]='_';
|
||||
char c=tmpfilename[i];
|
||||
if ((c>='0')&&(c<='9')) continue;
|
||||
if ((c>='A')&&(c<='Z')) continue;
|
||||
if ((c>='a')&&(c<='z')) continue;
|
||||
if ((c=='-')||(c==' ')) continue;
|
||||
|
||||
tmpfilename[i]='_';
|
||||
};
|
||||
|
||||
strncat(tmpfilename,".xiz",maxfilename+10);
|
||||
@@ -192,29 +200,31 @@ void Bank::savetoslot(unsigned int ninstrument,Part *part){
|
||||
remove(filename);
|
||||
part->saveXML(filename);
|
||||
addtobank(ninstrument,tmpfilename,(char *) part->Pname);
|
||||
|
||||
|
||||
delete[]filename;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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->loadXMLinstrument(ins[ninstrument].filename);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Makes current a bank directory
|
||||
*/
|
||||
int Bank::loadbank(const char *bankdirname){
|
||||
int Bank::loadbank(const char *bankdirname)
|
||||
{
|
||||
DIR *dir=opendir(bankdirname);
|
||||
clearbank();
|
||||
|
||||
@@ -223,59 +233,59 @@ int Bank::loadbank(const char *bankdirname){
|
||||
if (dirname!=NULL) delete[]dirname;
|
||||
dirname=new char[strlen(bankdirname)+1];
|
||||
snprintf(dirname,strlen(bankdirname)+1,"%s",bankdirname);
|
||||
|
||||
|
||||
bankfiletitle=dirname;
|
||||
|
||||
// printf("loadbank %s/\n",bankdirname);
|
||||
// printf("loadbank %s/\n",bankdirname);
|
||||
struct dirent *fn;
|
||||
|
||||
while ((fn=readdir(dir))){
|
||||
const char *filename= fn->d_name;
|
||||
|
||||
//sa verific daca e si extensia dorita
|
||||
if (strstr(filename,INSTRUMENT_EXTENSION)==NULL) continue;
|
||||
|
||||
//verify if the name is like this NNNN-name (where N is a digit)
|
||||
int no=0;
|
||||
unsigned int startname=0;
|
||||
|
||||
for (unsigned int i=0;i<4;i++) {
|
||||
if (strlen(filename)<=i) break;
|
||||
|
||||
if ((filename[i]>='0')&&(filename[i]<='9')) {
|
||||
no=no*10+(filename[i]-'0');
|
||||
startname++;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
if ((startname+1)<strlen(filename)) startname++;//to take out the "-"
|
||||
|
||||
char name[PART_MAX_NAME_LEN+1];
|
||||
ZERO(name,PART_MAX_NAME_LEN+1);
|
||||
snprintf(name,PART_MAX_NAME_LEN,"%s",filename);
|
||||
|
||||
//remove the file extension
|
||||
for (int i=strlen(name)-1;i>=2;i--){
|
||||
if (name[i]=='.') {
|
||||
name[i]='\0';
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
if (no!=0){//the instrument position in the bank is found
|
||||
addtobank(no-1,filename,&name[startname]);
|
||||
} else {
|
||||
addtobank(-1,filename,name);
|
||||
};
|
||||
|
||||
while ((fn=readdir(dir))) {
|
||||
const char *filename= fn->d_name;
|
||||
|
||||
//sa verific daca e si extensia dorita
|
||||
if (strstr(filename,INSTRUMENT_EXTENSION)==NULL) continue;
|
||||
|
||||
//verify if the name is like this NNNN-name (where N is a digit)
|
||||
int no=0;
|
||||
unsigned int startname=0;
|
||||
|
||||
for (unsigned int i=0;i<4;i++) {
|
||||
if (strlen(filename)<=i) break;
|
||||
|
||||
if ((filename[i]>='0')&&(filename[i]<='9')) {
|
||||
no=no*10+(filename[i]-'0');
|
||||
startname++;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
if ((startname+1)<strlen(filename)) startname++;//to take out the "-"
|
||||
|
||||
char name[PART_MAX_NAME_LEN+1];
|
||||
ZERO(name,PART_MAX_NAME_LEN+1);
|
||||
snprintf(name,PART_MAX_NAME_LEN,"%s",filename);
|
||||
|
||||
//remove the file extension
|
||||
for (int i=strlen(name)-1;i>=2;i--) {
|
||||
if (name[i]=='.') {
|
||||
name[i]='\0';
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
if (no!=0) {//the instrument position in the bank is found
|
||||
addtobank(no-1,filename,&name[startname]);
|
||||
} else {
|
||||
addtobank(-1,filename,name);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
closedir(dir);
|
||||
|
||||
if (dirname!=NULL) {
|
||||
sprintf(config.cfg.currentBankDir,"%s",dirname);
|
||||
sprintf(config.cfg.currentBankDir,"%s",dirname);
|
||||
};
|
||||
|
||||
return(0);
|
||||
@@ -284,16 +294,17 @@ int Bank::loadbank(const char *bankdirname){
|
||||
/*
|
||||
* Makes a new bank, put it on a file and makes it current bank
|
||||
*/
|
||||
int Bank::newbank(const char *newbankdirname){
|
||||
int Bank::newbank(const char *newbankdirname)
|
||||
{
|
||||
int result;
|
||||
char tmpfilename[MAX_STRING_SIZE];
|
||||
char bankdir[MAX_STRING_SIZE];
|
||||
snprintf(bankdir,MAX_STRING_SIZE,"%s",config.cfg.bankRootDirList[0]);
|
||||
|
||||
if (((bankdir[strlen(bankdir)-1])!='/')&&((bankdir[strlen(bankdir)-1])!='\\')){
|
||||
strncat(bankdir,"/",MAX_STRING_SIZE);
|
||||
if (((bankdir[strlen(bankdir)-1])!='/')&&((bankdir[strlen(bankdir)-1])!='\\')) {
|
||||
strncat(bankdir,"/",MAX_STRING_SIZE);
|
||||
};
|
||||
strncat(bankdir,newbankdirname,MAX_STRING_SIZE-1);
|
||||
strncat(bankdir,newbankdirname,MAX_STRING_SIZE);
|
||||
#ifdef OS_WINDOWS
|
||||
result=mkdir(bankdir);
|
||||
#else
|
||||
@@ -305,57 +316,62 @@ int Bank::newbank(const char *newbankdirname){
|
||||
// printf("%s\n",tmpfilename);
|
||||
FILE *tmpfile=fopen(tmpfilename,"w+");
|
||||
fclose(tmpfile);
|
||||
|
||||
|
||||
return(loadbank(bankdir));
|
||||
};
|
||||
|
||||
/*
|
||||
* Check if the bank is locked (i.e. the file opened was readonly)
|
||||
*/
|
||||
int Bank::locked(){
|
||||
int Bank::locked()
|
||||
{
|
||||
return(dirname==NULL);
|
||||
};
|
||||
|
||||
/*
|
||||
* Swaps a slot with another
|
||||
*/
|
||||
void Bank::swapslot(unsigned int n1, unsigned int n2){
|
||||
void Bank::swapslot(unsigned int n1, unsigned int n2)
|
||||
{
|
||||
if ((n1==n2)||(locked())) return;
|
||||
if (emptyslot(n1)&&(emptyslot(n2))) return;
|
||||
if (emptyslot(n1)){//change n1 to n2 in order to make
|
||||
int tmp=n2;n2=n1;n1=tmp;
|
||||
if (emptyslot(n1)) {//change n1 to n2 in order to make
|
||||
int tmp=n2;
|
||||
n2=n1;
|
||||
n1=tmp;
|
||||
};
|
||||
|
||||
if (emptyslot(n2)){//this is just a movement from slot1 to slot2
|
||||
setname(n1,getname(n1),n2);
|
||||
ins[n2]=ins[n1];
|
||||
ins[n1].used=false;
|
||||
ins[n1].name[0]='\0';
|
||||
ins[n1].filename=NULL;
|
||||
ins[n1].info.PADsynth_used=0;
|
||||
|
||||
if (emptyslot(n2)) {//this is just a movement from slot1 to slot2
|
||||
setname(n1,getname(n1),n2);
|
||||
ins[n2]=ins[n1];
|
||||
ins[n1].used=false;
|
||||
ins[n1].name[0]='\0';
|
||||
ins[n1].filename=NULL;
|
||||
ins[n1].info.PADsynth_used=0;
|
||||
} else {//if both slots are used
|
||||
if (strcmp(ins[n1].name,ins[n2].name)==0){//change the name of the second instrument if the name are equal
|
||||
strncat(ins[n2].name,"2",PART_MAX_NAME_LEN);
|
||||
};
|
||||
setname(n1,getname(n1),n2);
|
||||
setname(n2,getname(n2),n1);
|
||||
ins_t tmp;
|
||||
tmp.used=true;
|
||||
strcpy(tmp.name,ins[n2].name);
|
||||
char *tmpfilename=ins[n2].filename;
|
||||
bool padsynth_used=ins[n2].info.PADsynth_used;
|
||||
|
||||
ins[n2]=ins[n1];
|
||||
strcpy(ins[n1].name,tmp.name);
|
||||
ins[n1].filename=tmpfilename;
|
||||
ins[n1].info.PADsynth_used=padsynth_used;
|
||||
if (strcmp(ins[n1].name,ins[n2].name)==0) {//change the name of the second instrument if the name are equal
|
||||
strncat(ins[n2].name,"2",PART_MAX_NAME_LEN);
|
||||
};
|
||||
setname(n1,getname(n1),n2);
|
||||
setname(n2,getname(n2),n1);
|
||||
ins_t tmp;
|
||||
tmp.used=true;
|
||||
strcpy(tmp.name,ins[n2].name);
|
||||
char *tmpfilename=ins[n2].filename;
|
||||
bool padsynth_used=ins[n2].info.PADsynth_used;
|
||||
|
||||
ins[n2]=ins[n1];
|
||||
strcpy(ins[n1].name,tmp.name);
|
||||
ins[n1].filename=tmpfilename;
|
||||
ins[n1].info.PADsynth_used=padsynth_used;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
//a helper function that compares 2 banks[] arrays
|
||||
int Bank_compar(const void *a,const void *b){
|
||||
int Bank_compar(const void *a,const void *b)
|
||||
{
|
||||
struct Bank::bankstruct *bank1= (Bank::bankstruct *)a;
|
||||
struct Bank::bankstruct *bank2= (Bank::bankstruct *)b;
|
||||
if (((bank1->name)==NULL)||((bank2->name)==NULL)) return(0);
|
||||
@@ -369,156 +385,160 @@ int Bank_compar(const void *a,const void *b){
|
||||
* Re-scan for directories containing instrument banks
|
||||
*/
|
||||
|
||||
void Bank::rescanforbanks(){
|
||||
for (int i=0;i<MAX_NUM_BANKS;i++){
|
||||
if (banks[i].dir!=NULL) delete []banks[i].dir;
|
||||
if (banks[i].name!=NULL) delete []banks[i].name;
|
||||
banks[i].dir=NULL;
|
||||
banks[i].name=NULL;
|
||||
void Bank::rescanforbanks()
|
||||
{
|
||||
for (int i=0;i<MAX_NUM_BANKS;i++) {
|
||||
if (banks[i].dir!=NULL) delete []banks[i].dir;
|
||||
if (banks[i].name!=NULL) delete []banks[i].name;
|
||||
banks[i].dir=NULL;
|
||||
banks[i].name=NULL;
|
||||
};
|
||||
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (config.cfg.bankRootDirList[i]!=NULL) scanrootdir(config.cfg.bankRootDirList[i]);
|
||||
|
||||
//sort the banks
|
||||
for (int j=0;j<MAX_NUM_BANKS-1;j++){
|
||||
for (int i=j+1;i<MAX_NUM_BANKS;i++){
|
||||
if (Bank_compar(&banks[i],&banks[j])) {
|
||||
char *tmpname=banks[i].name;
|
||||
char *tmpdir=banks[i].dir;
|
||||
for (int j=0;j<MAX_NUM_BANKS-1;j++) {
|
||||
for (int i=j+1;i<MAX_NUM_BANKS;i++) {
|
||||
if (Bank_compar(&banks[i],&banks[j])) {
|
||||
char *tmpname=banks[i].name;
|
||||
char *tmpdir=banks[i].dir;
|
||||
|
||||
banks[i].name=banks[j].name;
|
||||
banks[i].dir=banks[j].dir;
|
||||
banks[i].name=banks[j].name;
|
||||
banks[i].dir=banks[j].dir;
|
||||
|
||||
banks[j].name=tmpname;
|
||||
banks[j].dir=tmpdir;
|
||||
|
||||
};
|
||||
};
|
||||
banks[j].name=tmpname;
|
||||
banks[j].dir=tmpdir;
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//remove duplicate bank names
|
||||
int dupl=0;
|
||||
for (int j=0;j<MAX_NUM_BANKS-1;j++){
|
||||
for (int i=j+1;i<MAX_NUM_BANKS;i++){
|
||||
if ((banks[i].name==NULL)||(banks[j].name==NULL)) continue;
|
||||
if (strcmp(banks[i].name,banks[j].name)==0) {//add a [1] to the first bankname and [n] to others
|
||||
char *tmpname=banks[i].name;
|
||||
banks[i].name=new char[strlen(tmpname)+100];
|
||||
sprintf(banks[i].name,"%s[%d]",tmpname,dupl+2);
|
||||
delete[]tmpname;
|
||||
|
||||
if (dupl==0){
|
||||
char *tmpname=banks[j].name;
|
||||
banks[j].name=new char[strlen(tmpname)+100];
|
||||
sprintf(banks[j].name,"%s[1]",tmpname);
|
||||
delete[]tmpname;
|
||||
};
|
||||
|
||||
dupl++;
|
||||
} else dupl=0;
|
||||
};
|
||||
for (int j=0;j<MAX_NUM_BANKS-1;j++) {
|
||||
for (int i=j+1;i<MAX_NUM_BANKS;i++) {
|
||||
if ((banks[i].name==NULL)||(banks[j].name==NULL)) continue;
|
||||
if (strcmp(banks[i].name,banks[j].name)==0) {//add a [1] to the first bankname and [n] to others
|
||||
char *tmpname=banks[i].name;
|
||||
banks[i].name=new char[strlen(tmpname)+100];
|
||||
sprintf(banks[i].name,"%s[%d]",tmpname,dupl+2);
|
||||
delete[]tmpname;
|
||||
|
||||
if (dupl==0) {
|
||||
char *tmpname=banks[j].name;
|
||||
banks[j].name=new char[strlen(tmpname)+100];
|
||||
sprintf(banks[j].name,"%s[1]",tmpname);
|
||||
delete[]tmpname;
|
||||
};
|
||||
|
||||
dupl++;
|
||||
} else dupl=0;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// private stuff
|
||||
|
||||
void Bank::scanrootdir(char *rootdir){
|
||||
void Bank::scanrootdir(char *rootdir)
|
||||
{
|
||||
// printf("Scanning root dir:%s\n",rootdir);
|
||||
DIR *dir=opendir(rootdir);
|
||||
if (dir==NULL) return;
|
||||
|
||||
const int maxdirsize=1000;
|
||||
struct {
|
||||
char dir[maxdirsize];
|
||||
char name[maxdirsize];
|
||||
char dir[maxdirsize];
|
||||
char name[maxdirsize];
|
||||
}bank;
|
||||
|
||||
const char *separator="/";
|
||||
if (strlen(rootdir)) {
|
||||
char tmp=rootdir[strlen(rootdir)-1];
|
||||
if ((tmp=='/') || (tmp=='\\')) separator="";
|
||||
char tmp=rootdir[strlen(rootdir)-1];
|
||||
if ((tmp=='/') || (tmp=='\\')) separator="";
|
||||
};
|
||||
|
||||
struct dirent *fn;
|
||||
while ((fn=readdir(dir))){
|
||||
const char *dirname=fn->d_name;
|
||||
if (dirname[0]=='.') continue;
|
||||
|
||||
snprintf(bank.dir,maxdirsize,"%s%s%s/",rootdir,separator,dirname);
|
||||
snprintf(bank.name,maxdirsize,"%s",dirname);
|
||||
//find out if the directory contains at least 1 instrument
|
||||
bool isbank=false;
|
||||
|
||||
DIR *d=opendir(bank.dir);
|
||||
if (d==NULL) continue;
|
||||
|
||||
struct dirent *fname;
|
||||
|
||||
while((fname=readdir(d))){
|
||||
if ((strstr(fname->d_name,INSTRUMENT_EXTENSION)!=NULL)||
|
||||
(strstr(fname->d_name,FORCE_BANK_DIR_FILE)!=NULL)){
|
||||
isbank=true;
|
||||
break;//aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank
|
||||
};
|
||||
};
|
||||
|
||||
closedir(d);
|
||||
|
||||
if (isbank) {
|
||||
int pos=-1;
|
||||
for (int i=1;i<MAX_NUM_BANKS;i++){ //banks[0] e liber intotdeauna
|
||||
if (banks[i].name==NULL) {
|
||||
pos=i;
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
if (pos>=0) {
|
||||
banks[pos].name=new char[maxdirsize];
|
||||
banks[pos].dir=new char[maxdirsize];
|
||||
snprintf(banks[pos].name,maxdirsize,"%s",bank.name);
|
||||
snprintf(banks[pos].dir,maxdirsize,"%s",bank.dir);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
struct dirent *fn;
|
||||
while ((fn=readdir(dir))) {
|
||||
const char *dirname=fn->d_name;
|
||||
if (dirname[0]=='.') continue;
|
||||
|
||||
snprintf(bank.dir,maxdirsize,"%s%s%s/",rootdir,separator,dirname);
|
||||
snprintf(bank.name,maxdirsize,"%s",dirname);
|
||||
//find out if the directory contains at least 1 instrument
|
||||
bool isbank=false;
|
||||
|
||||
DIR *d=opendir(bank.dir);
|
||||
if (d==NULL) continue;
|
||||
|
||||
struct dirent *fname;
|
||||
|
||||
while ((fname=readdir(d))) {
|
||||
if ((strstr(fname->d_name,INSTRUMENT_EXTENSION)!=NULL)||
|
||||
(strstr(fname->d_name,FORCE_BANK_DIR_FILE)!=NULL)) {
|
||||
isbank=true;
|
||||
break;//aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank
|
||||
};
|
||||
};
|
||||
|
||||
closedir(d);
|
||||
|
||||
if (isbank) {
|
||||
int pos=-1;
|
||||
for (int i=1;i<MAX_NUM_BANKS;i++) { //banks[0] e liber intotdeauna
|
||||
if (banks[i].name==NULL) {
|
||||
pos=i;
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
if (pos>=0) {
|
||||
banks[pos].name=new char[maxdirsize];
|
||||
banks[pos].dir=new char[maxdirsize];
|
||||
snprintf(banks[pos].name,maxdirsize,"%s",bank.name);
|
||||
snprintf(banks[pos].dir,maxdirsize,"%s",bank.dir);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
closedir(dir);
|
||||
|
||||
|
||||
};
|
||||
|
||||
void Bank::clearbank(){
|
||||
void Bank::clearbank()
|
||||
{
|
||||
for (int i=0;i<BANK_SIZE;i++) deletefrombank(i);
|
||||
if (dirname!=NULL) delete[]dirname;
|
||||
bankfiletitle=NULL;
|
||||
dirname=NULL;
|
||||
};
|
||||
|
||||
int Bank::addtobank(int pos, const char *filename, const char* name){
|
||||
if ((pos>=0)&&(pos<BANK_SIZE)){
|
||||
if (ins[pos].used) pos=-1;//force it to find a new free position
|
||||
int Bank::addtobank(int pos, const char *filename, const char* name)
|
||||
{
|
||||
if ((pos>=0)&&(pos<BANK_SIZE)) {
|
||||
if (ins[pos].used) pos=-1;//force it to find a new free position
|
||||
} else if (pos>=BANK_SIZE) pos=-1;
|
||||
|
||||
|
||||
|
||||
|
||||
if (pos<0) {//find a free position
|
||||
for (int i=BANK_SIZE-1;i>=0;i--)
|
||||
if (!ins[i].used) {
|
||||
pos=i;
|
||||
break;
|
||||
};
|
||||
|
||||
for (int i=BANK_SIZE-1;i>=0;i--)
|
||||
if (!ins[i].used) {
|
||||
pos=i;
|
||||
break;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
if (pos<0) return (-1);//the bank is full
|
||||
|
||||
// printf("%s %d\n",filename,pos);
|
||||
// printf("%s %d\n",filename,pos);
|
||||
|
||||
deletefrombank(pos);
|
||||
|
||||
|
||||
ins[pos].used=true;
|
||||
snprintf(ins[pos].name,PART_MAX_NAME_LEN,"%s",name);
|
||||
|
||||
@@ -530,33 +550,35 @@ int Bank::addtobank(int pos, const char *filename, const char* name){
|
||||
snprintf(ins[pos].filename,len+1,"%s/%s",dirname,filename);
|
||||
|
||||
//see if PADsynth is used
|
||||
if (config.cfg.CheckPADsynth){
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
xml->checkfileinformation(ins[pos].filename);
|
||||
|
||||
ins[pos].info.PADsynth_used=xml->information.PADsynth_used;
|
||||
delete xml;
|
||||
if (config.cfg.CheckPADsynth) {
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
xml->checkfileinformation(ins[pos].filename);
|
||||
|
||||
ins[pos].info.PADsynth_used=xml->information.PADsynth_used;
|
||||
delete xml;
|
||||
} else ins[pos].info.PADsynth_used=false;
|
||||
|
||||
|
||||
return(0);
|
||||
};
|
||||
|
||||
bool Bank::isPADsynth_used(unsigned int ninstrument){
|
||||
bool Bank::isPADsynth_used(unsigned int ninstrument)
|
||||
{
|
||||
if (config.cfg.CheckPADsynth==0) return(0);
|
||||
else return(ins[ninstrument].info.PADsynth_used);
|
||||
else return(ins[ninstrument].info.PADsynth_used);
|
||||
};
|
||||
|
||||
|
||||
void Bank::deletefrombank(int pos){
|
||||
void Bank::deletefrombank(int pos)
|
||||
{
|
||||
if ((pos<0)||(pos>=BANK_SIZE)) return;
|
||||
ins[pos].used=false;
|
||||
ZERO(ins[pos].name,PART_MAX_NAME_LEN+1);
|
||||
if (ins[pos].filename!=NULL) {
|
||||
delete []ins[pos].filename;
|
||||
ins[pos].filename=NULL;
|
||||
delete []ins[pos].filename;
|
||||
ins[pos].filename=NULL;
|
||||
};
|
||||
|
||||
|
||||
ZERO(tmpinsname[pos],PART_MAX_NAME_LEN+20);
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Bank.C - Instrument Bank
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -29,71 +29,79 @@
|
||||
|
||||
#define BANK_SIZE 160
|
||||
|
||||
/*
|
||||
/**
|
||||
* The max. number of banks that are used
|
||||
*/
|
||||
#define MAX_NUM_BANKS 400
|
||||
|
||||
/**The instrument Bank
|
||||
* \todo add in strings to replace char* */
|
||||
class Bank
|
||||
{
|
||||
public:
|
||||
/**Constructor*/
|
||||
Bank();
|
||||
~Bank();
|
||||
char *getname(unsigned int ninstrument);
|
||||
char *getnamenumbered(unsigned int ninstrument);
|
||||
void setname(unsigned int ninstrument,const char *newname,int newslot);//if newslot==-1 then this is ignored, else it will be put on that slot
|
||||
bool isPADsynth_used(unsigned int ninstrument);
|
||||
|
||||
class Bank{
|
||||
public:
|
||||
Bank();
|
||||
~Bank();
|
||||
char *getname(unsigned int ninstrument);
|
||||
char *getnamenumbered(unsigned int ninstrument);
|
||||
void setname(unsigned int ninstrument,const char *newname,int newslot);//if newslot==-1 then this is ignored, else it will be put on that slot
|
||||
bool isPADsynth_used(unsigned int ninstrument);
|
||||
|
||||
//returns 0 if the slot is not empty or 1 if the slot is empty
|
||||
int emptyslot(unsigned int ninstrument);
|
||||
/**returns 0 if the slot is not empty or 1 if the slot is empty
|
||||
* \todo start using bool before facepalm*/
|
||||
int emptyslot(unsigned int ninstrument);
|
||||
|
||||
void clearslot(unsigned int ninstrument);
|
||||
void savetoslot(unsigned int ninstrument,Part *part);
|
||||
void loadfromslot(unsigned int ninstrument,Part *part);
|
||||
/**Empties out the selected slot*/
|
||||
void clearslot(unsigned int ninstrument);
|
||||
/**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 swapslot(unsigned int n1,unsigned int n2);
|
||||
/**Swaps Slots*/
|
||||
void swapslot(unsigned int n1,unsigned int n2);
|
||||
|
||||
int loadbank(const char *bankdirname);
|
||||
int newbank(const char *newbankdirname);
|
||||
|
||||
char *bankfiletitle; //this is shown on the UI of the bank (the title of the window)
|
||||
int locked();
|
||||
|
||||
void rescanforbanks();
|
||||
|
||||
struct bankstruct{
|
||||
char *dir;
|
||||
char *name;
|
||||
};
|
||||
|
||||
bankstruct banks[MAX_NUM_BANKS];
|
||||
|
||||
private:
|
||||
|
||||
//it adds a filename to the bank
|
||||
//if pos is -1 it try to find a position
|
||||
//returns -1 if the bank is full, or 0 if the instrument was added
|
||||
int addtobank(int pos,const char* filename,const char* name);
|
||||
|
||||
void deletefrombank(int pos);
|
||||
|
||||
void clearbank();
|
||||
|
||||
char defaultinsname[PART_MAX_NAME_LEN];
|
||||
char tmpinsname[BANK_SIZE][PART_MAX_NAME_LEN+20];//this keeps the numbered names
|
||||
|
||||
struct ins_t{
|
||||
bool used;
|
||||
char name[PART_MAX_NAME_LEN+1];
|
||||
char *filename;
|
||||
struct{
|
||||
bool PADsynth_used;
|
||||
} info;
|
||||
}ins[BANK_SIZE];
|
||||
|
||||
char *dirname;
|
||||
int loadbank(const char *bankdirname);
|
||||
int newbank(const char *newbankdirname);
|
||||
|
||||
void scanrootdir(char *rootdir);//scans a root dir for banks
|
||||
char *bankfiletitle; //this is shown on the UI of the bank (the title of the window)
|
||||
int locked();
|
||||
|
||||
void rescanforbanks();
|
||||
|
||||
struct bankstruct {
|
||||
char *dir;
|
||||
char *name;
|
||||
};
|
||||
|
||||
bankstruct banks[MAX_NUM_BANKS];
|
||||
|
||||
private:
|
||||
|
||||
//it adds a filename to the bank
|
||||
//if pos is -1 it try to find a position
|
||||
//returns -1 if the bank is full, or 0 if the instrument was added
|
||||
int addtobank(int pos,const char* filename,const char* name);
|
||||
|
||||
void deletefrombank(int pos);
|
||||
|
||||
void clearbank();
|
||||
|
||||
char defaultinsname[PART_MAX_NAME_LEN];
|
||||
char tmpinsname[BANK_SIZE][PART_MAX_NAME_LEN+20];//this keeps the numbered names
|
||||
|
||||
struct ins_t {
|
||||
bool used;
|
||||
char name[PART_MAX_NAME_LEN+1];
|
||||
char *filename;
|
||||
struct {
|
||||
bool PADsynth_used;
|
||||
} info;
|
||||
}ins[BANK_SIZE];
|
||||
|
||||
char *dirname;
|
||||
|
||||
void scanrootdir(char *rootdir);//scans a root dir for banks
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
18
plugins/zynaddsubfx/src/Misc/CMakeLists.txt
Normal file
18
plugins/zynaddsubfx/src/Misc/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
include_directories(${MXML_INCLUDE_DIR})
|
||||
|
||||
set(zynaddsubfx_misc_SRCS
|
||||
Bank.cpp
|
||||
Config.cpp
|
||||
Dump.cpp
|
||||
Master.cpp
|
||||
Microtonal.cpp
|
||||
Part.cpp
|
||||
Util.cpp
|
||||
XMLwrapper.cpp
|
||||
)
|
||||
|
||||
add_library(zynaddsubfx_misc STATIC
|
||||
${zynaddsubfx_misc_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries(zynaddsubfx_misc zynaddsubfx_output)
|
||||
@@ -1,331 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Config.C - Configuration file functions
|
||||
Copyright (C) 2003-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#endif
|
||||
|
||||
#include "Config.h"
|
||||
#include "XMLwrapper.h"
|
||||
|
||||
Config::Config(){
|
||||
};
|
||||
void Config::init(){
|
||||
maxstringsize=MAX_STRING_SIZE;//for ui
|
||||
//defaults
|
||||
cfg.SampleRate=44100;
|
||||
cfg.SoundBufferSize=256;
|
||||
cfg.OscilSize=1024;
|
||||
cfg.SwapStereo=0;
|
||||
|
||||
cfg.LinuxOSSWaveOutDev=new char[MAX_STRING_SIZE];
|
||||
snprintf(cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE,"/dev/dsp");
|
||||
cfg.LinuxOSSSeqInDev=new char[MAX_STRING_SIZE];
|
||||
snprintf(cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE,"/dev/sequencer");
|
||||
|
||||
cfg.DumpFile=new char[MAX_STRING_SIZE];
|
||||
snprintf(cfg.DumpFile,MAX_STRING_SIZE,"zynaddsubfx_dump.txt");
|
||||
|
||||
cfg.WindowsWaveOutId=0;
|
||||
cfg.WindowsMidiInId=0;
|
||||
|
||||
cfg.BankUIAutoClose=0;
|
||||
cfg.DumpNotesToFile=0;
|
||||
cfg.DumpAppend=1;
|
||||
|
||||
cfg.GzipCompression=3;
|
||||
|
||||
cfg.Interpolation=0;
|
||||
cfg.CheckPADsynth=1;
|
||||
|
||||
cfg.UserInterfaceMode=0;
|
||||
cfg.VirKeybLayout=1;
|
||||
winwavemax=1;winmidimax=1;
|
||||
//try to find out how many input midi devices are there
|
||||
#ifdef WINMIDIIN
|
||||
winmidimax=midiInGetNumDevs();
|
||||
if (winmidimax==0) winmidimax=1;
|
||||
#endif
|
||||
winmididevices=new winmidionedevice[winmidimax];
|
||||
for (int i=0;i<winmidimax;i++) {
|
||||
winmididevices[i].name=new char[MAX_STRING_SIZE];
|
||||
for (int j=0;j<MAX_STRING_SIZE;j++) winmididevices[i].name[j]='\0';
|
||||
};
|
||||
|
||||
|
||||
//get the midi input devices name
|
||||
#ifdef WINMIDIIN
|
||||
MIDIINCAPS midiincaps;
|
||||
for (int i=0;i<winmidimax;i++){
|
||||
if (! midiInGetDevCaps(i,&midiincaps,sizeof(MIDIINCAPS)))
|
||||
snprintf(winmididevices[i].name,MAX_STRING_SIZE,"%s",midiincaps.szPname);
|
||||
};
|
||||
#endif
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) cfg.bankRootDirList[i]=NULL;
|
||||
cfg.currentBankDir=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.currentBankDir,"./testbnk");
|
||||
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) cfg.presetsDirList[i]=NULL;
|
||||
|
||||
char filename[MAX_STRING_SIZE];
|
||||
getConfigFileName(filename,MAX_STRING_SIZE);
|
||||
readConfig(filename);
|
||||
|
||||
if (cfg.bankRootDirList[0]==NULL){
|
||||
#if defined(OS_LINUX)
|
||||
//banks
|
||||
cfg.bankRootDirList[0]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[0],"~/banks");
|
||||
|
||||
cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[1],"./");
|
||||
|
||||
cfg.bankRootDirList[2]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[2],"/usr/share/zynaddsubfx/banks");
|
||||
|
||||
cfg.bankRootDirList[3]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[3],"/usr/local/share/zynaddsubfx/banks");
|
||||
|
||||
cfg.bankRootDirList[4]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[4],"../banks");
|
||||
|
||||
cfg.bankRootDirList[5]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[5],"banks");
|
||||
|
||||
#else
|
||||
//banks
|
||||
cfg.bankRootDirList[0]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[0],"./");
|
||||
|
||||
#ifdef VSTAUDIOOUT
|
||||
cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[1],"c:/Program Files/ZynAddSubFX/banks");
|
||||
#else
|
||||
cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[1],"../banks");
|
||||
#endif
|
||||
cfg.bankRootDirList[2]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[2],"banks");
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
if (cfg.presetsDirList[0]==NULL){
|
||||
#if defined(OS_LINUX)
|
||||
//presets
|
||||
cfg.presetsDirList[0]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[0],"./");
|
||||
|
||||
cfg.presetsDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[1],"../presets");
|
||||
|
||||
cfg.presetsDirList[2]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[2],"presets");
|
||||
|
||||
cfg.presetsDirList[3]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[3],"/usr/share/zynaddsubfx/presets");
|
||||
|
||||
cfg.presetsDirList[4]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[4],"/usr/local/share/zynaddsubfx/presets");
|
||||
|
||||
#else
|
||||
//presets
|
||||
cfg.presetsDirList[0]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[0],"./");
|
||||
|
||||
#ifdef VSTAUDIOOUT
|
||||
cfg.presetsDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[1],"c:/Program Files/ZynAddSubFX/presets");
|
||||
#else
|
||||
cfg.presetsDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[1],"../presets");
|
||||
#endif
|
||||
|
||||
cfg.presetsDirList[2]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[2],"presets");
|
||||
#endif
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
Config::~Config(){
|
||||
|
||||
delete [] cfg.LinuxOSSWaveOutDev;
|
||||
delete [] cfg.LinuxOSSSeqInDev;
|
||||
delete [] cfg.DumpFile;
|
||||
|
||||
for (int i=0;i<winmidimax;i++) delete [] winmididevices[i].name;
|
||||
delete [] winmididevices;
|
||||
};
|
||||
|
||||
|
||||
void Config::save(){
|
||||
char filename[MAX_STRING_SIZE];
|
||||
getConfigFileName(filename,MAX_STRING_SIZE);
|
||||
saveConfig(filename);
|
||||
};
|
||||
|
||||
void Config::clearbankrootdirlist(){
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) {
|
||||
if (cfg.bankRootDirList[i]==NULL) delete(cfg.bankRootDirList[i]);
|
||||
cfg.bankRootDirList[i]=NULL;
|
||||
};
|
||||
};
|
||||
|
||||
void Config::clearpresetsdirlist(){
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) {
|
||||
if (cfg.presetsDirList[i]==NULL) delete(cfg.presetsDirList[i]);
|
||||
cfg.presetsDirList[i]=NULL;
|
||||
};
|
||||
};
|
||||
|
||||
void Config::readConfig(const char *filename){
|
||||
XMLwrapper *xmlcfg=new XMLwrapper();
|
||||
if (xmlcfg->loadXMLfile(filename)<0) return;
|
||||
if (xmlcfg->enterbranch("CONFIGURATION")){
|
||||
cfg.SampleRate=xmlcfg->getpar("sample_rate",cfg.SampleRate,4000,1024000);
|
||||
cfg.SoundBufferSize=xmlcfg->getpar("sound_buffer_size",cfg.SoundBufferSize,16,8192);
|
||||
cfg.OscilSize=xmlcfg->getpar("oscil_size",cfg.OscilSize,MAX_AD_HARMONICS*2,131072);
|
||||
cfg.SwapStereo=xmlcfg->getpar("swap_stereo",cfg.SwapStereo,0,1);
|
||||
cfg.BankUIAutoClose=xmlcfg->getpar("bank_window_auto_close",cfg.BankUIAutoClose,0,1);
|
||||
|
||||
cfg.DumpNotesToFile=xmlcfg->getpar("dump_notes_to_file",cfg.DumpNotesToFile,0,1);
|
||||
cfg.DumpAppend=xmlcfg->getpar("dump_append",cfg.DumpAppend,0,1);
|
||||
xmlcfg->getparstr("dump_file",cfg.DumpFile,MAX_STRING_SIZE);
|
||||
|
||||
cfg.GzipCompression=xmlcfg->getpar("gzip_compression",cfg.GzipCompression,0,9);
|
||||
|
||||
xmlcfg->getparstr("bank_current",cfg.currentBankDir,MAX_STRING_SIZE);
|
||||
cfg.Interpolation=xmlcfg->getpar("interpolation",cfg.Interpolation,0,1);
|
||||
|
||||
cfg.CheckPADsynth=xmlcfg->getpar("check_pad_synth",cfg.CheckPADsynth,0,1);
|
||||
|
||||
|
||||
cfg.UserInterfaceMode=xmlcfg->getpar("user_interface_mode",cfg.UserInterfaceMode,0,2);
|
||||
cfg.VirKeybLayout=xmlcfg->getpar("virtual_keyboard_layout",cfg.VirKeybLayout,0,10);
|
||||
|
||||
//get bankroot dirs
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++){
|
||||
if (xmlcfg->enterbranch("BANKROOT",i)){
|
||||
cfg.bankRootDirList[i]=new char[MAX_STRING_SIZE];
|
||||
xmlcfg->getparstr("bank_root",cfg.bankRootDirList[i],MAX_STRING_SIZE);
|
||||
xmlcfg->exitbranch();
|
||||
};
|
||||
};
|
||||
|
||||
//get preset root dirs
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++){
|
||||
if (xmlcfg->enterbranch("PRESETSROOT",i)){
|
||||
cfg.presetsDirList[i]=new char[MAX_STRING_SIZE];
|
||||
xmlcfg->getparstr("presets_root",cfg.presetsDirList[i],MAX_STRING_SIZE);
|
||||
xmlcfg->exitbranch();
|
||||
};
|
||||
};
|
||||
|
||||
//linux stuff
|
||||
xmlcfg->getparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE);
|
||||
xmlcfg->getparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE);
|
||||
|
||||
//windows stuff
|
||||
cfg.WindowsWaveOutId=xmlcfg->getpar("windows_wave_out_id",cfg.WindowsWaveOutId,0,winwavemax);
|
||||
cfg.WindowsMidiInId=xmlcfg->getpar("windows_midi_in_id",cfg.WindowsMidiInId,0,winmidimax);
|
||||
|
||||
xmlcfg->exitbranch();
|
||||
};
|
||||
delete(xmlcfg);
|
||||
|
||||
cfg.OscilSize=(int) pow(2,ceil(log (cfg.OscilSize-1.0)/log(2.0)));
|
||||
|
||||
};
|
||||
|
||||
void Config::saveConfig(const char *filename){
|
||||
XMLwrapper *xmlcfg=new XMLwrapper();
|
||||
|
||||
xmlcfg->beginbranch("CONFIGURATION");
|
||||
|
||||
xmlcfg->addpar("sample_rate",cfg.SampleRate);
|
||||
xmlcfg->addpar("sound_buffer_size",cfg.SoundBufferSize);
|
||||
xmlcfg->addpar("oscil_size",cfg.OscilSize);
|
||||
xmlcfg->addpar("swap_stereo",cfg.SwapStereo);
|
||||
xmlcfg->addpar("bank_window_auto_close",cfg.BankUIAutoClose);
|
||||
|
||||
xmlcfg->addpar("dump_notes_to_file",cfg.DumpNotesToFile);
|
||||
xmlcfg->addpar("dump_append",cfg.DumpAppend);
|
||||
xmlcfg->addparstr("dump_file",cfg.DumpFile);
|
||||
|
||||
xmlcfg->addpar("gzip_compression",cfg.GzipCompression);
|
||||
|
||||
xmlcfg->addpar("check_pad_synth",cfg.CheckPADsynth);
|
||||
|
||||
xmlcfg->addparstr("bank_current",cfg.currentBankDir);
|
||||
|
||||
xmlcfg->addpar("user_interface_mode",cfg.UserInterfaceMode);
|
||||
xmlcfg->addpar("virtual_keyboard_layout",cfg.VirKeybLayout);
|
||||
|
||||
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (cfg.bankRootDirList[i]!=NULL) {
|
||||
xmlcfg->beginbranch("BANKROOT",i);
|
||||
xmlcfg->addparstr("bank_root",cfg.bankRootDirList[i]);
|
||||
xmlcfg->endbranch();
|
||||
};
|
||||
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (cfg.presetsDirList[i]!=NULL) {
|
||||
xmlcfg->beginbranch("PRESETSROOT",i);
|
||||
xmlcfg->addparstr("presets_root",cfg.presetsDirList[i]);
|
||||
xmlcfg->endbranch();
|
||||
};
|
||||
|
||||
xmlcfg->addpar("interpolation",cfg.Interpolation);
|
||||
|
||||
//linux stuff
|
||||
xmlcfg->addparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev);
|
||||
xmlcfg->addparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev);
|
||||
|
||||
//windows stuff
|
||||
xmlcfg->addpar("windows_wave_out_id",cfg.WindowsWaveOutId);
|
||||
xmlcfg->addpar("windows_midi_in_id",cfg.WindowsMidiInId);
|
||||
|
||||
xmlcfg->endbranch();
|
||||
|
||||
int tmp=cfg.GzipCompression;
|
||||
cfg.GzipCompression=0;
|
||||
xmlcfg->saveXMLfile(filename);
|
||||
cfg.GzipCompression=tmp;
|
||||
|
||||
delete(xmlcfg);
|
||||
};
|
||||
|
||||
void Config::getConfigFileName(char *name, int namesize){
|
||||
name[0]=0;
|
||||
#ifdef OS_LINUX
|
||||
snprintf(name,namesize,"%s%s",getenv("HOME"),"/.zynaddsubfxXML.cfg");
|
||||
#else
|
||||
snprintf(name,namesize,"%s","zynaddsubfxXML.cfg");
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
341
plugins/zynaddsubfx/src/Misc/Config.cpp
Normal file
341
plugins/zynaddsubfx/src/Misc/Config.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Config.C - Configuration file functions
|
||||
Copyright (C) 2003-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#endif
|
||||
|
||||
#include "Config.h"
|
||||
#include "XMLwrapper.h"
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
};
|
||||
void Config::init()
|
||||
{
|
||||
maxstringsize=MAX_STRING_SIZE;//for ui
|
||||
//defaults
|
||||
cfg.SampleRate=44100;
|
||||
cfg.SoundBufferSize=256;
|
||||
cfg.OscilSize=1024;
|
||||
cfg.SwapStereo=0;
|
||||
|
||||
cfg.LinuxOSSWaveOutDev=new char[MAX_STRING_SIZE];
|
||||
snprintf(cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE,"/dev/dsp");
|
||||
cfg.LinuxOSSSeqInDev=new char[MAX_STRING_SIZE];
|
||||
snprintf(cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE,"/dev/sequencer");
|
||||
|
||||
cfg.DumpFile=new char[MAX_STRING_SIZE];
|
||||
snprintf(cfg.DumpFile,MAX_STRING_SIZE,"zynaddsubfx_dump.txt");
|
||||
|
||||
cfg.WindowsWaveOutId=0;
|
||||
cfg.WindowsMidiInId=0;
|
||||
|
||||
cfg.BankUIAutoClose=0;
|
||||
cfg.DumpNotesToFile=0;
|
||||
cfg.DumpAppend=1;
|
||||
|
||||
cfg.GzipCompression=3;
|
||||
|
||||
cfg.Interpolation=0;
|
||||
cfg.CheckPADsynth=1;
|
||||
|
||||
cfg.UserInterfaceMode=0;
|
||||
cfg.VirKeybLayout=1;
|
||||
winwavemax=1;
|
||||
winmidimax=1;
|
||||
//try to find out how many input midi devices are there
|
||||
#ifdef WINMIDIIN
|
||||
winmidimax=midiInGetNumDevs();
|
||||
if (winmidimax==0) winmidimax=1;
|
||||
#endif
|
||||
winmididevices=new winmidionedevice[winmidimax];
|
||||
for (int i=0;i<winmidimax;i++) {
|
||||
winmididevices[i].name=new char[MAX_STRING_SIZE];
|
||||
for (int j=0;j<MAX_STRING_SIZE;j++) winmididevices[i].name[j]='\0';
|
||||
};
|
||||
|
||||
|
||||
//get the midi input devices name
|
||||
#ifdef WINMIDIIN
|
||||
MIDIINCAPS midiincaps;
|
||||
for (int i=0;i<winmidimax;i++) {
|
||||
if (! midiInGetDevCaps(i,&midiincaps,sizeof(MIDIINCAPS)))
|
||||
snprintf(winmididevices[i].name,MAX_STRING_SIZE,"%s",midiincaps.szPname);
|
||||
};
|
||||
#endif
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) cfg.bankRootDirList[i]=NULL;
|
||||
cfg.currentBankDir=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.currentBankDir,"./testbnk");
|
||||
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) cfg.presetsDirList[i]=NULL;
|
||||
|
||||
char filename[MAX_STRING_SIZE];
|
||||
getConfigFileName(filename,MAX_STRING_SIZE);
|
||||
readConfig(filename);
|
||||
|
||||
if (cfg.bankRootDirList[0]==NULL) {
|
||||
#if defined(OS_LINUX)
|
||||
//banks
|
||||
cfg.bankRootDirList[0]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[0],"~/banks");
|
||||
|
||||
cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[1],"./");
|
||||
|
||||
cfg.bankRootDirList[2]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[2],"/usr/share/zynaddsubfx/banks");
|
||||
|
||||
cfg.bankRootDirList[3]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[3],"/usr/local/share/zynaddsubfx/banks");
|
||||
|
||||
cfg.bankRootDirList[4]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[4],"../banks");
|
||||
|
||||
cfg.bankRootDirList[5]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[5],"banks");
|
||||
|
||||
#else
|
||||
//banks
|
||||
cfg.bankRootDirList[0]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[0],"./");
|
||||
|
||||
#ifdef VSTAUDIOOUT
|
||||
cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[1],"c:/Program Files/ZynAddSubFX/banks");
|
||||
#else
|
||||
cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[1],"../banks");
|
||||
#endif
|
||||
cfg.bankRootDirList[2]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.bankRootDirList[2],"banks");
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
if (cfg.presetsDirList[0]==NULL) {
|
||||
#if defined(OS_LINUX)
|
||||
//presets
|
||||
cfg.presetsDirList[0]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[0],"./");
|
||||
|
||||
cfg.presetsDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[1],"../presets");
|
||||
|
||||
cfg.presetsDirList[2]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[2],"presets");
|
||||
|
||||
cfg.presetsDirList[3]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[3],"/usr/share/zynaddsubfx/presets");
|
||||
|
||||
cfg.presetsDirList[4]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[4],"/usr/local/share/zynaddsubfx/presets");
|
||||
|
||||
#else
|
||||
//presets
|
||||
cfg.presetsDirList[0]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[0],"./");
|
||||
|
||||
#ifdef VSTAUDIOOUT
|
||||
cfg.presetsDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[1],"c:/Program Files/ZynAddSubFX/presets");
|
||||
#else
|
||||
cfg.presetsDirList[1]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[1],"../presets");
|
||||
#endif
|
||||
|
||||
cfg.presetsDirList[2]=new char[MAX_STRING_SIZE];
|
||||
sprintf(cfg.presetsDirList[2],"presets");
|
||||
#endif
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
Config::~Config()
|
||||
{
|
||||
|
||||
delete [] cfg.LinuxOSSWaveOutDev;
|
||||
delete [] cfg.LinuxOSSSeqInDev;
|
||||
delete [] cfg.DumpFile;
|
||||
|
||||
for (int i=0;i<winmidimax;i++) delete [] winmididevices[i].name;
|
||||
delete [] winmididevices;
|
||||
};
|
||||
|
||||
|
||||
void Config::save()
|
||||
{
|
||||
char filename[MAX_STRING_SIZE];
|
||||
getConfigFileName(filename,MAX_STRING_SIZE);
|
||||
saveConfig(filename);
|
||||
};
|
||||
|
||||
void Config::clearbankrootdirlist()
|
||||
{
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) {
|
||||
if (cfg.bankRootDirList[i]==NULL) delete(cfg.bankRootDirList[i]);
|
||||
cfg.bankRootDirList[i]=NULL;
|
||||
};
|
||||
};
|
||||
|
||||
void Config::clearpresetsdirlist()
|
||||
{
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) {
|
||||
if (cfg.presetsDirList[i]==NULL) delete(cfg.presetsDirList[i]);
|
||||
cfg.presetsDirList[i]=NULL;
|
||||
};
|
||||
};
|
||||
|
||||
void Config::readConfig(const char *filename)
|
||||
{
|
||||
XMLwrapper *xmlcfg=new XMLwrapper();
|
||||
if (xmlcfg->loadXMLfile(filename)<0) return;
|
||||
if (xmlcfg->enterbranch("CONFIGURATION")) {
|
||||
cfg.SampleRate=xmlcfg->getpar("sample_rate",cfg.SampleRate,4000,1024000);
|
||||
cfg.SoundBufferSize=xmlcfg->getpar("sound_buffer_size",cfg.SoundBufferSize,16,8192);
|
||||
cfg.OscilSize=xmlcfg->getpar("oscil_size",cfg.OscilSize,MAX_AD_HARMONICS*2,131072);
|
||||
cfg.SwapStereo=xmlcfg->getpar("swap_stereo",cfg.SwapStereo,0,1);
|
||||
cfg.BankUIAutoClose=xmlcfg->getpar("bank_window_auto_close",cfg.BankUIAutoClose,0,1);
|
||||
|
||||
cfg.DumpNotesToFile=xmlcfg->getpar("dump_notes_to_file",cfg.DumpNotesToFile,0,1);
|
||||
cfg.DumpAppend=xmlcfg->getpar("dump_append",cfg.DumpAppend,0,1);
|
||||
xmlcfg->getparstr("dump_file",cfg.DumpFile,MAX_STRING_SIZE);
|
||||
|
||||
cfg.GzipCompression=xmlcfg->getpar("gzip_compression",cfg.GzipCompression,0,9);
|
||||
|
||||
xmlcfg->getparstr("bank_current",cfg.currentBankDir,MAX_STRING_SIZE);
|
||||
cfg.Interpolation=xmlcfg->getpar("interpolation",cfg.Interpolation,0,1);
|
||||
|
||||
cfg.CheckPADsynth=xmlcfg->getpar("check_pad_synth",cfg.CheckPADsynth,0,1);
|
||||
|
||||
|
||||
cfg.UserInterfaceMode=xmlcfg->getpar("user_interface_mode",cfg.UserInterfaceMode,0,2);
|
||||
cfg.VirKeybLayout=xmlcfg->getpar("virtual_keyboard_layout",cfg.VirKeybLayout,0,10);
|
||||
|
||||
//get bankroot dirs
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) {
|
||||
if (xmlcfg->enterbranch("BANKROOT",i)) {
|
||||
cfg.bankRootDirList[i]=new char[MAX_STRING_SIZE];
|
||||
xmlcfg->getparstr("bank_root",cfg.bankRootDirList[i],MAX_STRING_SIZE);
|
||||
xmlcfg->exitbranch();
|
||||
};
|
||||
};
|
||||
|
||||
//get preset root dirs
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) {
|
||||
if (xmlcfg->enterbranch("PRESETSROOT",i)) {
|
||||
cfg.presetsDirList[i]=new char[MAX_STRING_SIZE];
|
||||
xmlcfg->getparstr("presets_root",cfg.presetsDirList[i],MAX_STRING_SIZE);
|
||||
xmlcfg->exitbranch();
|
||||
};
|
||||
};
|
||||
|
||||
//linux stuff
|
||||
xmlcfg->getparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE);
|
||||
xmlcfg->getparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE);
|
||||
|
||||
//windows stuff
|
||||
cfg.WindowsWaveOutId=xmlcfg->getpar("windows_wave_out_id",cfg.WindowsWaveOutId,0,winwavemax);
|
||||
cfg.WindowsMidiInId=xmlcfg->getpar("windows_midi_in_id",cfg.WindowsMidiInId,0,winmidimax);
|
||||
|
||||
xmlcfg->exitbranch();
|
||||
};
|
||||
delete(xmlcfg);
|
||||
|
||||
cfg.OscilSize=(int) pow(2,ceil(log (cfg.OscilSize-1.0)/log(2.0)));
|
||||
|
||||
};
|
||||
|
||||
void Config::saveConfig(const char *filename)
|
||||
{
|
||||
XMLwrapper *xmlcfg=new XMLwrapper();
|
||||
|
||||
xmlcfg->beginbranch("CONFIGURATION");
|
||||
|
||||
xmlcfg->addpar("sample_rate",cfg.SampleRate);
|
||||
xmlcfg->addpar("sound_buffer_size",cfg.SoundBufferSize);
|
||||
xmlcfg->addpar("oscil_size",cfg.OscilSize);
|
||||
xmlcfg->addpar("swap_stereo",cfg.SwapStereo);
|
||||
xmlcfg->addpar("bank_window_auto_close",cfg.BankUIAutoClose);
|
||||
|
||||
xmlcfg->addpar("dump_notes_to_file",cfg.DumpNotesToFile);
|
||||
xmlcfg->addpar("dump_append",cfg.DumpAppend);
|
||||
xmlcfg->addparstr("dump_file",cfg.DumpFile);
|
||||
|
||||
xmlcfg->addpar("gzip_compression",cfg.GzipCompression);
|
||||
|
||||
xmlcfg->addpar("check_pad_synth",cfg.CheckPADsynth);
|
||||
|
||||
xmlcfg->addparstr("bank_current",cfg.currentBankDir);
|
||||
|
||||
xmlcfg->addpar("user_interface_mode",cfg.UserInterfaceMode);
|
||||
xmlcfg->addpar("virtual_keyboard_layout",cfg.VirKeybLayout);
|
||||
|
||||
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (cfg.bankRootDirList[i]!=NULL) {
|
||||
xmlcfg->beginbranch("BANKROOT",i);
|
||||
xmlcfg->addparstr("bank_root",cfg.bankRootDirList[i]);
|
||||
xmlcfg->endbranch();
|
||||
};
|
||||
|
||||
for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (cfg.presetsDirList[i]!=NULL) {
|
||||
xmlcfg->beginbranch("PRESETSROOT",i);
|
||||
xmlcfg->addparstr("presets_root",cfg.presetsDirList[i]);
|
||||
xmlcfg->endbranch();
|
||||
};
|
||||
|
||||
xmlcfg->addpar("interpolation",cfg.Interpolation);
|
||||
|
||||
//linux stuff
|
||||
xmlcfg->addparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev);
|
||||
xmlcfg->addparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev);
|
||||
|
||||
//windows stuff
|
||||
xmlcfg->addpar("windows_wave_out_id",cfg.WindowsWaveOutId);
|
||||
xmlcfg->addpar("windows_midi_in_id",cfg.WindowsMidiInId);
|
||||
|
||||
xmlcfg->endbranch();
|
||||
|
||||
int tmp=cfg.GzipCompression;
|
||||
cfg.GzipCompression=0;
|
||||
xmlcfg->saveXMLfile(filename);
|
||||
cfg.GzipCompression=tmp;
|
||||
|
||||
delete(xmlcfg);
|
||||
};
|
||||
|
||||
void Config::getConfigFileName(char *name, int namesize)
|
||||
{
|
||||
name[0]=0;
|
||||
#ifdef OS_LINUX
|
||||
snprintf(name,namesize,"%s%s",getenv("HOME"),"/.zynaddsubfxXML.cfg");
|
||||
#else
|
||||
snprintf(name,namesize,"%s","zynaddsubfxXML.cfg");
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Config.h - Configuration file functions
|
||||
Copyright (C) 2003-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -26,42 +26,46 @@
|
||||
#define MAX_STRING_SIZE 4000
|
||||
#define MAX_BANK_ROOT_DIRS 100
|
||||
|
||||
class Config{
|
||||
public:
|
||||
Config();
|
||||
~Config();
|
||||
struct {
|
||||
char *LinuxOSSWaveOutDev,*LinuxOSSSeqInDev;
|
||||
int SampleRate,SoundBufferSize,OscilSize,SwapStereo;
|
||||
int WindowsWaveOutId,WindowsMidiInId;
|
||||
int BankUIAutoClose;
|
||||
int DumpNotesToFile,DumpAppend;
|
||||
int GzipCompression;
|
||||
int Interpolation;
|
||||
char *DumpFile;
|
||||
char *bankRootDirList[MAX_BANK_ROOT_DIRS],*currentBankDir;
|
||||
char *presetsDirList[MAX_BANK_ROOT_DIRS];
|
||||
int CheckPADsynth;
|
||||
int UserInterfaceMode;
|
||||
int VirKeybLayout;
|
||||
} cfg;
|
||||
int winwavemax,winmidimax;//number of wave/midi devices on Windows
|
||||
int maxstringsize;
|
||||
|
||||
struct winmidionedevice{
|
||||
char *name;
|
||||
};
|
||||
winmidionedevice *winmididevices;
|
||||
/**Configuration file functions*/
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
/** Constructor*/
|
||||
Config();
|
||||
/** Destructor*/
|
||||
~Config();
|
||||
struct {
|
||||
char *LinuxOSSWaveOutDev,*LinuxOSSSeqInDev;
|
||||
int SampleRate,SoundBufferSize,OscilSize,SwapStereo;
|
||||
int WindowsWaveOutId,WindowsMidiInId;
|
||||
int BankUIAutoClose;
|
||||
int DumpNotesToFile,DumpAppend;
|
||||
int GzipCompression;
|
||||
int Interpolation;
|
||||
char *DumpFile;
|
||||
char *bankRootDirList[MAX_BANK_ROOT_DIRS],*currentBankDir;
|
||||
char *presetsDirList[MAX_BANK_ROOT_DIRS];
|
||||
int CheckPADsynth;
|
||||
int UserInterfaceMode;
|
||||
int VirKeybLayout;
|
||||
} cfg;
|
||||
int winwavemax,winmidimax;//number of wave/midi devices on Windows
|
||||
int maxstringsize;
|
||||
|
||||
void clearbankrootdirlist();
|
||||
void clearpresetsdirlist();
|
||||
void init();
|
||||
void save();
|
||||
|
||||
private:
|
||||
void readConfig(const char *filename);
|
||||
void saveConfig(const char *filename);
|
||||
void getConfigFileName(char *name,int namesize);
|
||||
struct winmidionedevice {
|
||||
char *name;
|
||||
};
|
||||
winmidionedevice *winmididevices;
|
||||
|
||||
void clearbankrootdirlist();
|
||||
void clearpresetsdirlist();
|
||||
void init();
|
||||
void save();
|
||||
|
||||
private:
|
||||
void readConfig(const char *filename);
|
||||
void saveConfig(const char *filename);
|
||||
void getConfigFileName(char *name,int namesize);
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
100
plugins/zynaddsubfx/src/Misc/Control.h
Normal file
100
plugins/zynaddsubfx/src/Misc/Control.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Control.h - Defines a variable that can be controled from a frontend
|
||||
|
||||
Copyright (C) 2009 Harald Hvaal
|
||||
Author: Harald Hvaal
|
||||
|
||||
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 or later) 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 _CONTROL_H_
|
||||
#define _CONTROL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
class Control
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The parent is the logical owner of this control. Parent should only
|
||||
* be null for the root node.
|
||||
* The id is a string uniquely identifying this control within the
|
||||
* context of the parent control. No spaces or dots are allowed in this
|
||||
* id.
|
||||
* Children id's are denoted by <parent-id>.<children-id>, so that one
|
||||
* can refer to any control in the hierarchy by separating them with
|
||||
* dots. Example: Main.AddSynth.FrequencyLFO.Amplitude
|
||||
*/
|
||||
Control(Control *parent, string id);
|
||||
|
||||
/**
|
||||
* Will recursively get the XML representation for all the subcontrols.
|
||||
* Used for saving to file and copy-pasting settings
|
||||
*/
|
||||
string getXMLRepresentation();
|
||||
|
||||
/**
|
||||
* Set the value of this (and possibly subcomponents as well) based on
|
||||
* a xml description.
|
||||
*/
|
||||
void restoreFromXML(string xml);
|
||||
|
||||
/**
|
||||
* Register a controluser. This will cause this user to be notified
|
||||
* whenever the contents of the control changes.
|
||||
*/
|
||||
void registerControlUser(ControlUser *user);
|
||||
|
||||
/**
|
||||
* This should return a string representation of the controls internal
|
||||
* value
|
||||
*/
|
||||
virtual string getStringRepresentation() = 0;
|
||||
|
||||
};
|
||||
|
||||
class FloatControl : public Control
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Set the value of this control. If the ControlUser variable is set,
|
||||
* then this user will not be updated with the new value. This is to
|
||||
* avoid setting a value being set back to the source that set it
|
||||
* (which would be redundant, or possibly causing infinite setValue
|
||||
* loops).
|
||||
* NOTE: this function is thread-safe (using a mutex internally)
|
||||
*/
|
||||
void setValue(float value, ControlUser *user = NULL);
|
||||
|
||||
/**
|
||||
* Reimplemented from Control
|
||||
*/
|
||||
virtual string getStringRepresentation();
|
||||
|
||||
float value();
|
||||
};
|
||||
|
||||
class ControlUser
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Pure virtual method, to notify the controluser that the value has
|
||||
* been changed internally, and needs to be read again.
|
||||
*/
|
||||
virtual void controlUpdated(Control *control) = 0;
|
||||
};
|
||||
|
||||
#endif /* _CONTROL_H_ */
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Dump.C - It dumps the notes to a text file
|
||||
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "Util.h"
|
||||
#include "Dump.h"
|
||||
|
||||
Dump dump;
|
||||
|
||||
Dump::Dump(){
|
||||
file=NULL;
|
||||
tick=0;
|
||||
k=0;
|
||||
keyspressed=0;
|
||||
};
|
||||
|
||||
Dump::~Dump(){
|
||||
if (file!=NULL) {
|
||||
double duration=(double)tick*(double) SOUND_BUFFER_SIZE/(double) SAMPLE_RATE;
|
||||
fprintf(file,"\n# statistics: duration = %d seconds; keyspressed = %d\n\n\n\n",(int) duration,keyspressed);
|
||||
fclose(file);
|
||||
};
|
||||
};
|
||||
|
||||
void Dump::startnow(){
|
||||
if (file!=NULL) return;//the file is already open
|
||||
|
||||
if (config.cfg.DumpNotesToFile!=0){
|
||||
if (config.cfg.DumpAppend!=0) file=fopen(config.cfg.DumpFile,"a");
|
||||
else file=fopen(config.cfg.DumpFile,"w");
|
||||
if (file==NULL) return;
|
||||
if (config.cfg.DumpAppend!=0) fprintf(file,"%s","#************************************\n");
|
||||
|
||||
time_t tm=time(NULL);
|
||||
|
||||
fprintf(file,"#date/time = %s\n",ctime(&tm));
|
||||
fprintf(file,"#1 tick = %g milliseconds\n",SOUND_BUFFER_SIZE*1000.0/SAMPLE_RATE);
|
||||
fprintf(file,"SAMPLERATE = %d\n",SAMPLE_RATE);
|
||||
fprintf(file,"TICKSIZE = %d #samples\n",SOUND_BUFFER_SIZE);
|
||||
fprintf(file,"\n\nSTART\n");
|
||||
};
|
||||
};
|
||||
|
||||
void Dump::inctick(){
|
||||
tick++;
|
||||
};
|
||||
|
||||
|
||||
void Dump::dumpnote(char chan,char note, char vel){
|
||||
if (file==NULL) return;
|
||||
if (note==0) return;
|
||||
if (vel==0) fprintf(file,"n %d -> %d %d \n",tick,chan,note);//note off
|
||||
else fprintf(file,"N %d -> %d %d %d \n",tick,chan,note,vel);//note on
|
||||
|
||||
if (vel!=0) keyspressed++;
|
||||
#ifndef JACKAUDIOOUT
|
||||
if (k++>25) {
|
||||
fflush(file);
|
||||
k=0;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
void Dump::dumpcontroller(char chan,unsigned int type,int par){
|
||||
if (file==NULL) return;
|
||||
switch(type){
|
||||
case C_pitchwheel:fprintf(file,"P %d -> %d %d\n",tick,chan,par);
|
||||
break;
|
||||
default:fprintf(file,"C %d -> %d %d %d\n",tick,chan,type,par);
|
||||
break;
|
||||
};
|
||||
#ifndef JACKAUDIOOUT
|
||||
if (k++>25) {
|
||||
fflush(file);
|
||||
k=0;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
107
plugins/zynaddsubfx/src/Misc/Dump.cpp
Normal file
107
plugins/zynaddsubfx/src/Misc/Dump.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Dump.C - It dumps the notes to a text file
|
||||
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "Util.h"
|
||||
#include "Dump.h"
|
||||
|
||||
Dump dump;
|
||||
|
||||
Dump::Dump()
|
||||
{
|
||||
file=NULL;
|
||||
tick=0;
|
||||
k=0;
|
||||
keyspressed=0;
|
||||
};
|
||||
|
||||
Dump::~Dump()
|
||||
{
|
||||
if (file!=NULL) {
|
||||
double duration=(double)tick*(double) SOUND_BUFFER_SIZE/(double) SAMPLE_RATE;
|
||||
fprintf(file,"\n# statistics: duration = %d seconds; keyspressed = %d\n\n\n\n",(int) duration,keyspressed);
|
||||
fclose(file);
|
||||
};
|
||||
};
|
||||
|
||||
void Dump::startnow()
|
||||
{
|
||||
if (file!=NULL) return;//the file is already open
|
||||
|
||||
if (config.cfg.DumpNotesToFile!=0) {
|
||||
if (config.cfg.DumpAppend!=0) file=fopen(config.cfg.DumpFile,"a");
|
||||
else file=fopen(config.cfg.DumpFile,"w");
|
||||
if (file==NULL) return;
|
||||
if (config.cfg.DumpAppend!=0) fprintf(file,"%s","#************************************\n");
|
||||
|
||||
time_t tm=time(NULL);
|
||||
|
||||
fprintf(file,"#date/time = %s\n",ctime(&tm));
|
||||
fprintf(file,"#1 tick = %g milliseconds\n",SOUND_BUFFER_SIZE*1000.0/SAMPLE_RATE);
|
||||
fprintf(file,"SAMPLERATE = %d\n",SAMPLE_RATE);
|
||||
fprintf(file,"TICKSIZE = %d #samples\n",SOUND_BUFFER_SIZE);
|
||||
fprintf(file,"\n\nSTART\n");
|
||||
};
|
||||
};
|
||||
|
||||
void Dump::inctick()
|
||||
{
|
||||
tick++;
|
||||
};
|
||||
|
||||
|
||||
void Dump::dumpnote(char chan,char note, char vel)
|
||||
{
|
||||
if (file==NULL) return;
|
||||
if (note==0) return;
|
||||
if (vel==0) fprintf(file,"n %d -> %d %d \n",tick,chan,note);//note off
|
||||
else fprintf(file,"N %d -> %d %d %d \n",tick,chan,note,vel);//note on
|
||||
|
||||
if (vel!=0) keyspressed++;
|
||||
#ifndef JACKAUDIOOUT
|
||||
if (k++>25) {
|
||||
fflush(file);
|
||||
k=0;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
void Dump::dumpcontroller(char chan,unsigned int type,int par)
|
||||
{
|
||||
if (file==NULL) return;
|
||||
switch (type) {
|
||||
case C_pitchwheel:
|
||||
fprintf(file,"P %d -> %d %d\n",tick,chan,par);
|
||||
break;
|
||||
default:
|
||||
fprintf(file,"C %d -> %d %d %d\n",tick,chan,type,par);
|
||||
break;
|
||||
};
|
||||
#ifndef JACKAUDIOOUT
|
||||
if (k++>25) {
|
||||
fflush(file);
|
||||
k=0;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Dump.h - It dumps the notes to a text file
|
||||
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -24,20 +24,40 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class Dump{
|
||||
public:
|
||||
Dump();
|
||||
~Dump();
|
||||
void startnow();
|
||||
void inctick();
|
||||
|
||||
void dumpnote(char chan,char note, char vel);
|
||||
void dumpcontroller(char chan,unsigned int type,int par);
|
||||
|
||||
private:
|
||||
FILE *file;
|
||||
int tick;
|
||||
int k;
|
||||
int keyspressed;
|
||||
/**Object used to dump the notes into a text file
|
||||
* \todo see if this object should have knowledge about the file
|
||||
* that it will write to
|
||||
* \todo upgrade from stdio to iostream*/
|
||||
class Dump
|
||||
{
|
||||
public:
|
||||
/**Constructor*/
|
||||
Dump();
|
||||
/**Destructor
|
||||
* Closes the dumpfile*/
|
||||
~Dump();
|
||||
/**Open dumpfile and prepare it for dumps
|
||||
* \todo see if this fits better in the constructor*/
|
||||
void startnow();
|
||||
/**Tick the timestamp*/
|
||||
void inctick();
|
||||
/**Dump Note to dumpfile
|
||||
* @param chan The channel of the note
|
||||
* @param note The note
|
||||
* @param vel The velocity of the note*/
|
||||
void dumpnote(char chan,char note, char vel);
|
||||
/** Dump the Controller
|
||||
* @param chan The channel of the Controller
|
||||
* @param type The type
|
||||
* @param par The value of the controller
|
||||
* \todo figure out what type is exactly meaning*/
|
||||
void dumpcontroller(char chan,unsigned int type,int par);
|
||||
|
||||
private:
|
||||
FILE *file;
|
||||
int tick;
|
||||
int k;//This appears to be a constant used to flush the file
|
||||
//periodically when JACK is used
|
||||
int keyspressed;
|
||||
};
|
||||
#endif
|
||||
|
||||
104
plugins/zynaddsubfx/src/Misc/LASHClient.cpp
Normal file
104
plugins/zynaddsubfx/src/Misc/LASHClient.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
LASHClient.C - LASH support
|
||||
Copyright (C) 2006-2009 Lars Luthman
|
||||
Author: Lars Luthman
|
||||
|
||||
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 or later) 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 <unistd.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "LASHClient.h"
|
||||
|
||||
|
||||
LASHClient::LASHClient(int* argc, char*** argv)
|
||||
{
|
||||
client = lash_init(lash_extract_args(argc, argv), "ZynAddSubFX",
|
||||
LASH_Config_File, LASH_PROTOCOL(2, 0));
|
||||
}
|
||||
|
||||
|
||||
void LASHClient::setalsaid(int id)
|
||||
{
|
||||
if (lash_enabled(client)) {
|
||||
if (id != -1)
|
||||
lash_alsa_client_id(client, id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LASHClient::setjackname(const char* name)
|
||||
{
|
||||
if (lash_enabled(client)) {
|
||||
if (name != NULL) {
|
||||
lash_jack_client_name(client, name);
|
||||
|
||||
lash_event_t *event = lash_event_new_with_type(LASH_Client_Name);
|
||||
lash_event_set_string(event, name);
|
||||
lash_send_event(client, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LASHClient::Event LASHClient::checkevents(std::string& filename)
|
||||
{
|
||||
|
||||
if (!lash_enabled(client))
|
||||
return NoEvent;
|
||||
|
||||
Event received = NoEvent;
|
||||
lash_event_t* event;
|
||||
while (event = lash_get_event(client)) {
|
||||
|
||||
// save
|
||||
if (lash_event_get_type(event) == LASH_Save_File) {
|
||||
std::cerr<<"LASH event: LASH_Save_File"<<std::endl;
|
||||
filename = std::string(lash_event_get_string(event)) + "/master.xmz";
|
||||
received = Save;
|
||||
break;
|
||||
}
|
||||
|
||||
// restore
|
||||
else if (lash_event_get_type(event) == LASH_Restore_File) {
|
||||
std::cerr<<"LASH event: LASH_Restore_File"<<std::endl;
|
||||
filename = std::string(lash_event_get_string(event)) + "/master.xmz";
|
||||
received = Restore;
|
||||
break;
|
||||
}
|
||||
|
||||
// quit
|
||||
else if (lash_event_get_type(event) == LASH_Quit) {
|
||||
std::cerr<<"LASH event: LASH_Quit"<<std::endl;
|
||||
received = Quit;
|
||||
break;
|
||||
}
|
||||
|
||||
lash_event_destroy(event);
|
||||
}
|
||||
return received;
|
||||
}
|
||||
|
||||
|
||||
void LASHClient::confirmevent(Event event)
|
||||
{
|
||||
if (event == Save)
|
||||
lash_send_event(client, lash_event_new_with_type(LASH_Save_File));
|
||||
else if (event == Restore)
|
||||
lash_send_event(client, lash_event_new_with_type(LASH_Restore_File));
|
||||
}
|
||||
66
plugins/zynaddsubfx/src/Misc/LASHClient.h
Normal file
66
plugins/zynaddsubfx/src/Misc/LASHClient.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
LASHClient.h - LASH support
|
||||
Copyright (C) 2006-2009 Lars Luthman
|
||||
Author: Lars Luthman
|
||||
|
||||
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 or later) 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 LASHClient_h
|
||||
#define LASHClient_h
|
||||
|
||||
#include <string>
|
||||
#include <pthread.h>
|
||||
#include <lash/lash.h>
|
||||
|
||||
|
||||
/** This class wraps up some functions for initialising and polling
|
||||
* the LASH daemon.
|
||||
* \todo fix indentation nonconformism
|
||||
* \todo see why there is no destructor*/
|
||||
class LASHClient
|
||||
{
|
||||
public:
|
||||
/**Enum to represent the LASH events that are currently handled*/
|
||||
enum Event {
|
||||
Save,
|
||||
Restore,
|
||||
Quit,
|
||||
NoEvent
|
||||
};
|
||||
|
||||
/** Constructor
|
||||
* @param argc number of arguments
|
||||
* @param argv the text arguments*/
|
||||
LASHClient(int* argc, char*** argv);
|
||||
|
||||
/**set the ALSA id
|
||||
* @param id new ALSA id*/
|
||||
void setalsaid(int id);
|
||||
/**Set the JACK name
|
||||
* @param name the new name*/
|
||||
void setjackname(const char* name);
|
||||
Event checkevents(std::string& filename);
|
||||
void confirmevent(Event event);
|
||||
|
||||
private:
|
||||
|
||||
lash_client_t* client;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,738 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Master.C - It sends Midi Messages to Parts, receives samples from parts,
|
||||
process them with system/insertion effects and mix them
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Master.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
Master::Master(){
|
||||
swaplr=0;
|
||||
|
||||
pthread_mutex_init(&mutex,NULL);
|
||||
fft=new FFTwrapper(OSCIL_SIZE);
|
||||
|
||||
tmpmixl=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
tmpmixr=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
audiooutl=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
audiooutr=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
|
||||
ksoundbuffersample=-1;//this is only time when this is -1; this means that the GetAudioOutSamples was never called
|
||||
ksoundbuffersamplelow=0.0;
|
||||
oldsamplel=0.0;oldsampler=0.0;
|
||||
shutup=0;
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
vuoutpeakpart[npart]=1e-9;
|
||||
fakepeakpart[npart]=0;
|
||||
};
|
||||
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
audiooutl[i]=0.0;
|
||||
audiooutr[i]=0.0;
|
||||
};
|
||||
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++)
|
||||
part[npart]=new Part(µtonal,fft,&mutex);
|
||||
|
||||
|
||||
|
||||
//Insertion Effects init
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++)
|
||||
insefx[nefx]=new EffectMgr(1,&mutex);
|
||||
|
||||
//System Effects init
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) {
|
||||
sysefx[nefx]=new EffectMgr(0,&mutex);
|
||||
};
|
||||
|
||||
|
||||
defaults();
|
||||
};
|
||||
|
||||
void Master::defaults(){
|
||||
volume=1.0;
|
||||
setPvolume(80);
|
||||
setPkeyshift(64);
|
||||
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
part[npart]->defaults();
|
||||
part[npart]->Prcvchn=npart%NUM_MIDI_CHANNELS;
|
||||
};
|
||||
|
||||
partonoff(0,1);//enable the first part
|
||||
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++) {
|
||||
insefx[nefx]->defaults();
|
||||
Pinsparts[nefx]=-1;
|
||||
};
|
||||
|
||||
//System Effects init
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) {
|
||||
sysefx[nefx]->defaults();
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
//if (nefx==0) setPsysefxvol(npart,nefx,64);
|
||||
//else
|
||||
setPsysefxvol(npart,nefx,0);
|
||||
};
|
||||
for (int nefxto=0;nefxto<NUM_SYS_EFX;nefxto++)
|
||||
setPsysefxsend(nefx,nefxto,0);
|
||||
};
|
||||
|
||||
// sysefx[0]->changeeffect(1);
|
||||
microtonal.defaults();
|
||||
ShutUp();
|
||||
};
|
||||
|
||||
/*
|
||||
* Note On Messages (velocity=0 for NoteOff)
|
||||
*/
|
||||
void Master::NoteOn(unsigned char chan,unsigned char note,unsigned char velocity){
|
||||
dump.dumpnote(chan,note,velocity);
|
||||
|
||||
noteon(chan,note,velocity);
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal Note On (velocity=0 for NoteOff)
|
||||
*/
|
||||
void Master::noteon(unsigned char chan,unsigned char note,unsigned char velocity){
|
||||
int npart;
|
||||
if (velocity!=0){
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
if (chan==part[npart]->Prcvchn){
|
||||
fakepeakpart[npart]=velocity*2;
|
||||
if (part[npart]->Penabled!=0) part[npart]->NoteOn(note,velocity,keyshift);
|
||||
};
|
||||
};
|
||||
}else{
|
||||
this->NoteOff(chan,note);
|
||||
};
|
||||
HDDRecorder.triggernow();
|
||||
};
|
||||
|
||||
/*
|
||||
* Note Off Messages
|
||||
*/
|
||||
void Master::NoteOff(unsigned char chan,unsigned char note){
|
||||
dump.dumpnote(chan,note,0);
|
||||
|
||||
noteoff(chan,note);
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal Note Off
|
||||
*/
|
||||
void Master::noteoff(unsigned char chan,unsigned char note){
|
||||
int npart;
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
if ((chan==part[npart]->Prcvchn) && (part[npart]->Penabled!=0))
|
||||
part[npart]->NoteOff(note);
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Controllers
|
||||
*/
|
||||
void Master::SetController(unsigned char chan,unsigned int type,int par){
|
||||
dump.dumpcontroller(chan,type,par);
|
||||
|
||||
setcontroller(chan,type,par);
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal Controllers
|
||||
*/
|
||||
void Master::setcontroller(unsigned char chan,unsigned int type,int par){
|
||||
if ((type==C_dataentryhi)||(type==C_dataentrylo)||
|
||||
(type==C_nrpnhi)||(type==C_nrpnlo)){//Process RPN and NRPN by the Master (ignore the chan)
|
||||
ctl.setparameternumber(type,par);
|
||||
|
||||
int parhi=-1,parlo=-1,valhi=-1,vallo=-1;
|
||||
if (ctl.getnrpn(&parhi,&parlo,&valhi,&vallo)==0){//this is NRPN
|
||||
//fprintf(stderr,"rcv. NRPN: %d %d %d %d\n",parhi,parlo,valhi,vallo);
|
||||
switch (parhi){
|
||||
case 0x04://System Effects
|
||||
if (parlo<NUM_SYS_EFX) {
|
||||
sysefx[parlo]->seteffectpar_nolock(valhi,vallo);
|
||||
};
|
||||
break;
|
||||
case 0x08://Insertion Effects
|
||||
if (parlo<NUM_INS_EFX) {
|
||||
insefx[parlo]->seteffectpar_nolock(valhi,vallo);
|
||||
};
|
||||
break;
|
||||
|
||||
};
|
||||
};
|
||||
} else {//other controllers
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++){//Send the controller to all part assigned to the channel
|
||||
if ((chan==part[npart]->Prcvchn) && (part[npart]->Penabled!=0))
|
||||
part[npart]->SetController(type,par);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Enable/Disable a part
|
||||
*/
|
||||
void Master::partonoff(int npart,int what){
|
||||
if (npart>=NUM_MIDI_PARTS) return;
|
||||
if (what==0){//disable part
|
||||
fakepeakpart[npart]=0;
|
||||
part[npart]->Penabled=0;
|
||||
part[npart]->cleanup();
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++){
|
||||
if (Pinsparts[nefx]==npart) {
|
||||
insefx[nefx]->cleanup();
|
||||
};
|
||||
};
|
||||
} else {//enabled
|
||||
part[npart]->Penabled=1;
|
||||
fakepeakpart[npart]=0;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Master audio out (the final sound)
|
||||
*/
|
||||
void Master::AudioOut(REALTYPE *outl,REALTYPE *outr){
|
||||
int i,npart,nefx;
|
||||
|
||||
/* //test!!!!!!!!!!!!! se poate bloca aici (mutex)
|
||||
if (seq.play){
|
||||
int type,par1,par2,again,midichan;
|
||||
int ntrack=1;
|
||||
// do{
|
||||
again=seq.getevent(ntrack,&midichan,&type,&par1,&par2);
|
||||
if (type>0) {
|
||||
// printf("aaa\n");
|
||||
|
||||
if (type==1){//note_on or note_off
|
||||
if (par2!=0) NoteOn(midichan,par1,par2);
|
||||
else NoteOff(midichan,par1);
|
||||
};
|
||||
};
|
||||
// } while (again);
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
// printf("zzzz\n");
|
||||
|
||||
|
||||
//Swaps the Left channel with Right Channel (if it is asked for)
|
||||
if (swaplr!=0){
|
||||
REALTYPE *tmp=outl;
|
||||
outl=outr;
|
||||
outr=tmp;
|
||||
};
|
||||
|
||||
//clean up the output samples
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
outl[i]=0.0;
|
||||
outr[i]=0.0;
|
||||
};
|
||||
|
||||
//Compute part samples and store them part[npart]->partoutl,partoutr
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++)
|
||||
if (part[npart]->Penabled!=0) part[npart]->ComputePartSmps();
|
||||
|
||||
//Insertion effects
|
||||
for (nefx=0;nefx<NUM_INS_EFX;nefx++){
|
||||
if (Pinsparts[nefx]>=0) {
|
||||
int efxpart=Pinsparts[nefx];
|
||||
if (part[efxpart]->Penabled!=0)
|
||||
insefx[nefx]->out(part[efxpart]->partoutl,part[efxpart]->partoutr);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//Apply the part volumes and pannings (after insertion effects)
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
if (part[npart]->Penabled==0) continue;
|
||||
|
||||
REALTYPE newvol_l=part[npart]->volume;
|
||||
REALTYPE newvol_r=part[npart]->volume;
|
||||
REALTYPE oldvol_l=part[npart]->oldvolumel;
|
||||
REALTYPE oldvol_r=part[npart]->oldvolumer;
|
||||
REALTYPE pan=part[npart]->panning;
|
||||
if (pan<0.5) newvol_l*=pan*2.0;
|
||||
else newvol_r*=(1.0-pan)*2.0;
|
||||
|
||||
if (ABOVE_AMPLITUDE_THRESHOLD(oldvol_l,newvol_l)||
|
||||
ABOVE_AMPLITUDE_THRESHOLD(oldvol_r,newvol_r)){//the volume or the panning has changed and needs interpolation
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE vol_l=INTERPOLATE_AMPLITUDE(oldvol_l,newvol_l,i,SOUND_BUFFER_SIZE);
|
||||
REALTYPE vol_r=INTERPOLATE_AMPLITUDE(oldvol_r,newvol_r,i,SOUND_BUFFER_SIZE);
|
||||
part[npart]->partoutl[i]*=vol_l;
|
||||
part[npart]->partoutr[i]*=vol_r;
|
||||
};
|
||||
part[npart]->oldvolumel=newvol_l;
|
||||
part[npart]->oldvolumer=newvol_r;
|
||||
|
||||
} else {
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {//the volume did not changed
|
||||
part[npart]->partoutl[i]*=newvol_l;
|
||||
part[npart]->partoutr[i]*=newvol_r;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//System effects
|
||||
for (nefx=0;nefx<NUM_SYS_EFX;nefx++){
|
||||
if (sysefx[nefx]->geteffect()==0) continue;//the effect is disabled
|
||||
|
||||
//Clean up the samples used by the system effects
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
tmpmixl[i]=0.0;
|
||||
tmpmixr[i]=0.0;
|
||||
};
|
||||
|
||||
//Mix the channels according to the part settings about System Effect
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
//skip if the part has no output to effect
|
||||
if (Psysefxvol[nefx][npart]==0) continue;
|
||||
|
||||
//skip if the part is disabled
|
||||
if (part[npart]->Penabled==0) continue;
|
||||
|
||||
//the output volume of each part to system effect
|
||||
REALTYPE vol=sysefxvol[nefx][npart];
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
tmpmixl[i]+=part[npart]->partoutl[i]*vol;
|
||||
tmpmixr[i]+=part[npart]->partoutr[i]*vol;
|
||||
};
|
||||
};
|
||||
|
||||
// system effect send to next ones
|
||||
for (int nefxfrom=0;nefxfrom<nefx;nefxfrom++){
|
||||
if (Psysefxsend[nefxfrom][nefx]!=0){
|
||||
REALTYPE v=sysefxsend[nefxfrom][nefx];
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
tmpmixl[i]+=sysefx[nefxfrom]->efxoutl[i]*v;
|
||||
tmpmixr[i]+=sysefx[nefxfrom]->efxoutr[i]*v;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sysefx[nefx]->out(tmpmixl,tmpmixr);
|
||||
|
||||
//Add the System Effect to sound output
|
||||
REALTYPE outvol=sysefx[nefx]->sysefxgetvolume();
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
outl[i]+=tmpmixl[i]*outvol;
|
||||
outr[i]+=tmpmixr[i]*outvol;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
//Mix all parts
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {//the volume did not changed
|
||||
outl[i]+=part[npart]->partoutl[i];
|
||||
outr[i]+=part[npart]->partoutr[i];
|
||||
};
|
||||
};
|
||||
|
||||
//Insertion effects for Master Out
|
||||
for (nefx=0;nefx<NUM_INS_EFX;nefx++){
|
||||
if (Pinsparts[nefx] == -2)
|
||||
insefx[nefx]->out(outl,outr);
|
||||
};
|
||||
|
||||
//Master Volume
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
outl[i]*=volume;
|
||||
outr[i]*=volume;
|
||||
};
|
||||
|
||||
//Peak computation (for vumeters)
|
||||
vuoutpeakl=1e-12;vuoutpeakr=1e-12;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
if (fabs(outl[i])>vuoutpeakl) vuoutpeakl=fabs(outl[i]);
|
||||
if (fabs(outr[i])>vuoutpeakr) vuoutpeakr=fabs(outr[i]);
|
||||
};
|
||||
if ((vuoutpeakl>1.0)||(vuoutpeakr>1.0)) vuclipped=1;
|
||||
if (vumaxoutpeakl<vuoutpeakl) vumaxoutpeakl=vuoutpeakl;
|
||||
if (vumaxoutpeakr<vuoutpeakr) vumaxoutpeakr=vuoutpeakr;
|
||||
|
||||
//RMS Peak computation (for vumeters)
|
||||
vurmspeakl=1e-12;vurmspeakr=1e-12;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
vurmspeakl+=outl[i]*outl[i];
|
||||
vurmspeakr+=outr[i]*outr[i];
|
||||
};
|
||||
vurmspeakl=sqrt(vurmspeakl/SOUND_BUFFER_SIZE);
|
||||
vurmspeakr=sqrt(vurmspeakr/SOUND_BUFFER_SIZE);
|
||||
|
||||
//Part Peak computation (for Part vumeters or fake part vumeters)
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
vuoutpeakpart[npart]=1.0e-12;
|
||||
if (part[npart]->Penabled!=0) {
|
||||
REALTYPE *outl=part[npart]->partoutl,
|
||||
*outr=part[npart]->partoutr;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE tmp=fabs(outl[i]+outr[i]);
|
||||
if (tmp>vuoutpeakpart[npart]) vuoutpeakpart[npart]=tmp;
|
||||
};
|
||||
vuoutpeakpart[npart]*=volume;
|
||||
} else {
|
||||
if (fakepeakpart[npart]>1) fakepeakpart[npart]--;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//Shutup if it is asked (with fade-out)
|
||||
if (shutup!=0){
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE tmp=(SOUND_BUFFER_SIZE-i)/(REALTYPE) SOUND_BUFFER_SIZE;
|
||||
outl[i]*=tmp;
|
||||
outr[i]*=tmp;
|
||||
};
|
||||
ShutUp();
|
||||
};
|
||||
|
||||
//update the LFO's time
|
||||
LFOParams::time++;
|
||||
|
||||
if (HDDRecorder.recording()) HDDRecorder.recordbuffer(outl,outr);
|
||||
dump.inctick();
|
||||
};
|
||||
|
||||
void Master::GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr){
|
||||
if (ksoundbuffersample==-1){//first time
|
||||
AudioOut(&audiooutl[0],&audiooutr[0]);
|
||||
ksoundbuffersample=0;
|
||||
};
|
||||
|
||||
|
||||
if (samplerate==SAMPLE_RATE){//no resample
|
||||
int ksample=0;
|
||||
while (ksample<nsamples){
|
||||
outl[ksample]=audiooutl[ksoundbuffersample];
|
||||
outr[ksample]=audiooutr[ksoundbuffersample];
|
||||
|
||||
ksample++;
|
||||
ksoundbuffersample++;
|
||||
if (ksoundbuffersample>=SOUND_BUFFER_SIZE){
|
||||
AudioOut(&audiooutl[0],&audiooutr[0]);
|
||||
ksoundbuffersample=0;
|
||||
};
|
||||
};
|
||||
} else {//Resample
|
||||
int ksample=0;
|
||||
REALTYPE srinc=SAMPLE_RATE/(REALTYPE)samplerate;
|
||||
|
||||
while (ksample<nsamples){
|
||||
if (ksoundbuffersample!=0){
|
||||
outl[ksample]=audiooutl[ksoundbuffersample]*ksoundbuffersamplelow
|
||||
+audiooutl[ksoundbuffersample-1]*(1.0-ksoundbuffersamplelow);
|
||||
outr[ksample]=audiooutr[ksoundbuffersample]*ksoundbuffersamplelow
|
||||
+audiooutr[ksoundbuffersample-1]*(1.0-ksoundbuffersamplelow);
|
||||
} else {
|
||||
outl[ksample]=audiooutl[ksoundbuffersample]*ksoundbuffersamplelow
|
||||
+oldsamplel*(1.0-ksoundbuffersamplelow);
|
||||
outr[ksample]=audiooutr[ksoundbuffersample]*ksoundbuffersamplelow
|
||||
+oldsampler*(1.0-ksoundbuffersamplelow);
|
||||
};
|
||||
|
||||
ksample++;
|
||||
|
||||
ksoundbuffersamplelow+=srinc;
|
||||
if (ksoundbuffersamplelow>=1.0){
|
||||
ksoundbuffersample+=(int) floor(ksoundbuffersamplelow);
|
||||
ksoundbuffersamplelow=ksoundbuffersamplelow-floor(ksoundbuffersamplelow);
|
||||
};
|
||||
|
||||
if (ksoundbuffersample>=SOUND_BUFFER_SIZE){
|
||||
oldsamplel=audiooutl[SOUND_BUFFER_SIZE-1];
|
||||
oldsampler=audiooutr[SOUND_BUFFER_SIZE-1];
|
||||
AudioOut(&audiooutl[0],&audiooutr[0]);
|
||||
ksoundbuffersample=0;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Master::~Master(){
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) delete part[npart];
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++) delete insefx[nefx];
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) delete sysefx[nefx];
|
||||
|
||||
delete [] audiooutl;
|
||||
delete [] audiooutr;
|
||||
delete [] tmpmixl;
|
||||
delete [] tmpmixr;
|
||||
delete (fft);
|
||||
|
||||
pthread_mutex_destroy(&mutex);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Master::setPvolume(char Pvolume_){
|
||||
Pvolume=Pvolume_;
|
||||
volume=dB2rap((Pvolume-96.0)/96.0*40.0);
|
||||
};
|
||||
|
||||
void Master::setPkeyshift(char Pkeyshift_){
|
||||
Pkeyshift=Pkeyshift_;
|
||||
keyshift=(int)Pkeyshift-64;
|
||||
};
|
||||
|
||||
|
||||
void Master::setPsysefxvol(int Ppart,int Pefx,char Pvol){
|
||||
Psysefxvol[Pefx][Ppart]=Pvol;
|
||||
sysefxvol[Pefx][Ppart]=pow(0.1,(1.0-Pvol/96.0)*2.0);
|
||||
};
|
||||
|
||||
void Master::setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol){
|
||||
Psysefxsend[Pefxfrom][Pefxto]=Pvol;
|
||||
sysefxsend[Pefxfrom][Pefxto]=pow(0.1,(1.0-Pvol/96.0)*2.0);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Panic! (Clean up all parts and effects)
|
||||
*/
|
||||
void Master::ShutUp(){
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
part[npart]->cleanup();
|
||||
fakepeakpart[npart]=0;
|
||||
};
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++) insefx[nefx]->cleanup();
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) sysefx[nefx]->cleanup();
|
||||
vuresetpeaks();
|
||||
shutup=0;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Reset peaks and clear the "cliped" flag (for VU-meter)
|
||||
*/
|
||||
void Master::vuresetpeaks(){
|
||||
vuoutpeakl=1e-9;vuoutpeakr=1e-9;vumaxoutpeakl=1e-9;vumaxoutpeakr=1e-9;
|
||||
vuclipped=0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void Master::applyparameters(){
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
part[npart]->applyparameters();
|
||||
};
|
||||
};
|
||||
|
||||
void Master::add2XML(XMLwrapper *xml){
|
||||
xml->addpar("volume",Pvolume);
|
||||
xml->addpar("key_shift",Pkeyshift);
|
||||
xml->addparbool("nrpn_receive",ctl.NRPN.receive);
|
||||
|
||||
xml->beginbranch("MICROTONAL");
|
||||
microtonal.add2XML(xml);
|
||||
xml->endbranch();
|
||||
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
xml->beginbranch("PART",npart);
|
||||
part[npart]->add2XML(xml);
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
xml->beginbranch("SYSTEM_EFFECTS");
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++){
|
||||
xml->beginbranch("SYSTEM_EFFECT",nefx);
|
||||
xml->beginbranch("EFFECT");
|
||||
sysefx[nefx]->add2XML(xml);
|
||||
xml->endbranch();
|
||||
|
||||
for (int pefx=0;pefx<NUM_MIDI_PARTS;pefx++){
|
||||
xml->beginbranch("VOLUME",pefx);
|
||||
xml->addpar("vol",Psysefxvol[nefx][pefx]);
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
for (int tonefx=nefx+1;tonefx<NUM_SYS_EFX;tonefx++){
|
||||
xml->beginbranch("SENDTO",tonefx);
|
||||
xml->addpar("send_vol",Psysefxsend[nefx][tonefx]);
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
|
||||
xml->endbranch();
|
||||
};
|
||||
xml->endbranch();
|
||||
|
||||
xml->beginbranch("INSERTION_EFFECTS");
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++){
|
||||
xml->beginbranch("INSERTION_EFFECT",nefx);
|
||||
xml->addpar("part",Pinsparts[nefx]);
|
||||
|
||||
xml->beginbranch("EFFECT");
|
||||
insefx[nefx]->add2XML(xml);
|
||||
xml->endbranch();
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
xml->endbranch();
|
||||
|
||||
};
|
||||
|
||||
|
||||
int Master::getalldata(char **data){
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
|
||||
xml->beginbranch("MASTER");
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
add2XML(xml);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
xml->endbranch();
|
||||
|
||||
*data=xml->getXMLdata();
|
||||
delete (xml);
|
||||
return(strlen(*data)+1);
|
||||
};
|
||||
|
||||
void Master::putalldata(char *data,int size){
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
if (!xml->putXMLdata(data)) {
|
||||
delete(xml);
|
||||
return;
|
||||
};
|
||||
|
||||
if (xml->enterbranch("MASTER")==0) return;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
getfromXML(xml);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
xml->exitbranch();
|
||||
|
||||
delete(xml);
|
||||
};
|
||||
|
||||
int Master::saveXML(char *filename){
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
|
||||
xml->beginbranch("MASTER");
|
||||
add2XML(xml);
|
||||
xml->endbranch();
|
||||
|
||||
int result=xml->saveXMLfile(filename);
|
||||
delete (xml);
|
||||
return(result);
|
||||
};
|
||||
|
||||
|
||||
|
||||
int Master::loadXML(char *filename){
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
if (xml->loadXMLfile(filename)<0) {
|
||||
delete(xml);
|
||||
return(-1);
|
||||
};
|
||||
|
||||
if (xml->enterbranch("MASTER")==0) return(-10);
|
||||
getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
|
||||
delete(xml);
|
||||
return(0);
|
||||
};
|
||||
|
||||
void Master::getfromXML(XMLwrapper *xml){
|
||||
setPvolume(xml->getpar127("volume",Pvolume));
|
||||
setPkeyshift(xml->getpar127("key_shift",Pkeyshift));
|
||||
ctl.NRPN.receive=xml->getparbool("nrpn_receive",ctl.NRPN.receive);
|
||||
|
||||
|
||||
part[0]->Penabled=0;
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++){
|
||||
if (xml->enterbranch("PART",npart)==0) continue;
|
||||
part[npart]->getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
if (xml->enterbranch("MICROTONAL")){
|
||||
microtonal.getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
sysefx[0]->changeeffect(0);
|
||||
if (xml->enterbranch("SYSTEM_EFFECTS")){
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++){
|
||||
if (xml->enterbranch("SYSTEM_EFFECT",nefx)==0) continue;
|
||||
if (xml->enterbranch("EFFECT")){
|
||||
sysefx[nefx]->getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
for (int partefx=0;partefx<NUM_MIDI_PARTS;partefx++){
|
||||
if (xml->enterbranch("VOLUME",partefx)==0) continue;
|
||||
setPsysefxvol(partefx,nefx,xml->getpar127("vol",Psysefxvol[partefx][nefx]));
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
for (int tonefx=nefx+1;tonefx<NUM_SYS_EFX;tonefx++){
|
||||
if (xml->enterbranch("SENDTO",tonefx)==0) continue;
|
||||
setPsysefxsend(nefx,tonefx,xml->getpar127("send_vol",Psysefxsend[nefx][tonefx]));
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
|
||||
if (xml->enterbranch("INSERTION_EFFECTS")){
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++){
|
||||
|
||||
if (xml->enterbranch("INSERTION_EFFECT",nefx)==0) continue;
|
||||
Pinsparts[nefx]=xml->getpar("part",Pinsparts[nefx],-2,NUM_MIDI_PARTS);
|
||||
if (xml->enterbranch("EFFECT")){
|
||||
insefx[nefx]->getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
|
||||
};
|
||||
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
778
plugins/zynaddsubfx/src/Misc/Master.cpp
Normal file
778
plugins/zynaddsubfx/src/Misc/Master.cpp
Normal file
@@ -0,0 +1,778 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Master.C - It sends Midi Messages to Parts, receives samples from parts,
|
||||
process them with system/insertion effects and mix them
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 "Master.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
Master::Master()
|
||||
{
|
||||
swaplr=0;
|
||||
|
||||
pthread_mutex_init(&mutex,NULL);
|
||||
fft=new FFTwrapper(OSCIL_SIZE);
|
||||
|
||||
tmpmixl=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
tmpmixr=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
audiooutl=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
audiooutr=new REALTYPE[SOUND_BUFFER_SIZE];
|
||||
|
||||
ksoundbuffersample=-1;//this is only time when this is -1; this means that the GetAudioOutSamples was never called
|
||||
ksoundbuffersamplelow=0.0;
|
||||
oldsamplel=0.0;
|
||||
oldsampler=0.0;
|
||||
shutup=0;
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
vuoutpeakpart[npart]=1e-9;
|
||||
fakepeakpart[npart]=0;
|
||||
};
|
||||
|
||||
for (int i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
audiooutl[i]=0.0;
|
||||
audiooutr[i]=0.0;
|
||||
};
|
||||
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++)
|
||||
part[npart]=new Part(µtonal,fft,&mutex);
|
||||
|
||||
|
||||
|
||||
//Insertion Effects init
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++)
|
||||
insefx[nefx]=new EffectMgr(1,&mutex);
|
||||
|
||||
//System Effects init
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) {
|
||||
sysefx[nefx]=new EffectMgr(0,&mutex);
|
||||
};
|
||||
|
||||
|
||||
defaults();
|
||||
};
|
||||
|
||||
void Master::defaults()
|
||||
{
|
||||
volume=1.0;
|
||||
setPvolume(80);
|
||||
setPkeyshift(64);
|
||||
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
part[npart]->defaults();
|
||||
part[npart]->Prcvchn=npart%NUM_MIDI_CHANNELS;
|
||||
};
|
||||
|
||||
partonoff(0,1);//enable the first part
|
||||
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++) {
|
||||
insefx[nefx]->defaults();
|
||||
Pinsparts[nefx]=-1;
|
||||
};
|
||||
|
||||
//System Effects init
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) {
|
||||
sysefx[nefx]->defaults();
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
//if (nefx==0) setPsysefxvol(npart,nefx,64);
|
||||
//else
|
||||
setPsysefxvol(npart,nefx,0);
|
||||
};
|
||||
for (int nefxto=0;nefxto<NUM_SYS_EFX;nefxto++)
|
||||
setPsysefxsend(nefx,nefxto,0);
|
||||
};
|
||||
|
||||
// sysefx[0]->changeeffect(1);
|
||||
microtonal.defaults();
|
||||
ShutUp();
|
||||
};
|
||||
|
||||
/*
|
||||
* Note On Messages (velocity=0 for NoteOff)
|
||||
*/
|
||||
void Master::NoteOn(unsigned char chan,unsigned char note,unsigned char velocity)
|
||||
{
|
||||
dump.dumpnote(chan,note,velocity);
|
||||
|
||||
noteon(chan,note,velocity);
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal Note On (velocity=0 for NoteOff)
|
||||
*/
|
||||
void Master::noteon(unsigned char chan,unsigned char note,unsigned char velocity)
|
||||
{
|
||||
int npart;
|
||||
if (velocity!=0) {
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
if (chan==part[npart]->Prcvchn) {
|
||||
fakepeakpart[npart]=velocity*2;
|
||||
if (part[npart]->Penabled!=0) part[npart]->NoteOn(note,velocity,keyshift);
|
||||
};
|
||||
};
|
||||
} else {
|
||||
this->NoteOff(chan,note);
|
||||
};
|
||||
HDDRecorder.triggernow();
|
||||
};
|
||||
|
||||
/*
|
||||
* Note Off Messages
|
||||
*/
|
||||
void Master::NoteOff(unsigned char chan,unsigned char note)
|
||||
{
|
||||
dump.dumpnote(chan,note,0);
|
||||
|
||||
noteoff(chan,note);
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal Note Off
|
||||
*/
|
||||
void Master::noteoff(unsigned char chan,unsigned char note)
|
||||
{
|
||||
int npart;
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
if ((chan==part[npart]->Prcvchn) && (part[npart]->Penabled!=0))
|
||||
part[npart]->NoteOff(note);
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Controllers
|
||||
*/
|
||||
void Master::SetController(unsigned char chan,unsigned int type,int par)
|
||||
{
|
||||
dump.dumpcontroller(chan,type,par);
|
||||
|
||||
setcontroller(chan,type,par);
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal Controllers
|
||||
*/
|
||||
void Master::setcontroller(unsigned char chan,unsigned int type,int par)
|
||||
{
|
||||
if ((type==C_dataentryhi)||(type==C_dataentrylo)||
|
||||
(type==C_nrpnhi)||(type==C_nrpnlo)) {//Process RPN and NRPN by the Master (ignore the chan)
|
||||
ctl.setparameternumber(type,par);
|
||||
|
||||
int parhi=-1,parlo=-1,valhi=-1,vallo=-1;
|
||||
if (ctl.getnrpn(&parhi,&parlo,&valhi,&vallo)==0) {//this is NRPN
|
||||
//fprintf(stderr,"rcv. NRPN: %d %d %d %d\n",parhi,parlo,valhi,vallo);
|
||||
switch (parhi) {
|
||||
case 0x04://System Effects
|
||||
if (parlo<NUM_SYS_EFX) {
|
||||
sysefx[parlo]->seteffectpar_nolock(valhi,vallo);
|
||||
};
|
||||
break;
|
||||
case 0x08://Insertion Effects
|
||||
if (parlo<NUM_INS_EFX) {
|
||||
insefx[parlo]->seteffectpar_nolock(valhi,vallo);
|
||||
};
|
||||
break;
|
||||
|
||||
};
|
||||
};
|
||||
} else {//other controllers
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {//Send the controller to all part assigned to the channel
|
||||
if ((chan==part[npart]->Prcvchn) && (part[npart]->Penabled!=0))
|
||||
part[npart]->SetController(type,par);
|
||||
};
|
||||
|
||||
if (type==C_allsoundsoff) { //cleanup insertion/system FX
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;++nefx) {
|
||||
sysefx[nefx]->cleanup();
|
||||
}
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;++nefx) {
|
||||
insefx[nefx]->cleanup();
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Enable/Disable a part
|
||||
*/
|
||||
void Master::partonoff(int npart,int what)
|
||||
{
|
||||
if (npart>=NUM_MIDI_PARTS) return;
|
||||
if (what==0) {//disable part
|
||||
fakepeakpart[npart]=0;
|
||||
part[npart]->Penabled=0;
|
||||
part[npart]->cleanup();
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++) {
|
||||
if (Pinsparts[nefx]==npart) {
|
||||
insefx[nefx]->cleanup();
|
||||
};
|
||||
};
|
||||
} else {//enabled
|
||||
part[npart]->Penabled=1;
|
||||
fakepeakpart[npart]=0;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Master audio out (the final sound)
|
||||
*/
|
||||
void Master::AudioOut(REALTYPE *outl,REALTYPE *outr)
|
||||
{
|
||||
int i,npart,nefx;
|
||||
|
||||
/* //test!!!!!!!!!!!!! se poate bloca aici (mutex)
|
||||
if (seq.play){
|
||||
int type,par1,par2,again,midichan;
|
||||
int ntrack=1;
|
||||
// do{
|
||||
again=seq.getevent(ntrack,&midichan,&type,&par1,&par2);
|
||||
if (type>0) {
|
||||
// printf("aaa\n");
|
||||
|
||||
if (type==1){//note_on or note_off
|
||||
if (par2!=0) NoteOn(midichan,par1,par2);
|
||||
else NoteOff(midichan,par1);
|
||||
};
|
||||
};
|
||||
// } while (again);
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
// printf("zzzz\n");
|
||||
|
||||
|
||||
//Swaps the Left channel with Right Channel (if it is asked for)
|
||||
if (swaplr!=0) {
|
||||
REALTYPE *tmp=outl;
|
||||
outl=outr;
|
||||
outr=tmp;
|
||||
};
|
||||
|
||||
//clean up the output samples
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
outl[i]=0.0;
|
||||
outr[i]=0.0;
|
||||
};
|
||||
|
||||
//Compute part samples and store them part[npart]->partoutl,partoutr
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++)
|
||||
if (part[npart]->Penabled!=0) part[npart]->ComputePartSmps();
|
||||
|
||||
//Insertion effects
|
||||
for (nefx=0;nefx<NUM_INS_EFX;nefx++) {
|
||||
if (Pinsparts[nefx]>=0) {
|
||||
int efxpart=Pinsparts[nefx];
|
||||
if (part[efxpart]->Penabled!=0)
|
||||
insefx[nefx]->out(part[efxpart]->partoutl,part[efxpart]->partoutr);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//Apply the part volumes and pannings (after insertion effects)
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
if (part[npart]->Penabled==0) continue;
|
||||
|
||||
REALTYPE newvol_l=part[npart]->volume;
|
||||
REALTYPE newvol_r=part[npart]->volume;
|
||||
REALTYPE oldvol_l=part[npart]->oldvolumel;
|
||||
REALTYPE oldvol_r=part[npart]->oldvolumer;
|
||||
REALTYPE pan=part[npart]->panning;
|
||||
if (pan<0.5) newvol_l*=pan*2.0;
|
||||
else newvol_r*=(1.0-pan)*2.0;
|
||||
|
||||
if (ABOVE_AMPLITUDE_THRESHOLD(oldvol_l,newvol_l)||
|
||||
ABOVE_AMPLITUDE_THRESHOLD(oldvol_r,newvol_r)) {//the volume or the panning has changed and needs interpolation
|
||||
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE vol_l=INTERPOLATE_AMPLITUDE(oldvol_l,newvol_l,i,SOUND_BUFFER_SIZE);
|
||||
REALTYPE vol_r=INTERPOLATE_AMPLITUDE(oldvol_r,newvol_r,i,SOUND_BUFFER_SIZE);
|
||||
part[npart]->partoutl[i]*=vol_l;
|
||||
part[npart]->partoutr[i]*=vol_r;
|
||||
};
|
||||
part[npart]->oldvolumel=newvol_l;
|
||||
part[npart]->oldvolumer=newvol_r;
|
||||
|
||||
} else {
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {//the volume did not changed
|
||||
part[npart]->partoutl[i]*=newvol_l;
|
||||
part[npart]->partoutr[i]*=newvol_r;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//System effects
|
||||
for (nefx=0;nefx<NUM_SYS_EFX;nefx++) {
|
||||
if (sysefx[nefx]->geteffect()==0) continue;//the effect is disabled
|
||||
|
||||
//Clean up the samples used by the system effects
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
tmpmixl[i]=0.0;
|
||||
tmpmixr[i]=0.0;
|
||||
};
|
||||
|
||||
//Mix the channels according to the part settings about System Effect
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
//skip if the part has no output to effect
|
||||
if (Psysefxvol[nefx][npart]==0) continue;
|
||||
|
||||
//skip if the part is disabled
|
||||
if (part[npart]->Penabled==0) continue;
|
||||
|
||||
//the output volume of each part to system effect
|
||||
REALTYPE vol=sysefxvol[nefx][npart];
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
tmpmixl[i]+=part[npart]->partoutl[i]*vol;
|
||||
tmpmixr[i]+=part[npart]->partoutr[i]*vol;
|
||||
};
|
||||
};
|
||||
|
||||
// system effect send to next ones
|
||||
for (int nefxfrom=0;nefxfrom<nefx;nefxfrom++) {
|
||||
if (Psysefxsend[nefxfrom][nefx]!=0) {
|
||||
REALTYPE v=sysefxsend[nefxfrom][nefx];
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
tmpmixl[i]+=sysefx[nefxfrom]->efxoutl[i]*v;
|
||||
tmpmixr[i]+=sysefx[nefxfrom]->efxoutr[i]*v;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sysefx[nefx]->out(tmpmixl,tmpmixr);
|
||||
|
||||
//Add the System Effect to sound output
|
||||
REALTYPE outvol=sysefx[nefx]->sysefxgetvolume();
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
outl[i]+=tmpmixl[i]*outvol;
|
||||
outr[i]+=tmpmixr[i]*outvol;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
//Mix all parts
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {//the volume did not changed
|
||||
outl[i]+=part[npart]->partoutl[i];
|
||||
outr[i]+=part[npart]->partoutr[i];
|
||||
};
|
||||
};
|
||||
|
||||
//Insertion effects for Master Out
|
||||
for (nefx=0;nefx<NUM_INS_EFX;nefx++) {
|
||||
if (Pinsparts[nefx] == -2)
|
||||
insefx[nefx]->out(outl,outr);
|
||||
};
|
||||
|
||||
//Master Volume
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
outl[i]*=volume;
|
||||
outr[i]*=volume;
|
||||
};
|
||||
|
||||
//Peak computation (for vumeters)
|
||||
vuoutpeakl=1e-12;
|
||||
vuoutpeakr=1e-12;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
if (fabs(outl[i])>vuoutpeakl) vuoutpeakl=fabs(outl[i]);
|
||||
if (fabs(outr[i])>vuoutpeakr) vuoutpeakr=fabs(outr[i]);
|
||||
};
|
||||
if ((vuoutpeakl>1.0)||(vuoutpeakr>1.0)) vuclipped=1;
|
||||
if (vumaxoutpeakl<vuoutpeakl) vumaxoutpeakl=vuoutpeakl;
|
||||
if (vumaxoutpeakr<vuoutpeakr) vumaxoutpeakr=vuoutpeakr;
|
||||
|
||||
//RMS Peak computation (for vumeters)
|
||||
vurmspeakl=1e-12;
|
||||
vurmspeakr=1e-12;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
vurmspeakl+=outl[i]*outl[i];
|
||||
vurmspeakr+=outr[i]*outr[i];
|
||||
};
|
||||
vurmspeakl=sqrt(vurmspeakl/SOUND_BUFFER_SIZE);
|
||||
vurmspeakr=sqrt(vurmspeakr/SOUND_BUFFER_SIZE);
|
||||
|
||||
//Part Peak computation (for Part vumeters or fake part vumeters)
|
||||
for (npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
vuoutpeakpart[npart]=1.0e-12;
|
||||
if (part[npart]->Penabled!=0) {
|
||||
REALTYPE *outl=part[npart]->partoutl,
|
||||
*outr=part[npart]->partoutr;
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE tmp=fabs(outl[i]+outr[i]);
|
||||
if (tmp>vuoutpeakpart[npart]) vuoutpeakpart[npart]=tmp;
|
||||
};
|
||||
vuoutpeakpart[npart]*=volume;
|
||||
} else {
|
||||
if (fakepeakpart[npart]>1) fakepeakpart[npart]--;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//Shutup if it is asked (with fade-out)
|
||||
if (shutup!=0) {
|
||||
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
|
||||
REALTYPE tmp=(SOUND_BUFFER_SIZE-i)/(REALTYPE) SOUND_BUFFER_SIZE;
|
||||
outl[i]*=tmp;
|
||||
outr[i]*=tmp;
|
||||
};
|
||||
ShutUp();
|
||||
};
|
||||
|
||||
//update the LFO's time
|
||||
LFOParams::time++;
|
||||
|
||||
if (HDDRecorder.recording()) HDDRecorder.recordbuffer(outl,outr);
|
||||
dump.inctick();
|
||||
};
|
||||
|
||||
void Master::GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr)
|
||||
{
|
||||
if (ksoundbuffersample==-1) {//first time
|
||||
AudioOut(&audiooutl[0],&audiooutr[0]);
|
||||
ksoundbuffersample=0;
|
||||
};
|
||||
|
||||
|
||||
if (samplerate==SAMPLE_RATE) {//no resample
|
||||
int ksample=0;
|
||||
while (ksample<nsamples) {
|
||||
outl[ksample]=audiooutl[ksoundbuffersample];
|
||||
outr[ksample]=audiooutr[ksoundbuffersample];
|
||||
|
||||
ksample++;
|
||||
ksoundbuffersample++;
|
||||
if (ksoundbuffersample>=SOUND_BUFFER_SIZE) {
|
||||
AudioOut(&audiooutl[0],&audiooutr[0]);
|
||||
ksoundbuffersample=0;
|
||||
};
|
||||
};
|
||||
} else {//Resample
|
||||
int ksample=0;
|
||||
REALTYPE srinc=SAMPLE_RATE/(REALTYPE)samplerate;
|
||||
|
||||
while (ksample<nsamples) {
|
||||
if (ksoundbuffersample!=0) {
|
||||
outl[ksample]=audiooutl[ksoundbuffersample]*ksoundbuffersamplelow
|
||||
+audiooutl[ksoundbuffersample-1]*(1.0-ksoundbuffersamplelow);
|
||||
outr[ksample]=audiooutr[ksoundbuffersample]*ksoundbuffersamplelow
|
||||
+audiooutr[ksoundbuffersample-1]*(1.0-ksoundbuffersamplelow);
|
||||
} else {
|
||||
outl[ksample]=audiooutl[ksoundbuffersample]*ksoundbuffersamplelow
|
||||
+oldsamplel*(1.0-ksoundbuffersamplelow);
|
||||
outr[ksample]=audiooutr[ksoundbuffersample]*ksoundbuffersamplelow
|
||||
+oldsampler*(1.0-ksoundbuffersamplelow);
|
||||
};
|
||||
|
||||
ksample++;
|
||||
|
||||
ksoundbuffersamplelow+=srinc;
|
||||
if (ksoundbuffersamplelow>=1.0) {
|
||||
ksoundbuffersample+=(int) floor(ksoundbuffersamplelow);
|
||||
ksoundbuffersamplelow=ksoundbuffersamplelow-floor(ksoundbuffersamplelow);
|
||||
};
|
||||
|
||||
if (ksoundbuffersample>=SOUND_BUFFER_SIZE) {
|
||||
oldsamplel=audiooutl[SOUND_BUFFER_SIZE-1];
|
||||
oldsampler=audiooutr[SOUND_BUFFER_SIZE-1];
|
||||
AudioOut(&audiooutl[0],&audiooutr[0]);
|
||||
ksoundbuffersample=0;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Master::~Master()
|
||||
{
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) delete part[npart];
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++) delete insefx[nefx];
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) delete sysefx[nefx];
|
||||
|
||||
delete [] audiooutl;
|
||||
delete [] audiooutr;
|
||||
delete [] tmpmixl;
|
||||
delete [] tmpmixr;
|
||||
delete (fft);
|
||||
|
||||
pthread_mutex_destroy(&mutex);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Parameter control
|
||||
*/
|
||||
void Master::setPvolume(char Pvolume_)
|
||||
{
|
||||
Pvolume=Pvolume_;
|
||||
volume=dB2rap((Pvolume-96.0)/96.0*40.0);
|
||||
};
|
||||
|
||||
void Master::setPkeyshift(char Pkeyshift_)
|
||||
{
|
||||
Pkeyshift=Pkeyshift_;
|
||||
keyshift=(int)Pkeyshift-64;
|
||||
};
|
||||
|
||||
|
||||
void Master::setPsysefxvol(int Ppart,int Pefx,char Pvol)
|
||||
{
|
||||
Psysefxvol[Pefx][Ppart]=Pvol;
|
||||
sysefxvol[Pefx][Ppart]=pow(0.1,(1.0-Pvol/96.0)*2.0);
|
||||
};
|
||||
|
||||
void Master::setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol)
|
||||
{
|
||||
Psysefxsend[Pefxfrom][Pefxto]=Pvol;
|
||||
sysefxsend[Pefxfrom][Pefxto]=pow(0.1,(1.0-Pvol/96.0)*2.0);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Panic! (Clean up all parts and effects)
|
||||
*/
|
||||
void Master::ShutUp()
|
||||
{
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
part[npart]->cleanup();
|
||||
fakepeakpart[npart]=0;
|
||||
};
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++) insefx[nefx]->cleanup();
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) sysefx[nefx]->cleanup();
|
||||
vuresetpeaks();
|
||||
shutup=0;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Reset peaks and clear the "cliped" flag (for VU-meter)
|
||||
*/
|
||||
void Master::vuresetpeaks()
|
||||
{
|
||||
vuoutpeakl=1e-9;
|
||||
vuoutpeakr=1e-9;
|
||||
vumaxoutpeakl=1e-9;
|
||||
vumaxoutpeakr=1e-9;
|
||||
vuclipped=0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void Master::applyparameters()
|
||||
{
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
part[npart]->applyparameters();
|
||||
};
|
||||
};
|
||||
|
||||
void Master::add2XML(XMLwrapper *xml)
|
||||
{
|
||||
xml->addpar("volume",Pvolume);
|
||||
xml->addpar("key_shift",Pkeyshift);
|
||||
xml->addparbool("nrpn_receive",ctl.NRPN.receive);
|
||||
|
||||
xml->beginbranch("MICROTONAL");
|
||||
microtonal.add2XML(xml);
|
||||
xml->endbranch();
|
||||
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
xml->beginbranch("PART",npart);
|
||||
part[npart]->add2XML(xml);
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
xml->beginbranch("SYSTEM_EFFECTS");
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) {
|
||||
xml->beginbranch("SYSTEM_EFFECT",nefx);
|
||||
xml->beginbranch("EFFECT");
|
||||
sysefx[nefx]->add2XML(xml);
|
||||
xml->endbranch();
|
||||
|
||||
for (int pefx=0;pefx<NUM_MIDI_PARTS;pefx++) {
|
||||
xml->beginbranch("VOLUME",pefx);
|
||||
xml->addpar("vol",Psysefxvol[nefx][pefx]);
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
for (int tonefx=nefx+1;tonefx<NUM_SYS_EFX;tonefx++) {
|
||||
xml->beginbranch("SENDTO",tonefx);
|
||||
xml->addpar("send_vol",Psysefxsend[nefx][tonefx]);
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
|
||||
xml->endbranch();
|
||||
};
|
||||
xml->endbranch();
|
||||
|
||||
xml->beginbranch("INSERTION_EFFECTS");
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++) {
|
||||
xml->beginbranch("INSERTION_EFFECT",nefx);
|
||||
xml->addpar("part",Pinsparts[nefx]);
|
||||
|
||||
xml->beginbranch("EFFECT");
|
||||
insefx[nefx]->add2XML(xml);
|
||||
xml->endbranch();
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
xml->endbranch();
|
||||
|
||||
};
|
||||
|
||||
|
||||
int Master::getalldata(char **data)
|
||||
{
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
|
||||
xml->beginbranch("MASTER");
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
add2XML(xml);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
xml->endbranch();
|
||||
|
||||
*data=xml->getXMLdata();
|
||||
delete (xml);
|
||||
return(strlen(*data)+1);
|
||||
};
|
||||
|
||||
void Master::putalldata(char *data,int size)
|
||||
{
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
if (!xml->putXMLdata(data)) {
|
||||
delete(xml);
|
||||
return;
|
||||
};
|
||||
|
||||
if (xml->enterbranch("MASTER")==0) return;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
getfromXML(xml);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
xml->exitbranch();
|
||||
|
||||
delete(xml);
|
||||
};
|
||||
|
||||
int Master::saveXML(const char *filename)
|
||||
{
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
|
||||
xml->beginbranch("MASTER");
|
||||
add2XML(xml);
|
||||
xml->endbranch();
|
||||
|
||||
int result=xml->saveXMLfile(filename);
|
||||
delete (xml);
|
||||
return(result);
|
||||
};
|
||||
|
||||
|
||||
|
||||
int Master::loadXML(const char *filename)
|
||||
{
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
if (xml->loadXMLfile(filename)<0) {
|
||||
delete(xml);
|
||||
return(-1);
|
||||
};
|
||||
|
||||
if (xml->enterbranch("MASTER")==0) return(-10);
|
||||
getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
|
||||
delete(xml);
|
||||
return(0);
|
||||
};
|
||||
|
||||
void Master::getfromXML(XMLwrapper *xml)
|
||||
{
|
||||
setPvolume(xml->getpar127("volume",Pvolume));
|
||||
setPkeyshift(xml->getpar127("key_shift",Pkeyshift));
|
||||
ctl.NRPN.receive=xml->getparbool("nrpn_receive",ctl.NRPN.receive);
|
||||
|
||||
|
||||
part[0]->Penabled=0;
|
||||
for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {
|
||||
if (xml->enterbranch("PART",npart)==0) continue;
|
||||
part[npart]->getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
if (xml->enterbranch("MICROTONAL")) {
|
||||
microtonal.getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
sysefx[0]->changeeffect(0);
|
||||
if (xml->enterbranch("SYSTEM_EFFECTS")) {
|
||||
for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) {
|
||||
if (xml->enterbranch("SYSTEM_EFFECT",nefx)==0) continue;
|
||||
if (xml->enterbranch("EFFECT")) {
|
||||
sysefx[nefx]->getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
for (int partefx=0;partefx<NUM_MIDI_PARTS;partefx++) {
|
||||
if (xml->enterbranch("VOLUME",partefx)==0) continue;
|
||||
setPsysefxvol(partefx,nefx,xml->getpar127("vol",Psysefxvol[partefx][nefx]));
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
for (int tonefx=nefx+1;tonefx<NUM_SYS_EFX;tonefx++) {
|
||||
if (xml->enterbranch("SENDTO",tonefx)==0) continue;
|
||||
setPsysefxsend(nefx,tonefx,xml->getpar127("send_vol",Psysefxsend[nefx][tonefx]));
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
|
||||
if (xml->enterbranch("INSERTION_EFFECTS")) {
|
||||
for (int nefx=0;nefx<NUM_INS_EFX;nefx++) {
|
||||
|
||||
if (xml->enterbranch("INSERTION_EFFECT",nefx)==0) continue;
|
||||
Pinsparts[nefx]=xml->getpar("part",Pinsparts[nefx],-2,NUM_MIDI_PARTS);
|
||||
if (xml->enterbranch("EFFECT")) {
|
||||
insefx[nefx]->getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
|
||||
};
|
||||
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Master.h - It sends Midi Messages to Parts, receives samples from parts,
|
||||
process them with system/insertion effects and mix them
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -36,127 +36,132 @@
|
||||
#include "XMLwrapper.h"
|
||||
|
||||
extern Dump dump;
|
||||
class Master{
|
||||
public:
|
||||
Master();
|
||||
~Master();
|
||||
/** It sends Midi Messages to Parts, receives samples from parts,
|
||||
* process them with system/insertion effects and mix them */
|
||||
class Master
|
||||
{
|
||||
public:
|
||||
/** Constructor*/
|
||||
Master();
|
||||
/** Destructor*/
|
||||
~Master();
|
||||
|
||||
//saves all settings to a XML file
|
||||
//returns 0 for ok or <0 if there is an error
|
||||
int saveXML(char *filename);
|
||||
/**Saves all settings to a XML file
|
||||
* @return 0 for ok or <0 if there is an error*/
|
||||
int saveXML(const char *filename);
|
||||
|
||||
//this adds the parameters to the XML data
|
||||
void add2XML(XMLwrapper *xml);
|
||||
/**This adds the parameters to the XML data*/
|
||||
void add2XML(XMLwrapper *xml);
|
||||
|
||||
void defaults();
|
||||
void defaults();
|
||||
|
||||
|
||||
//loads all settings from a XML file
|
||||
//returns 0 for ok or -1 if there is an error
|
||||
int loadXML(char *filename);
|
||||
void applyparameters();
|
||||
/**loads all settings from a XML file
|
||||
* @return 0 for ok or -1 if there is an error*/
|
||||
int loadXML(const char *filename);
|
||||
void applyparameters();
|
||||
|
||||
void getfromXML(XMLwrapper *xml);
|
||||
|
||||
//get all data to a newly allocated array (used for VST)
|
||||
//returns the datasize
|
||||
int getalldata(char **data);
|
||||
//put all data from the *data array to zynaddsubfx parameters (used for VST)
|
||||
void putalldata(char *data,int size);
|
||||
void getfromXML(XMLwrapper *xml);
|
||||
|
||||
/**get all data to a newly allocated array (used for VST)
|
||||
* @return the datasize*/
|
||||
int getalldata(char **data);
|
||||
/**put all data from the *data array to zynaddsubfx parameters (used for VST)*/
|
||||
void putalldata(char *data,int size);
|
||||
|
||||
|
||||
|
||||
//Midi IN
|
||||
void NoteOn(unsigned char chan,unsigned char note,unsigned char velocity);
|
||||
void NoteOff(unsigned char chan,unsigned char note);
|
||||
void SetController(unsigned char chan,unsigned int type,int par);
|
||||
//void NRPN...
|
||||
|
||||
|
||||
void ShutUp();
|
||||
int shutup;
|
||||
|
||||
//Audio Output
|
||||
void AudioOut(REALTYPE *outl,REALTYPE *outr);
|
||||
//Audio Output (for callback mode). This allows the program to be controled by an external program
|
||||
void GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr);
|
||||
//Midi IN
|
||||
void NoteOn(unsigned char chan,unsigned char note,unsigned char velocity);
|
||||
void NoteOff(unsigned char chan,unsigned char note);
|
||||
void SetController(unsigned char chan,unsigned int type,int par);
|
||||
//void NRPN...
|
||||
|
||||
|
||||
void partonoff(int npart,int what);
|
||||
|
||||
//parts
|
||||
Part *part[NUM_MIDI_PARTS];
|
||||
|
||||
//parameters
|
||||
unsigned char Pvolume;
|
||||
unsigned char Pkeyshift;
|
||||
unsigned char Psysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS];
|
||||
unsigned char Psysefxsend[NUM_SYS_EFX][NUM_SYS_EFX];
|
||||
|
||||
//parameters control
|
||||
void setPvolume(char Pvolume_);
|
||||
void setPkeyshift(char Pkeyshift_);
|
||||
void setPsysefxvol(int Ppart,int Pefx,char Pvol);
|
||||
void setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol);
|
||||
void ShutUp();
|
||||
int shutup;
|
||||
|
||||
//effects
|
||||
EffectMgr *sysefx[NUM_SYS_EFX];//system
|
||||
EffectMgr *insefx[NUM_INS_EFX];//insertion
|
||||
/**Audio Output*/
|
||||
void AudioOut(REALTYPE *outl,REALTYPE *outr);
|
||||
/**Audio Output (for callback mode). This allows the program to be controled by an external program*/
|
||||
void GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr);
|
||||
|
||||
|
||||
void partonoff(int npart,int what);
|
||||
|
||||
/**parts \todo see if this can be made to be dynamic*/
|
||||
Part *part[NUM_MIDI_PARTS];
|
||||
|
||||
//parameters
|
||||
unsigned char Pvolume;
|
||||
unsigned char Pkeyshift;
|
||||
unsigned char Psysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS];
|
||||
unsigned char Psysefxsend[NUM_SYS_EFX][NUM_SYS_EFX];
|
||||
|
||||
//parameters control
|
||||
void setPvolume(char Pvolume_);
|
||||
void setPkeyshift(char Pkeyshift_);
|
||||
void setPsysefxvol(int Ppart,int Pefx,char Pvol);
|
||||
void setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol);
|
||||
|
||||
//effects
|
||||
EffectMgr *sysefx[NUM_SYS_EFX];//system
|
||||
EffectMgr *insefx[NUM_INS_EFX];//insertion
|
||||
// void swapcopyeffects(int what,int type,int neff1,int neff2);
|
||||
|
||||
//HDD recorder
|
||||
Recorder HDDRecorder;
|
||||
//HDD recorder
|
||||
Recorder HDDRecorder;
|
||||
|
||||
//part that's apply the insertion effect; -1 to disable
|
||||
short int Pinsparts[NUM_INS_EFX];
|
||||
|
||||
//peaks for VU-meter
|
||||
void vuresetpeaks();
|
||||
REALTYPE vuoutpeakl,vuoutpeakr,vumaxoutpeakl,vumaxoutpeakr,vurmspeakl,vurmspeakr;
|
||||
int vuclipped;
|
||||
|
||||
//peaks for part VU-meters
|
||||
REALTYPE vuoutpeakpart[NUM_MIDI_PARTS];
|
||||
unsigned char fakepeakpart[NUM_MIDI_PARTS];//this is used to compute the "peak" when the part is disabled
|
||||
//part that's apply the insertion effect; -1 to disable
|
||||
short int Pinsparts[NUM_INS_EFX];
|
||||
|
||||
Controller ctl;
|
||||
int swaplr;//1 if L and R are swapped
|
||||
//peaks for VU-meter
|
||||
void vuresetpeaks();
|
||||
REALTYPE vuoutpeakl,vuoutpeakr,vumaxoutpeakl,vumaxoutpeakr,vurmspeakl,vurmspeakr;
|
||||
int vuclipped;
|
||||
|
||||
//Sequencer
|
||||
Sequencer seq;
|
||||
|
||||
//other objects
|
||||
Microtonal microtonal;
|
||||
Bank bank;
|
||||
|
||||
FFTwrapper *fft;
|
||||
pthread_mutex_t mutex;
|
||||
//peaks for part VU-meters
|
||||
REALTYPE vuoutpeakpart[NUM_MIDI_PARTS];
|
||||
unsigned char fakepeakpart[NUM_MIDI_PARTS];//this is used to compute the "peak" when the part is disabled
|
||||
|
||||
private:
|
||||
REALTYPE volume;
|
||||
REALTYPE sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS];
|
||||
REALTYPE sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX];
|
||||
Controller ctl;
|
||||
int swaplr;//1 if L and R are swapped
|
||||
|
||||
//Temporary mixing samples for part samples which is sent to system effect
|
||||
REALTYPE *tmpmixl;
|
||||
REALTYPE *tmpmixr;
|
||||
//Sequencer
|
||||
Sequencer seq;
|
||||
|
||||
//other objects
|
||||
Microtonal microtonal;
|
||||
Bank bank;
|
||||
|
||||
FFTwrapper *fft;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
private:
|
||||
REALTYPE volume;
|
||||
REALTYPE sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS];
|
||||
REALTYPE sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX];
|
||||
|
||||
//Temporary mixing samples for part samples which is sent to system effect
|
||||
REALTYPE *tmpmixl;
|
||||
REALTYPE *tmpmixr;
|
||||
|
||||
|
||||
int keyshift;
|
||||
int keyshift;
|
||||
|
||||
//Audio Output samples (if it used GetAudioOutSamples - eg. for Jack output; elsewhere is unused)
|
||||
REALTYPE *audiooutl;
|
||||
REALTYPE *audiooutr;
|
||||
|
||||
int ksoundbuffersample;//this is used to know if there is need to call AudioOut by GetAudioOutSamples method
|
||||
REALTYPE ksoundbuffersamplelow;//this is used for resampling (eg. if Jack samplerate!= SAMPLE_RATE)
|
||||
REALTYPE oldsamplel,oldsampler;//this is used for resampling
|
||||
//Audio Output samples (if it used GetAudioOutSamples - eg. for Jack output; elsewhere is unused)
|
||||
REALTYPE *audiooutl;
|
||||
REALTYPE *audiooutr;
|
||||
|
||||
//Theese are called by the NoteOn, NoteOff,SetController (which are from external sources like MIDI, Virtual Keyboard)
|
||||
//and are called by internal parts of the program (like sequencer)
|
||||
void noteon(unsigned char chan,unsigned char note,unsigned char velocity);
|
||||
void noteoff(unsigned char chan,unsigned char note);
|
||||
void setcontroller(unsigned char chan,unsigned int type,int par);
|
||||
int ksoundbuffersample;//this is used to know if there is need to call AudioOut by GetAudioOutSamples method
|
||||
REALTYPE ksoundbuffersamplelow;//this is used for resampling (eg. if Jack samplerate!= SAMPLE_RATE)
|
||||
REALTYPE oldsamplel,oldsampler;//this is used for resampling
|
||||
|
||||
//These are called by the NoteOn, NoteOff,SetController (which are from external sources like MIDI, Virtual Keyboard)
|
||||
//and are called by internal parts of the program (like sequencer)
|
||||
void noteon(unsigned char chan,unsigned char note,unsigned char velocity);
|
||||
void noteoff(unsigned char chan,unsigned char note);
|
||||
void setcontroller(unsigned char chan,unsigned int type,int par);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,514 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Microtonal.C - Tuning settings and microtonal capabilities
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <math.h>
|
||||
#include <string.h>
|
||||
#include "Microtonal.h"
|
||||
|
||||
#define MAX_LINE_SIZE 80
|
||||
|
||||
Microtonal::Microtonal(){
|
||||
Pname=new unsigned char[MICROTONAL_MAX_NAME_LEN];
|
||||
Pcomment=new unsigned char[MICROTONAL_MAX_NAME_LEN];
|
||||
defaults();
|
||||
};
|
||||
|
||||
void Microtonal::defaults(){
|
||||
Pinvertupdown=0;
|
||||
Pinvertupdowncenter=60;
|
||||
octavesize=12;
|
||||
Penabled=0;
|
||||
PAnote=69;
|
||||
PAfreq=440.0;
|
||||
Pscaleshift=64;
|
||||
|
||||
Pfirstkey=0;Plastkey=127;
|
||||
Pmiddlenote=60;Pmapsize=12;
|
||||
Pmappingenabled=0;
|
||||
|
||||
for (int i=0;i<128;i++) Pmapping[i]=i;
|
||||
|
||||
for (int i=0;i<MAX_OCTAVE_SIZE;i++){
|
||||
octave[i].tuning=tmpoctave[i].tuning=pow(2,(i%octavesize+1)/12.0);
|
||||
octave[i].type=tmpoctave[i].type=1;
|
||||
octave[i].x1=tmpoctave[i].x1=(i%octavesize+1)*100;
|
||||
octave[i].x2=tmpoctave[i].x2=0;
|
||||
};
|
||||
octave[11].type=2;octave[11].x1=2;octave[11].x2=1;
|
||||
for (int i=0;i<MICROTONAL_MAX_NAME_LEN;i++){
|
||||
Pname[i]='\0';
|
||||
Pcomment[i]='\0';
|
||||
};
|
||||
snprintf((char *) Pname,MICROTONAL_MAX_NAME_LEN,"12tET");
|
||||
snprintf((char *) Pcomment,MICROTONAL_MAX_NAME_LEN,"Equal Temperament 12 notes per octave");
|
||||
Pglobalfinedetune=64;
|
||||
};
|
||||
|
||||
Microtonal::~Microtonal(){
|
||||
delete [] Pname;
|
||||
delete [] Pcomment;
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the size of the octave
|
||||
*/
|
||||
unsigned char Microtonal::getoctavesize(){
|
||||
if (Penabled!=0) return(octavesize);
|
||||
else return(12);
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the frequency according the note number
|
||||
*/
|
||||
REALTYPE Microtonal::getnotefreq(int note,int keyshift){
|
||||
// in this function will appears many times things like this:
|
||||
// var=(a+b*100)%b
|
||||
// I had written this way because if I use var=a%b gives unwanted results when a<0
|
||||
// This is the same with divisions.
|
||||
|
||||
if ((Pinvertupdown!=0)&&((Pmappingenabled==0)||(Penabled==0))) note=(int) Pinvertupdowncenter*2-note;
|
||||
|
||||
//compute global fine detune
|
||||
REALTYPE globalfinedetunerap=pow(2.0,(Pglobalfinedetune-64.0)/1200.0);//-64.0 .. 63.0 cents
|
||||
|
||||
if (Penabled==0) return(pow(2.0,(note-PAnote+keyshift)/12.0)*PAfreq*globalfinedetunerap);//12tET
|
||||
|
||||
int scaleshift=((int)Pscaleshift-64+(int) octavesize*100)%octavesize;
|
||||
|
||||
//compute the keyshift
|
||||
REALTYPE rap_keyshift=1.0;
|
||||
if (keyshift!=0){
|
||||
int kskey=(keyshift+(int)octavesize*100)%octavesize;
|
||||
int ksoct=(keyshift+(int)octavesize*100)/octavesize-100;
|
||||
rap_keyshift=(kskey==0) ? (1.0):(octave[kskey-1].tuning);
|
||||
rap_keyshift*=pow(octave[octavesize-1].tuning,ksoct);
|
||||
};
|
||||
|
||||
//if the mapping is enabled
|
||||
if (Pmappingenabled!=0){
|
||||
if ((note<Pfirstkey)||(note>Plastkey)) return (-1.0);
|
||||
//Compute how many mapped keys are from middle note to reference note
|
||||
//and find out the proportion between the freq. of middle note and "A" note
|
||||
int tmp=PAnote-Pmiddlenote,minus=0;
|
||||
if (tmp<0) { tmp=-tmp; minus=1; };
|
||||
int deltanote=0;
|
||||
for (int i=0;i<tmp;i++) if (Pmapping[i%Pmapsize]>=0) deltanote++;
|
||||
REALTYPE rap_anote_middlenote=(deltanote==0) ? (1.0) : (octave[(deltanote-1)%octavesize].tuning);
|
||||
if (deltanote!=0) rap_anote_middlenote*=pow(octave[octavesize-1].tuning,(deltanote-1)/octavesize);
|
||||
if (minus!=0) rap_anote_middlenote=1.0/rap_anote_middlenote;
|
||||
|
||||
//Convert from note (midi) to degree (note from the tunning)
|
||||
int degoct=(note-(int)Pmiddlenote+(int) Pmapsize*200)/(int)Pmapsize-200;
|
||||
int degkey=(note-Pmiddlenote+(int)Pmapsize*100)%Pmapsize;
|
||||
degkey=Pmapping[degkey];
|
||||
if (degkey<0) return(-1.0);//this key is not mapped
|
||||
|
||||
//invert the keyboard upside-down if it is asked for
|
||||
//TODO: do the right way by using Pinvertupdowncenter
|
||||
if (Pinvertupdown!=0){
|
||||
degkey=octavesize-degkey-1;
|
||||
degoct=-degoct;
|
||||
};
|
||||
//compute the frequency of the note
|
||||
degkey=degkey+scaleshift;
|
||||
degoct+=degkey/octavesize;
|
||||
degkey%=octavesize;
|
||||
|
||||
REALTYPE freq=(degkey==0) ? (1.0):octave[degkey-1].tuning;
|
||||
freq*=pow(octave[octavesize-1].tuning,degoct);
|
||||
freq*=PAfreq/rap_anote_middlenote;
|
||||
freq*=globalfinedetunerap;
|
||||
if (scaleshift!=0) freq/=octave[scaleshift-1].tuning;
|
||||
return(freq*rap_keyshift);
|
||||
} else {//if the mapping is disabled
|
||||
int nt=note-PAnote+scaleshift;
|
||||
int ntkey=(nt+(int)octavesize*100)%octavesize;
|
||||
int ntoct=(nt-ntkey)/octavesize;
|
||||
|
||||
REALTYPE oct=octave[octavesize-1].tuning;
|
||||
REALTYPE freq=octave[(ntkey+octavesize-1)%octavesize].tuning*pow(oct,ntoct)*PAfreq;
|
||||
if (ntkey==0) freq/=oct;
|
||||
if (scaleshift!=0) freq/=octave[scaleshift-1].tuning;
|
||||
// fprintf(stderr,"note=%d freq=%.3f cents=%d\n",note,freq,(int)floor(log(freq/PAfreq)/log(2.0)*1200.0+0.5));
|
||||
freq*=globalfinedetunerap;
|
||||
return(freq*rap_keyshift);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Convert a line to tunings; returns -1 if it ok
|
||||
*/
|
||||
int Microtonal::linetotunings(unsigned int nline,const char *line){
|
||||
int x1=-1,x2=-1,type=-1;
|
||||
REALTYPE x=-1.0,tmp,tuning=1.0;
|
||||
if (strstr(line,"/")==NULL){
|
||||
if (strstr(line,".")==NULL){// M case (M=M/1)
|
||||
sscanf(line,"%d",&x1);
|
||||
x2=1;
|
||||
type=2;//division
|
||||
} else {// float number case
|
||||
sscanf(line,"%f",&x);
|
||||
if (x<0.000001) return(1);
|
||||
type=1;//float type(cents)
|
||||
};
|
||||
} else {// M/N case
|
||||
sscanf(line,"%d/%d",&x1,&x2);
|
||||
if ((x1<0)||(x2<0)) return(1);
|
||||
if (x2==0) x2=1;
|
||||
type=2;//division
|
||||
};
|
||||
|
||||
if (x1<=0) x1=1;//not allow zero frequency sounds (consider 0 as 1)
|
||||
|
||||
//convert to float if the number are too big
|
||||
if ((type==2)&&((x1>(128*128*128-1))||(x2>(128*128*128-1)))){
|
||||
type=1;
|
||||
x=((REALTYPE) x1)/x2;
|
||||
};
|
||||
switch (type){
|
||||
case 1: x1=(int) floor(x);
|
||||
tmp=fmod(x,1.0);
|
||||
x2=(int) (floor (tmp*1e6));
|
||||
tuning=pow(2.0,x/1200.0);
|
||||
break;
|
||||
case 2: x=((REALTYPE)x1)/x2;
|
||||
tuning=x;
|
||||
break;
|
||||
};
|
||||
|
||||
tmpoctave[nline].tuning=tuning;
|
||||
tmpoctave[nline].type=type;
|
||||
tmpoctave[nline].x1=x1;
|
||||
tmpoctave[nline].x2=x2;
|
||||
|
||||
return(-1);//ok
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert the text to tunnings
|
||||
*/
|
||||
int Microtonal::texttotunings(const char *text){
|
||||
unsigned int i,k=0,nl=0;
|
||||
char *lin;
|
||||
lin=new char[MAX_LINE_SIZE+1];
|
||||
while (k<strlen(text)){
|
||||
for (i=0;i<MAX_LINE_SIZE;i++){
|
||||
lin[i]=text[k++];
|
||||
if (lin[i]<0x20) break;
|
||||
};
|
||||
lin[i]='\0';
|
||||
if (strlen(lin)==0) continue;
|
||||
int err=linetotunings(nl,lin);
|
||||
if (err!=-1) {
|
||||
delete [] lin;
|
||||
return(nl);//Parse error
|
||||
};
|
||||
nl++;
|
||||
};
|
||||
delete [] lin;
|
||||
if (nl>MAX_OCTAVE_SIZE) nl=MAX_OCTAVE_SIZE;
|
||||
if (nl==0) return(-2);//the input is empty
|
||||
octavesize=nl;
|
||||
for (i=0;i<octavesize;i++){
|
||||
octave[i].tuning=tmpoctave[i].tuning;
|
||||
octave[i].type=tmpoctave[i].type;
|
||||
octave[i].x1=tmpoctave[i].x1;
|
||||
octave[i].x2=tmpoctave[i].x2;
|
||||
};
|
||||
return(-1);//ok
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert the text to mapping
|
||||
*/
|
||||
void Microtonal::texttomapping(const char *text){
|
||||
unsigned int i,k=0;
|
||||
char *lin;
|
||||
lin=new char[MAX_LINE_SIZE+1];
|
||||
for (i=0;i<128;i++) Pmapping[i]=-1;
|
||||
int tx=0;
|
||||
while (k<strlen(text)){
|
||||
for (i=0;i<MAX_LINE_SIZE;i++){
|
||||
lin[i]=text[k++];
|
||||
if (lin[i]<0x20) break;
|
||||
};
|
||||
lin[i]='\0';
|
||||
if (strlen(lin)==0) continue;
|
||||
|
||||
int tmp=0;
|
||||
if (sscanf(lin,"%d",&tmp)==0) tmp=-1;
|
||||
if (tmp<-1) tmp=-1;
|
||||
Pmapping[tx]=tmp;
|
||||
|
||||
if ((tx++)>127) break;
|
||||
};
|
||||
delete [] lin;
|
||||
|
||||
if (tx==0) tx=1;
|
||||
Pmapsize=tx;
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert tunning to text line
|
||||
*/
|
||||
void Microtonal::tuningtoline(int n,char *line,int maxn){
|
||||
if ((n>octavesize) || (n>MAX_OCTAVE_SIZE)) {
|
||||
line[0]='\0';
|
||||
return;
|
||||
};
|
||||
if (octave[n].type==1) snprintf(line,maxn,"%d.%d",octave[n].x1,octave[n].x2);
|
||||
if (octave[n].type==2) snprintf(line,maxn,"%d/%d",octave[n].x1,octave[n].x2);
|
||||
};
|
||||
|
||||
|
||||
int Microtonal::loadline(FILE *file,char *line){
|
||||
do {
|
||||
if (fgets(line,500,file)==0) return(1);
|
||||
} while (line[0]=='!');
|
||||
return(0);
|
||||
};
|
||||
/*
|
||||
* Loads the tunnings from a scl file
|
||||
*/
|
||||
int Microtonal::loadscl(const char *filename){
|
||||
FILE *file=fopen(filename, "r");
|
||||
char tmp[500];
|
||||
fseek(file,0,SEEK_SET);
|
||||
//loads the short description
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
for (int i=0;i<500;i++) if (tmp[i]<32) tmp[i]=0;
|
||||
snprintf((char *) Pname,MICROTONAL_MAX_NAME_LEN,"%s",tmp);
|
||||
snprintf((char *) Pcomment,MICROTONAL_MAX_NAME_LEN,"%s",tmp);
|
||||
//loads the number of the notes
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
int nnotes=MAX_OCTAVE_SIZE;
|
||||
sscanf(&tmp[0],"%d",&nnotes);
|
||||
if (nnotes>MAX_OCTAVE_SIZE) return (2);
|
||||
//load the tunnings
|
||||
for (int nline=0;nline<nnotes;nline++){
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
linetotunings(nline,&tmp[0]);
|
||||
};
|
||||
fclose(file);
|
||||
|
||||
octavesize=nnotes;
|
||||
for (int i=0;i<octavesize;i++){
|
||||
octave[i].tuning=tmpoctave[i].tuning;
|
||||
octave[i].type=tmpoctave[i].type;
|
||||
octave[i].x1=tmpoctave[i].x1;
|
||||
octave[i].x2=tmpoctave[i].x2;
|
||||
};
|
||||
|
||||
return(0);
|
||||
};
|
||||
|
||||
/*
|
||||
* Loads the mapping from a kbm file
|
||||
*/
|
||||
int Microtonal::loadkbm(const char *filename){
|
||||
FILE *file=fopen(filename, "r");
|
||||
int x;
|
||||
char tmp[500];
|
||||
|
||||
fseek(file,0,SEEK_SET);
|
||||
//loads the mapsize
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
|
||||
if (x<1) x=0;if (x>127) x=127;//just in case...
|
||||
Pmapsize=x;
|
||||
//loads first MIDI note to retune
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
|
||||
if (x<1) x=0;if (x>127) x=127;//just in case...
|
||||
Pfirstkey=x;
|
||||
//loads last MIDI note to retune
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
|
||||
if (x<1) x=0;if (x>127) x=127;//just in case...
|
||||
Plastkey=x;
|
||||
//loads last the middle note where scale fro scale degree=0
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
|
||||
if (x<1) x=0;if (x>127) x=127;//just in case...
|
||||
Pmiddlenote=x;
|
||||
//loads the reference note
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
|
||||
if (x<1) x=0;if (x>127) x=127;//just in case...
|
||||
PAnote=x;
|
||||
//loads the reference freq.
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
REALTYPE tmpPAfreq=440.0;
|
||||
if (sscanf(&tmp[0],"%f",&tmpPAfreq)==0) return(2);
|
||||
PAfreq=tmpPAfreq;
|
||||
|
||||
//the scale degree(which is the octave) is not loaded, it is obtained by the tunnings with getoctavesize() method
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
|
||||
//load the mappings
|
||||
if (Pmapsize!=0){
|
||||
for (int nline=0;nline<Pmapsize;nline++){
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) x=-1;
|
||||
Pmapping[nline]=x;
|
||||
};
|
||||
Pmappingenabled=1;
|
||||
} else {
|
||||
Pmappingenabled=0;
|
||||
Pmapping[0]=0;
|
||||
Pmapsize=1;
|
||||
};
|
||||
fclose(file);
|
||||
|
||||
return(0);
|
||||
};
|
||||
|
||||
|
||||
|
||||
void Microtonal::add2XML(XMLwrapper *xml){
|
||||
xml->addparstr("name",(char *) Pname);
|
||||
xml->addparstr("comment",(char *) Pcomment);
|
||||
|
||||
xml->addparbool("invert_up_down",Pinvertupdown);
|
||||
xml->addparbool("invert_up_down_center",Pinvertupdowncenter);
|
||||
|
||||
xml->addparbool("enabled",Penabled);
|
||||
xml->addpar("global_fine_detune",Pglobalfinedetune);
|
||||
|
||||
xml->addpar("a_note",PAnote);
|
||||
xml->addparreal("a_freq",PAfreq);
|
||||
|
||||
if ((Penabled==0)&&(xml->minimal)) return;
|
||||
|
||||
xml->beginbranch("SCALE");
|
||||
xml->addpar("scale_shift",Pscaleshift);
|
||||
xml->addpar("first_key",Pfirstkey);
|
||||
xml->addpar("last_key",Plastkey);
|
||||
xml->addpar("middle_note",Pmiddlenote);
|
||||
|
||||
xml->beginbranch("OCTAVE");
|
||||
xml->addpar("octave_size",octavesize);
|
||||
for (int i=0;i<octavesize;i++){
|
||||
xml->beginbranch("DEGREE",i);
|
||||
if (octave[i].type==1){
|
||||
xml->addparreal("cents",octave[i].tuning);
|
||||
};
|
||||
if (octave[i].type==2){
|
||||
xml->addpar("numerator",octave[i].x1);
|
||||
xml->addpar("denominator",octave[i].x2);
|
||||
};
|
||||
xml->endbranch();
|
||||
};
|
||||
xml->endbranch();
|
||||
|
||||
xml->beginbranch("KEYBOARD_MAPPING");
|
||||
xml->addpar("map_size",Pmapsize);
|
||||
xml->addpar("mapping_enabled",Pmappingenabled);
|
||||
for (int i=0;i<Pmapsize;i++){
|
||||
xml->beginbranch("KEYMAP",i);
|
||||
xml->addpar("degree",Pmapping[i]);
|
||||
xml->endbranch();
|
||||
};
|
||||
xml->endbranch();
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
void Microtonal::getfromXML(XMLwrapper *xml){
|
||||
xml->getparstr("name",(char *) Pname,MICROTONAL_MAX_NAME_LEN);
|
||||
xml->getparstr("comment",(char *) Pcomment,MICROTONAL_MAX_NAME_LEN);
|
||||
|
||||
Pinvertupdown=xml->getparbool("invert_up_down",Pinvertupdown);
|
||||
Pinvertupdowncenter=xml->getparbool("invert_up_down_center",Pinvertupdowncenter);
|
||||
|
||||
Penabled=xml->getparbool("enabled",Penabled);
|
||||
Pglobalfinedetune=xml->getpar127("global_fine_detune",Pglobalfinedetune);
|
||||
|
||||
PAnote=xml->getpar127("a_note",PAnote);
|
||||
PAfreq=xml->getparreal("a_freq",PAfreq,1.0,10000.0);
|
||||
|
||||
if (xml->enterbranch("SCALE")){
|
||||
Pscaleshift=xml->getpar127("scale_shift",Pscaleshift);
|
||||
Pfirstkey=xml->getpar127("first_key",Pfirstkey);
|
||||
Plastkey=xml->getpar127("last_key",Plastkey);
|
||||
Pmiddlenote=xml->getpar127("middle_note",Pmiddlenote);
|
||||
|
||||
if (xml->enterbranch("OCTAVE")){
|
||||
octavesize=xml->getpar127("octave_size",octavesize);
|
||||
for (int i=0;i<octavesize;i++){
|
||||
if (xml->enterbranch("DEGREE",i)==0) continue;
|
||||
octave[i].x2=0;
|
||||
octave[i].tuning=xml->getparreal("cents",octave[i].tuning);
|
||||
octave[i].x1=xml->getpar127("numerator",octave[i].x1);
|
||||
octave[i].x2=xml->getpar127("denominator",octave[i].x2);
|
||||
|
||||
if (octave[i].x2!=0) octave[i].type=2;
|
||||
else octave[i].type=1;
|
||||
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
if (xml->enterbranch("KEYBOARD_MAPPING")){
|
||||
Pmapsize=xml->getpar127("map_size",Pmapsize);
|
||||
Pmappingenabled=xml->getpar127("mapping_enabled",Pmappingenabled);
|
||||
for (int i=0;i<Pmapsize;i++){
|
||||
if (xml->enterbranch("KEYMAP",i)==0) continue;
|
||||
Pmapping[i]=xml->getpar127("degree",Pmapping[i]);
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
int Microtonal::saveXML(char *filename){
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
|
||||
xml->beginbranch("MICROTONAL");
|
||||
add2XML(xml);
|
||||
xml->endbranch();
|
||||
|
||||
int result=xml->saveXMLfile(filename);
|
||||
delete (xml);
|
||||
return(result);
|
||||
};
|
||||
|
||||
int Microtonal::loadXML(char *filename){
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
if (xml->loadXMLfile(filename)<0) {
|
||||
delete(xml);
|
||||
return(-1);
|
||||
};
|
||||
|
||||
if (xml->enterbranch("MICROTONAL")==0) return(-10);
|
||||
getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
|
||||
delete(xml);
|
||||
return(0);
|
||||
};
|
||||
|
||||
|
||||
597
plugins/zynaddsubfx/src/Misc/Microtonal.cpp
Normal file
597
plugins/zynaddsubfx/src/Misc/Microtonal.cpp
Normal file
@@ -0,0 +1,597 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Microtonal.C - Tuning settings and microtonal capabilities
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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 <math.h>
|
||||
#include <string.h>
|
||||
#include "Microtonal.h"
|
||||
|
||||
#define MAX_LINE_SIZE 80
|
||||
|
||||
Microtonal::Microtonal()
|
||||
{
|
||||
Pname=new unsigned char[MICROTONAL_MAX_NAME_LEN];
|
||||
Pcomment=new unsigned char[MICROTONAL_MAX_NAME_LEN];
|
||||
defaults();
|
||||
};
|
||||
|
||||
void Microtonal::defaults()
|
||||
{
|
||||
Pinvertupdown=0;
|
||||
Pinvertupdowncenter=60;
|
||||
octavesize=12;
|
||||
Penabled=0;
|
||||
PAnote=69;
|
||||
PAfreq=440.0;
|
||||
Pscaleshift=64;
|
||||
|
||||
Pfirstkey=0;
|
||||
Plastkey=127;
|
||||
Pmiddlenote=60;
|
||||
Pmapsize=12;
|
||||
Pmappingenabled=0;
|
||||
|
||||
for (int i=0;i<128;i++) Pmapping[i]=i;
|
||||
|
||||
for (int i=0;i<MAX_OCTAVE_SIZE;i++) {
|
||||
octave[i].tuning=tmpoctave[i].tuning=pow(2,(i%octavesize+1)/12.0);
|
||||
octave[i].type=tmpoctave[i].type=1;
|
||||
octave[i].x1=tmpoctave[i].x1=(i%octavesize+1)*100;
|
||||
octave[i].x2=tmpoctave[i].x2=0;
|
||||
};
|
||||
octave[11].type=2;
|
||||
octave[11].x1=2;
|
||||
octave[11].x2=1;
|
||||
for (int i=0;i<MICROTONAL_MAX_NAME_LEN;i++) {
|
||||
Pname[i]='\0';
|
||||
Pcomment[i]='\0';
|
||||
};
|
||||
snprintf((char *) Pname,MICROTONAL_MAX_NAME_LEN,"12tET");
|
||||
snprintf((char *) Pcomment,MICROTONAL_MAX_NAME_LEN,"Equal Temperament 12 notes per octave");
|
||||
Pglobalfinedetune=64;
|
||||
};
|
||||
|
||||
Microtonal::~Microtonal()
|
||||
{
|
||||
delete [] Pname;
|
||||
delete [] Pcomment;
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the size of the octave
|
||||
*/
|
||||
unsigned char Microtonal::getoctavesize() const
|
||||
{
|
||||
if (Penabled!=0) return(octavesize);
|
||||
else return(12);
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the frequency according the note number
|
||||
*/
|
||||
REALTYPE Microtonal::getnotefreq(int note,int keyshift) const
|
||||
{
|
||||
// in this function will appears many times things like this:
|
||||
// var=(a+b*100)%b
|
||||
// I had written this way because if I use var=a%b gives unwanted results when a<0
|
||||
// This is the same with divisions.
|
||||
|
||||
if ((Pinvertupdown!=0)&&((Pmappingenabled==0)||(Penabled==0))) note=(int) Pinvertupdowncenter*2-note;
|
||||
|
||||
//compute global fine detune
|
||||
REALTYPE globalfinedetunerap=pow(2.0,(Pglobalfinedetune-64.0)/1200.0);//-64.0 .. 63.0 cents
|
||||
|
||||
if (Penabled==0) return(pow(2.0,(note-PAnote+keyshift)/12.0)*PAfreq*globalfinedetunerap);//12tET
|
||||
|
||||
int scaleshift=((int)Pscaleshift-64+(int) octavesize*100)%octavesize;
|
||||
|
||||
//compute the keyshift
|
||||
REALTYPE rap_keyshift=1.0;
|
||||
if (keyshift!=0) {
|
||||
int kskey=(keyshift+(int)octavesize*100)%octavesize;
|
||||
int ksoct=(keyshift+(int)octavesize*100)/octavesize-100;
|
||||
rap_keyshift=(kskey==0) ? (1.0):(octave[kskey-1].tuning);
|
||||
rap_keyshift*=pow(octave[octavesize-1].tuning,ksoct);
|
||||
};
|
||||
|
||||
//if the mapping is enabled
|
||||
if (Pmappingenabled!=0) {
|
||||
if ((note<Pfirstkey)||(note>Plastkey)) return (-1.0);
|
||||
//Compute how many mapped keys are from middle note to reference note
|
||||
//and find out the proportion between the freq. of middle note and "A" note
|
||||
int tmp=PAnote-Pmiddlenote,minus=0;
|
||||
if (tmp<0) {
|
||||
tmp=-tmp;
|
||||
minus=1;
|
||||
};
|
||||
int deltanote=0;
|
||||
for (int i=0;i<tmp;i++) if (Pmapping[i%Pmapsize]>=0) deltanote++;
|
||||
REALTYPE rap_anote_middlenote=(deltanote==0) ? (1.0) : (octave[(deltanote-1)%octavesize].tuning);
|
||||
if (deltanote!=0) rap_anote_middlenote*=pow(octave[octavesize-1].tuning,(deltanote-1)/octavesize);
|
||||
if (minus!=0) rap_anote_middlenote=1.0/rap_anote_middlenote;
|
||||
|
||||
//Convert from note (midi) to degree (note from the tunning)
|
||||
int degoct=(note-(int)Pmiddlenote+(int) Pmapsize*200)/(int)Pmapsize-200;
|
||||
int degkey=(note-Pmiddlenote+(int)Pmapsize*100)%Pmapsize;
|
||||
degkey=Pmapping[degkey];
|
||||
if (degkey<0) return(-1.0);//this key is not mapped
|
||||
|
||||
//invert the keyboard upside-down if it is asked for
|
||||
//TODO: do the right way by using Pinvertupdowncenter
|
||||
if (Pinvertupdown!=0) {
|
||||
degkey=octavesize-degkey-1;
|
||||
degoct=-degoct;
|
||||
};
|
||||
//compute the frequency of the note
|
||||
degkey=degkey+scaleshift;
|
||||
degoct+=degkey/octavesize;
|
||||
degkey%=octavesize;
|
||||
|
||||
REALTYPE freq=(degkey==0) ? (1.0):octave[degkey-1].tuning;
|
||||
freq*=pow(octave[octavesize-1].tuning,degoct);
|
||||
freq*=PAfreq/rap_anote_middlenote;
|
||||
freq*=globalfinedetunerap;
|
||||
if (scaleshift!=0) freq/=octave[scaleshift-1].tuning;
|
||||
return(freq*rap_keyshift);
|
||||
} else {//if the mapping is disabled
|
||||
int nt=note-PAnote+scaleshift;
|
||||
int ntkey=(nt+(int)octavesize*100)%octavesize;
|
||||
int ntoct=(nt-ntkey)/octavesize;
|
||||
|
||||
REALTYPE oct=octave[octavesize-1].tuning;
|
||||
REALTYPE freq=octave[(ntkey+octavesize-1)%octavesize].tuning*pow(oct,ntoct)*PAfreq;
|
||||
if (ntkey==0) freq/=oct;
|
||||
if (scaleshift!=0) freq/=octave[scaleshift-1].tuning;
|
||||
// fprintf(stderr,"note=%d freq=%.3f cents=%d\n",note,freq,(int)floor(log(freq/PAfreq)/log(2.0)*1200.0+0.5));
|
||||
freq*=globalfinedetunerap;
|
||||
return(freq*rap_keyshift);
|
||||
};
|
||||
};
|
||||
|
||||
bool Microtonal::operator==(const Microtonal µ) const
|
||||
{
|
||||
return(!(*this!=micro));
|
||||
}
|
||||
|
||||
bool Microtonal::operator!=(const Microtonal µ) const
|
||||
{
|
||||
|
||||
//A simple macro to test equality MiCRotonal EQuals (not the perfect
|
||||
//approach, but good enough)
|
||||
#define MCREQ( x ) if(x!=micro.x)return true;
|
||||
|
||||
//for floats
|
||||
#define FMCREQ( x ) if(!((x<micro.x+0.0001)&&(x>micro.x-0.0001)))return true;
|
||||
|
||||
MCREQ(Pinvertupdown);
|
||||
MCREQ(Pinvertupdowncenter);
|
||||
MCREQ(octavesize);
|
||||
MCREQ(Penabled);
|
||||
MCREQ(PAnote);
|
||||
FMCREQ(PAfreq);
|
||||
MCREQ(Pscaleshift);
|
||||
|
||||
MCREQ(Pfirstkey);
|
||||
MCREQ(Plastkey);
|
||||
MCREQ(Pmiddlenote);
|
||||
MCREQ(Pmapsize);
|
||||
MCREQ(Pmappingenabled);
|
||||
|
||||
for (int i=0;i<128;i++)
|
||||
MCREQ(Pmapping[i]);
|
||||
|
||||
for (int i=0;i<octavesize;i++) {
|
||||
FMCREQ(octave[i].tuning);
|
||||
MCREQ(octave[i].type);
|
||||
MCREQ(octave[i].x1);
|
||||
MCREQ(octave[i].x2);
|
||||
}
|
||||
if(strcmp((const char *)this->Pname,(const char *)micro.Pname))
|
||||
return true;
|
||||
if(strcmp((const char *)this->Pcomment,(const char *)micro.Pcomment))
|
||||
return true;
|
||||
MCREQ(Pglobalfinedetune);
|
||||
return false;
|
||||
|
||||
//undefine macros, as they are no longer needed
|
||||
#undef MCREQ
|
||||
#undef FMCREQ
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a line to tunings; returns -1 if it ok
|
||||
*/
|
||||
int Microtonal::linetotunings(unsigned int nline,const char *line)
|
||||
{
|
||||
int x1=-1,x2=-1,type=-1;
|
||||
REALTYPE x=-1.0,tmp,tuning=1.0;
|
||||
if (strstr(line,"/")==NULL) {
|
||||
if (strstr(line,".")==NULL) {// M case (M=M/1)
|
||||
sscanf(line,"%d",&x1);
|
||||
x2=1;
|
||||
type=2;//division
|
||||
} else {// float number case
|
||||
sscanf(line,"%f",&x);
|
||||
if (x<0.000001) return(1);
|
||||
type=1;//float type(cents)
|
||||
};
|
||||
} else {// M/N case
|
||||
sscanf(line,"%d/%d",&x1,&x2);
|
||||
if ((x1<0)||(x2<0)) return(1);
|
||||
if (x2==0) x2=1;
|
||||
type=2;//division
|
||||
};
|
||||
|
||||
if (x1<=0) x1=1;//not allow zero frequency sounds (consider 0 as 1)
|
||||
|
||||
//convert to float if the number are too big
|
||||
if ((type==2)&&((x1>(128*128*128-1))||(x2>(128*128*128-1)))) {
|
||||
type=1;
|
||||
x=((REALTYPE) x1)/x2;
|
||||
};
|
||||
switch (type) {
|
||||
case 1:
|
||||
x1=(int) floor(x);
|
||||
tmp=fmod(x,1.0);
|
||||
x2=(int) (floor (tmp*1e6));
|
||||
tuning=pow(2.0,x/1200.0);
|
||||
break;
|
||||
case 2:
|
||||
x=((REALTYPE)x1)/x2;
|
||||
tuning=x;
|
||||
break;
|
||||
};
|
||||
|
||||
tmpoctave[nline].tuning=tuning;
|
||||
tmpoctave[nline].type=type;
|
||||
tmpoctave[nline].x1=x1;
|
||||
tmpoctave[nline].x2=x2;
|
||||
|
||||
return(-1);//ok
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert the text to tunnings
|
||||
*/
|
||||
int Microtonal::texttotunings(const char *text)
|
||||
{
|
||||
unsigned int i,k=0,nl=0;
|
||||
char *lin;
|
||||
lin=new char[MAX_LINE_SIZE+1];
|
||||
while (k<strlen(text)) {
|
||||
for (i=0;i<MAX_LINE_SIZE;i++) {
|
||||
lin[i]=text[k++];
|
||||
if (lin[i]<0x20) break;
|
||||
};
|
||||
lin[i]='\0';
|
||||
if (strlen(lin)==0) continue;
|
||||
int err=linetotunings(nl,lin);
|
||||
if (err!=-1) {
|
||||
delete [] lin;
|
||||
return(nl);//Parse error
|
||||
};
|
||||
nl++;
|
||||
};
|
||||
delete [] lin;
|
||||
if (nl>MAX_OCTAVE_SIZE) nl=MAX_OCTAVE_SIZE;
|
||||
if (nl==0) return(-2);//the input is empty
|
||||
octavesize=nl;
|
||||
for (i=0;i<octavesize;i++) {
|
||||
octave[i].tuning=tmpoctave[i].tuning;
|
||||
octave[i].type=tmpoctave[i].type;
|
||||
octave[i].x1=tmpoctave[i].x1;
|
||||
octave[i].x2=tmpoctave[i].x2;
|
||||
};
|
||||
return(-1);//ok
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert the text to mapping
|
||||
*/
|
||||
void Microtonal::texttomapping(const char *text)
|
||||
{
|
||||
unsigned int i,k=0;
|
||||
char *lin;
|
||||
lin=new char[MAX_LINE_SIZE+1];
|
||||
for (i=0;i<128;i++) Pmapping[i]=-1;
|
||||
int tx=0;
|
||||
while (k<strlen(text)) {
|
||||
for (i=0;i<MAX_LINE_SIZE;i++) {
|
||||
lin[i]=text[k++];
|
||||
if (lin[i]<0x20) break;
|
||||
};
|
||||
lin[i]='\0';
|
||||
if (strlen(lin)==0) continue;
|
||||
|
||||
int tmp=0;
|
||||
if (sscanf(lin,"%d",&tmp)==0) tmp=-1;
|
||||
if (tmp<-1) tmp=-1;
|
||||
Pmapping[tx]=tmp;
|
||||
|
||||
if ((tx++)>127) break;
|
||||
};
|
||||
delete [] lin;
|
||||
|
||||
if (tx==0) tx=1;
|
||||
Pmapsize=tx;
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert tunning to text line
|
||||
*/
|
||||
void Microtonal::tuningtoline(int n,char *line,int maxn)
|
||||
{
|
||||
if ((n>octavesize) || (n>MAX_OCTAVE_SIZE)) {
|
||||
line[0]='\0';
|
||||
return;
|
||||
};
|
||||
if (octave[n].type==1) snprintf(line,maxn,"%d.%d",octave[n].x1,octave[n].x2);
|
||||
if (octave[n].type==2) snprintf(line,maxn,"%d/%d",octave[n].x1,octave[n].x2);
|
||||
};
|
||||
|
||||
|
||||
int Microtonal::loadline(FILE *file,char *line)
|
||||
{
|
||||
do {
|
||||
if (fgets(line,500,file)==0) return(1);
|
||||
} while (line[0]=='!');
|
||||
return(0);
|
||||
};
|
||||
/*
|
||||
* Loads the tunnings from a scl file
|
||||
*/
|
||||
int Microtonal::loadscl(const char *filename)
|
||||
{
|
||||
FILE *file=fopen(filename, "r");
|
||||
char tmp[500];
|
||||
fseek(file,0,SEEK_SET);
|
||||
//loads the short description
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
for (int i=0;i<500;i++) if (tmp[i]<32) tmp[i]=0;
|
||||
snprintf((char *) Pname,MICROTONAL_MAX_NAME_LEN,"%s",tmp);
|
||||
snprintf((char *) Pcomment,MICROTONAL_MAX_NAME_LEN,"%s",tmp);
|
||||
//loads the number of the notes
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
int nnotes=MAX_OCTAVE_SIZE;
|
||||
sscanf(&tmp[0],"%d",&nnotes);
|
||||
if (nnotes>MAX_OCTAVE_SIZE) return (2);
|
||||
//load the tunnings
|
||||
for (int nline=0;nline<nnotes;nline++) {
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
linetotunings(nline,&tmp[0]);
|
||||
};
|
||||
fclose(file);
|
||||
|
||||
octavesize=nnotes;
|
||||
for (int i=0;i<octavesize;i++) {
|
||||
octave[i].tuning=tmpoctave[i].tuning;
|
||||
octave[i].type=tmpoctave[i].type;
|
||||
octave[i].x1=tmpoctave[i].x1;
|
||||
octave[i].x2=tmpoctave[i].x2;
|
||||
};
|
||||
|
||||
return(0);
|
||||
};
|
||||
|
||||
/*
|
||||
* Loads the mapping from a kbm file
|
||||
*/
|
||||
int Microtonal::loadkbm(const char *filename)
|
||||
{
|
||||
FILE *file=fopen(filename, "r");
|
||||
int x;
|
||||
char tmp[500];
|
||||
|
||||
fseek(file,0,SEEK_SET);
|
||||
//loads the mapsize
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
|
||||
if (x<1) x=0;
|
||||
if (x>127) x=127;//just in case...
|
||||
Pmapsize=x;
|
||||
//loads first MIDI note to retune
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
|
||||
if (x<1) x=0;
|
||||
if (x>127) x=127;//just in case...
|
||||
Pfirstkey=x;
|
||||
//loads last MIDI note to retune
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
|
||||
if (x<1) x=0;
|
||||
if (x>127) x=127;//just in case...
|
||||
Plastkey=x;
|
||||
//loads last the middle note where scale fro scale degree=0
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
|
||||
if (x<1) x=0;
|
||||
if (x>127) x=127;//just in case...
|
||||
Pmiddlenote=x;
|
||||
//loads the reference note
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) return(2);
|
||||
if (x<1) x=0;
|
||||
if (x>127) x=127;//just in case...
|
||||
PAnote=x;
|
||||
//loads the reference freq.
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
REALTYPE tmpPAfreq=440.0;
|
||||
if (sscanf(&tmp[0],"%f",&tmpPAfreq)==0) return(2);
|
||||
PAfreq=tmpPAfreq;
|
||||
|
||||
//the scale degree(which is the octave) is not loaded, it is obtained by the tunnings with getoctavesize() method
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
|
||||
//load the mappings
|
||||
if (Pmapsize!=0) {
|
||||
for (int nline=0;nline<Pmapsize;nline++) {
|
||||
if (loadline(file,&tmp[0])!=0) return(2);
|
||||
if (sscanf(&tmp[0],"%d",&x)==0) x=-1;
|
||||
Pmapping[nline]=x;
|
||||
};
|
||||
Pmappingenabled=1;
|
||||
} else {
|
||||
Pmappingenabled=0;
|
||||
Pmapping[0]=0;
|
||||
Pmapsize=1;
|
||||
};
|
||||
fclose(file);
|
||||
|
||||
return(0);
|
||||
};
|
||||
|
||||
|
||||
|
||||
void Microtonal::add2XML(XMLwrapper *xml)const
|
||||
{
|
||||
xml->addparstr("name",(char *) Pname);
|
||||
xml->addparstr("comment",(char *) Pcomment);
|
||||
|
||||
xml->addparbool("invert_up_down",Pinvertupdown);
|
||||
xml->addpar("invert_up_down_center",Pinvertupdowncenter);
|
||||
|
||||
xml->addparbool("enabled",Penabled);
|
||||
xml->addpar("global_fine_detune",Pglobalfinedetune);
|
||||
|
||||
xml->addpar("a_note",PAnote);
|
||||
xml->addparreal("a_freq",PAfreq);
|
||||
|
||||
if ((Penabled==0)&&(xml->minimal)) return;
|
||||
|
||||
xml->beginbranch("SCALE");
|
||||
xml->addpar("scale_shift",Pscaleshift);
|
||||
xml->addpar("first_key",Pfirstkey);
|
||||
xml->addpar("last_key",Plastkey);
|
||||
xml->addpar("middle_note",Pmiddlenote);
|
||||
|
||||
xml->beginbranch("OCTAVE");
|
||||
xml->addpar("octave_size",octavesize);
|
||||
for (int i=0;i<octavesize;i++) {
|
||||
xml->beginbranch("DEGREE",i);
|
||||
if (octave[i].type==1) {
|
||||
xml->addparreal("cents",octave[i].tuning);
|
||||
};
|
||||
if (octave[i].type==2) {
|
||||
xml->addpar("numerator",octave[i].x1);
|
||||
xml->addpar("denominator",octave[i].x2);
|
||||
};
|
||||
xml->endbranch();
|
||||
};
|
||||
xml->endbranch();
|
||||
|
||||
xml->beginbranch("KEYBOARD_MAPPING");
|
||||
xml->addpar("map_size",Pmapsize);
|
||||
xml->addpar("mapping_enabled",Pmappingenabled);
|
||||
for (int i=0;i<Pmapsize;i++) {
|
||||
xml->beginbranch("KEYMAP",i);
|
||||
xml->addpar("degree",Pmapping[i]);
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
xml->endbranch();
|
||||
xml->endbranch();
|
||||
};
|
||||
|
||||
void Microtonal::getfromXML(XMLwrapper *xml)
|
||||
{
|
||||
xml->getparstr("name",(char *) Pname,MICROTONAL_MAX_NAME_LEN);
|
||||
xml->getparstr("comment",(char *) Pcomment,MICROTONAL_MAX_NAME_LEN);
|
||||
|
||||
Pinvertupdown=xml->getparbool("invert_up_down",Pinvertupdown);
|
||||
Pinvertupdowncenter=xml->getpar127("invert_up_down_center",Pinvertupdowncenter);
|
||||
|
||||
Penabled=xml->getparbool("enabled",Penabled);
|
||||
Pglobalfinedetune=xml->getpar127("global_fine_detune",Pglobalfinedetune);
|
||||
|
||||
PAnote=xml->getpar127("a_note",PAnote);
|
||||
PAfreq=xml->getparreal("a_freq",PAfreq,1.0,10000.0);
|
||||
|
||||
if (xml->enterbranch("SCALE")) {
|
||||
Pscaleshift=xml->getpar127("scale_shift",Pscaleshift);
|
||||
Pfirstkey=xml->getpar127("first_key",Pfirstkey);
|
||||
Plastkey=xml->getpar127("last_key",Plastkey);
|
||||
Pmiddlenote=xml->getpar127("middle_note",Pmiddlenote);
|
||||
|
||||
if (xml->enterbranch("OCTAVE")) {
|
||||
octavesize=xml->getpar127("octave_size",octavesize);
|
||||
for (int i=0;i<octavesize;i++) {
|
||||
if (xml->enterbranch("DEGREE",i)==0) continue;
|
||||
octave[i].x2=0;
|
||||
octave[i].tuning=xml->getparreal("cents",octave[i].tuning);
|
||||
octave[i].x1=xml->getpar127("numerator",octave[i].x1);
|
||||
octave[i].x2=xml->getpar127("denominator",octave[i].x2);
|
||||
|
||||
if (octave[i].x2!=0) octave[i].type=2;
|
||||
else octave[i].type=1;
|
||||
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
|
||||
if (xml->enterbranch("KEYBOARD_MAPPING")) {
|
||||
Pmapsize=xml->getpar127("map_size",Pmapsize);
|
||||
Pmappingenabled=xml->getpar127("mapping_enabled",Pmappingenabled);
|
||||
for (int i=0;i<Pmapsize;i++) {
|
||||
if (xml->enterbranch("KEYMAP",i)==0) continue;
|
||||
Pmapping[i]=xml->getpar127("degree",Pmapping[i]);
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
xml->exitbranch();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
int Microtonal::saveXML(const char *filename)const
|
||||
{
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
|
||||
xml->beginbranch("MICROTONAL");
|
||||
add2XML(xml);
|
||||
xml->endbranch();
|
||||
|
||||
int result=xml->saveXMLfile(filename);
|
||||
delete (xml);
|
||||
return(result);
|
||||
};
|
||||
|
||||
int Microtonal::loadXML(const char *filename)
|
||||
{
|
||||
XMLwrapper *xml=new XMLwrapper();
|
||||
if (xml->loadXMLfile(filename)<0) {
|
||||
delete(xml);
|
||||
return(-1);
|
||||
};
|
||||
|
||||
if (xml->enterbranch("MICROTONAL")==0) return(-10);
|
||||
getfromXML(xml);
|
||||
xml->exitbranch();
|
||||
|
||||
delete(xml);
|
||||
return(0);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Microtonal.h - Tuning settings and microtonal capabilities
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -31,81 +31,107 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class Microtonal{
|
||||
public:
|
||||
Microtonal();
|
||||
~Microtonal();
|
||||
void defaults();
|
||||
REALTYPE getnotefreq(int note,int keyshift);
|
||||
|
||||
|
||||
//Parameters
|
||||
//if the keys are inversed (the pitch is lower to keys from the right direction)
|
||||
unsigned char Pinvertupdown;
|
||||
/**Tuning settings and microtonal capabilities*/
|
||||
class Microtonal
|
||||
{
|
||||
public:
|
||||
/**Constructor*/
|
||||
Microtonal();
|
||||
/**Destructor*/
|
||||
~Microtonal();
|
||||
void defaults();
|
||||
/**Calculates the frequency for a given note
|
||||
*/
|
||||
REALTYPE getnotefreq(int note,int keyshift) const;
|
||||
|
||||
//the central key of the inversion
|
||||
unsigned char Pinvertupdowncenter;
|
||||
|
||||
//0 for 12 key temperate scale, 1 for microtonal
|
||||
unsigned char Penabled;
|
||||
//Parameters
|
||||
/**if the keys are inversed (the pitch is lower to keys from the right direction)*/
|
||||
unsigned char Pinvertupdown;
|
||||
|
||||
//the note of "A" key
|
||||
unsigned char PAnote;
|
||||
/**the central key of the inversion*/
|
||||
unsigned char Pinvertupdowncenter;
|
||||
|
||||
//the frequency of the "A" note
|
||||
REALTYPE PAfreq;
|
||||
|
||||
//if the scale is "tuned" to a note, you can tune to other note
|
||||
unsigned char Pscaleshift;
|
||||
/**0 for 12 key temperate scale, 1 for microtonal*/
|
||||
unsigned char Penabled;
|
||||
|
||||
//first and last key (to retune)
|
||||
unsigned char Pfirstkey;
|
||||
unsigned char Plastkey;
|
||||
|
||||
//The middle note where scale degree 0 is mapped to
|
||||
unsigned char Pmiddlenote;
|
||||
|
||||
//Map size
|
||||
unsigned char Pmapsize;
|
||||
/**the note of "A" key*/
|
||||
unsigned char PAnote;
|
||||
|
||||
//Mapping ON/OFF
|
||||
unsigned char Pmappingenabled;
|
||||
//Mapping (keys)
|
||||
short int Pmapping[128];
|
||||
|
||||
unsigned char Pglobalfinedetune;
|
||||
|
||||
// Functions
|
||||
unsigned char getoctavesize();
|
||||
void tuningtoline(int n,char *line,int maxn);
|
||||
int loadscl(const char *filename);//load the tunnings from a .scl file
|
||||
int loadkbm(const char *filename);//load the mapping from .kbm file
|
||||
int texttotunings(const char *text);
|
||||
void texttomapping(const char *text);
|
||||
unsigned char *Pname;
|
||||
unsigned char *Pcomment;
|
||||
/**the frequency of the "A" note*/
|
||||
REALTYPE PAfreq;
|
||||
|
||||
void add2XML(XMLwrapper *xml);
|
||||
void getfromXML(XMLwrapper *xml);
|
||||
int saveXML(char *filename);
|
||||
int loadXML(char *filename);
|
||||
/**if the scale is "tuned" to a note, you can tune to other note*/
|
||||
unsigned char Pscaleshift;
|
||||
|
||||
private:
|
||||
int linetotunings(unsigned int nline,const char *line);
|
||||
int loadline(FILE *file,char *line);//loads a line from the text file, while ignoring the lines beggining with "!"
|
||||
unsigned char octavesize;
|
||||
struct {
|
||||
unsigned char type;//1 for cents or 2 for division
|
||||
//first and last key (to retune)
|
||||
unsigned char Pfirstkey;
|
||||
unsigned char Plastkey;
|
||||
|
||||
/**The middle note where scale degree 0 is mapped to*/
|
||||
unsigned char Pmiddlenote;
|
||||
|
||||
/**Map size*/
|
||||
unsigned char Pmapsize;
|
||||
|
||||
/**Mapping ON/OFF*/
|
||||
unsigned char Pmappingenabled;
|
||||
/**Mapping (keys)*/
|
||||
short int Pmapping[128];
|
||||
|
||||
/**Fine detune to be applied to all notes*/
|
||||
unsigned char Pglobalfinedetune;
|
||||
|
||||
// Functions
|
||||
/** Return the current octave size*/
|
||||
unsigned char getoctavesize() const;
|
||||
/**Convert tunning to string*/
|
||||
void tuningtoline(int n,char *line,int maxn);
|
||||
/**load the tunnings from a .scl file*/
|
||||
int loadscl(const char *filename);
|
||||
/**load the mapping from .kbm file*/
|
||||
int loadkbm(const char *filename);
|
||||
/**Load text into the internal tunings
|
||||
*
|
||||
*\todo better description*/
|
||||
int texttotunings(const char *text);
|
||||
/**Load text into the internal mappings
|
||||
*
|
||||
*\todo better description*/
|
||||
void texttomapping(const char *text);
|
||||
|
||||
/**Name of Microtonal tuning*/
|
||||
unsigned char *Pname;
|
||||
/**Comment about the tuning*/
|
||||
unsigned char *Pcomment;
|
||||
|
||||
void add2XML(XMLwrapper *xml)const;
|
||||
void getfromXML(XMLwrapper *xml);
|
||||
int saveXML(const char *filename)const;
|
||||
int loadXML(const char *filename);
|
||||
|
||||
//simple operators primarily for debug
|
||||
bool operator==(const Microtonal µ) const;
|
||||
bool operator!=(const Microtonal µ) const;
|
||||
|
||||
private:
|
||||
int linetotunings(unsigned int nline,const char *line);
|
||||
int loadline(FILE *file,char *line);//loads a line from the text file, while ignoring the lines beggining with "!"
|
||||
unsigned char octavesize;
|
||||
struct {
|
||||
unsigned char type;//1 for cents or 2 for division
|
||||
|
||||
// the real tuning (eg. +1.05946 for one halftone)
|
||||
// or 2.0 for one octave
|
||||
REALTYPE tuning;
|
||||
|
||||
//the real tunning is x1/x2
|
||||
unsigned int x1,x2;
|
||||
|
||||
} octave[MAX_OCTAVE_SIZE],tmpoctave[MAX_OCTAVE_SIZE];
|
||||
|
||||
// the real tuning (eg. +1.05946 for one halftone)
|
||||
// or 2.0 for one octave
|
||||
REALTYPE tuning;
|
||||
|
||||
//the real tunning is x1/x2
|
||||
unsigned int x1,x2;
|
||||
|
||||
} octave[MAX_OCTAVE_SIZE],tmpoctave[MAX_OCTAVE_SIZE];
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1138
plugins/zynaddsubfx/src/Misc/Part.cpp
Normal file
1138
plugins/zynaddsubfx/src/Misc/Part.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Part.h - Part implementation
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -40,140 +40,147 @@
|
||||
|
||||
#include <list> // For the monomemnotes list.
|
||||
|
||||
class Part{
|
||||
/** Part implementation*/
|
||||
class Part
|
||||
{
|
||||
|
||||
public:
|
||||
Part(Microtonal *microtonal_,FFTwrapper *fft_,pthread_mutex_t *mutex_);
|
||||
~Part();
|
||||
public:
|
||||
/**Constructor
|
||||
* @param microtonal_ Pointer to the microtonal object
|
||||
* @param fft_ Pointer to the FFTwrapper
|
||||
* @param mutex_ Pointer to the master pthread_mutex_t*/
|
||||
Part(Microtonal *microtonal_,FFTwrapper *fft_,pthread_mutex_t *mutex_);
|
||||
/**Destructor*/
|
||||
~Part();
|
||||
|
||||
/* Midi commands implemented */
|
||||
void NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift);
|
||||
void NoteOff(unsigned char note);
|
||||
void AllNotesOff();//panic
|
||||
void SetController(unsigned int type,int par);
|
||||
void RelaseSustainedKeys();//this is called when the sustain pedal is relased
|
||||
void RelaseAllKeys();//this is called on AllNotesOff controller
|
||||
// Midi commands implemented
|
||||
void NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift);
|
||||
void NoteOff(unsigned char note);
|
||||
void AllNotesOff();//panic
|
||||
void SetController(unsigned int type,int par);
|
||||
void RelaseSustainedKeys();//this is called when the sustain pedal is relased
|
||||
void RelaseAllKeys();//this is called on AllNotesOff controller
|
||||
|
||||
/* The synthesizer part output */
|
||||
void ComputePartSmps();//Part output
|
||||
|
||||
//instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank)
|
||||
/* The synthesizer part output */
|
||||
void ComputePartSmps();//Part output
|
||||
|
||||
//instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank)
|
||||
|
||||
|
||||
//saves the instrument settings to a XML file
|
||||
//returns 0 for ok or <0 if there is an error
|
||||
int saveXML(char *filename);
|
||||
int loadXMLinstrument(const char *filename);
|
||||
//saves the instrument settings to a XML file
|
||||
//returns 0 for ok or <0 if there is an error
|
||||
int saveXML(char *filename);
|
||||
int loadXMLinstrument(const char *filename);
|
||||
|
||||
void add2XML(XMLwrapper *xml);
|
||||
void add2XMLinstrument(XMLwrapper *xml);
|
||||
|
||||
void defaults();
|
||||
void defaultsinstrument();
|
||||
|
||||
void applyparameters();
|
||||
|
||||
void getfromXML(XMLwrapper *xml);
|
||||
void getfromXMLinstrument(XMLwrapper *xml);
|
||||
void add2XML(XMLwrapper *xml);
|
||||
void add2XMLinstrument(XMLwrapper *xml);
|
||||
|
||||
void cleanup();
|
||||
void defaults();
|
||||
void defaultsinstrument();
|
||||
|
||||
void applyparameters();
|
||||
|
||||
void getfromXML(XMLwrapper *xml);
|
||||
void getfromXMLinstrument(XMLwrapper *xml);
|
||||
|
||||
void cleanup();
|
||||
|
||||
// ADnoteParameters *ADPartParameters;
|
||||
// SUBnoteParameters *SUBPartParameters;
|
||||
|
||||
//the part's kit
|
||||
struct {
|
||||
//the part's kit
|
||||
struct {
|
||||
unsigned char Penabled,Pmuted,Pminkey,Pmaxkey;
|
||||
unsigned char *Pname;
|
||||
unsigned char Padenabled,Psubenabled,Ppadenabled;
|
||||
unsigned char Psendtoparteffect;
|
||||
unsigned char *Pname;
|
||||
unsigned char Padenabled,Psubenabled,Ppadenabled;
|
||||
unsigned char Psendtoparteffect;
|
||||
ADnoteParameters *adpars;
|
||||
SUBnoteParameters *subpars;
|
||||
PADnoteParameters *padpars;
|
||||
} kit[NUM_KIT_ITEMS];
|
||||
} kit[NUM_KIT_ITEMS];
|
||||
|
||||
|
||||
//Part parameters
|
||||
void setkeylimit(unsigned char Pkeylimit);
|
||||
void setkititemstatus(int kititem,int Penabled_);
|
||||
|
||||
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
|
||||
unsigned char Pmaxkey;//the maximum key that the part receives noteon messages
|
||||
void setPvolume(char Pvolume);
|
||||
unsigned char Pkeyshift;//Part keyshift
|
||||
unsigned char Prcvchn;//from what midi channel it receive commnads
|
||||
unsigned char Ppanning;//part panning
|
||||
void setPpanning(char Ppanning);
|
||||
unsigned char Pvelsns;//velocity sensing (amplitude velocity scale)
|
||||
unsigned char Pveloffs;//velocity offset
|
||||
unsigned char Pnoteon;//if the part receives NoteOn messages
|
||||
unsigned char Pkitmode;//if the kitmode is enabled
|
||||
unsigned char Pdrummode;//if all keys are mapped and the system is 12tET (used for drums)
|
||||
//Part parameters
|
||||
void setkeylimit(unsigned char Pkeylimit);
|
||||
void setkititemstatus(int kititem,int Penabled_);
|
||||
|
||||
unsigned char Ppolymode;//Part mode - 0=monophonic , 1=polyphonic
|
||||
unsigned char Plegatomode;// 0=normal, 1=legato
|
||||
unsigned char Pkeylimit;//how many keys are alowed to be played same time (0=off), the older will be relased
|
||||
|
||||
unsigned char *Pname; //name of the instrument
|
||||
struct{//instrument additional information
|
||||
unsigned char Ptype;
|
||||
unsigned char Pauthor[MAX_INFO_TEXT_SIZE+1];
|
||||
unsigned char Pcomments[MAX_INFO_TEXT_SIZE+1];
|
||||
} info;
|
||||
|
||||
|
||||
REALTYPE *partoutl;//Left channel output of the part
|
||||
REALTYPE *partoutr;//Right channel output of the part
|
||||
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*/
|
||||
unsigned char Pmaxkey;//the maximum key that the part receives noteon messages
|
||||
void setPvolume(char Pvolume);
|
||||
unsigned char Pkeyshift;//Part keyshift
|
||||
unsigned char Prcvchn;//from what midi channel it receive commnads
|
||||
unsigned char Ppanning;//part panning
|
||||
void setPpanning(char Ppanning);
|
||||
unsigned char Pvelsns;//velocity sensing (amplitude velocity scale)
|
||||
unsigned char Pveloffs;//velocity offset
|
||||
unsigned char Pnoteon;//if the part receives NoteOn messages
|
||||
unsigned char Pkitmode;//if the kitmode is enabled
|
||||
unsigned char Pdrummode;//if all keys are mapped and the system is 12tET (used for drums)
|
||||
|
||||
REALTYPE *partfxinputl[NUM_PART_EFX+1],*partfxinputr[NUM_PART_EFX+1];//Left and right signal that pass thru part effects; partfxinput l/r [NUM_PART_EFX] is for "no effect" buffer
|
||||
unsigned char Ppolymode;//Part mode - 0=monophonic , 1=polyphonic
|
||||
unsigned char Plegatomode;// 0=normal, 1=legato
|
||||
unsigned char Pkeylimit;//how many keys are alowed to be played same time (0=off), the older will be relased
|
||||
|
||||
enum NoteStatus{KEY_OFF,KEY_PLAYING,KEY_RELASED_AND_SUSTAINED,KEY_RELASED};
|
||||
unsigned char *Pname; //name of the instrument
|
||||
struct {//instrument additional information
|
||||
unsigned char Ptype;
|
||||
unsigned char Pauthor[MAX_INFO_TEXT_SIZE+1];
|
||||
unsigned char Pcomments[MAX_INFO_TEXT_SIZE+1];
|
||||
} info;
|
||||
|
||||
REALTYPE volume,oldvolumel,oldvolumer;//this is applied by Master
|
||||
REALTYPE panning;//this is applied by Master, too
|
||||
|
||||
Controller ctl;//Part controllers
|
||||
|
||||
EffectMgr *partefx[NUM_PART_EFX];//insertion part effects (they are part of the instrument)
|
||||
unsigned char Pefxroute[NUM_PART_EFX];//how the effect's output is routed(to next effect/to out)
|
||||
bool Pefxbypass[NUM_PART_EFX+1];//if the effects are bypassed
|
||||
|
||||
REALTYPE *partoutl;//Left channel output of the part
|
||||
REALTYPE *partoutr;//Right channel output of the part
|
||||
|
||||
pthread_mutex_t *mutex;
|
||||
|
||||
int lastnote;
|
||||
|
||||
private:
|
||||
void KillNotePos(int pos);
|
||||
void RelaseNotePos(int pos);
|
||||
void MonoMemRenote(); // MonoMem stuff.
|
||||
REALTYPE *partfxinputl[NUM_PART_EFX+1],*partfxinputr[NUM_PART_EFX+1];//Left and right signal that pass thru part effects; partfxinput l/r [NUM_PART_EFX] is for "no effect" buffer
|
||||
|
||||
int killallnotes;//is set to 1 if I want to kill all notes
|
||||
|
||||
struct PartNotes{
|
||||
enum NoteStatus {KEY_OFF,KEY_PLAYING,KEY_RELASED_AND_SUSTAINED,KEY_RELASED};
|
||||
|
||||
REALTYPE volume,oldvolumel,oldvolumer;//this is applied by Master
|
||||
REALTYPE panning;//this is applied by Master, too
|
||||
|
||||
Controller ctl;//Part controllers
|
||||
|
||||
EffectMgr *partefx[NUM_PART_EFX];//insertion part effects (they are part of the instrument)
|
||||
unsigned char Pefxroute[NUM_PART_EFX];//how the effect's output is routed(to next effect/to out)
|
||||
bool Pefxbypass[NUM_PART_EFX];//if the effects are bypassed
|
||||
|
||||
|
||||
pthread_mutex_t *mutex;
|
||||
|
||||
int lastnote;
|
||||
|
||||
private:
|
||||
void KillNotePos(int pos);
|
||||
void RelaseNotePos(int pos);
|
||||
void MonoMemRenote(); // MonoMem stuff.
|
||||
|
||||
int killallnotes;//is set to 1 if I want to kill all notes
|
||||
|
||||
struct PartNotes {
|
||||
NoteStatus status;
|
||||
int note;//if there is no note playing, the "note"=-1
|
||||
int itemsplaying;
|
||||
struct {
|
||||
ADnote *adnote;
|
||||
SUBnote *subnote;
|
||||
PADnote *padnote;
|
||||
int sendtoparteffect;
|
||||
} kititem[NUM_KIT_ITEMS];
|
||||
int time;
|
||||
};
|
||||
int itemsplaying;
|
||||
struct {
|
||||
ADnote *adnote;
|
||||
SUBnote *subnote;
|
||||
PADnote *padnote;
|
||||
int sendtoparteffect;
|
||||
} kititem[NUM_KIT_ITEMS];
|
||||
int time;
|
||||
};
|
||||
|
||||
int lastpos, lastposb; // To keep track of previously used pos and posb.
|
||||
bool lastlegatomodevalid; // To keep track of previous legatomodevalid.
|
||||
int lastpos, lastposb; // To keep track of previously used pos and posb.
|
||||
bool lastlegatomodevalid; // To keep track of previous legatomodevalid.
|
||||
|
||||
// MonoMem stuff
|
||||
std::list<unsigned char> monomemnotes; // A list to remember held notes.
|
||||
struct {
|
||||
unsigned char velocity;
|
||||
int mkeyshift;// I'm not sure masterkeyshift should be remembered.
|
||||
} monomem[256]; /* 256 is to cover all possible note values.
|
||||
// MonoMem stuff
|
||||
std::list<unsigned char> monomemnotes; // A list to remember held notes.
|
||||
struct {
|
||||
unsigned char velocity;
|
||||
int mkeyshift;// I'm not sure masterkeyshift should be remembered.
|
||||
} monomem[256]; /* 256 is to cover all possible note values.
|
||||
monomem[] is used in conjunction with the list to
|
||||
store the velocity and masterkeyshift values of a
|
||||
given note (the list only store note values).
|
||||
@@ -181,14 +188,14 @@ class Part{
|
||||
velocity value of the note 'note'.
|
||||
*/
|
||||
|
||||
PartNotes partnote[POLIPHONY];
|
||||
|
||||
REALTYPE *tmpoutl;//used to get the note
|
||||
REALTYPE *tmpoutr;
|
||||
|
||||
REALTYPE oldfreq;//this is used for portamento
|
||||
Microtonal *microtonal;
|
||||
FFTwrapper *fft;
|
||||
PartNotes partnote[POLIPHONY];
|
||||
|
||||
REALTYPE *tmpoutl;//used to get the note
|
||||
REALTYPE *tmpoutr;
|
||||
|
||||
REALTYPE oldfreq;//this is used for portamento
|
||||
Microtonal *microtonal;
|
||||
FFTwrapper *fft;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
37
plugins/zynaddsubfx/src/Misc/Stereo.cpp
Normal file
37
plugins/zynaddsubfx/src/Misc/Stereo.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Stereo.C - Object for storing a pair of objects
|
||||
Copyright (C) 2009-2009 Mark McCurry
|
||||
Author: 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
|
||||
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 or later) 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
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
Stereo<T>::Stereo(const T &left, const T &right)
|
||||
:leftChannel(left),rightChannel(right)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
Stereo<T>::Stereo(const T &val)
|
||||
:leftChannel(val),rightChannel(val)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
void Stereo<T>::operator=(const Stereo<T> & nstr)
|
||||
{
|
||||
leftChannel=nstr.leftChannel;
|
||||
rightChannel=nstr.rightChannel;
|
||||
}
|
||||
67
plugins/zynaddsubfx/src/Misc/Stereo.h
Normal file
67
plugins/zynaddsubfx/src/Misc/Stereo.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
Stereo.h - Object for storing a pair of objects
|
||||
Copyright (C) 2009-2009 Mark McCurry
|
||||
Author: 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
|
||||
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 or later) 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 STEREO_H
|
||||
#define STEREO_H
|
||||
|
||||
template <class T>
|
||||
class Stereo
|
||||
{
|
||||
public:
|
||||
Stereo(const T &left,const T &right);
|
||||
|
||||
/**Initializes Stereo with left and right set to val
|
||||
* @param val the value for both channels*/
|
||||
Stereo(const T &val);
|
||||
~Stereo() {};
|
||||
|
||||
void operator=(const Stereo<T> &smp);
|
||||
T &left() {
|
||||
return leftChannel;
|
||||
};
|
||||
T &right() {
|
||||
return rightChannel;
|
||||
};
|
||||
T &l() {
|
||||
return leftChannel;
|
||||
};
|
||||
T &r() {
|
||||
return rightChannel;
|
||||
};
|
||||
const T &left()const {
|
||||
return leftChannel;
|
||||
};
|
||||
const T &right()const {
|
||||
return rightChannel;
|
||||
};
|
||||
const T &l()const {
|
||||
return leftChannel;
|
||||
};
|
||||
const T &r()const {
|
||||
return rightChannel;
|
||||
};
|
||||
private:
|
||||
T leftChannel;
|
||||
T rightChannel;
|
||||
|
||||
};
|
||||
#include "Stereo.cpp"
|
||||
#endif
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Util.C - Miscellaneous functions
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -42,17 +42,19 @@ REALTYPE *denormalkillbuf;
|
||||
/*
|
||||
* Transform the velocity according the scaling parameter (velocity sensing)
|
||||
*/
|
||||
REALTYPE VelF(REALTYPE velocity,unsigned char scaling){
|
||||
REALTYPE VelF(REALTYPE velocity,unsigned char scaling)
|
||||
{
|
||||
REALTYPE x;
|
||||
x=pow(VELOCITY_MAX_SCALE,(64.0-scaling)/64.0);
|
||||
if ((scaling==127)||(velocity>0.99)) return(1.0);
|
||||
else return(pow(velocity,x));
|
||||
else return(pow(velocity,x));
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the detune in cents
|
||||
* Get the detune in cents
|
||||
*/
|
||||
REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned short int finedetune){
|
||||
REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned short int finedetune)
|
||||
{
|
||||
REALTYPE det=0.0,octdet=0.0,cdet=0.0,findet=0.0;
|
||||
//Get Octave
|
||||
int octave=coarsedetune/1024;
|
||||
@@ -62,49 +64,57 @@ REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned s
|
||||
//Coarse and fine detune
|
||||
int cdetune=coarsedetune%1024;
|
||||
if (cdetune>512) cdetune-=1024;
|
||||
|
||||
|
||||
int fdetune=finedetune-8192;
|
||||
|
||||
switch (type){
|
||||
switch (type) {
|
||||
// case 1: is used for the default (see below)
|
||||
case 2: cdet=fabs(cdetune*10.0);
|
||||
findet=fabs(fdetune/8192.0)*10.0;
|
||||
break;
|
||||
case 3: cdet=fabs(cdetune*100);
|
||||
findet=pow(10,fabs(fdetune/8192.0)*3.0)/10.0-0.1;
|
||||
break;
|
||||
case 4: cdet=fabs(cdetune*701.95500087);//perfect fifth
|
||||
findet=(pow(2,fabs(fdetune/8192.0)*12.0)-1.0)/4095*1200;
|
||||
break;
|
||||
//case ...: need to update N_DETUNE_TYPES, if you'll add more
|
||||
default:cdet=fabs(cdetune*50.0);
|
||||
findet=fabs(fdetune/8192.0)*35.0;//almost like "Paul's Sound Designer 2"
|
||||
break;
|
||||
case 2:
|
||||
cdet=fabs(cdetune*10.0);
|
||||
findet=fabs(fdetune/8192.0)*10.0;
|
||||
break;
|
||||
case 3:
|
||||
cdet=fabs(cdetune*100);
|
||||
findet=pow(10,fabs(fdetune/8192.0)*3.0)/10.0-0.1;
|
||||
break;
|
||||
case 4:
|
||||
cdet=fabs(cdetune*701.95500087);//perfect fifth
|
||||
findet=(pow(2,fabs(fdetune/8192.0)*12.0)-1.0)/4095*1200;
|
||||
break;
|
||||
//case ...: need to update N_DETUNE_TYPES, if you'll add more
|
||||
default:
|
||||
cdet=fabs(cdetune*50.0);
|
||||
findet=fabs(fdetune/8192.0)*35.0;//almost like "Paul's Sound Designer 2"
|
||||
break;
|
||||
};
|
||||
if (finedetune<8192) findet=-findet;
|
||||
if (cdetune<0) cdet=-cdet;
|
||||
|
||||
|
||||
det=octdet+cdet+findet;
|
||||
return(det);
|
||||
};
|
||||
|
||||
|
||||
bool fileexists(char *filename){
|
||||
bool fileexists(const char *filename)
|
||||
{
|
||||
struct stat tmp;
|
||||
int result=stat(filename,&tmp);
|
||||
if (result>=0) return(true);
|
||||
|
||||
|
||||
return(false);
|
||||
};
|
||||
|
||||
void newFFTFREQS(FFTFREQS *f,int size){
|
||||
void newFFTFREQS(FFTFREQS *f,int size)
|
||||
{
|
||||
f->c=new REALTYPE[size];
|
||||
f->s=new REALTYPE[size];
|
||||
for (int i=0;i<size;i++){
|
||||
f->c[i]=0.0;f->s[i]=0.0;
|
||||
for (int i=0;i<size;i++) {
|
||||
f->c[i]=0.0;
|
||||
f->s[i]=0.0;
|
||||
};
|
||||
};
|
||||
void deleteFFTFREQS(FFTFREQS *f){
|
||||
void deleteFFTFREQS(FFTFREQS *f)
|
||||
{
|
||||
delete[] f->c;
|
||||
delete[] f->s;
|
||||
f->c=f->s=NULL;
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
Util.h - Miscellaneous functions
|
||||
Copyright (C) 2002-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -32,12 +32,12 @@
|
||||
//Velocity Sensing function
|
||||
extern REALTYPE VelF(REALTYPE velocity,unsigned char scaling);
|
||||
|
||||
bool fileexists(char *filename);
|
||||
bool fileexists(const char *filename);
|
||||
|
||||
#define N_DETUNE_TYPES 4 //the number of detune types
|
||||
extern REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned short int finedetune);
|
||||
|
||||
extern REALTYPE *denormalkillbuf;//the buffer to add noise in order to avoid denormalisation
|
||||
extern REALTYPE *denormalkillbuf;/**<the buffer to add noise in order to avoid denormalisation*/
|
||||
|
||||
extern Config config;
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
|
||||
XMLwrapper.C - XML wrapper
|
||||
Copyright (C) 2003-2005 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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
|
||||
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,
|
||||
@@ -21,50 +21,58 @@
|
||||
*/
|
||||
|
||||
#include "XMLwrapper.h"
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstdarg>
|
||||
#include <zlib.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "../globals.h"
|
||||
#include "Util.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int xml_k=0;
|
||||
char tabs[STACKSIZE+2];
|
||||
|
||||
const char *XMLwrapper_whitespace_callback(mxml_node_t *node,int where){
|
||||
const char *XMLwrapper_whitespace_callback(mxml_node_t *node,int where)
|
||||
{
|
||||
const char *name=node->value.element.name;
|
||||
|
||||
if ((where==MXML_WS_BEFORE_OPEN)&&(!strcmp(name,"?xml"))) return(NULL);
|
||||
if ((where==MXML_WS_BEFORE_CLOSE)&&(!strcmp(name,"string"))) return(NULL);
|
||||
|
||||
if ((where==MXML_WS_BEFORE_OPEN)||(where==MXML_WS_BEFORE_CLOSE)) {
|
||||
/* const char *tmp=node->value.element.name;
|
||||
if (tmp!=NULL) {
|
||||
if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) {
|
||||
printf("%s ",tmp);
|
||||
if (where==MXML_WS_BEFORE_OPEN) xml_k++;
|
||||
if (where==MXML_WS_BEFORE_CLOSE) xml_k--;
|
||||
if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1;
|
||||
if (xml_k<0) xml_k=0;
|
||||
printf("%d\n",xml_k);
|
||||
printf("\n");
|
||||
};
|
||||
|
||||
};
|
||||
int i=0;
|
||||
for (i=1;i<xml_k;i++) tabs[i]='\t';
|
||||
tabs[0]='\n';tabs[i+1]='\0';
|
||||
if (where==MXML_WS_BEFORE_OPEN) return(tabs);
|
||||
else return("\n");
|
||||
*/
|
||||
return("\n");
|
||||
/* const char *tmp=node->value.element.name;
|
||||
if (tmp!=NULL) {
|
||||
if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) {
|
||||
printf("%s ",tmp);
|
||||
if (where==MXML_WS_BEFORE_OPEN) xml_k++;
|
||||
if (where==MXML_WS_BEFORE_CLOSE) xml_k--;
|
||||
if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1;
|
||||
if (xml_k<0) xml_k=0;
|
||||
printf("%d\n",xml_k);
|
||||
printf("\n");
|
||||
};
|
||||
|
||||
};
|
||||
int i=0;
|
||||
for (i=1;i<xml_k;i++) tabs[i]='\t';
|
||||
tabs[0]='\n';tabs[i+1]='\0';
|
||||
if (where==MXML_WS_BEFORE_OPEN) return(tabs);
|
||||
else return("\n");
|
||||
*/
|
||||
return("\n");
|
||||
};
|
||||
|
||||
|
||||
return(0);
|
||||
};
|
||||
|
||||
|
||||
XMLwrapper::XMLwrapper(){
|
||||
XMLwrapper::XMLwrapper()
|
||||
{
|
||||
ZERO(&parentstack,(int)sizeof(parentstack));
|
||||
ZERO(&values,(int)sizeof(values));
|
||||
|
||||
@@ -72,50 +80,53 @@ XMLwrapper::XMLwrapper(){
|
||||
stackpos=0;
|
||||
|
||||
information.PADsynth_used=false;
|
||||
|
||||
|
||||
tree=mxmlNewElement(MXML_NO_PARENT,"?xml version=\"1.0\" encoding=\"UTF-8\"?");
|
||||
/* for mxml 2.1 (and older)
|
||||
tree=mxmlNewElement(MXML_NO_PARENT,"?xml");
|
||||
mxmlElementSetAttr(tree,"version","1.0");
|
||||
mxmlElementSetAttr(tree,"encoding","UTF-8");
|
||||
*/
|
||||
|
||||
/* for mxml 2.1 (and older)
|
||||
tree=mxmlNewElement(MXML_NO_PARENT,"?xml");
|
||||
mxmlElementSetAttr(tree,"version","1.0");
|
||||
mxmlElementSetAttr(tree,"encoding","UTF-8");
|
||||
*/
|
||||
|
||||
mxml_node_t *doctype=mxmlNewElement(tree,"!DOCTYPE");
|
||||
mxmlElementSetAttr(doctype,"ZynAddSubFX-data",NULL);
|
||||
|
||||
node=root=mxmlNewElement(tree,"ZynAddSubFX-data");
|
||||
|
||||
|
||||
mxmlElementSetAttr(root,"version-major","1");
|
||||
mxmlElementSetAttr(root,"version-minor","1");
|
||||
mxmlElementSetAttr(root,"ZynAddSubFX-author","Nasca Octavian Paul");
|
||||
|
||||
//make the empty branch that will contain the information parameters
|
||||
info=addparams0("INFORMATION");
|
||||
|
||||
|
||||
//save zynaddsubfx specifications
|
||||
beginbranch("BASE_PARAMETERS");
|
||||
addpar("max_midi_parts",NUM_MIDI_PARTS);
|
||||
addpar("max_kit_items_per_instrument",NUM_KIT_ITEMS);
|
||||
addpar("max_midi_parts",NUM_MIDI_PARTS);
|
||||
addpar("max_kit_items_per_instrument",NUM_KIT_ITEMS);
|
||||
|
||||
addpar("max_system_effects",NUM_SYS_EFX);
|
||||
addpar("max_insertion_effects",NUM_INS_EFX);
|
||||
addpar("max_instrument_effects",NUM_PART_EFX);
|
||||
addpar("max_system_effects",NUM_SYS_EFX);
|
||||
addpar("max_insertion_effects",NUM_INS_EFX);
|
||||
addpar("max_instrument_effects",NUM_PART_EFX);
|
||||
|
||||
addpar("max_addsynth_voices",NUM_VOICES);
|
||||
addpar("max_addsynth_voices",NUM_VOICES);
|
||||
endbranch();
|
||||
|
||||
};
|
||||
|
||||
XMLwrapper::~XMLwrapper(){
|
||||
XMLwrapper::~XMLwrapper()
|
||||
{
|
||||
if (tree!=NULL) mxmlDelete(tree);
|
||||
};
|
||||
|
||||
bool XMLwrapper::checkfileinformation(const char *filename){
|
||||
bool XMLwrapper::checkfileinformation(const char *filename)
|
||||
{
|
||||
stackpos=0;
|
||||
ZERO(&parentstack,(int)sizeof(parentstack));
|
||||
information.PADsynth_used=false;
|
||||
|
||||
if (tree!=NULL) mxmlDelete(tree);tree=NULL;
|
||||
if (tree!=NULL) mxmlDelete(tree);
|
||||
tree=NULL;
|
||||
char *xmldata=doloadfile(filename);
|
||||
if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed
|
||||
|
||||
@@ -124,31 +135,31 @@ bool XMLwrapper::checkfileinformation(const char *filename){
|
||||
char *end=strstr(xmldata,"</INFORMATION>");
|
||||
|
||||
if ((start==NULL)||(end==NULL)||(start>end)) {
|
||||
delete []xmldata;
|
||||
return(false);
|
||||
delete []xmldata;
|
||||
return(false);
|
||||
};
|
||||
end+=strlen("</INFORMATION>");
|
||||
end[0]='\0';
|
||||
|
||||
end[0]='\0';
|
||||
|
||||
tree=mxmlNewElement(MXML_NO_PARENT,"?xml");
|
||||
node=root=mxmlLoadString(tree,xmldata,MXML_OPAQUE_CALLBACK);
|
||||
if (root==NULL) {
|
||||
delete []xmldata;
|
||||
mxmlDelete(tree);
|
||||
node=root=tree=NULL;
|
||||
return(false);
|
||||
delete []xmldata;
|
||||
mxmlDelete(tree);
|
||||
node=root=tree=NULL;
|
||||
return(false);
|
||||
};
|
||||
|
||||
root=mxmlFindElement(tree,tree,"INFORMATION",NULL,NULL,MXML_DESCEND);
|
||||
push(root);
|
||||
|
||||
if (root==NULL){
|
||||
delete []xmldata;
|
||||
mxmlDelete(tree);
|
||||
node=root=tree=NULL;
|
||||
return(false);
|
||||
if (root==NULL) {
|
||||
delete []xmldata;
|
||||
mxmlDelete(tree);
|
||||
node=root=tree=NULL;
|
||||
return(false);
|
||||
};
|
||||
|
||||
|
||||
information.PADsynth_used=getparbool("PADsynth_used",false);
|
||||
|
||||
exitbranch();
|
||||
@@ -162,33 +173,29 @@ bool XMLwrapper::checkfileinformation(const char *filename){
|
||||
|
||||
/* SAVE XML members */
|
||||
|
||||
int XMLwrapper::saveXMLfile(const char *filename){
|
||||
int XMLwrapper::saveXMLfile(const string &filename)
|
||||
{
|
||||
char *xmldata=getXMLdata();
|
||||
if (xmldata==NULL) return(-2);
|
||||
|
||||
int compression=config.cfg.GzipCompression;
|
||||
|
||||
int fnsize=strlen(filename)+100;
|
||||
char *filenamenew=new char [fnsize];
|
||||
snprintf(filenamenew,fnsize,"%s",filename);
|
||||
|
||||
int result=dosavefile(filenamenew,compression,xmldata);
|
||||
|
||||
delete []filenamenew;
|
||||
free(xmldata);
|
||||
int result=dosavefile(filename.c_str(),compression,xmldata);
|
||||
|
||||
free(xmldata);
|
||||
return(result);
|
||||
};
|
||||
|
||||
char *XMLwrapper::getXMLdata(){
|
||||
char *XMLwrapper::getXMLdata()
|
||||
{
|
||||
xml_k=0;
|
||||
ZERO(tabs,STACKSIZE+2);
|
||||
|
||||
|
||||
mxml_node_t *oldnode=node;
|
||||
|
||||
|
||||
node=info;
|
||||
//Info storing
|
||||
addparbool("PADsynth_used",information.PADsynth_used);
|
||||
|
||||
|
||||
node=oldnode;
|
||||
char *xmldata=mxmlSaveAllocString(tree,XMLwrapper_whitespace_callback);
|
||||
|
||||
@@ -196,62 +203,70 @@ char *XMLwrapper::getXMLdata(){
|
||||
};
|
||||
|
||||
|
||||
int XMLwrapper::dosavefile(const char *filename,int compression,const char *xmldata){
|
||||
if (compression==0){
|
||||
FILE *file;
|
||||
file=fopen(filename,"w");
|
||||
if (file==NULL) return(-1);
|
||||
fputs(xmldata,file);
|
||||
fclose(file);
|
||||
int XMLwrapper::dosavefile(const char *filename,int compression,const char *xmldata)
|
||||
{
|
||||
if (compression==0) {
|
||||
FILE *file;
|
||||
file=fopen(filename,"w");
|
||||
if (file==NULL) return(-1);
|
||||
fputs(xmldata,file);
|
||||
fclose(file);
|
||||
} else {
|
||||
if (compression>9) compression=9;
|
||||
if (compression<1) compression=1;
|
||||
char options[10];
|
||||
snprintf(options,10,"wb%d",compression);
|
||||
if (compression>9) compression=9;
|
||||
if (compression<1) compression=1;
|
||||
char options[10];
|
||||
snprintf(options,10,"wb%d",compression);
|
||||
|
||||
gzFile gzfile;
|
||||
gzfile=gzopen(filename,options);
|
||||
if (gzfile==NULL) return(-1);
|
||||
gzputs(gzfile,xmldata);
|
||||
gzclose(gzfile);
|
||||
gzFile gzfile;
|
||||
gzfile=gzopen(filename,options);
|
||||
if (gzfile==NULL) return(-1);
|
||||
gzputs(gzfile,xmldata);
|
||||
gzclose(gzfile);
|
||||
};
|
||||
|
||||
|
||||
return(0);
|
||||
};
|
||||
|
||||
|
||||
|
||||
void XMLwrapper::addpar(const char *name,int val){
|
||||
addparams2("par","name",name,"value",int2str(val));
|
||||
void XMLwrapper::addpar(const string &name,int val)
|
||||
{
|
||||
addparams2("par","name",name.c_str(),"value",int2str(val));
|
||||
};
|
||||
|
||||
void XMLwrapper::addparreal(const char *name,REALTYPE val){
|
||||
addparams2("par_real","name",name,"value",real2str(val));
|
||||
void XMLwrapper::addparreal(const string &name,REALTYPE val)
|
||||
{
|
||||
addparams2("par_real","name",name.c_str(),"value",real2str(val));
|
||||
};
|
||||
|
||||
void XMLwrapper::addparbool(const char *name,int val){
|
||||
if (val!=0) addparams2("par_bool","name",name,"value","yes");
|
||||
else addparams2("par_bool","name",name,"value","no");
|
||||
void XMLwrapper::addparbool(const string &name,int val)
|
||||
{
|
||||
if (val!=0) addparams2("par_bool","name",name.c_str(),"value","yes");
|
||||
else addparams2("par_bool","name",name.c_str(),"value","no");
|
||||
};
|
||||
|
||||
void XMLwrapper::addparstr(const char *name,const char *val){
|
||||
void XMLwrapper::addparstr(const string &name,const string &val)
|
||||
{
|
||||
mxml_node_t *element=mxmlNewElement(node,"string");
|
||||
mxmlElementSetAttr(element,"name",name);
|
||||
mxmlNewText(element,0,val);
|
||||
mxmlElementSetAttr(element,"name",name.c_str());
|
||||
mxmlNewText(element,0,val.c_str());
|
||||
};
|
||||
|
||||
|
||||
void XMLwrapper::beginbranch(const char *name){
|
||||
void XMLwrapper::beginbranch(const string &name)
|
||||
{
|
||||
push(node);
|
||||
node=addparams0(name);
|
||||
node=addparams0(name.c_str());
|
||||
};
|
||||
|
||||
void XMLwrapper::beginbranch(const char *name,int id){
|
||||
void XMLwrapper::beginbranch(const string &name,int id)
|
||||
{
|
||||
push(node);
|
||||
node=addparams1(name,"id",int2str(id));
|
||||
node=addparams1(name.c_str(),"id",int2str(id));
|
||||
};
|
||||
|
||||
void XMLwrapper::endbranch(){
|
||||
void XMLwrapper::endbranch()
|
||||
{
|
||||
node=pop();
|
||||
};
|
||||
|
||||
@@ -259,7 +274,8 @@ void XMLwrapper::endbranch(){
|
||||
|
||||
/* LOAD XML members */
|
||||
|
||||
int XMLwrapper::loadXMLfile(const char *filename){
|
||||
int XMLwrapper::loadXMLfile(const string &filename)
|
||||
{
|
||||
if (tree!=NULL) mxmlDelete(tree);
|
||||
tree=NULL;
|
||||
|
||||
@@ -268,16 +284,16 @@ int XMLwrapper::loadXMLfile(const char *filename){
|
||||
|
||||
stackpos=0;
|
||||
|
||||
const char *xmldata=doloadfile(filename);
|
||||
const char *xmldata=doloadfile(filename.c_str());
|
||||
if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed
|
||||
|
||||
|
||||
root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK);
|
||||
|
||||
delete []xmldata;
|
||||
|
||||
if (tree==NULL) return(-2);//this is not XML
|
||||
|
||||
|
||||
|
||||
|
||||
node=root=mxmlFindElement(tree,tree,"ZynAddSubFX-data",NULL,NULL,MXML_DESCEND);
|
||||
if (root==NULL) return(-3);//the XML doesnt embbed zynaddsubfx data
|
||||
push(root);
|
||||
@@ -289,51 +305,39 @@ int XMLwrapper::loadXMLfile(const char *filename){
|
||||
};
|
||||
|
||||
|
||||
char *XMLwrapper::doloadfile(const char *filename){
|
||||
char *xmldata=NULL;
|
||||
int filesize=-1;
|
||||
|
||||
//try get filesize as gzip data (first)
|
||||
gzFile gzfile=gzopen(filename,"rb");
|
||||
if (gzfile!=NULL){//this is a gzip file
|
||||
// first check it's size
|
||||
while(!gzeof(gzfile)) {
|
||||
gzseek (gzfile,1024*1024,SEEK_CUR);
|
||||
if (gztell(gzfile)>10000000) {
|
||||
gzclose(gzfile);
|
||||
goto notgzip;//the file is too big
|
||||
};
|
||||
};
|
||||
filesize=gztell(gzfile);
|
||||
char *XMLwrapper::doloadfile(const string &filename)
|
||||
{
|
||||
char * xmldata = NULL;
|
||||
gzFile gzfile = gzopen(filename.c_str(),"rb");
|
||||
|
||||
//rewind the file and load the data
|
||||
xmldata=new char[filesize+1];
|
||||
ZERO(xmldata,filesize+1);
|
||||
if (gzfile != NULL) {//The possibly compressed file opened
|
||||
|
||||
gzrewind(gzfile);
|
||||
gzread(gzfile,xmldata,filesize);
|
||||
|
||||
gzclose(gzfile);
|
||||
return (xmldata);
|
||||
} else {//this is not a gzip file
|
||||
notgzip:
|
||||
FILE *file=fopen(filename,"rb");
|
||||
if (file==NULL) return(NULL);
|
||||
fseek(file,0,SEEK_END);
|
||||
filesize=ftell(file);
|
||||
stringstream strBuf; //reading stream
|
||||
const int bufSize = 500; //fetch size
|
||||
char fetchBuf[bufSize+1];//fetch buffer
|
||||
int read = 0; //chars read in last fetch
|
||||
|
||||
xmldata=new char [filesize+1];
|
||||
ZERO(xmldata,filesize+1);
|
||||
|
||||
rewind(file);
|
||||
fread(xmldata,filesize,1,file);
|
||||
|
||||
fclose(file);
|
||||
return(xmldata);
|
||||
};
|
||||
};
|
||||
fetchBuf[bufSize] = 0;//force null termination
|
||||
|
||||
bool XMLwrapper::putXMLdata(const char *xmldata){
|
||||
while(bufSize == (read = gzread(gzfile, fetchBuf, bufSize)))
|
||||
strBuf << fetchBuf;
|
||||
|
||||
fetchBuf[read] = 0;//Truncate last partial read
|
||||
strBuf << fetchBuf;
|
||||
|
||||
gzclose(gzfile);
|
||||
|
||||
//Place data in output format
|
||||
string tmp = strBuf.str();
|
||||
xmldata = new char[tmp.size()+1];
|
||||
strncpy(xmldata, tmp.c_str(), tmp.size()+1);
|
||||
}
|
||||
|
||||
return xmldata;
|
||||
}
|
||||
|
||||
bool XMLwrapper::putXMLdata(const char *xmldata)
|
||||
{
|
||||
if (tree!=NULL) mxmlDelete(tree);
|
||||
tree=NULL;
|
||||
|
||||
@@ -343,11 +347,11 @@ bool XMLwrapper::putXMLdata(const char *xmldata){
|
||||
stackpos=0;
|
||||
|
||||
if (xmldata==NULL) return (false);
|
||||
|
||||
|
||||
root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK);
|
||||
|
||||
if (tree==NULL) return(false);
|
||||
|
||||
|
||||
node=root=mxmlFindElement(tree,tree,"ZynAddSubFX-data",NULL,NULL,MXML_DESCEND);
|
||||
if (root==NULL) return (false);;
|
||||
push(root);
|
||||
@@ -357,17 +361,19 @@ bool XMLwrapper::putXMLdata(const char *xmldata){
|
||||
|
||||
|
||||
|
||||
int XMLwrapper::enterbranch(const char *name){
|
||||
node=mxmlFindElement(peek(),peek(),name,NULL,NULL,MXML_DESCEND_FIRST);
|
||||
int XMLwrapper::enterbranch(const string &name)
|
||||
{
|
||||
node=mxmlFindElement(peek(),peek(),name.c_str(),NULL,NULL,MXML_DESCEND_FIRST);
|
||||
if (node==NULL) return(0);
|
||||
|
||||
push(node);
|
||||
return(1);
|
||||
};
|
||||
|
||||
int XMLwrapper::enterbranch(const char *name,int id){
|
||||
int XMLwrapper::enterbranch(const string &name,int id)
|
||||
{
|
||||
snprintf(tmpstr,TMPSTR_SIZE,"%d",id);
|
||||
node=mxmlFindElement(peek(),peek(),name,"id",tmpstr,MXML_DESCEND_FIRST);
|
||||
node=mxmlFindElement(peek(),peek(),name.c_str(),"id",tmpstr,MXML_DESCEND_FIRST);
|
||||
if (node==NULL) return(0);
|
||||
|
||||
push(node);
|
||||
@@ -375,142 +381,157 @@ int XMLwrapper::enterbranch(const char *name,int id){
|
||||
};
|
||||
|
||||
|
||||
void XMLwrapper::exitbranch(){
|
||||
void XMLwrapper::exitbranch()
|
||||
{
|
||||
/**@bug Does not set the current node correctly*/
|
||||
pop();
|
||||
};
|
||||
|
||||
|
||||
int XMLwrapper::getbranchid(int min, int max){
|
||||
int XMLwrapper::getbranchid(int min, int max)
|
||||
{
|
||||
int id=str2int(mxmlElementGetAttr(node,"id"));
|
||||
if ((min==0)&&(max==0)) return(id);
|
||||
|
||||
|
||||
if (id<min) id=min;
|
||||
else if (id>max) id=max;
|
||||
else if (id>max) id=max;
|
||||
|
||||
return(id);
|
||||
};
|
||||
|
||||
int XMLwrapper::getpar(const char *name,int defaultpar,int min,int max){
|
||||
node=mxmlFindElement(peek(),peek(),"par","name",name,MXML_DESCEND_FIRST);
|
||||
int XMLwrapper::getpar(const string &name,int defaultpar,int min,int max)
|
||||
{
|
||||
node=mxmlFindElement(peek(),peek(),"par","name",name.c_str(),MXML_DESCEND_FIRST);
|
||||
if (node==NULL) return(defaultpar);
|
||||
|
||||
const char *strval=mxmlElementGetAttr(node,"value");
|
||||
if (strval==NULL) return(defaultpar);
|
||||
|
||||
|
||||
int val=str2int(strval);
|
||||
if (val<min) val=min;
|
||||
else if (val>max) val=max;
|
||||
|
||||
else if (val>max) val=max;
|
||||
|
||||
return(val);
|
||||
};
|
||||
|
||||
int XMLwrapper::getpar127(const char *name,int defaultpar){
|
||||
int XMLwrapper::getpar127(const string &name,int defaultpar)
|
||||
{
|
||||
return(getpar(name,defaultpar,0,127));
|
||||
};
|
||||
|
||||
int XMLwrapper::getparbool(const char *name,int defaultpar){
|
||||
node=mxmlFindElement(peek(),peek(),"par_bool","name",name,MXML_DESCEND_FIRST);
|
||||
int XMLwrapper::getparbool(const string &name,int defaultpar)
|
||||
{
|
||||
node=mxmlFindElement(peek(),peek(),"par_bool","name",name.c_str(),MXML_DESCEND_FIRST);
|
||||
if (node==NULL) return(defaultpar);
|
||||
|
||||
const char *strval=mxmlElementGetAttr(node,"value");
|
||||
if (strval==NULL) return(defaultpar);
|
||||
|
||||
|
||||
if ((strval[0]=='Y')||(strval[0]=='y')) return(1);
|
||||
else return(0);
|
||||
else return(0);
|
||||
};
|
||||
|
||||
void XMLwrapper::getparstr(const char *name,char *par,int maxstrlen){
|
||||
void XMLwrapper::getparstr(const string &name,char *par,int maxstrlen)
|
||||
{
|
||||
ZERO(par,maxstrlen);
|
||||
node=mxmlFindElement(peek(),peek(),"string","name",name,MXML_DESCEND_FIRST);
|
||||
|
||||
node=mxmlFindElement(peek(),peek(),"string","name",name.c_str(),MXML_DESCEND_FIRST);
|
||||
|
||||
if (node==NULL) return;
|
||||
if (node->child==NULL) return;
|
||||
if (node->child->type!=MXML_OPAQUE) return;
|
||||
|
||||
|
||||
snprintf(par,maxstrlen,"%s",node->child->value.element.name);
|
||||
|
||||
|
||||
};
|
||||
|
||||
REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar){
|
||||
REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar)
|
||||
{
|
||||
node=mxmlFindElement(peek(),peek(),"par_real","name",name,MXML_DESCEND_FIRST);
|
||||
if (node==NULL) return(defaultpar);
|
||||
|
||||
const char *strval=mxmlElementGetAttr(node,"value");
|
||||
if (strval==NULL) return(defaultpar);
|
||||
|
||||
|
||||
return(str2real(strval));
|
||||
};
|
||||
|
||||
REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max){
|
||||
REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max)
|
||||
{
|
||||
REALTYPE result=getparreal(name,defaultpar);
|
||||
|
||||
|
||||
if (result<min) result=min;
|
||||
else if (result>max) result=max;
|
||||
else if (result>max) result=max;
|
||||
return(result);
|
||||
};
|
||||
|
||||
|
||||
/** Private members **/
|
||||
|
||||
char *XMLwrapper::int2str(int x){
|
||||
char *XMLwrapper::int2str(int x)
|
||||
{
|
||||
snprintf(tmpstr,TMPSTR_SIZE,"%d",x);
|
||||
return(tmpstr);
|
||||
};
|
||||
|
||||
char *XMLwrapper::real2str(REALTYPE x){
|
||||
char *XMLwrapper::real2str(REALTYPE x)
|
||||
{
|
||||
snprintf(tmpstr,TMPSTR_SIZE,"%g",x);
|
||||
return(tmpstr);
|
||||
};
|
||||
|
||||
int XMLwrapper::str2int(const char *str){
|
||||
int XMLwrapper::str2int(const char *str)
|
||||
{
|
||||
if (str==NULL) return(0);
|
||||
int result=strtol(str,NULL,10);
|
||||
return(result);
|
||||
};
|
||||
|
||||
REALTYPE XMLwrapper::str2real(const char *str){
|
||||
REALTYPE XMLwrapper::str2real(const char *str)
|
||||
{
|
||||
if (str==NULL) return(0.0);
|
||||
REALTYPE result=strtod(str,NULL);
|
||||
return(result);
|
||||
};
|
||||
|
||||
|
||||
mxml_node_t *XMLwrapper::addparams0(const char *name){
|
||||
mxml_node_t *XMLwrapper::addparams0(const char *name)
|
||||
{
|
||||
mxml_node_t *element=mxmlNewElement(node,name);
|
||||
return(element);
|
||||
};
|
||||
|
||||
mxml_node_t *XMLwrapper::addparams1(const char *name,const char *par1,const char *val1){
|
||||
mxml_node_t *XMLwrapper::addparams1(const char *name,const char *par1,const char *val1)
|
||||
{
|
||||
mxml_node_t *element=mxmlNewElement(node,name);
|
||||
mxmlElementSetAttr(element,par1,val1);
|
||||
return(element);
|
||||
};
|
||||
|
||||
mxml_node_t *XMLwrapper::addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2){
|
||||
mxml_node_t *XMLwrapper::addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2)
|
||||
{
|
||||
mxml_node_t *element=mxmlNewElement(node,name);
|
||||
mxmlElementSetAttr(element,par1,val1);
|
||||
mxmlElementSetAttr(element,par2,val2);
|
||||
return(element);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void XMLwrapper::push(mxml_node_t *node){
|
||||
void XMLwrapper::push(mxml_node_t *node)
|
||||
{
|
||||
if (stackpos>=STACKSIZE-1) {
|
||||
printf("BUG!: XMLwrapper::push() - full parentstack\n");
|
||||
return;
|
||||
cerr << "BUG!: XMLwrapper::push() - full parentstack" << endl;
|
||||
return;
|
||||
};
|
||||
stackpos++;
|
||||
parentstack[stackpos]=node;
|
||||
|
||||
|
||||
// printf("push %d - %s\n",stackpos,node->value.element.name);
|
||||
|
||||
|
||||
};
|
||||
mxml_node_t *XMLwrapper::pop(){
|
||||
mxml_node_t *XMLwrapper::pop()
|
||||
{
|
||||
if (stackpos<=0) {
|
||||
printf("BUG!: XMLwrapper::pop() - empty parentstack\n");
|
||||
return (root);
|
||||
cerr << "BUG!: XMLwrapper::pop() - empty parentstack" << endl;
|
||||
return (root);
|
||||
};
|
||||
mxml_node_t *node=parentstack[stackpos];
|
||||
parentstack[stackpos]=NULL;
|
||||
@@ -521,10 +542,11 @@ mxml_node_t *XMLwrapper::pop(){
|
||||
return(node);
|
||||
};
|
||||
|
||||
mxml_node_t *XMLwrapper::peek(){
|
||||
mxml_node_t *XMLwrapper::peek()
|
||||
{
|
||||
if (stackpos<=0) {
|
||||
printf("BUG!: XMLwrapper::peek() - empty parentstack\n");
|
||||
return (root);
|
||||
cerr << "BUG!: XMLwrapper::peek() - empty parentstack" << endl;
|
||||
return (root);
|
||||
};
|
||||
return(parentstack[stackpos]);
|
||||
};
|
||||
@@ -1,12 +1,14 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
XML.h - XML wrapper
|
||||
|
||||
XMLwrapper.h - XML wrapper
|
||||
Copyright (C) 2003-2005 Nasca Octavian Paul
|
||||
Copyright (C) 2009-2009 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
|
||||
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,
|
||||
@@ -20,7 +22,8 @@
|
||||
|
||||
*/
|
||||
|
||||
#include <mxml/mxml.h>
|
||||
#include <mxml.h>
|
||||
#include <string>
|
||||
#ifndef REALTYPE
|
||||
#define REALTYPE float
|
||||
#endif
|
||||
@@ -33,143 +36,282 @@
|
||||
//the maxim tree depth
|
||||
#define STACKSIZE 100
|
||||
|
||||
class XMLwrapper{
|
||||
public:
|
||||
XMLwrapper();
|
||||
~XMLwrapper();
|
||||
|
||||
/********************************/
|
||||
/* SAVE to XML */
|
||||
/********************************/
|
||||
/**Mxml wrapper*/
|
||||
class XMLwrapper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* Will Construct the object and fill in top level branch
|
||||
* */
|
||||
XMLwrapper();
|
||||
|
||||
//returns 0 if ok or -1 if the file cannot be saved
|
||||
int saveXMLfile(const char *filename);
|
||||
/**Destructor*/
|
||||
~XMLwrapper();
|
||||
|
||||
//returns the new allocated string that contains the XML data (used for clipboard)
|
||||
//the string is NULL terminated
|
||||
char *getXMLdata();
|
||||
|
||||
//add simple parameter (name and value)
|
||||
void addpar(const char *name,int val);
|
||||
void addparreal(const char *name,REALTYPE val);
|
||||
|
||||
//add boolean parameter (name and boolean value)
|
||||
//if the value is 0 => "yes", else "no"
|
||||
void addparbool(const char *name,int val);
|
||||
/**
|
||||
* Saves the XML to a file.
|
||||
* @param filename the name of the destination file.
|
||||
* @returns 0 if ok or -1 if the file cannot be saved.
|
||||
*/
|
||||
int saveXMLfile(const std::string &filename);
|
||||
|
||||
//add string parameter (name and string)
|
||||
void addparstr(const char *name,const char *val);
|
||||
/**
|
||||
* Return XML tree as a string.
|
||||
* Note: The string must be freed with free() to deallocate
|
||||
* @returns a newly allocated NULL terminated string of the XML data.
|
||||
*/
|
||||
char *getXMLdata();
|
||||
|
||||
//add a branch
|
||||
void beginbranch(const char *name);
|
||||
void beginbranch(const char *name, int id);
|
||||
/**
|
||||
* Add simple parameter.
|
||||
* @param name The name of the mXML node.
|
||||
* @param val The string value of the mXml node
|
||||
*/
|
||||
void addpar(const std::string &name,int val);
|
||||
|
||||
//this must be called after each branch (nodes that contains child nodes)
|
||||
void endbranch();
|
||||
/**
|
||||
* Adds a realtype parameter.
|
||||
* @param name The name of the mXML node.
|
||||
* @param val The REALTYPE value of the node.
|
||||
*/
|
||||
void addparreal(const std::string &name,REALTYPE val);
|
||||
|
||||
/********************************/
|
||||
/* LOAD from XML */
|
||||
/********************************/
|
||||
|
||||
//returns 0 if ok or -1 if the file cannot be loaded
|
||||
int loadXMLfile(const char *filename);
|
||||
/**
|
||||
* Add boolean parameter.
|
||||
* \todo Fix this reverse boolean logic.
|
||||
* @param name The name of the mXML node.
|
||||
* @param val The boolean value of the node (0->"yes";else->"no").
|
||||
*/
|
||||
void addparbool(const std::string &name,int val);
|
||||
|
||||
//used by the clipboard
|
||||
bool putXMLdata(const char *xmldata);
|
||||
|
||||
//enter into the branch
|
||||
//returns 1 if is ok, or 0 otherwise
|
||||
int enterbranch(const char *name);
|
||||
/**
|
||||
* Add string parameter.
|
||||
* @param name The name of the mXML node.
|
||||
* @param val The string value of the node.
|
||||
*/
|
||||
void addparstr(const std::string &name,const std::string &val);
|
||||
|
||||
|
||||
//enter into the branch with id
|
||||
//returns 1 if is ok, or 0 otherwise
|
||||
int enterbranch(const char *name, int id);
|
||||
/**
|
||||
* Create a new branch.
|
||||
* @param name Name of new branch
|
||||
* @see void endbranch()
|
||||
*/
|
||||
void beginbranch(const std::string &name);
|
||||
/**
|
||||
* Create a new branch.
|
||||
* @param name Name of new branch
|
||||
* @param id "id" value of branch
|
||||
* @see void endbranch()
|
||||
*/
|
||||
void beginbranch(const std::string &name, int id);
|
||||
|
||||
//exits from a branch
|
||||
void exitbranch();
|
||||
|
||||
//get the the branch_id and limits it between the min and max
|
||||
//if min==max==0, it will not limit it
|
||||
//if there isn't any id, will return min
|
||||
//this must be called only imediately after enterbranch()
|
||||
int getbranchid(int min, int max);
|
||||
/**Closes new branches.
|
||||
* This must be called to exit each branch created by beginbranch( ).
|
||||
* @see void beginbranch(const std::string &name)
|
||||
* @see void beginbranch(const std::string &name, int id)
|
||||
*/
|
||||
void endbranch();
|
||||
|
||||
//it returns the parameter and limits it between min and max
|
||||
//if min==max==0, it will not limit it
|
||||
//if no parameter will be here, the defaultpar will be returned
|
||||
int getpar(const char *name,int defaultpar,int min,int max);
|
||||
/**
|
||||
* Loads file into XMLwrapper.
|
||||
* @param filename file to be loaded
|
||||
* @returns 0 if ok or -1 if the file cannot be loaded
|
||||
*/
|
||||
int loadXMLfile(const std::string &filename);
|
||||
|
||||
//the same as getpar, but the limits are 0 and 127
|
||||
int getpar127(const char *name,int defaultpar);
|
||||
|
||||
int getparbool(const char *name,int defaultpar);
|
||||
/**
|
||||
* Loads string into XMLwrapper.
|
||||
* @param xmldata NULL terminated string of XML data.
|
||||
* @returns true if successful.
|
||||
*/
|
||||
bool putXMLdata(const char *xmldata);
|
||||
|
||||
void getparstr(const char *name,char *par,int maxstrlen);
|
||||
REALTYPE getparreal(const char *name,REALTYPE defaultpar);
|
||||
REALTYPE getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max);
|
||||
/**
|
||||
* Enters the branch.
|
||||
* @param name Name of branch.
|
||||
* @returns 1 if is ok, or 0 otherwise.
|
||||
*/
|
||||
int enterbranch(const std::string &name);
|
||||
|
||||
bool minimal;//false if all parameters will be stored (used only for clipboard)
|
||||
|
||||
struct {
|
||||
bool PADsynth_used;
|
||||
}information;
|
||||
|
||||
//opens a file and parse only the "information" data on it
|
||||
//returns "true" if all went ok or "false" on errors
|
||||
bool checkfileinformation(const char *filename);
|
||||
|
||||
private:
|
||||
|
||||
int dosavefile(const char *filename,int compression,const char *xmldata);
|
||||
char *doloadfile(const char *filename);
|
||||
/**
|
||||
* Enter into the branch \c name with id \c id.
|
||||
* @param name Name of branch.
|
||||
* @param id Value of branch's "id".
|
||||
* @returns 1 if is ok, or 0 otherwise.
|
||||
*/
|
||||
int enterbranch(const std::string &name, int id);
|
||||
|
||||
|
||||
mxml_node_t *tree;//all xml data
|
||||
mxml_node_t *root;//xml data used by zynaddsubfx
|
||||
mxml_node_t *node;//current node
|
||||
mxml_node_t *info;//this node is used to store the information about the data
|
||||
|
||||
//adds params like this:
|
||||
// <name>
|
||||
//returns the node
|
||||
mxml_node_t *addparams0(const char *name);
|
||||
/**Exits from a branch*/
|
||||
void exitbranch();
|
||||
|
||||
//adds params like this:
|
||||
// <name par1="val1">
|
||||
//returns the node
|
||||
mxml_node_t *addparams1(const char *name,const char *par1,const char *val1);
|
||||
/**Get the the branch_id and limits it between the min and max.
|
||||
* if min==max==0, it will not limit it
|
||||
* if there isn't any id, will return min
|
||||
* this must be called only imediately after enterbranch()
|
||||
*/
|
||||
int getbranchid(int min, int max);
|
||||
|
||||
//adds params like this:
|
||||
// <name par1="val1" par2="val2">
|
||||
//returns the node
|
||||
mxml_node_t *addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2);
|
||||
|
||||
char *int2str(int x);
|
||||
char *real2str(REALTYPE x);
|
||||
|
||||
int str2int(const char *str);
|
||||
REALTYPE str2real(const char *str);
|
||||
|
||||
char tmpstr[TMPSTR_SIZE];
|
||||
|
||||
|
||||
//this is used to store the parents
|
||||
mxml_node_t *parentstack[STACKSIZE];
|
||||
int stackpos;
|
||||
/**
|
||||
* Returns the integer value stored in node name.
|
||||
* It returns the integer value between the limits min and max.
|
||||
* If min==max==0, then the value will not be limited.
|
||||
* If there is no location named name, then defaultpar will be returned.
|
||||
* @param name The parameter name.
|
||||
* @param defaultpar The default value if the real value is not found.
|
||||
* @param min The minimum return value.
|
||||
* @param max The maximum return value.
|
||||
*/
|
||||
int getpar(const std::string &name,int defaultpar,int min,int max);
|
||||
|
||||
|
||||
void push(mxml_node_t *node);
|
||||
mxml_node_t *pop();
|
||||
mxml_node_t *peek();
|
||||
/**
|
||||
* Returns the integer value stored in the node with range [0,127].
|
||||
* @param name The parameter name.
|
||||
* @param defaultpar The default value if the real value is not found.
|
||||
*/
|
||||
int getpar127(const std::string &name,int defaultpar);
|
||||
|
||||
/**
|
||||
* Returns the boolean value stored in the node.
|
||||
* @param name The parameter name.
|
||||
* @param defaultpar The default value if the real value is not found.
|
||||
*/
|
||||
int getparbool(const std::string &name,int defaultpar);
|
||||
|
||||
/**
|
||||
* Get the string value stored in the node.
|
||||
* @param name The parameter name.
|
||||
* @param par Pointer to destination string
|
||||
* @param maxstrlen Max string length for destination
|
||||
*/
|
||||
void getparstr(const std::string &name,char *par,int maxstrlen);
|
||||
|
||||
/**
|
||||
* Returns the real value stored in the node.
|
||||
* @param name The parameter name.
|
||||
* @param defaultpar The default value if the real value is not found.
|
||||
*/
|
||||
REALTYPE getparreal(const char *name,REALTYPE defaultpar);
|
||||
|
||||
/**
|
||||
* Returns the real value stored in the node.
|
||||
* @param name The parameter name.
|
||||
* @param defaultpar The default value if the real value is not found.
|
||||
* @param min The minimum value
|
||||
* @param max The maximum value
|
||||
*/
|
||||
REALTYPE getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max);
|
||||
|
||||
bool minimal;/**<false if all parameters will be stored (used only for clipboard)*/
|
||||
|
||||
struct {
|
||||
bool PADsynth_used;/**<if PADsynth is used*/
|
||||
}information;/**<Defines if PADsynth is used*/
|
||||
|
||||
/**
|
||||
* Opens a file and parses the "information" section data on it.
|
||||
* @returns "true" if all went ok or "false" on errors.
|
||||
*/
|
||||
bool checkfileinformation(const char *filename);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Save the file.
|
||||
* @param filename File to save to
|
||||
* @param compression Level of gzip compression
|
||||
* @param xmldata String to be saved
|
||||
*/
|
||||
int dosavefile(const char *filename,int compression,const char *xmldata);
|
||||
|
||||
/**
|
||||
* Loads specified file and returns data.
|
||||
*
|
||||
* Will load a gziped file or an uncompressed file.
|
||||
* @param filename the file
|
||||
* @return The decompressed data
|
||||
*/
|
||||
char *doloadfile(const std::string &filename);
|
||||
|
||||
|
||||
mxml_node_t *tree;/**<all xml data*/
|
||||
mxml_node_t *root;/**<xml data used by zynaddsubfx*/
|
||||
mxml_node_t *node;/**<current node*/
|
||||
mxml_node_t *info;/**<Node used to store the information about the data*/
|
||||
|
||||
/**
|
||||
* Adds params like this:
|
||||
* <name>.
|
||||
* @returns The node
|
||||
*/
|
||||
mxml_node_t *addparams0(const char *name);
|
||||
|
||||
/**
|
||||
* Adds params like this:
|
||||
* <name par1="val1">.
|
||||
* @returns The node
|
||||
*/
|
||||
mxml_node_t *addparams1(const char *name,const char *par1,const char *val1);
|
||||
|
||||
/**
|
||||
* Adds params like this:
|
||||
* <name par1="val1" par2="val2">.
|
||||
* @returns the node
|
||||
*/
|
||||
mxml_node_t *addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2);
|
||||
|
||||
/**
|
||||
* Convert integer to string
|
||||
* @param x integer input
|
||||
* @returns string output
|
||||
*/
|
||||
char *int2str(int x);
|
||||
|
||||
/**
|
||||
* Convert integer to string
|
||||
* @param x integer input
|
||||
* @returns string output
|
||||
*/
|
||||
char *real2str(REALTYPE x);
|
||||
|
||||
/**
|
||||
* Convert string to int
|
||||
* @param str string input
|
||||
* @returns integer output
|
||||
*/
|
||||
int str2int(const char *str);
|
||||
|
||||
/**
|
||||
* Convert string to realtype
|
||||
* @param x integer input
|
||||
* @returns string output
|
||||
*/
|
||||
REALTYPE str2real(const char *str);
|
||||
|
||||
/**Temporary string for various uses*/
|
||||
char tmpstr[TMPSTR_SIZE];
|
||||
|
||||
|
||||
/**this is used to store the parents.
|
||||
* @todo Use the stack class provided by C++*/
|
||||
mxml_node_t *parentstack[STACKSIZE];
|
||||
int stackpos;/**<position in stack*/
|
||||
|
||||
|
||||
void push(mxml_node_t *node);
|
||||
|
||||
/**Pops top node off of parent stack*/
|
||||
mxml_node_t *pop();
|
||||
/**Returns top node off of parent stack*/
|
||||
mxml_node_t *peek();
|
||||
|
||||
struct {
|
||||
struct {
|
||||
int major;/**<major version number.*/
|
||||
int minor;/**<minor version number.*/
|
||||
}xml_version;/**<Stores ZynAddSubFX versioning information*/
|
||||
}values;/**< Stores ZynAddSubFX versioning information*/
|
||||
|
||||
//theese are used to store the values
|
||||
struct{
|
||||
struct {
|
||||
int major,minor;
|
||||
}xml_version;
|
||||
}values;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
33
plugins/zynaddsubfx/src/Output/CMakeLists.txt
Normal file
33
plugins/zynaddsubfx/src/Output/CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
set(zynaddsubfx_output_SRCS
|
||||
Recorder.cpp
|
||||
WAVaudiooutput.cpp
|
||||
)
|
||||
|
||||
if(AlsaMidiOutput)
|
||||
set(zynaddsubfx_output_SRCS
|
||||
${zynaddsubfx_output_SRCS}
|
||||
OSSaudiooutput.cpp)
|
||||
set(zynaddsubfx_output_lib ${ASOUND_LIBRARY})
|
||||
endif(AlsaMidiOutput)
|
||||
|
||||
if(JackOutput)
|
||||
include_directories(${JACK_INCLUDE_DIR})
|
||||
set(zynaddsubfx_output_SRCS
|
||||
${zynaddsubfx_output_SRCS}
|
||||
JACKaudiooutput.cpp)
|
||||
set(zynaddsubfx_output_lib ${JACK_LIBRARIES})
|
||||
endif(JackOutput)
|
||||
|
||||
if(PortAudioOutput)
|
||||
include_directories(${PORTAUDIO_INCLUDE_DIR})
|
||||
set(zynaddsubfx_output_SRCS
|
||||
${zynaddsubfx_output_SRCS}
|
||||
PAaudiooutput.cpp)
|
||||
set(zynaddsubfx_output_lib ${PORTAUDIO_LIBRARIES})
|
||||
endif(PortAudioOutput)
|
||||
|
||||
add_library(zynaddsubfx_output STATIC
|
||||
${zynaddsubfx_output_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries(zynaddsubfx_output ${zynaddsubfx_output_lib})
|
||||
@@ -1,279 +0,0 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
DSSIaudiooutput.C - Audio functions for DSSI
|
||||
Copyright (C) 2002 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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
|
||||
|
||||
*/
|
||||
|
||||
//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
|
||||
#include <string.h>
|
||||
#include "DSSIaudiooutput.h"
|
||||
|
||||
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;
|
||||
|
||||
|
||||
static void cleanupTS(LADSPA_Handle instance){
|
||||
free(instance);
|
||||
}
|
||||
static void connectPortTS(LADSPA_Handle instance, unsigned long port,
|
||||
LADSPA_Data * data){
|
||||
TS *plugin;
|
||||
plugin = (TS *) instance;
|
||||
switch (port) {
|
||||
case 0:
|
||||
plugin->outl = data;
|
||||
break;
|
||||
case 1:
|
||||
plugin->outr = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const LADSPA_Descriptor *ladspa_descriptor(unsigned long index){
|
||||
switch (index) {
|
||||
case 0:
|
||||
return tsLDescriptor;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const DSSI_Descriptor *dssi_descriptor(unsigned long index){
|
||||
// FILE *a=fopen("/tmp/zzzzz11z","w");
|
||||
// fprintf(a,"aaaaaaaaaaa TEST\n");
|
||||
// fclose(a);
|
||||
switch (index) {
|
||||
case 0:
|
||||
return tsDDescriptor;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static LADSPA_Handle instantiateTS(const LADSPA_Descriptor * descriptor,
|
||||
unsigned long s_rate)
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
TS *plugin_data = (TS *) instance;
|
||||
|
||||
// for (i=0; i<MIDI_NOTES; i++) {
|
||||
// plugin_data->data[i].active = 0;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
static void runTS(LADSPA_Handle instance, unsigned long sample_count,
|
||||
snd_seq_event_t *events, unsigned long event_count){
|
||||
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;
|
||||
}
|
||||
|
||||
if (event_count > 0) {
|
||||
printf("trivial_synth: have %ld events\n", event_count);
|
||||
}
|
||||
|
||||
for (pos = 0, event_pos = 0; pos < sample_count; pos++) {
|
||||
|
||||
while (event_pos < event_count
|
||||
&& pos == events[event_pos].time.tick) {
|
||||
|
||||
printf("trivial_synth: event type %d\n", events[event_pos].type);
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static void runTSWrapper(LADSPA_Handle instance,
|
||||
unsigned long sample_count){
|
||||
runTS(instance, sample_count, NULL, 0);
|
||||
}
|
||||
|
||||
int getControllerTS(LADSPA_Handle instance, unsigned long port){
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _init(){
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void _fini(){
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//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();
|
||||
};
|
||||
|
||||
*/
|
||||
288
plugins/zynaddsubfx/src/Output/DSSIaudiooutput.cpp
Normal file
288
plugins/zynaddsubfx/src/Output/DSSIaudiooutput.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
ZynAddSubFX - a software synthesizer
|
||||
|
||||
DSSIaudiooutput.C - Audio functions for DSSI
|
||||
Copyright (C) 2002 Nasca Octavian Paul
|
||||
Author: Nasca Octavian Paul
|
||||
|
||||
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 or later) 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
|
||||
|
||||
*/
|
||||
|
||||
//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
|
||||
#include <string.h>
|
||||
#include "DSSIaudiooutput.h"
|
||||
|
||||
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;
|
||||
|
||||
|
||||
static void cleanupTS(LADSPA_Handle instance)
|
||||
{
|
||||
free(instance);
|
||||
}
|
||||
static void connectPortTS(LADSPA_Handle instance, unsigned long port,
|
||||
LADSPA_Data * data)
|
||||
{
|
||||
TS *plugin;
|
||||
plugin = (TS *) instance;
|
||||
switch (port) {
|
||||
case 0:
|
||||
plugin->outl = data;
|
||||
break;
|
||||
case 1:
|
||||
plugin->outr = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const LADSPA_Descriptor *ladspa_descriptor(unsigned long index)
|
||||
{
|
||||
switch (index) {
|
||||
case 0:
|
||||
return tsLDescriptor;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const DSSI_Descriptor *dssi_descriptor(unsigned long index)
|
||||
{
|
||||
// FILE *a=fopen("/tmp/zzzzz11z","w");
|
||||
// fprintf(a,"aaaaaaaaaaa TEST\n");
|
||||
// fclose(a);
|
||||
switch (index) {
|
||||
case 0:
|
||||
return tsDDescriptor;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static LADSPA_Handle instantiateTS(const LADSPA_Descriptor * descriptor,
|
||||
unsigned long s_rate)
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
TS *plugin_data = (TS *) instance;
|
||||
|
||||
// for (i=0; i<MIDI_NOTES; i++) {
|
||||
// plugin_data->data[i].active = 0;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
static void runTS(LADSPA_Handle instance, unsigned long sample_count,
|
||||
snd_seq_event_t *events, unsigned long event_count)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (event_count > 0) {
|
||||
printf("trivial_synth: have %ld events\n", event_count);
|
||||
}
|
||||
|
||||
for (pos = 0, event_pos = 0; pos < sample_count; pos++) {
|
||||
|
||||
while (event_pos < event_count
|
||||
&& pos == events[event_pos].time.tick) {
|
||||
|
||||
printf("trivial_synth: event type %d\n", events[event_pos].type);
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static void runTSWrapper(LADSPA_Handle instance,
|
||||
unsigned long sample_count)
|
||||
{
|
||||
runTS(instance, sample_count, NULL, 0);
|
||||
}
|
||||
|
||||
int getControllerTS(LADSPA_Handle instance, unsigned long port)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _init()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void _fini()
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//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();
|
||||
};
|
||||
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user